forked from cerc-io/laconicd-deprecated
conflicts
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
package evm
|
||||
|
||||
import (
|
||||
"github.com/cosmos/ethermint/x/evm/keeper"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
// nolint
|
||||
const (
|
||||
ModuleName = types.ModuleName
|
||||
StoreKey = types.StoreKey
|
||||
RouterKey = types.RouterKey
|
||||
DefaultParamspace = types.DefaultParamspace
|
||||
)
|
||||
|
||||
// nolint
|
||||
var (
|
||||
NewKeeper = keeper.NewKeeper
|
||||
TxDecoder = types.TxDecoder
|
||||
)
|
||||
|
||||
//nolint
|
||||
type (
|
||||
Keeper = keeper.Keeper
|
||||
GenesisState = types.GenesisState
|
||||
)
|
||||
+61
-44
@@ -1,88 +1,105 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
|
||||
rpctypes "github.com/cosmos/ethermint/rpc/types"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
// GetQueryCmd defines evm module queries through the cli
|
||||
func GetQueryCmd(moduleName string, cdc *codec.Codec) *cobra.Command {
|
||||
evmQueryCmd := &cobra.Command{
|
||||
// GetQueryCmd returns the parent command for all x/bank CLi query commands.
|
||||
func GetQueryCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: types.ModuleName,
|
||||
Short: "Querying commands for the evm module",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
evmQueryCmd.AddCommand(flags.GetCommands(
|
||||
GetCmdGetStorageAt(moduleName, cdc),
|
||||
GetCmdGetCode(moduleName, cdc),
|
||||
)...)
|
||||
return evmQueryCmd
|
||||
|
||||
cmd.AddCommand(
|
||||
GetStorageCmd(),
|
||||
GetCodeCmd(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// GetCmdGetStorageAt queries a key in an accounts storage
|
||||
func GetCmdGetStorageAt(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "storage [account] [key]",
|
||||
Short: "Gets storage for an account at a given key",
|
||||
// GetStorageCmd queries a key in an accounts storage
|
||||
func GetStorageCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "storage [address] [key]",
|
||||
Short: "Gets storage for an account with a given key and height",
|
||||
Long: "Gets storage for an account with a given key and height. If the height is not provided, it will use the latest height from context.",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
|
||||
account, err := accountToHex(args[0])
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not parse account address")
|
||||
return err
|
||||
}
|
||||
|
||||
queryClient := types.NewQueryClient(clientCtx)
|
||||
|
||||
address, err := accountToHex(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key := formatKeyToHash(args[1])
|
||||
|
||||
res, _, err := clientCtx.Query(
|
||||
fmt.Sprintf("custom/%s/storage/%s/%s", queryRoute, account, key))
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not resolve: %s", err)
|
||||
req := &types.QueryStorageRequest{
|
||||
Address: address,
|
||||
Key: key,
|
||||
}
|
||||
var out types.QueryResStorage
|
||||
cdc.MustUnmarshalJSON(res, &out)
|
||||
return clientCtx.PrintOutput(out)
|
||||
|
||||
res, err := queryClient.Storage(rpctypes.ContextWithHeight(clientCtx.Height), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
},
|
||||
}
|
||||
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// GetCmdGetCode queries the code field of a given address
|
||||
func GetCmdGetCode(queryRoute string, cdc *codec.Codec) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "code [account]",
|
||||
// GetCodeCmd queries the code field of a given address
|
||||
func GetCodeCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "code [address]",
|
||||
Short: "Gets code from an account",
|
||||
Long: "Gets code from an account. If the height is not provided, it will use the latest height from context.",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx := context.NewCLIContext().WithCodec(cdc)
|
||||
|
||||
account, err := accountToHex(args[0])
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not parse account address")
|
||||
return err
|
||||
}
|
||||
|
||||
res, _, err := clientCtx.Query(
|
||||
fmt.Sprintf("custom/%s/code/%s", queryRoute, account))
|
||||
queryClient := types.NewQueryClient(clientCtx)
|
||||
|
||||
address, err := accountToHex(args[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not resolve: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
var out types.QueryResCode
|
||||
cdc.MustUnmarshalJSON(res, &out)
|
||||
return clientCtx.PrintOutput(out)
|
||||
req := &types.QueryCodeRequest{
|
||||
Address: address,
|
||||
}
|
||||
|
||||
res, err := queryClient.Code(rpctypes.ContextWithHeight(clientCtx.Height), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
},
|
||||
}
|
||||
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
+32
-33
@@ -1,90 +1,89 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
clientrest "github.com/cosmos/cosmos-sdk/client/rest"
|
||||
"github.com/cosmos/cosmos-sdk/types/rest"
|
||||
authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/client/utils"
|
||||
|
||||
rpctypes "github.com/cosmos/ethermint/rpc/types"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// RegisterRoutes - Central function to define routes that get registered by the main application
|
||||
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) {
|
||||
r.HandleFunc("/txs/{hash}", QueryTxRequestHandlerFn(cliCtx)).Methods("GET")
|
||||
r.HandleFunc("/txs", authrest.QueryTxsRequestHandlerFn(cliCtx)).Methods("GET") // default from auth
|
||||
r.HandleFunc("/txs", authrest.BroadcastTxRequest(cliCtx)).Methods("POST") // default from auth
|
||||
r.HandleFunc("/txs/encode", authrest.EncodeTxRequestHandlerFn(cliCtx)).Methods("POST") // default from auth
|
||||
r.HandleFunc("/txs/decode", authrest.DecodeTxRequestHandlerFn(cliCtx)).Methods("POST") // default from auth
|
||||
// RegisterTxRoutes - Central function to define routes that get registered by the main application
|
||||
func RegisterTxRoutes(clientCtx client.Context, rtr *mux.Router) {
|
||||
r := clientrest.WithHTTPDeprecationHeaders(rtr)
|
||||
r.HandleFunc("/txs/{hash}", QueryTxRequestHandlerFn(clientCtx)).Methods("GET")
|
||||
r.HandleFunc("/txs", authrest.QueryTxsRequestHandlerFn(clientCtx)).Methods("GET")
|
||||
r.HandleFunc("/txs", authrest.BroadcastTxRequest(clientCtx)).Methods("POST")
|
||||
r.HandleFunc("/txs/encode", authrest.EncodeTxRequestHandlerFn(clientCtx)).Methods("POST")
|
||||
r.HandleFunc("/txs/decode", authrest.DecodeTxRequestHandlerFn(clientCtx)).Methods("POST")
|
||||
}
|
||||
|
||||
func QueryTxRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
|
||||
// QueryTxRequestHandlerFn implements a REST handler that queries a transaction
|
||||
// by hash in a committed block.
|
||||
func QueryTxRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
hashHexStr := vars["hash"]
|
||||
|
||||
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
|
||||
clientCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, clientCtx, r)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
ethHashPrefix := "0x"
|
||||
if strings.HasPrefix(hashHexStr, ethHashPrefix) {
|
||||
// eth Tx
|
||||
ethHashPrefixLength := len(ethHashPrefix)
|
||||
output, err := getEthTransactionByHash(cliCtx, hashHexStr[ethHashPrefixLength:])
|
||||
if err != nil {
|
||||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
rest.PostProcessResponseBare(w, cliCtx, output)
|
||||
if !strings.HasPrefix(hashHexStr, ethHashPrefix) {
|
||||
authrest.QueryTxRequestHandlerFn(clientCtx)
|
||||
return
|
||||
}
|
||||
|
||||
output, err := utils.QueryTx(cliCtx, hashHexStr)
|
||||
// eth Tx
|
||||
ethHashPrefixLength := len(ethHashPrefix)
|
||||
output, err := getEthTransactionByHash(clientCtx, hashHexStr[ethHashPrefixLength:])
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), hashHexStr) {
|
||||
rest.WriteErrorResponse(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
rest.PostProcessResponseBare(w, cliCtx, output)
|
||||
}
|
||||
|
||||
rest.PostProcessResponseBare(w, clientCtx, output)
|
||||
}
|
||||
}
|
||||
|
||||
// GetTransactionByHash returns the transaction identified by hash.
|
||||
func getEthTransactionByHash(cliCtx context.CLIContext, hashHex string) ([]byte, error) {
|
||||
func getEthTransactionByHash(clientCtx client.Context, hashHex string) ([]byte, error) {
|
||||
hash, err := hex.DecodeString(hashHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node, err := cliCtx.GetNode()
|
||||
node, err := clientCtx.GetNode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx, err := node.Tx(hash, false)
|
||||
|
||||
tx, err := node.Tx(context.Background(), hash, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Can either cache or just leave this out if not necessary
|
||||
block, err := node.Block(&tx.Height)
|
||||
block, err := node.Block(context.Background(), &tx.Height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockHash := common.BytesToHash(block.Block.Hash())
|
||||
|
||||
ethTx, err := rpctypes.RawTxToEthTx(cliCtx, tx.Tx)
|
||||
ethTx, err := rpctypes.RawTxToEthTx(clientCtx, tx.Tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+10
-10
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
@@ -20,9 +20,9 @@ func InitGenesis(
|
||||
ctx sdk.Context,
|
||||
k keeper.Keeper,
|
||||
accountKeeper types.AccountKeeper, // nolint: interfacer
|
||||
data GenesisState,
|
||||
bankKeeper types.BankKeeper,
|
||||
data types.GenesisState,
|
||||
) []abci.ValidatorUpdate {
|
||||
|
||||
k.SetParams(ctx, data.Params)
|
||||
evmDenom := data.Params.EvmDenom
|
||||
|
||||
@@ -44,10 +44,9 @@ func InitGenesis(
|
||||
)
|
||||
}
|
||||
|
||||
evmBalance := acc.GetCoins().AmountOf(evmDenom)
|
||||
|
||||
evmBalance := bankKeeper.GetBalance(ctx, accAddress, evmDenom)
|
||||
k.SetBalance(ctx, address, evmBalance.Amount.BigInt())
|
||||
k.SetNonce(ctx, address, acc.GetSequence())
|
||||
k.SetBalance(ctx, address, evmBalance.BigInt())
|
||||
k.SetCode(ctx, address, ethcmn.Hex2Bytes(account.Code))
|
||||
|
||||
for _, storage := range account.Storage {
|
||||
@@ -57,7 +56,8 @@ func InitGenesis(
|
||||
|
||||
var err error
|
||||
for _, txLog := range data.TxsLogs {
|
||||
if err = k.SetLogs(ctx, ethcmn.HexToHash(txLog.Hash), txLog.Logs); err != nil {
|
||||
err = k.SetLogs(ctx, ethcmn.HexToHash(txLog.Hash), txLog.EthLogs())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -81,10 +81,10 @@ func InitGenesis(
|
||||
}
|
||||
|
||||
// ExportGenesis exports genesis state of the EVM module
|
||||
func ExportGenesis(ctx sdk.Context, k keeper.Keeper, ak types.AccountKeeper) GenesisState {
|
||||
func ExportGenesis(ctx sdk.Context, k keeper.Keeper, ak types.AccountKeeper) *types.GenesisState {
|
||||
// nolint: prealloc
|
||||
var ethGenAccounts []types.GenesisAccount
|
||||
ak.IterateAccounts(ctx, func(account authexported.Account) bool {
|
||||
ak.IterateAccounts(ctx, func(account authtypes.AccountI) bool {
|
||||
ethAccount, ok := account.(*ethermint.EthAccount)
|
||||
if !ok {
|
||||
// ignore non EthAccounts
|
||||
@@ -110,7 +110,7 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper, ak types.AccountKeeper) Gen
|
||||
|
||||
config, _ := k.GetChainConfig(ctx)
|
||||
|
||||
return GenesisState{
|
||||
return &types.GenesisState{
|
||||
Accounts: ethGenAccounts,
|
||||
TxsLogs: k.GetAllTxLogs(ctx),
|
||||
ChainConfig: config,
|
||||
|
||||
+11
-11
@@ -1,7 +1,6 @@
|
||||
package evm_test
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
@@ -14,12 +13,12 @@ import (
|
||||
)
|
||||
|
||||
func (suite *EvmTestSuite) TestExportImport() {
|
||||
var genState types.GenesisState
|
||||
var genState *types.GenesisState
|
||||
suite.Require().NotPanics(func() {
|
||||
genState = evm.ExportGenesis(suite.ctx, *suite.app.EvmKeeper, suite.app.AccountKeeper)
|
||||
})
|
||||
|
||||
_ = evm.InitGenesis(suite.ctx, *suite.app.EvmKeeper, suite.app.AccountKeeper, genState)
|
||||
_ = evm.InitGenesis(suite.ctx, *suite.app.EvmKeeper, suite.app.AccountKeeper, suite.app.BankKeeper, *genState)
|
||||
}
|
||||
|
||||
func (suite *EvmTestSuite) TestInitGenesis() {
|
||||
@@ -31,7 +30,7 @@ func (suite *EvmTestSuite) TestInitGenesis() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
genState types.GenesisState
|
||||
genState *types.GenesisState
|
||||
expPanic bool
|
||||
}{
|
||||
{
|
||||
@@ -45,11 +44,12 @@ func (suite *EvmTestSuite) TestInitGenesis() {
|
||||
func() {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||
suite.Require().NotNil(acc)
|
||||
err := acc.SetCoins(sdk.NewCoins(ethermint.NewPhotonCoinInt64(1)))
|
||||
|
||||
err := suite.app.BankKeeper.SetBalance(suite.ctx, address.Bytes(), ethermint.NewPhotonCoinInt64(1))
|
||||
suite.Require().NoError(err)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
},
|
||||
types.GenesisState{
|
||||
&types.GenesisState{
|
||||
Params: types.DefaultParams(),
|
||||
Accounts: []types.GenesisAccount{
|
||||
{
|
||||
@@ -65,7 +65,7 @@ func (suite *EvmTestSuite) TestInitGenesis() {
|
||||
{
|
||||
"account not found",
|
||||
func() {},
|
||||
types.GenesisState{
|
||||
&types.GenesisState{
|
||||
Params: types.DefaultParams(),
|
||||
Accounts: []types.GenesisAccount{
|
||||
{
|
||||
@@ -79,9 +79,9 @@ func (suite *EvmTestSuite) TestInitGenesis() {
|
||||
"invalid account type",
|
||||
func() {
|
||||
acc := authtypes.NewBaseAccountWithAddress(address.Bytes())
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, &acc)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
},
|
||||
types.GenesisState{
|
||||
&types.GenesisState{
|
||||
Params: types.DefaultParams(),
|
||||
Accounts: []types.GenesisAccount{
|
||||
{
|
||||
@@ -102,13 +102,13 @@ func (suite *EvmTestSuite) TestInitGenesis() {
|
||||
if tc.expPanic {
|
||||
suite.Require().Panics(
|
||||
func() {
|
||||
_ = evm.InitGenesis(suite.ctx, *suite.app.EvmKeeper, suite.app.AccountKeeper, tc.genState)
|
||||
_ = evm.InitGenesis(suite.ctx, *suite.app.EvmKeeper, suite.app.AccountKeeper, suite.app.BankKeeper, *tc.genState)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
suite.Require().NotPanics(
|
||||
func() {
|
||||
_ = evm.InitGenesis(suite.ctx, *suite.app.EvmKeeper, suite.app.AccountKeeper, tc.genState)
|
||||
_ = evm.InitGenesis(suite.ctx, *suite.app.EvmKeeper, suite.app.AccountKeeper, suite.app.BankKeeper, *tc.genState)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
+43
-114
@@ -1,20 +1,24 @@
|
||||
package evm
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"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"
|
||||
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// NewHandler returns a handler for Ethermint type messages.
|
||||
func NewHandler(k *Keeper) sdk.Handler {
|
||||
return func(ctx sdk.Context, msg sdk.Msg) (result *sdk.Result, err error) {
|
||||
func NewHandler(k keeper.Keeper) sdk.Handler {
|
||||
defer telemetry.MeasureSince(time.Now(), "evm", "state_transition")
|
||||
|
||||
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
|
||||
@@ -46,116 +50,41 @@ func NewHandler(k *Keeper) sdk.Handler {
|
||||
}
|
||||
}()
|
||||
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case types.MsgEthereumTx:
|
||||
result, err = handleMsgEthereumTx(ctx, k, msg)
|
||||
case types.MsgEthermint:
|
||||
result, err = handleMsgEthermint(ctx, k, msg)
|
||||
case *types.MsgEthereumTx:
|
||||
// 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 nil, err
|
||||
}
|
||||
|
||||
// log state transition result
|
||||
var recipientLog string
|
||||
if res.ContractAddress != "" {
|
||||
recipientLog = fmt.Sprintf("contract address %s", res.ContractAddress)
|
||||
} else {
|
||||
recipientLog = fmt.Sprintf("recipient address %s", msg.Data.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
|
||||
|
||||
return result, nil
|
||||
|
||||
default:
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg)
|
||||
}
|
||||
if err != nil {
|
||||
types.CopyCommitStateDB(snapshotStateDB, k.CommitStateDB)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
|
||||
// handleMsgEthereumTx handles an Ethereum specific tx
|
||||
func handleMsgEthereumTx(ctx sdk.Context, k *Keeper, msg types.MsgEthereumTx) (*sdk.Result, error) {
|
||||
// execute state transition
|
||||
res, err := k.EthereumTx(ctx, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// log state transition result
|
||||
k.Logger(ctx).Info(res.Log)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// handleMsgEthermint handles an sdk.StdTx for an Ethereum state transition
|
||||
func handleMsgEthermint(ctx sdk.Context, k *Keeper, msg types.MsgEthermint) (*sdk.Result, error) {
|
||||
// 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 := common.BytesToHash(txHash)
|
||||
|
||||
st := types.StateTransition{
|
||||
AccountNonce: msg.AccountNonce,
|
||||
Price: msg.Price.BigInt(),
|
||||
GasLimit: msg.GasLimit,
|
||||
Amount: msg.Amount.BigInt(),
|
||||
Payload: msg.Payload,
|
||||
Csdb: k.CommitStateDB.WithContext(ctx),
|
||||
ChainID: chainIDEpoch,
|
||||
TxHash: ðHash,
|
||||
Sender: common.BytesToAddress(msg.From.Bytes()),
|
||||
Simulate: ctx.IsCheckTx(),
|
||||
}
|
||||
|
||||
if msg.Recipient != nil {
|
||||
to := common.BytesToAddress(msg.Recipient.Bytes())
|
||||
st.Recipient = &to
|
||||
}
|
||||
|
||||
if !st.Simulate {
|
||||
// Prepare db for logs
|
||||
k.CommitStateDB.Prepare(ethHash, k.TxCount)
|
||||
k.TxCount++
|
||||
}
|
||||
|
||||
config, found := k.GetChainConfig(ctx)
|
||||
if !found {
|
||||
return nil, types.ErrChainConfigNotFound
|
||||
}
|
||||
|
||||
executionResult, err := st.TransitionDb(ctx, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// update block bloom filter
|
||||
if !st.Simulate {
|
||||
k.Bloom.Or(k.Bloom, executionResult.Bloom)
|
||||
|
||||
// update transaction logs in KVStore
|
||||
err = k.SetLogs(ctx, common.BytesToHash(txHash), executionResult.Logs)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg)
|
||||
}
|
||||
}
|
||||
|
||||
// log successful execution
|
||||
k.Logger(ctx).Info(executionResult.Result.Log)
|
||||
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeEthermint,
|
||||
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
|
||||
sdk.NewAttribute(sdk.AttributeKeySender, msg.From.String()),
|
||||
),
|
||||
})
|
||||
|
||||
if msg.Recipient != nil {
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
types.EventTypeEthermint,
|
||||
sdk.NewAttribute(types.AttributeKeyRecipient, msg.Recipient.String()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// set the events to the result
|
||||
executionResult.Result.Events = ctx.EventManager().Events()
|
||||
return executionResult.Result, nil
|
||||
}
|
||||
|
||||
+68
-102
@@ -3,7 +3,6 @@ package evm_test
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -24,11 +23,9 @@ import (
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm"
|
||||
"github.com/cosmos/ethermint/x/evm/keeper"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
|
||||
type EvmTestSuite struct {
|
||||
@@ -36,19 +33,32 @@ type EvmTestSuite struct {
|
||||
|
||||
ctx sdk.Context
|
||||
handler sdk.Handler
|
||||
querier sdk.Querier
|
||||
app *app.EthermintApp
|
||||
codec *codec.Codec
|
||||
codec codec.BinaryMarshaler
|
||||
|
||||
privKey *ethsecp256k1.PrivKey
|
||||
from ethcmn.Address
|
||||
to sdk.AccAddress
|
||||
}
|
||||
|
||||
func (suite *EvmTestSuite) SetupTest() {
|
||||
checkTx := false
|
||||
|
||||
suite.app = app.Setup(checkTx)
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()})
|
||||
suite.handler = evm.NewHandler(suite.app.EvmKeeper)
|
||||
suite.querier = keeper.NewQuerier(*suite.app.EvmKeeper)
|
||||
suite.codec = codec.New()
|
||||
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.codec = suite.app.AppCodec()
|
||||
|
||||
privKey, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.to = sdk.AccAddress(privKey.PubKey().Address())
|
||||
|
||||
suite.privKey, err = ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.from = ethcmn.BytesToAddress(privKey.PubKey().Address().Bytes())
|
||||
|
||||
}
|
||||
|
||||
func TestEvmTestSuite(t *testing.T) {
|
||||
@@ -56,11 +66,8 @@ func TestEvmTestSuite(t *testing.T) {
|
||||
}
|
||||
|
||||
func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
|
||||
privkey, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
sender := ethcmn.HexToAddress(privkey.PubKey().Address().String())
|
||||
|
||||
var tx types.MsgEthereumTx
|
||||
var tx *types.MsgEthereumTx
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
@@ -70,15 +77,15 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
|
||||
{
|
||||
"passed",
|
||||
func() {
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, sender, big.NewInt(100))
|
||||
tx = types.NewMsgEthereumTx(0, &sender, big.NewInt(100), 0, big.NewInt(10000), nil)
|
||||
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)
|
||||
|
||||
// parse context chain ID to big.Int
|
||||
chainID, err := ethermint.ParseChainID(suite.ctx.ChainID())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// sign transaction
|
||||
err = tx.Sign(chainID, privkey.ToECDSA())
|
||||
err = tx.Sign(chainID, suite.privKey.ToECDSA())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
true,
|
||||
@@ -93,7 +100,7 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// sign transaction
|
||||
err = tx.Sign(chainID, privkey.ToECDSA())
|
||||
err = tx.Sign(chainID, suite.privKey.ToECDSA())
|
||||
suite.Require().NoError(err)
|
||||
},
|
||||
false,
|
||||
@@ -141,62 +148,6 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *EvmTestSuite) TestMsgEthermint() {
|
||||
var (
|
||||
tx types.MsgEthermint
|
||||
from = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
|
||||
to = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
|
||||
)
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"passed",
|
||||
func() {
|
||||
tx = types.NewMsgEthermint(0, &to, sdk.NewInt(1), 100000, sdk.NewInt(2), []byte("test"), from)
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, ethcmn.BytesToAddress(from.Bytes()), big.NewInt(100))
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid state transition",
|
||||
func() {
|
||||
tx = types.NewMsgEthermint(0, &to, sdk.NewInt(1), 100000, sdk.NewInt(2), []byte("test"), from)
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid chain ID",
|
||||
func() {
|
||||
suite.ctx = suite.ctx.WithChainID("chainID")
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run("", func() {
|
||||
suite.SetupTest() // reset
|
||||
//nolint
|
||||
tc.malleate()
|
||||
|
||||
res, err := suite.handler(suite.ctx, tx)
|
||||
|
||||
//nolint
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
suite.Require().Nil(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *EvmTestSuite) TestHandlerLogs() {
|
||||
// Test contract:
|
||||
|
||||
@@ -231,20 +182,47 @@ func (suite *EvmTestSuite) TestHandlerLogs() {
|
||||
result, err := suite.handler(suite.ctx, tx)
|
||||
suite.Require().NoError(err, "failed to handle eth tx msg")
|
||||
|
||||
resultData, err := types.DecodeResultData(result.Data)
|
||||
txResponse, err := types.DecodeTxResponse(result.Data)
|
||||
suite.Require().NoError(err, "failed to decode result data")
|
||||
|
||||
suite.Require().Equal(len(resultData.Logs), 1)
|
||||
suite.Require().Equal(len(resultData.Logs[0].Topics), 2)
|
||||
suite.Require().Equal(len(txResponse.TxLogs.Logs), 1)
|
||||
suite.Require().Equal(len(txResponse.TxLogs.Logs[0].Topics), 2)
|
||||
|
||||
hash := []byte{1}
|
||||
err = suite.app.EvmKeeper.SetLogs(suite.ctx, ethcmn.BytesToHash(hash), resultData.Logs)
|
||||
err = suite.app.EvmKeeper.SetLogs(suite.ctx, ethcmn.BytesToHash(hash), txResponse.TxLogs.EthLogs())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
logs, err := suite.app.EvmKeeper.GetLogs(suite.ctx, ethcmn.BytesToHash(hash))
|
||||
suite.Require().NoError(err, "failed to get logs")
|
||||
|
||||
suite.Require().Equal(logs, resultData.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *EvmTestSuite) TestQueryTxLogs() {
|
||||
@@ -264,31 +242,19 @@ func (suite *EvmTestSuite) TestQueryTxLogs() {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(result)
|
||||
|
||||
resultData, err := types.DecodeResultData(result.Data)
|
||||
txResponse, err := types.DecodeTxResponse(result.Data)
|
||||
suite.Require().NoError(err, "failed to decode result data")
|
||||
|
||||
suite.Require().Equal(len(resultData.Logs), 1)
|
||||
suite.Require().Equal(len(resultData.Logs[0].Topics), 2)
|
||||
suite.Require().Equal(len(txResponse.TxLogs.Logs), 1)
|
||||
suite.Require().Equal(len(txResponse.TxLogs.Logs[0].Topics), 2)
|
||||
|
||||
// get logs by tx hash
|
||||
hash := resultData.TxHash.Bytes()
|
||||
hash := txResponse.TxLogs.Hash
|
||||
|
||||
logs, err := suite.app.EvmKeeper.GetLogs(suite.ctx, ethcmn.BytesToHash(hash))
|
||||
logs, err := suite.app.EvmKeeper.GetLogs(suite.ctx, ethcmn.HexToHash(hash))
|
||||
suite.Require().NoError(err, "failed to get logs")
|
||||
|
||||
suite.Require().Equal(logs, resultData.Logs)
|
||||
|
||||
// query tx logs
|
||||
path := []string{"transactionLogs", fmt.Sprintf("0x%x", hash)}
|
||||
res, err := suite.querier(suite.ctx, path, abci.RequestQuery{})
|
||||
suite.Require().NoError(err, "failed to query txLogs")
|
||||
|
||||
var txLogs types.QueryETHLogs
|
||||
suite.codec.MustUnmarshalJSON(res, &txLogs)
|
||||
|
||||
// amino decodes an empty byte array as nil, whereas JSON decodes it as []byte{} causing a discrepancy
|
||||
resultData.Logs[0].Data = []byte{}
|
||||
suite.Require().Equal(txLogs.Logs[0], resultData.Logs[0])
|
||||
suite.Require().Equal(logs, txResponse.TxLogs.EthLogs())
|
||||
}
|
||||
|
||||
func (suite *EvmTestSuite) TestDeployAndCallContract() {
|
||||
@@ -361,13 +327,13 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
|
||||
result, err := suite.handler(suite.ctx, tx)
|
||||
suite.Require().NoError(err, "failed to handle eth tx msg")
|
||||
|
||||
resultData, err := types.DecodeResultData(result.Data)
|
||||
txResponse, err := types.DecodeTxResponse(result.Data)
|
||||
suite.Require().NoError(err, "failed to decode result data")
|
||||
|
||||
// store - changeOwner
|
||||
gasLimit = uint64(100000000000)
|
||||
gasPrice = big.NewInt(100)
|
||||
receiver := common.HexToAddress(resultData.ContractAddress.String())
|
||||
receiver := common.HexToAddress(txResponse.ContractAddress)
|
||||
|
||||
storeAddr := "0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424"
|
||||
bytecode = common.FromHex(storeAddr)
|
||||
@@ -378,7 +344,7 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
|
||||
result, err = suite.handler(suite.ctx, tx)
|
||||
suite.Require().NoError(err, "failed to handle eth tx msg")
|
||||
|
||||
resultData, err = types.DecodeResultData(result.Data)
|
||||
txResponse, err = types.DecodeTxResponse(result.Data)
|
||||
suite.Require().NoError(err, "failed to decode result data")
|
||||
|
||||
// query - getOwner
|
||||
@@ -390,10 +356,10 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
|
||||
result, err = suite.handler(suite.ctx, tx)
|
||||
suite.Require().NoError(err, "failed to handle eth tx msg")
|
||||
|
||||
resultData, err = types.DecodeResultData(result.Data)
|
||||
txResponse, err = types.DecodeTxResponse(result.Data)
|
||||
suite.Require().NoError(err, "failed to decode result data")
|
||||
|
||||
getAddr := strings.ToLower(hexutils.BytesToHex(resultData.Ret))
|
||||
getAddr := strings.ToLower(hexutils.BytesToHex(txResponse.Ret))
|
||||
suite.Require().Equal(true, strings.HasSuffix(storeAddr, getAddr), "Fail to query the address")
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// BeginBlock sets the block hash -> block height map for the previous block height
|
||||
// BeginBlock sets the block height -> header hash 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 {
|
||||
@@ -25,9 +25,7 @@ func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
|
||||
currentHash := req.Hash
|
||||
height := req.Header.GetHeight()
|
||||
|
||||
k.SetHeightHash(ctx, uint64(height), common.BytesToHash(currentHash))
|
||||
k.SetBlockHash(ctx, currentHash, height)
|
||||
k.CommitStateDB.SetBlockHash(common.BytesToHash(currentHash))
|
||||
k.SetHeightHash(ctx, uint64(height), common.BytesToHash(hash))
|
||||
|
||||
// reset counters that are used on CommitStateDB.Prepare
|
||||
k.Bloom = big.NewInt(0)
|
||||
|
||||
@@ -5,19 +5,6 @@ import (
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestBeginBlock() {
|
||||
req := abci.RequestBeginBlock{
|
||||
Header: abci.Header{
|
||||
LastBlockId: abci.BlockID{
|
||||
Hash: []byte("last hash"),
|
||||
},
|
||||
Height: 10,
|
||||
},
|
||||
Hash: []byte("hash"),
|
||||
}
|
||||
|
||||
// get the initial consumption
|
||||
initialConsumed := suite.ctx.GasMeter().GasConsumed()
|
||||
|
||||
// update the counters
|
||||
suite.app.EvmKeeper.Bloom.SetInt64(10)
|
||||
suite.app.EvmKeeper.TxCount = 10
|
||||
@@ -25,18 +12,6 @@ func (suite *KeeperTestSuite) TestBeginBlock() {
|
||||
suite.app.EvmKeeper.BeginBlock(suite.ctx, abci.RequestBeginBlock{})
|
||||
suite.Require().NotZero(suite.app.EvmKeeper.Bloom.Int64())
|
||||
suite.Require().NotZero(suite.app.EvmKeeper.TxCount)
|
||||
|
||||
suite.Require().Equal(int64(initialConsumed), int64(suite.ctx.GasMeter().GasConsumed()))
|
||||
|
||||
suite.app.EvmKeeper.BeginBlock(suite.ctx, req)
|
||||
suite.Require().Zero(suite.app.EvmKeeper.Bloom.Int64())
|
||||
suite.Require().Zero(suite.app.EvmKeeper.TxCount)
|
||||
|
||||
suite.Require().Equal(int64(initialConsumed), int64(suite.ctx.GasMeter().GasConsumed()))
|
||||
|
||||
lastHeight, found := suite.app.EvmKeeper.GetBlockHash(suite.ctx, req.Hash)
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(int64(10), lastHeight)
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestEndBlock() {
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
var _ types.QueryServer = Keeper{}
|
||||
|
||||
// Account implements the Query/Account gRPC method
|
||||
func (q Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*types.QueryAccountResponse, error) {
|
||||
if req == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if len(req.Address) == 0 {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrZeroAddress.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
so := q.GetOrNewStateObject(ctx, ethcmn.HexToAddress(req.Address))
|
||||
balance, err := ethermint.MarshalBigInt(so.Balance())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.QueryAccountResponse{
|
||||
Balance: balance,
|
||||
CodeHash: so.CodeHash(),
|
||||
Nonce: so.Nonce(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Balance implements the Query/Balance gRPC method
|
||||
func (q Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*types.QueryBalanceResponse, error) {
|
||||
if req == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if len(req.Address) == 0 {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrZeroAddress.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
balanceInt := q.GetBalance(ctx, ethcmn.HexToAddress(req.Address))
|
||||
balance, err := ethermint.MarshalBigInt(balanceInt)
|
||||
if err != nil {
|
||||
return nil, status.Error(
|
||||
codes.Internal,
|
||||
"failed to marshal big.Int to string",
|
||||
)
|
||||
}
|
||||
|
||||
return &types.QueryBalanceResponse{
|
||||
Balance: balance,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Storage implements the Query/Storage gRPC method
|
||||
func (q Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (*types.QueryStorageResponse, error) {
|
||||
if req == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if len(req.Address) == 0 {
|
||||
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)
|
||||
|
||||
return &types.QueryStorageResponse{
|
||||
Value: state.String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Code implements the Query/Code gRPC method
|
||||
func (q Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.QueryCodeResponse, error) {
|
||||
if req == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if len(req.Address) == 0 {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrZeroAddress.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
address := ethcmn.HexToAddress(req.Address)
|
||||
code := q.GetCode(ctx, address)
|
||||
|
||||
return &types.QueryCodeResponse{
|
||||
Code: code,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TxLogs implements the Query/TxLogs gRPC method
|
||||
func (q Keeper) TxLogs(c context.Context, req *types.QueryTxLogsRequest) (*types.QueryTxLogsResponse, error) {
|
||||
if req == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if types.IsEmptyHash(req.Hash) {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrEmptyHash.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
hash := ethcmn.HexToHash(req.Hash)
|
||||
logs, err := q.GetLogs(ctx, hash)
|
||||
if err != nil {
|
||||
return nil, status.Error(
|
||||
codes.Internal,
|
||||
err.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
return &types.QueryTxLogsResponse{
|
||||
Logs: types.NewTransactionLogsFromEth(hash, logs).Logs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BlockLogs implements the Query/BlockLogs gRPC method
|
||||
func (q Keeper) BlockLogs(c context.Context, req *types.QueryBlockLogsRequest) (*types.QueryBlockLogsResponse, error) {
|
||||
if req == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||
}
|
||||
|
||||
if types.IsEmptyHash(req.Hash) {
|
||||
return nil, status.Error(
|
||||
codes.InvalidArgument,
|
||||
types.ErrEmptyHash.Error(),
|
||||
)
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
txLogs := q.GetAllTxLogs(ctx)
|
||||
|
||||
return &types.QueryBlockLogsResponse{
|
||||
TxLogs: txLogs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BlockBloom implements the Query/BlockBloom gRPC method
|
||||
func (q Keeper) BlockBloom(c context.Context, _ *types.QueryBlockBloomRequest) (*types.QueryBlockBloomResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
|
||||
// use block height provided through the gRPC header
|
||||
bloom, found := q.GetBlockBloom(ctx, ctx.BlockHeight())
|
||||
if !found {
|
||||
return nil, status.Errorf(
|
||||
codes.NotFound, "%s: height %d", types.ErrBloomNotFound.Error(), ctx.BlockHeight(),
|
||||
)
|
||||
}
|
||||
|
||||
return &types.QueryBlockBloomResponse{
|
||||
Bloom: bloom.Bytes(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Params implements the Query/Params gRPC method
|
||||
func (q Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
params := q.GetParams(ctx)
|
||||
|
||||
return &types.QueryParamsResponse{
|
||||
Params: params,
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,499 @@
|
||||
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,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
@@ -30,7 +30,7 @@ func (k Keeper) BalanceInvariant() sdk.Invariant {
|
||||
count int
|
||||
)
|
||||
|
||||
k.accountKeeper.IterateAccounts(ctx, func(account authexported.Account) bool {
|
||||
k.accountKeeper.IterateAccounts(ctx, func(account authtypes.AccountI) bool {
|
||||
ethAccount, ok := account.(*ethermint.EthAccount)
|
||||
if !ok {
|
||||
// ignore non EthAccounts
|
||||
@@ -38,10 +38,11 @@ func (k Keeper) BalanceInvariant() sdk.Invariant {
|
||||
}
|
||||
|
||||
evmDenom := k.GetParams(ctx).EvmDenom
|
||||
accountBalance := ethAccount.GetCoins().AmountOf(evmDenom)
|
||||
|
||||
accountBalance := k.bankKeeper.GetBalance(ctx, ethAccount.GetAddress(), evmDenom)
|
||||
evmBalance := k.GetBalance(ctx, ethAccount.EthAddress())
|
||||
|
||||
if evmBalance.Cmp(accountBalance.BigInt()) != 0 {
|
||||
if evmBalance.Cmp(accountBalance.Amount.BigInt()) != 0 {
|
||||
count++
|
||||
msg += fmt.Sprintf(
|
||||
"\tbalance mismatch for address %s: account balance %s, evm balance %s\n",
|
||||
@@ -70,7 +71,7 @@ func (k Keeper) NonceInvariant() sdk.Invariant {
|
||||
count int
|
||||
)
|
||||
|
||||
k.accountKeeper.IterateAccounts(ctx, func(account authexported.Account) bool {
|
||||
k.accountKeeper.IterateAccounts(ctx, func(account authtypes.AccountI) bool {
|
||||
ethAccount, ok := account.(*ethermint.EthAccount)
|
||||
if !ok {
|
||||
// ignore non EthAccounts
|
||||
|
||||
@@ -3,7 +3,6 @@ package keeper_test
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
@@ -28,7 +27,7 @@ func (suite *KeeperTestSuite) TestBalanceInvariant() {
|
||||
func() {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||
suite.Require().NotNil(acc)
|
||||
err := acc.SetCoins(sdk.NewCoins(ethermint.NewPhotonCoinInt64(1)))
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, acc.GetAddress(), ethermint.NewPhotonCoinInt64(1))
|
||||
suite.Require().NoError(err)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
@@ -41,7 +40,7 @@ func (suite *KeeperTestSuite) TestBalanceInvariant() {
|
||||
func() {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||
suite.Require().NotNil(acc)
|
||||
err := acc.SetCoins(sdk.NewCoins(ethermint.NewPhotonCoinInt64(1)))
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, acc.GetAddress(), ethermint.NewPhotonCoinInt64(1))
|
||||
suite.Require().NoError(err)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
@@ -53,7 +52,7 @@ func (suite *KeeperTestSuite) TestBalanceInvariant() {
|
||||
"invalid account type",
|
||||
func() {
|
||||
acc := authtypes.NewBaseAccountWithAddress(address.Bytes())
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, &acc)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -116,7 +115,7 @@ func (suite *KeeperTestSuite) TestNonceInvariant() {
|
||||
"invalid account type",
|
||||
func() {
|
||||
acc := authtypes.NewBaseAccountWithAddress(address.Bytes())
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, &acc)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
},
|
||||
false,
|
||||
},
|
||||
|
||||
+12
-38
@@ -1,7 +1,6 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
@@ -10,7 +9,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
@@ -21,8 +20,8 @@ import (
|
||||
// Keeper wraps the CommitStateDB, allowing us to pass in SDK context while adhering
|
||||
// to the StateDB interface.
|
||||
type Keeper struct {
|
||||
// Amino codec
|
||||
cdc *codec.Codec
|
||||
// Protobuf codec
|
||||
cdc codec.BinaryMarshaler
|
||||
// Store key required for the EVM Prefix KVStore. It is required by:
|
||||
// - storing Account's Storage State
|
||||
// - storing Account's Code
|
||||
@@ -32,6 +31,7 @@ type Keeper struct {
|
||||
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.
|
||||
@@ -43,7 +43,8 @@ type Keeper struct {
|
||||
|
||||
// NewKeeper generates new evm module keeper
|
||||
func NewKeeper(
|
||||
cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspace, ak types.AccountKeeper,
|
||||
cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, paramSpace paramtypes.Subspace,
|
||||
ak types.AccountKeeper, bankKeeper types.BankKeeper,
|
||||
) *Keeper {
|
||||
// set KeyTable if it has not already been set
|
||||
if !paramSpace.HasKeyTable() {
|
||||
@@ -53,9 +54,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{
|
||||
cdc: cdc,
|
||||
storeKey: storeKey,
|
||||
accountKeeper: ak,
|
||||
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, paramSpace, ak),
|
||||
bankKeeper: bankKeeper,
|
||||
storeKey: storeKey,
|
||||
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, paramSpace, ak, bankKeeper),
|
||||
TxCount: 0,
|
||||
Bloom: big.NewInt(0),
|
||||
}
|
||||
@@ -66,31 +68,6 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger {
|
||||
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Block hash mapping functions
|
||||
// Required by Web3 API.
|
||||
// TODO: remove once tendermint support block queries by hash.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// GetBlockHash gets block height from block consensus hash
|
||||
func (k Keeper) GetBlockHash(ctx sdk.Context, hash []byte) (int64, bool) {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixBlockHash)
|
||||
bz := store.Get(hash)
|
||||
if len(bz) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
height := binary.BigEndian.Uint64(bz)
|
||||
return int64(height), true
|
||||
}
|
||||
|
||||
// SetBlockHash sets the mapping from block consensus hash to block height
|
||||
func (k Keeper) SetBlockHash(ctx sdk.Context, hash []byte, height int64) {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixBlockHash)
|
||||
bz := sdk.Uint64ToBigEndian(uint64(height))
|
||||
store.Set(hash, bz)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Epoch Height -> hash mapping functions
|
||||
// Required by EVM context's GetHashFunc
|
||||
@@ -137,12 +114,10 @@ func (k Keeper) GetAllTxLogs(ctx sdk.Context) []types.TransactionLogs {
|
||||
|
||||
txsLogs := []types.TransactionLogs{}
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
hash := common.BytesToHash(iterator.Key())
|
||||
var logs []*ethtypes.Log
|
||||
k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &logs)
|
||||
var txLog types.TransactionLogs
|
||||
k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &txLog)
|
||||
|
||||
// add a new entry
|
||||
txLog := types.NewTransactionLogs(hash, logs)
|
||||
txsLogs = append(txsLogs, txLog)
|
||||
}
|
||||
return txsLogs
|
||||
@@ -166,7 +141,6 @@ 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) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
|
||||
bz := store.Get(types.KeyPrefixChainConfig)
|
||||
if len(bz) == 0 {
|
||||
return types.ChainConfig{}, false
|
||||
@@ -180,6 +154,6 @@ 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) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
bz := k.cdc.MustMarshalBinaryBare(config)
|
||||
bz := k.cdc.MustMarshalBinaryBare(&config)
|
||||
store.Set(types.KeyPrefixChainConfig, bz)
|
||||
}
|
||||
|
||||
+22
-28
@@ -7,19 +7,19 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
"github.com/cosmos/ethermint/app"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/keeper"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
|
||||
const addrHex = "0x756F45E3FA69347A9A973A725E3C98bC4db0b4c1"
|
||||
@@ -32,27 +32,31 @@ var (
|
||||
type KeeperTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
ctx sdk.Context
|
||||
querier sdk.Querier
|
||||
app *app.EthermintApp
|
||||
address ethcmn.Address
|
||||
ctx sdk.Context
|
||||
app *app.EthermintApp
|
||||
queryClient types.QueryClient
|
||||
address ethcmn.Address
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) SetupTest() {
|
||||
checkTx := false
|
||||
|
||||
suite.app = app.Setup(checkTx)
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()})
|
||||
suite.querier = keeper.NewQuerier(*suite.app.EvmKeeper)
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()})
|
||||
suite.address = ethcmn.HexToAddress(addrHex)
|
||||
|
||||
balance := sdk.NewCoins(ethermint.NewPhotonCoin(sdk.ZeroInt()))
|
||||
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
|
||||
types.RegisterQueryServer(queryHelper, suite.app.EvmKeeper)
|
||||
suite.queryClient = types.NewQueryClient(queryHelper)
|
||||
|
||||
balance := ethermint.NewPhotonCoin(sdk.ZeroInt())
|
||||
acc := ðermint.EthAccount{
|
||||
BaseAccount: auth.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), balance, nil, 0, 0),
|
||||
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0),
|
||||
CodeHash: ethcrypto.Keccak256(nil),
|
||||
}
|
||||
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, acc.GetAddress(), balance)
|
||||
}
|
||||
|
||||
func TestKeeperTestSuite(t *testing.T) {
|
||||
@@ -65,11 +69,13 @@ 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}
|
||||
|
||||
@@ -84,6 +90,7 @@ 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)
|
||||
|
||||
@@ -92,17 +99,19 @@ 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].Logs)
|
||||
suite.Require().Equal([]*ethtypes.Log{log2, log3}, txLogs[0].EthLogs())
|
||||
|
||||
suite.Require().Equal(ethHash.String(), txLogs[1].Hash)
|
||||
suite.Require().Equal([]*ethtypes.Log{log}, txLogs[1].Logs)
|
||||
suite.Require().Equal([]*ethtypes.Log{log}, txLogs[1].EthLogs())
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestDBStorage() {
|
||||
@@ -113,14 +122,6 @@ func (suite *KeeperTestSuite) TestDBStorage() {
|
||||
suite.app.EvmKeeper.SetState(suite.ctx, suite.address, ethcmn.HexToHash("0x2"), ethcmn.HexToHash("0x3"))
|
||||
suite.app.EvmKeeper.SetCode(suite.ctx, suite.address, []byte{0x1})
|
||||
|
||||
// Test block hash mapping functionality
|
||||
suite.app.EvmKeeper.SetBlockHash(suite.ctx, hash, 7)
|
||||
height, found := suite.app.EvmKeeper.GetBlockHash(suite.ctx, hash)
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(int64(7), height)
|
||||
|
||||
suite.app.EvmKeeper.SetBlockHash(suite.ctx, []byte{0x43, 0x32}, 8)
|
||||
|
||||
// Test block height mapping functionality
|
||||
testBloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
|
||||
suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 4, testBloom)
|
||||
@@ -131,13 +132,6 @@ func (suite *KeeperTestSuite) TestDBStorage() {
|
||||
suite.Require().Equal(suite.app.EvmKeeper.GetState(suite.ctx, suite.address, ethcmn.HexToHash("0x2")), ethcmn.HexToHash("0x3"))
|
||||
suite.Require().Equal(suite.app.EvmKeeper.GetCode(suite.ctx, suite.address), []byte{0x1})
|
||||
|
||||
height, found = suite.app.EvmKeeper.GetBlockHash(suite.ctx, hash)
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(height, int64(7))
|
||||
height, found = suite.app.EvmKeeper.GetBlockHash(suite.ctx, []byte{0x43, 0x32})
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(height, int64(8))
|
||||
|
||||
bloom, found := suite.app.EvmKeeper.GetBlockBloom(suite.ctx, 4)
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(bloom, testBloom)
|
||||
|
||||
+40
-14
@@ -1,17 +1,27 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"context"
|
||||
|
||||
"github.com/armon/go-metrics"
|
||||
|
||||
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"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
var _ types.MsgServer = Keeper{}
|
||||
|
||||
// EthereumTx implements the Msg/EthereumTx gRPC method.
|
||||
func (k Keeper) EthereumTx(ctx sdk.Context, msg types.MsgEthereumTx) (*sdk.Result, error) {
|
||||
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 {
|
||||
@@ -24,14 +34,18 @@ func (k Keeper) EthereumTx(ctx sdk.Context, msg types.MsgEthereumTx) (*sdk.Resul
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var recipient *common.Address
|
||||
if msg.Data.Recipient != nil {
|
||||
addr := common.HexToAddress(msg.Data.Recipient.Address)
|
||||
recipient = &addr
|
||||
}
|
||||
|
||||
txHash := tmtypes.Tx(ctx.TxBytes()).Hash()
|
||||
ethHash := common.BytesToHash(txHash)
|
||||
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)
|
||||
recipient = &addr
|
||||
labels = []metrics.Label{telemetry.NewLabel("operation", "call")}
|
||||
}
|
||||
|
||||
st := types.StateTransition{
|
||||
AccountNonce: msg.Data.AccountNonce,
|
||||
@@ -52,7 +66,8 @@ func (k Keeper) EthereumTx(ctx sdk.Context, msg types.MsgEthereumTx) (*sdk.Resul
|
||||
// other nodes, causing a consensus error
|
||||
if !st.Simulate {
|
||||
// Prepare db for logs
|
||||
k.CommitStateDB.Prepare(ethHash, k.TxCount)
|
||||
blockHash := types.HashFromContext(ctx)
|
||||
k.Prepare(ctx, ethHash, blockHash, k.TxCount)
|
||||
k.TxCount++
|
||||
}
|
||||
|
||||
@@ -71,16 +86,28 @@ func (k Keeper) EthereumTx(ctx sdk.Context, msg types.MsgEthereumTx) (*sdk.Resul
|
||||
k.Bloom.Or(k.Bloom, executionResult.Bloom)
|
||||
|
||||
// update transaction logs in KVStore
|
||||
err = k.SetLogs(ctx, common.BytesToHash(txHash), executionResult.Logs)
|
||||
err = k.SetLogs(ctx, ethcmn.BytesToHash(txHash), 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,
|
||||
)
|
||||
}
|
||||
}()
|
||||
|
||||
// emit events
|
||||
ctx.EventManager().EmitEvents(sdk.Events{
|
||||
sdk.NewEvent(
|
||||
types.EventTypeEthereumTx,
|
||||
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Data.Amount.String()),
|
||||
sdk.NewAttribute(sdk.AttributeKeyAmount, st.Amount.String()),
|
||||
),
|
||||
sdk.NewEvent(
|
||||
sdk.EventTypeMessage,
|
||||
@@ -98,6 +125,5 @@ func (k Keeper) EthereumTx(ctx sdk.Context, msg types.MsgEthereumTx) (*sdk.Resul
|
||||
)
|
||||
}
|
||||
|
||||
executionResult.Result.Events = ctx.EventManager().Events()
|
||||
return executionResult.Result, nil
|
||||
return executionResult.Response, nil
|
||||
}
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
"github.com/cosmos/ethermint/utils"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
)
|
||||
|
||||
// NewQuerier is the module level router for state queries
|
||||
func NewQuerier(keeper Keeper) sdk.Querier {
|
||||
return func(ctx sdk.Context, path []string, _ abci.RequestQuery) ([]byte, error) {
|
||||
if len(path) < 1 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"Insufficient parameters, at least 1 parameter is required")
|
||||
}
|
||||
|
||||
switch path[0] {
|
||||
case types.QueryBalance:
|
||||
return queryBalance(ctx, path, keeper)
|
||||
case types.QueryBlockNumber:
|
||||
return queryBlockNumber(ctx, keeper)
|
||||
case types.QueryStorage:
|
||||
return queryStorage(ctx, path, keeper)
|
||||
case types.QueryCode:
|
||||
return queryCode(ctx, path, keeper)
|
||||
case types.QueryHashToHeight:
|
||||
return queryHashToHeight(ctx, path, keeper)
|
||||
case types.QueryTransactionLogs:
|
||||
return queryTransactionLogs(ctx, path, keeper)
|
||||
case types.QueryBloom:
|
||||
return queryBlockBloom(ctx, path, keeper)
|
||||
case types.QueryLogs:
|
||||
return queryLogs(ctx, keeper)
|
||||
case types.QueryAccount:
|
||||
return queryAccount(ctx, path, keeper)
|
||||
default:
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, "unknown query endpoint")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func queryBalance(ctx sdk.Context, path []string, keeper Keeper) ([]byte, error) {
|
||||
if len(path) < 2 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"Insufficient parameters, at least 2 parameters is required")
|
||||
}
|
||||
|
||||
addr := ethcmn.HexToAddress(path[1])
|
||||
balance := keeper.GetBalance(ctx, addr)
|
||||
balanceStr, err := utils.MarshalBigInt(balance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := types.QueryResBalance{Balance: balanceStr}
|
||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, res)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
|
||||
}
|
||||
|
||||
return bz, nil
|
||||
}
|
||||
|
||||
func queryBlockNumber(ctx sdk.Context, keeper Keeper) ([]byte, error) {
|
||||
num := ctx.BlockHeight()
|
||||
bnRes := types.QueryResBlockNumber{Number: num}
|
||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, bnRes)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
|
||||
}
|
||||
|
||||
return bz, nil
|
||||
}
|
||||
|
||||
func queryStorage(ctx sdk.Context, path []string, keeper Keeper) ([]byte, error) {
|
||||
if len(path) < 3 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"Insufficient parameters, at least 3 parameters is required")
|
||||
}
|
||||
|
||||
addr := ethcmn.HexToAddress(path[1])
|
||||
key := ethcmn.HexToHash(path[2])
|
||||
val := keeper.GetState(ctx, addr, key)
|
||||
res := types.QueryResStorage{Value: val.Bytes()}
|
||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, res)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
|
||||
}
|
||||
return bz, nil
|
||||
}
|
||||
|
||||
func queryCode(ctx sdk.Context, path []string, keeper Keeper) ([]byte, error) {
|
||||
if len(path) < 2 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"Insufficient parameters, at least 2 parameters is required")
|
||||
}
|
||||
|
||||
addr := ethcmn.HexToAddress(path[1])
|
||||
code := keeper.GetCode(ctx, addr)
|
||||
res := types.QueryResCode{Code: code}
|
||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, res)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
|
||||
}
|
||||
|
||||
return bz, nil
|
||||
}
|
||||
|
||||
func queryHashToHeight(ctx sdk.Context, path []string, keeper Keeper) ([]byte, error) {
|
||||
if len(path) < 2 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"Insufficient parameters, at least 2 parameters is required")
|
||||
}
|
||||
|
||||
blockHash := ethcmn.FromHex(path[1])
|
||||
blockNumber, found := keeper.GetBlockHash(ctx, blockHash)
|
||||
if !found {
|
||||
return []byte{}, fmt.Errorf("block height not found for hash %s", path[1])
|
||||
}
|
||||
|
||||
res := types.QueryResBlockNumber{Number: blockNumber}
|
||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, res)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
|
||||
}
|
||||
|
||||
return bz, nil
|
||||
}
|
||||
|
||||
func queryBlockBloom(ctx sdk.Context, path []string, keeper Keeper) ([]byte, error) {
|
||||
if len(path) < 2 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"Insufficient parameters, at least 2 parameters is required")
|
||||
}
|
||||
|
||||
num, err := strconv.ParseInt(path[1], 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not unmarshal block height: %w", err)
|
||||
}
|
||||
|
||||
bloom, found := keeper.GetBlockBloom(ctx.WithBlockHeight(num), num)
|
||||
if !found {
|
||||
return nil, fmt.Errorf("block bloom not found for height %d", num)
|
||||
}
|
||||
|
||||
res := types.QueryBloomFilter{Bloom: bloom}
|
||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, res)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
|
||||
}
|
||||
|
||||
return bz, nil
|
||||
}
|
||||
|
||||
func queryTransactionLogs(ctx sdk.Context, path []string, keeper Keeper) ([]byte, error) {
|
||||
if len(path) < 2 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"Insufficient parameters, at least 2 parameters is required")
|
||||
}
|
||||
|
||||
txHash := ethcmn.HexToHash(path[1])
|
||||
|
||||
logs, err := keeper.GetLogs(ctx, txHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := types.QueryETHLogs{Logs: logs}
|
||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, res)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
|
||||
}
|
||||
|
||||
return bz, nil
|
||||
}
|
||||
|
||||
func queryLogs(ctx sdk.Context, keeper Keeper) ([]byte, error) {
|
||||
logs := keeper.AllLogs(ctx)
|
||||
|
||||
res := types.QueryETHLogs{Logs: logs}
|
||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, res)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
|
||||
}
|
||||
return bz, nil
|
||||
}
|
||||
|
||||
func queryAccount(ctx sdk.Context, path []string, keeper Keeper) ([]byte, error) {
|
||||
if len(path) < 2 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||
"Insufficient parameters, at least 2 parameters is required")
|
||||
}
|
||||
|
||||
addr := ethcmn.HexToAddress(path[1])
|
||||
so := keeper.GetOrNewStateObject(ctx, addr)
|
||||
|
||||
balance, err := utils.MarshalBigInt(so.Balance())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := types.QueryResAccount{
|
||||
Balance: balance,
|
||||
CodeHash: so.CodeHash(),
|
||||
Nonce: so.Nonce(),
|
||||
}
|
||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, res)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONMarshal, err.Error())
|
||||
}
|
||||
return bz, nil
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestQuerier() {
|
||||
|
||||
testCases := []struct {
|
||||
msg string
|
||||
path []string
|
||||
malleate func()
|
||||
expPass bool
|
||||
}{
|
||||
{"balance", []string{types.QueryBalance, addrHex}, func() {
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, suite.address, big.NewInt(5))
|
||||
}, true},
|
||||
// {"balance fail", []string{types.QueryBalance, "0x01232"}, func() {}, false},
|
||||
{"block number", []string{types.QueryBlockNumber, "0x0"}, func() {}, true},
|
||||
{"storage", []string{types.QueryStorage, "0x0", "0x0"}, func() {}, true},
|
||||
{"code", []string{types.QueryCode, "0x0"}, func() {}, true},
|
||||
{"hash to height", []string{types.QueryHashToHeight, hex}, func() {
|
||||
suite.app.EvmKeeper.SetBlockHash(suite.ctx, hash, 8)
|
||||
}, true},
|
||||
{"tx logs", []string{types.QueryTransactionLogs, "0x0"}, func() {}, true},
|
||||
{"bloom", []string{types.QueryBloom, "4"}, func() {
|
||||
testBloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
|
||||
suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 4, testBloom)
|
||||
}, true},
|
||||
{"logs", []string{types.QueryLogs, "0x0"}, func() {}, true},
|
||||
{"account", []string{types.QueryAccount, "0x0"}, func() {}, true},
|
||||
{"unknown request", []string{"other"}, func() {}, false},
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
suite.Run("", func() {
|
||||
//nolint
|
||||
tc := tc
|
||||
suite.SetupTest() // reset
|
||||
//nolint
|
||||
tc.malleate()
|
||||
|
||||
bz, err := suite.querier(suite.ctx, tc.path, abci.RequestQuery{})
|
||||
|
||||
//nolint
|
||||
if tc.expPass {
|
||||
//nolint
|
||||
suite.Require().NoError(err, "valid test %d failed: %s", i, tc.msg)
|
||||
suite.Require().NotZero(len(bz))
|
||||
} else {
|
||||
//nolint
|
||||
suite.Require().Error(err, "invalid test %d passed: %s", i, tc.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ func (suite *KeeperTestSuite) TestBloomFilter() {
|
||||
tHash := ethcmn.BytesToHash([]byte{0x1})
|
||||
suite.app.EvmKeeper.Prepare(suite.ctx, tHash, 0)
|
||||
contractAddress := ethcmn.BigToAddress(big.NewInt(1))
|
||||
log := ethtypes.Log{Address: contractAddress}
|
||||
log := ethtypes.Log{Address: contractAddress, Topics: []ethcmn.Hash{}}
|
||||
|
||||
testCase := []struct {
|
||||
name string
|
||||
@@ -196,11 +196,11 @@ func (suite *KeeperTestSuite) TestStateDB_Code() {
|
||||
func (suite *KeeperTestSuite) TestStateDB_Logs() {
|
||||
testCase := []struct {
|
||||
name string
|
||||
log ethtypes.Log
|
||||
log *ethtypes.Log
|
||||
}{
|
||||
{
|
||||
"state db log",
|
||||
ethtypes.Log{
|
||||
ðtypes.Log{
|
||||
Address: suite.address,
|
||||
Topics: []ethcmn.Hash{ethcmn.BytesToHash([]byte("topic"))},
|
||||
Data: []byte("data"),
|
||||
@@ -208,7 +208,7 @@ func (suite *KeeperTestSuite) TestStateDB_Logs() {
|
||||
TxHash: ethcmn.Hash{},
|
||||
TxIndex: 1,
|
||||
BlockHash: ethcmn.Hash{},
|
||||
Index: 1,
|
||||
Index: 0,
|
||||
Removed: false,
|
||||
},
|
||||
},
|
||||
@@ -216,7 +216,7 @@ func (suite *KeeperTestSuite) TestStateDB_Logs() {
|
||||
|
||||
for _, tc := range testCase {
|
||||
hash := ethcmn.BytesToHash([]byte("hash"))
|
||||
logs := []*ethtypes.Log{&tc.log}
|
||||
logs := []*ethtypes.Log{tc.log}
|
||||
|
||||
err := suite.app.EvmKeeper.SetLogs(suite.ctx, hash, logs)
|
||||
suite.Require().NoError(err, tc.name)
|
||||
@@ -229,7 +229,8 @@ func (suite *KeeperTestSuite) TestStateDB_Logs() {
|
||||
suite.Require().NoError(err, tc.name)
|
||||
suite.Require().Empty(dbLogs, tc.name)
|
||||
|
||||
suite.app.EvmKeeper.AddLog(suite.ctx, &tc.log)
|
||||
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.
|
||||
@@ -381,7 +382,7 @@ func (suite *KeeperTestSuite) TestSuiteDB_CopyState() {
|
||||
TxHash: ethcmn.Hash{},
|
||||
TxIndex: 1,
|
||||
BlockHash: ethcmn.Hash{},
|
||||
Index: 1,
|
||||
Index: 0,
|
||||
Removed: false,
|
||||
},
|
||||
},
|
||||
|
||||
+74
-50
@@ -1,15 +1,19 @@
|
||||
package evm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"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/module"
|
||||
|
||||
@@ -18,71 +22,87 @@ import (
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
var _ module.AppModuleBasic = AppModuleBasic{}
|
||||
var _ module.AppModule = AppModule{}
|
||||
var (
|
||||
_ module.AppModule = AppModule{}
|
||||
_ module.AppModuleBasic = AppModuleBasic{}
|
||||
)
|
||||
|
||||
// AppModuleBasic struct
|
||||
// AppModuleBasic defines the basic application module used by the evm module.
|
||||
type AppModuleBasic struct{}
|
||||
|
||||
// Name for app module basic
|
||||
// Name returns the evm module's name.
|
||||
func (AppModuleBasic) Name() string {
|
||||
return types.ModuleName
|
||||
}
|
||||
|
||||
// RegisterCodec registers types for module
|
||||
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
|
||||
types.RegisterCodec(cdc)
|
||||
// RegisterLegacyAminoCodec performs a no-op as the evm module doesn't support amino.
|
||||
func (AppModuleBasic) RegisterLegacyAminoCodec(_ *codec.LegacyAmino) {
|
||||
}
|
||||
|
||||
// DefaultGenesis is json default structure
|
||||
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
|
||||
return types.ModuleCdc.MustMarshalJSON(types.DefaultGenesisState())
|
||||
// DefaultGenesis returns default genesis state as raw bytes for the evm
|
||||
// module.
|
||||
func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage {
|
||||
return cdc.MustMarshalJSON(types.DefaultGenesisState())
|
||||
}
|
||||
|
||||
// ValidateGenesis is the validation check of the Genesis
|
||||
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
|
||||
func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, _ client.TxEncodingConfig, bz json.RawMessage) error {
|
||||
var genesisState types.GenesisState
|
||||
err := types.ModuleCdc.UnmarshalJSON(bz, &genesisState)
|
||||
if err != nil {
|
||||
return err
|
||||
if err := cdc.UnmarshalJSON(bz, &genesisState); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
|
||||
}
|
||||
|
||||
return genesisState.Validate()
|
||||
}
|
||||
|
||||
// RegisterRESTRoutes Registers rest routes
|
||||
func (AppModuleBasic) RegisterRESTRoutes(ctx context.CLIContext, rtr *mux.Router) {
|
||||
// RegisterRESTRoutes performs a no-op as the EVM module doesn't expose REST
|
||||
// endpoints
|
||||
func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {
|
||||
}
|
||||
|
||||
// GetQueryCmd Gets the root query command of this module
|
||||
func (AppModuleBasic) GetQueryCmd(cdc *codec.Codec) *cobra.Command {
|
||||
return cli.GetQueryCmd(types.ModuleName, cdc)
|
||||
// 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 {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetTxCmd Gets the root tx command of this module
|
||||
func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
|
||||
// GetTxCmd returns nil as the evm module doesn't support transactions through the CLI.
|
||||
func (AppModuleBasic) GetTxCmd() *cobra.Command {
|
||||
return nil
|
||||
}
|
||||
|
||||
//____________________________________________________________________________
|
||||
// GetQueryCmd returns no root query command for the evm module.
|
||||
func (AppModuleBasic) GetQueryCmd() *cobra.Command {
|
||||
return cli.GetQueryCmd()
|
||||
}
|
||||
|
||||
// RegisterInterfaces registers interfaces and implementations of the evm module.
|
||||
func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
||||
types.RegisterInterfaces(registry)
|
||||
}
|
||||
|
||||
// ____________________________________________________________________________
|
||||
|
||||
// AppModule implements an application module for the evm module.
|
||||
type AppModule struct {
|
||||
AppModuleBasic
|
||||
keeper *Keeper
|
||||
keeper *keeper.Keeper
|
||||
ak types.AccountKeeper
|
||||
bk types.BankKeeper
|
||||
}
|
||||
|
||||
// NewAppModule creates a new AppModule Object
|
||||
func NewAppModule(k *Keeper, ak types.AccountKeeper) AppModule {
|
||||
// NewAppModule creates a new AppModule object
|
||||
func NewAppModule(k *keeper.Keeper, ak types.AccountKeeper, bk types.BankKeeper) AppModule {
|
||||
return AppModule{
|
||||
AppModuleBasic: AppModuleBasic{},
|
||||
keeper: k,
|
||||
ak: ak,
|
||||
bk: bk,
|
||||
}
|
||||
}
|
||||
|
||||
// Name is module name
|
||||
// Name returns the evm module's name.
|
||||
func (AppModule) Name() string {
|
||||
return types.ModuleName
|
||||
}
|
||||
@@ -92,45 +112,49 @@ func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
|
||||
keeper.RegisterInvariants(ir, *am.keeper)
|
||||
}
|
||||
|
||||
// Route specifies path for transactions
|
||||
func (am AppModule) Route() string {
|
||||
return types.RouterKey
|
||||
// RegisterServices registers the evm module Msg and gRPC services.
|
||||
func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
types.RegisterMsgServer(cfg.MsgServer(), am.keeper)
|
||||
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
|
||||
}
|
||||
|
||||
// NewHandler sets up a new handler for module
|
||||
func (am AppModule) NewHandler() sdk.Handler {
|
||||
return NewHandler(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))
|
||||
}
|
||||
|
||||
// QuerierRoute sets up path for queries
|
||||
func (am AppModule) QuerierRoute() string {
|
||||
return types.ModuleName
|
||||
// QuerierRoute returns the evm module's querier route name.
|
||||
func (AppModule) QuerierRoute() string { return types.RouterKey }
|
||||
|
||||
// LegacyQuerierHandler returns nil as the evm module doesn't expose a legacy
|
||||
// Querier.
|
||||
func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewQuerierHandler sets up new querier handler for module
|
||||
func (am AppModule) NewQuerierHandler() sdk.Querier {
|
||||
return keeper.NewQuerier(*am.keeper)
|
||||
}
|
||||
|
||||
// BeginBlock function for module at start of each block
|
||||
// BeginBlock returns the begin block for the evm module.
|
||||
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
|
||||
am.keeper.BeginBlock(ctx, req)
|
||||
}
|
||||
|
||||
// EndBlock function for module at end of block
|
||||
// EndBlock returns the end blocker for the evm module. It returns no validator
|
||||
// updates.
|
||||
func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate {
|
||||
return am.keeper.EndBlock(ctx, req)
|
||||
}
|
||||
|
||||
// InitGenesis instantiates the genesis state
|
||||
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
|
||||
// InitGenesis performs genesis initialization for the evm module. It returns
|
||||
// no validator updates.
|
||||
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data json.RawMessage) []abci.ValidatorUpdate {
|
||||
var genesisState types.GenesisState
|
||||
types.ModuleCdc.MustUnmarshalJSON(data, &genesisState)
|
||||
return InitGenesis(ctx, *am.keeper, am.ak, genesisState)
|
||||
|
||||
cdc.MustUnmarshalJSON(data, &genesisState)
|
||||
return InitGenesis(ctx, *am.keeper, am.ak, am.bk, genesisState)
|
||||
}
|
||||
|
||||
// ExportGenesis exports the genesis state to be used by daemon
|
||||
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
|
||||
// ExportGenesis returns the exported genesis state as raw bytes for the evm
|
||||
// module.
|
||||
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage {
|
||||
gs := ExportGenesis(ctx, *am.keeper, am.ak)
|
||||
return types.ModuleCdc.MustMarshalJSON(gs)
|
||||
return cdc.MustMarshalJSON(gs)
|
||||
}
|
||||
|
||||
+11
-50
@@ -4,8 +4,6 @@ import (
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
@@ -13,37 +11,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// ChainConfig defines the Ethereum ChainConfig parameters using sdk.Int values instead of big.Int.
|
||||
//
|
||||
// NOTE 1: Since empty/uninitialized Ints (i.e with a nil big.Int value) are parsed to zero, we need to manually
|
||||
// specify that negative Int values will be considered as nil. See getBlockValue for reference.
|
||||
//
|
||||
// NOTE 2: This type is not a configurable Param since the SDK does not allow for validation against
|
||||
// a previous stored parameter values or the current block height (retrieved from context). If you
|
||||
// want to update the config values, use an software upgrade procedure.
|
||||
type ChainConfig struct {
|
||||
HomesteadBlock sdk.Int `json:"homestead_block" yaml:"homestead_block"` // Homestead switch block (< 0 no fork, 0 = already homestead)
|
||||
|
||||
DAOForkBlock sdk.Int `json:"dao_fork_block" yaml:"dao_fork_block"` // TheDAO hard-fork switch block (< 0 no fork)
|
||||
DAOForkSupport bool `json:"dao_fork_support" yaml:"dao_fork_support"` // Whether the nodes supports or opposes the DAO hard-fork
|
||||
|
||||
// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
|
||||
EIP150Block sdk.Int `json:"eip150_block" yaml:"eip150_block"` // EIP150 HF block (< 0 no fork)
|
||||
EIP150Hash string `json:"eip150_hash" yaml:"eip150_hash"` // EIP150 HF hash (needed for header only clients as only gas pricing changed)
|
||||
|
||||
EIP155Block sdk.Int `json:"eip155_block" yaml:"eip155_block"` // EIP155 HF block
|
||||
EIP158Block sdk.Int `json:"eip158_block" yaml:"eip158_block"` // EIP158 HF block
|
||||
|
||||
ByzantiumBlock sdk.Int `json:"byzantium_block" yaml:"byzantium_block"` // Byzantium switch block (< 0 no fork, 0 = already on byzantium)
|
||||
ConstantinopleBlock sdk.Int `json:"constantinople_block" yaml:"constantinople_block"` // Constantinople switch block (< 0 no fork, 0 = already activated)
|
||||
PetersburgBlock sdk.Int `json:"petersburg_block" yaml:"petersburg_block"` // Petersburg switch block (< 0 same as Constantinople)
|
||||
IstanbulBlock sdk.Int `json:"istanbul_block" yaml:"istanbul_block"` // Istanbul switch block (< 0 no fork, 0 = already on istanbul)
|
||||
MuirGlacierBlock sdk.Int `json:"muir_glacier_block" yaml:"muir_glacier_block"` // Eip-2384 (bomb delay) switch block (< 0 no fork, 0 = already activated)
|
||||
|
||||
YoloV2Block sdk.Int `json:"yoloV2_block" yaml:"yoloV2_block"` // YOLO v1: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet)
|
||||
EWASMBlock sdk.Int `json:"ewasm_block" yaml:"ewasm_block"` // EWASM switch block (< 0 no fork, 0 = already activated)
|
||||
}
|
||||
|
||||
// EthereumConfig returns an Ethereum ChainConfig for EVM state transitions.
|
||||
// All the negative or nil values are converted to nil
|
||||
func (cc ChainConfig) EthereumConfig(chainID *big.Int) *params.ChainConfig {
|
||||
@@ -66,23 +33,7 @@ func (cc ChainConfig) EthereumConfig(chainID *big.Int) *params.ChainConfig {
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface
|
||||
func (cc ChainConfig) String() string {
|
||||
out, _ := yaml.Marshal(cc)
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// DefaultChainConfig returns default evm parameters. Th
|
||||
// DefaultChainConfig returns default evm parameters.
|
||||
func DefaultChainConfig() ChainConfig {
|
||||
return ChainConfig{
|
||||
HomesteadBlock: sdk.ZeroInt(),
|
||||
@@ -174,3 +125,13 @@ 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,20 +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: "0"
|
||||
muir_glacier_block: "0"
|
||||
yoloV2_block: "-1"
|
||||
ewasm_block: "-1"
|
||||
`
|
||||
require.Equal(t, configStr, DefaultChainConfig().String())
|
||||
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())
|
||||
}
|
||||
|
||||
+22
-14
@@ -2,22 +2,30 @@ package types
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
// ModuleCdc defines the evm module's codec
|
||||
var ModuleCdc = codec.New()
|
||||
// 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{},
|
||||
)
|
||||
|
||||
// RegisterCodec registers all the necessary types and interfaces for the
|
||||
// evm module
|
||||
func RegisterCodec(cdc *codec.Codec) {
|
||||
cdc.RegisterConcrete(MsgEthereumTx{}, "ethermint/MsgEthereumTx", nil)
|
||||
cdc.RegisterConcrete(MsgEthermint{}, "ethermint/MsgEthermint", nil)
|
||||
cdc.RegisterConcrete(TxData{}, "ethermint/TxData", nil)
|
||||
cdc.RegisterConcrete(ChainConfig{}, "ethermint/ChainConfig", nil)
|
||||
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterCodec(ModuleCdc)
|
||||
codec.RegisterCrypto(ModuleCdc)
|
||||
ModuleCdc.Seal()
|
||||
}
|
||||
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())
|
||||
)
|
||||
|
||||
+11
-2
@@ -16,9 +16,18 @@ var (
|
||||
// ErrInvalidChainConfig returns an error resulting from an invalid ChainConfig.
|
||||
ErrInvalidChainConfig = sdkerrors.Register(ModuleName, 4, "invalid chain configuration")
|
||||
|
||||
// ErrZeroAddress returns an error resulting from an zero (empty) ethereum Address.
|
||||
ErrZeroAddress = sdkerrors.Register(ModuleName, 5, "invalid zero address")
|
||||
|
||||
// ErrEmptyHash returns an error resulting from an empty ethereum Hash.
|
||||
ErrEmptyHash = sdkerrors.Register(ModuleName, 6, "empty hash")
|
||||
|
||||
// ErrBloomNotFound returns an error if the block bloom cannot be found on the store.
|
||||
ErrBloomNotFound = sdkerrors.Register(ModuleName, 7, "block bloom not found")
|
||||
|
||||
// ErrCreateDisabled returns an error if the EnableCreate parameter is false.
|
||||
ErrCreateDisabled = sdkerrors.Register(ModuleName, 5, "EVM Create operation is disabled")
|
||||
ErrCreateDisabled = sdkerrors.Register(ModuleName, 8, "EVM Create operation is disabled")
|
||||
|
||||
// ErrCallDisabled returns an error if the EnableCall parameter is false.
|
||||
ErrCallDisabled = sdkerrors.Register(ModuleName, 6, "EVM Call operation is disabled")
|
||||
ErrCallDisabled = sdkerrors.Register(ModuleName, 9, "EVM Call operation is disabled")
|
||||
)
|
||||
|
||||
@@ -2,7 +2,6 @@ package types
|
||||
|
||||
// Evm module events
|
||||
const (
|
||||
EventTypeEthermint = TypeMsgEthermint
|
||||
EventTypeEthereumTx = TypeMsgEthereumTx
|
||||
|
||||
AttributeKeyContractAddress = "contract"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,15 +2,21 @@ package types
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
// AccountKeeper defines the expected account keeper interface
|
||||
type AccountKeeper interface {
|
||||
NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authexported.Account
|
||||
GetAllAccounts(ctx sdk.Context) (accounts []authexported.Account)
|
||||
IterateAccounts(ctx sdk.Context, cb func(account authexported.Account) bool)
|
||||
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authexported.Account
|
||||
SetAccount(ctx sdk.Context, account authexported.Account)
|
||||
RemoveAccount(ctx sdk.Context, account authexported.Account)
|
||||
NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
|
||||
GetAllAccounts(ctx sdk.Context) (accounts []authtypes.AccountI)
|
||||
IterateAccounts(ctx sdk.Context, cb func(account authtypes.AccountI) bool)
|
||||
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
|
||||
SetAccount(ctx sdk.Context, account authtypes.AccountI)
|
||||
RemoveAccount(ctx sdk.Context, account authtypes.AccountI)
|
||||
}
|
||||
|
||||
// BankKeeper defines the expected interface needed to retrieve account balances.
|
||||
type BankKeeper interface {
|
||||
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
|
||||
SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance sdk.Coin) error
|
||||
}
|
||||
|
||||
+2
-23
@@ -5,30 +5,9 @@ import (
|
||||
"fmt"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
type (
|
||||
// GenesisState defines the evm module genesis state
|
||||
GenesisState struct {
|
||||
Accounts []GenesisAccount `json:"accounts"`
|
||||
TxsLogs []TransactionLogs `json:"txs_logs"`
|
||||
ChainConfig ChainConfig `json:"chain_config"`
|
||||
Params Params `json:"params"`
|
||||
}
|
||||
|
||||
// GenesisAccount defines an account to be initialized in the genesis state.
|
||||
// Its main difference between with Geth's GenesisAccount is that it uses a custom
|
||||
// storage type and that it doesn't contain the private key field.
|
||||
// NOTE: balance is omitted as it is imported from the auth account balance.
|
||||
GenesisAccount struct {
|
||||
Address string `json:"address"`
|
||||
Code string `json:"code,omitempty"`
|
||||
Storage Storage `json:"storage,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
// Validate performs a basic validation of a GenesisAccount fields.
|
||||
func (ga GenesisAccount) Validate() error {
|
||||
if ethermint.IsZeroAddress(ga.Address) {
|
||||
@@ -43,8 +22,8 @@ func (ga GenesisAccount) Validate() error {
|
||||
|
||||
// DefaultGenesisState sets default evm genesis state with empty accounts and default params and
|
||||
// chain config values.
|
||||
func DefaultGenesisState() GenesisState {
|
||||
return GenesisState{
|
||||
func DefaultGenesisState() *GenesisState {
|
||||
return &GenesisState{
|
||||
Accounts: []GenesisAccount{},
|
||||
TxsLogs: []TransactionLogs{},
|
||||
ChainConfig: DefaultChainConfig(),
|
||||
|
||||
@@ -0,0 +1,811 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: ethermint/evm/v1alpha1/genesis.proto
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/gogo/protobuf/gogoproto"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// GenesisState defines the evm module's genesis state.
|
||||
type GenesisState struct {
|
||||
// accounts is an array containing the ethereum genesis accounts.
|
||||
Accounts []GenesisAccount `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts"`
|
||||
// chain_config defines the Ethereum chain configuration.
|
||||
ChainConfig ChainConfig `protobuf:"bytes,2,opt,name=chain_config,json=chainConfig,proto3" json:"chain_config" yaml:"chain_config"`
|
||||
// params defines all the paramaters of the module.
|
||||
Params Params `protobuf:"bytes,3,opt,name=params,proto3" json:"params"`
|
||||
TxsLogs []TransactionLogs `protobuf:"bytes,4,rep,name=txs_logs,json=txsLogs,proto3" json:"txs_logs" yaml:"txs_logs"`
|
||||
}
|
||||
|
||||
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}
|
||||
}
|
||||
func (m *GenesisState) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *GenesisState) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GenesisState.Merge(m, src)
|
||||
}
|
||||
func (m *GenesisState) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *GenesisState) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GenesisState.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GenesisState proto.InternalMessageInfo
|
||||
|
||||
func (m *GenesisState) GetAccounts() []GenesisAccount {
|
||||
if m != nil {
|
||||
return m.Accounts
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GenesisState) GetChainConfig() ChainConfig {
|
||||
if m != nil {
|
||||
return m.ChainConfig
|
||||
}
|
||||
return ChainConfig{}
|
||||
}
|
||||
|
||||
func (m *GenesisState) GetParams() Params {
|
||||
if m != nil {
|
||||
return m.Params
|
||||
}
|
||||
return Params{}
|
||||
}
|
||||
|
||||
func (m *GenesisState) GetTxsLogs() []TransactionLogs {
|
||||
if m != nil {
|
||||
return m.TxsLogs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenesisAccount defines an account to be initialized in the genesis state.
|
||||
// Its main difference between with Geth's GenesisAccount is that it uses a
|
||||
// custom storage type and that it doesn't contain the private key field.
|
||||
type GenesisAccount struct {
|
||||
// address defines an ethereum hex formated address of an account
|
||||
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||
// code defines the hex bytes of the account code.
|
||||
Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"`
|
||||
// storage defines the set of state key values for the account.
|
||||
Storage Storage `protobuf:"bytes,3,rep,name=storage,proto3,castrepeated=Storage" json:"storage"`
|
||||
}
|
||||
|
||||
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}
|
||||
}
|
||||
func (m *GenesisAccount) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *GenesisAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_GenesisAccount.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *GenesisAccount) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GenesisAccount.Merge(m, src)
|
||||
}
|
||||
func (m *GenesisAccount) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *GenesisAccount) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GenesisAccount.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GenesisAccount proto.InternalMessageInfo
|
||||
|
||||
func (m *GenesisAccount) GetAddress() string {
|
||||
if m != nil {
|
||||
return m.Address
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GenesisAccount) GetCode() string {
|
||||
if m != nil {
|
||||
return m.Code
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GenesisAccount) GetStorage() Storage {
|
||||
if m != nil {
|
||||
return m.Storage
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*GenesisState)(nil), "ethermint.evm.v1alpha1.GenesisState")
|
||||
proto.RegisterType((*GenesisAccount)(nil), "ethermint.evm.v1alpha1.GenesisAccount")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("ethermint/evm/v1alpha1/genesis.proto", fileDescriptor_8205a12b97b89a87)
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.TxsLogs) > 0 {
|
||||
for iNdEx := len(m.TxsLogs) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.TxsLogs[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintGenesis(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
}
|
||||
}
|
||||
{
|
||||
size, err := m.Params.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintGenesis(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
{
|
||||
size, err := m.ChainConfig.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintGenesis(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
if len(m.Accounts) > 0 {
|
||||
for iNdEx := len(m.Accounts) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.Accounts[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintGenesis(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *GenesisAccount) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *GenesisAccount) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *GenesisAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Storage) > 0 {
|
||||
for iNdEx := len(m.Storage) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
size, err := m.Storage[iNdEx].MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintGenesis(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
}
|
||||
if len(m.Code) > 0 {
|
||||
i -= len(m.Code)
|
||||
copy(dAtA[i:], m.Code)
|
||||
i = encodeVarintGenesis(dAtA, i, uint64(len(m.Code)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.Address) > 0 {
|
||||
i -= len(m.Address)
|
||||
copy(dAtA[i:], m.Address)
|
||||
i = encodeVarintGenesis(dAtA, i, uint64(len(m.Address)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovGenesis(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *GenesisState) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Accounts) > 0 {
|
||||
for _, e := range m.Accounts {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovGenesis(uint64(l))
|
||||
}
|
||||
}
|
||||
l = m.ChainConfig.Size()
|
||||
n += 1 + l + sovGenesis(uint64(l))
|
||||
l = m.Params.Size()
|
||||
n += 1 + l + sovGenesis(uint64(l))
|
||||
if len(m.TxsLogs) > 0 {
|
||||
for _, e := range m.TxsLogs {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovGenesis(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *GenesisAccount) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Address)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovGenesis(uint64(l))
|
||||
}
|
||||
l = len(m.Code)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovGenesis(uint64(l))
|
||||
}
|
||||
if len(m.Storage) > 0 {
|
||||
for _, e := range m.Storage {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovGenesis(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGenesis(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozGenesis(x uint64) (n int) {
|
||||
return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *GenesisState) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Accounts", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Accounts = append(m.Accounts, GenesisAccount{})
|
||||
if err := m.Accounts[len(m.Accounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ChainConfig", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.ChainConfig.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field TxsLogs", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.TxsLogs = append(m.TxsLogs, TransactionLogs{})
|
||||
if err := m.TxsLogs[len(m.TxsLogs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenesis(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *GenesisAccount) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: GenesisAccount: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: GenesisAccount: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Address = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Code = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Storage", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Storage = append(m.Storage, State{})
|
||||
if err := m.Storage[len(m.Storage)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenesis(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if (iNdEx + skippy) < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGenesis(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGenesis
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupGenesis
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthGenesis
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
+31
-31
@@ -6,7 +6,6 @@ import (
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
)
|
||||
@@ -14,7 +13,7 @@ import (
|
||||
type GenesisTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
address ethcmn.Address
|
||||
address string
|
||||
hash ethcmn.Hash
|
||||
code string
|
||||
}
|
||||
@@ -23,7 +22,7 @@ func (suite *GenesisTestSuite) SetupTest() {
|
||||
priv, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.address = ethcmn.BytesToAddress(priv.PubKey().Address().Bytes())
|
||||
suite.address = ethcmn.BytesToAddress(priv.PubKey().Address().Bytes()).String()
|
||||
suite.hash = ethcmn.BytesToHash([]byte("hash"))
|
||||
suite.code = ethcmn.Bytes2Hex([]byte{1, 2, 3})
|
||||
}
|
||||
@@ -33,6 +32,7 @@ func TestGenesisTestSuite(t *testing.T) {
|
||||
}
|
||||
|
||||
func (suite *GenesisTestSuite) TestValidateGenesisAccount() {
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
genesisAccount GenesisAccount
|
||||
@@ -41,7 +41,7 @@ func (suite *GenesisTestSuite) TestValidateGenesisAccount() {
|
||||
{
|
||||
"valid genesis account",
|
||||
GenesisAccount{
|
||||
Address: suite.address.String(),
|
||||
Address: suite.address,
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
NewState(suite.hash, suite.hash),
|
||||
@@ -59,7 +59,7 @@ func (suite *GenesisTestSuite) TestValidateGenesisAccount() {
|
||||
{
|
||||
"empty code bytes",
|
||||
GenesisAccount{
|
||||
Address: suite.address.String(),
|
||||
Address: suite.address,
|
||||
Code: "",
|
||||
},
|
||||
false,
|
||||
@@ -80,7 +80,7 @@ func (suite *GenesisTestSuite) TestValidateGenesisAccount() {
|
||||
func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
genState GenesisState
|
||||
genState *GenesisState
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
@@ -90,10 +90,10 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
},
|
||||
{
|
||||
name: "valid genesis",
|
||||
genState: GenesisState{
|
||||
genState: &GenesisState{
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: suite.address.String(),
|
||||
Address: suite.address,
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
{Key: suite.hash.String()},
|
||||
@@ -103,15 +103,15 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
TxsLogs: []TransactionLogs{
|
||||
{
|
||||
Hash: suite.hash.String(),
|
||||
Logs: []*ethtypes.Log{
|
||||
Logs: []*Log{
|
||||
{
|
||||
Address: suite.address,
|
||||
Topics: []ethcmn.Hash{suite.hash},
|
||||
Topics: []string{suite.hash.String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: suite.hash,
|
||||
TxHash: suite.hash.String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: suite.hash,
|
||||
BlockHash: suite.hash.String(),
|
||||
Index: 1,
|
||||
Removed: false,
|
||||
},
|
||||
@@ -125,12 +125,12 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
},
|
||||
{
|
||||
name: "empty genesis",
|
||||
genState: GenesisState{},
|
||||
genState: &GenesisState{},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid genesis",
|
||||
genState: GenesisState{
|
||||
genState: &GenesisState{
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: ethcmn.Address{}.String(),
|
||||
@@ -141,17 +141,17 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
},
|
||||
{
|
||||
name: "duplicated genesis account",
|
||||
genState: GenesisState{
|
||||
genState: &GenesisState{
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: suite.address.String(),
|
||||
Address: suite.address,
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
NewState(suite.hash, suite.hash),
|
||||
},
|
||||
},
|
||||
{
|
||||
Address: suite.address.String(),
|
||||
Address: suite.address,
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
NewState(suite.hash, suite.hash),
|
||||
@@ -163,10 +163,10 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
},
|
||||
{
|
||||
name: "duplicated tx log",
|
||||
genState: GenesisState{
|
||||
genState: &GenesisState{
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: suite.address.String(),
|
||||
Address: suite.address,
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
{Key: suite.hash.String()},
|
||||
@@ -176,15 +176,15 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
TxsLogs: []TransactionLogs{
|
||||
{
|
||||
Hash: suite.hash.String(),
|
||||
Logs: []*ethtypes.Log{
|
||||
Logs: []*Log{
|
||||
{
|
||||
Address: suite.address,
|
||||
Topics: []ethcmn.Hash{suite.hash},
|
||||
Topics: []string{suite.hash.String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: suite.hash,
|
||||
TxHash: suite.hash.String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: suite.hash,
|
||||
BlockHash: suite.hash.String(),
|
||||
Index: 1,
|
||||
Removed: false,
|
||||
},
|
||||
@@ -192,15 +192,15 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
},
|
||||
{
|
||||
Hash: suite.hash.String(),
|
||||
Logs: []*ethtypes.Log{
|
||||
Logs: []*Log{
|
||||
{
|
||||
Address: suite.address,
|
||||
Topics: []ethcmn.Hash{suite.hash},
|
||||
Topics: []string{suite.hash.String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: suite.hash,
|
||||
TxHash: suite.hash.String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: suite.hash,
|
||||
BlockHash: suite.hash.String(),
|
||||
Index: 1,
|
||||
Removed: false,
|
||||
},
|
||||
@@ -212,10 +212,10 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
},
|
||||
{
|
||||
name: "invalid tx log",
|
||||
genState: GenesisState{
|
||||
genState: &GenesisState{
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: suite.address.String(),
|
||||
Address: suite.address,
|
||||
Code: suite.code,
|
||||
Storage: Storage{
|
||||
{Key: suite.hash.String()},
|
||||
@@ -228,7 +228,7 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
},
|
||||
{
|
||||
name: "invalid params",
|
||||
genState: GenesisState{
|
||||
genState: &GenesisState{
|
||||
ChainConfig: DefaultChainConfig(),
|
||||
Params: Params{},
|
||||
},
|
||||
@@ -236,7 +236,7 @@ func (suite *GenesisTestSuite) TestValidateGenesis() {
|
||||
},
|
||||
{
|
||||
name: "invalid chain config",
|
||||
genState: GenesisState{
|
||||
genState: &GenesisState{
|
||||
ChainConfig: ChainConfig{},
|
||||
Params: DefaultParams(),
|
||||
},
|
||||
|
||||
@@ -240,8 +240,7 @@ func (ch suicideChange) revert(s *CommitStateDB) {
|
||||
so := s.getStateObject(*ch.account)
|
||||
if so != nil {
|
||||
so.suicided = ch.prev
|
||||
evmDenom := s.GetParams().EvmDenom
|
||||
so.setBalance(evmDenom, ch.prevBalance)
|
||||
so.setBalance(ch.prevBalance)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,8 +256,7 @@ func (ch touchChange) dirtied() *ethcmn.Address {
|
||||
}
|
||||
|
||||
func (ch balanceChange) revert(s *CommitStateDB) {
|
||||
evmDenom := s.GetParams().EvmDenom
|
||||
s.getStateObject(*ch.account).setBalance(evmDenom, ch.prev)
|
||||
s.getStateObject(*ch.account).setBalance(ch.prev)
|
||||
}
|
||||
|
||||
func (ch balanceChange) dirtied() *ethcmn.Address {
|
||||
|
||||
+44
-34
@@ -7,25 +7,42 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
tmdb "github.com/tendermint/tm-db"
|
||||
|
||||
sdkcodec "github.com/cosmos/cosmos-sdk/codec"
|
||||
"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"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
paramkeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
ethermintcodec "github.com/cosmos/ethermint/codec"
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
)
|
||||
|
||||
func newTestCodec() (codec.BinaryMarshaler, *codec.LegacyAmino) {
|
||||
interfaceRegistry := codectypes.NewInterfaceRegistry()
|
||||
cdc := codec.NewProtoCodec(interfaceRegistry)
|
||||
amino := codec.NewLegacyAmino()
|
||||
|
||||
sdk.RegisterLegacyAminoCodec(amino)
|
||||
|
||||
ethermintcodec.RegisterInterfaces(interfaceRegistry)
|
||||
|
||||
return cdc, amino
|
||||
}
|
||||
|
||||
type JournalTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
@@ -35,19 +52,6 @@ type JournalTestSuite struct {
|
||||
stateDB *CommitStateDB
|
||||
}
|
||||
|
||||
func newTestCodec() *sdkcodec.Codec {
|
||||
cdc := sdkcodec.New()
|
||||
|
||||
RegisterCodec(cdc)
|
||||
sdk.RegisterCodec(cdc)
|
||||
ethsecp256k1.RegisterCodec(cdc)
|
||||
sdkcodec.RegisterCrypto(cdc)
|
||||
auth.RegisterCodec(cdc)
|
||||
ethermint.RegisterCodec(cdc)
|
||||
|
||||
return cdc
|
||||
}
|
||||
|
||||
func (suite *JournalTestSuite) SetupTest() {
|
||||
suite.setup()
|
||||
|
||||
@@ -57,14 +61,14 @@ func (suite *JournalTestSuite) SetupTest() {
|
||||
suite.address = ethcmn.BytesToAddress(privkey.PubKey().Address().Bytes())
|
||||
suite.journal = newJournal()
|
||||
|
||||
balance := sdk.NewCoins(ethermint.NewPhotonCoin(sdk.NewInt(100)))
|
||||
balance := ethermint.NewPhotonCoin(sdk.NewInt(100))
|
||||
acc := ðermint.EthAccount{
|
||||
BaseAccount: auth.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), balance, nil, 0, 0),
|
||||
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0),
|
||||
CodeHash: ethcrypto.Keccak256(nil),
|
||||
}
|
||||
|
||||
suite.stateDB.accountKeeper.SetAccount(suite.ctx, acc)
|
||||
// suite.stateDB.bankKeeper.SetBalance(suite.ctx, sdk.AccAddress(suite.address.Bytes()), balance)
|
||||
suite.stateDB.bankKeeper.SetBalance(suite.ctx, sdk.AccAddress(suite.address.Bytes()), balance)
|
||||
suite.stateDB.SetLogs(ethcmn.BytesToHash([]byte("txhash")), []*ethtypes.Log{
|
||||
{
|
||||
Address: suite.address,
|
||||
@@ -96,36 +100,41 @@ func (suite *JournalTestSuite) SetupTest() {
|
||||
// the latter would result in a cycle dependency. We also want to avoid declaring the journal methods public
|
||||
// to maintain consistency with the Geth implementation.
|
||||
func (suite *JournalTestSuite) setup() {
|
||||
authKey := sdk.NewKVStoreKey(auth.StoreKey)
|
||||
paramsKey := sdk.NewKVStoreKey(params.StoreKey)
|
||||
paramsTKey := sdk.NewTransientStoreKey(params.TStoreKey)
|
||||
// bankKey := sdk.NewKVStoreKey(bank.StoreKey)
|
||||
authKey := sdk.NewKVStoreKey(authtypes.StoreKey)
|
||||
paramsKey := sdk.NewKVStoreKey(paramtypes.StoreKey)
|
||||
paramsTKey := sdk.NewTransientStoreKey(paramtypes.TStoreKey)
|
||||
bankKey := sdk.NewKVStoreKey(banktypes.StoreKey)
|
||||
storeKey := sdk.NewKVStoreKey(StoreKey)
|
||||
|
||||
db := tmdb.NewDB("state", tmdb.GoLevelDBBackend, "temp")
|
||||
db, err := tmdb.NewDB("state", tmdb.GoLevelDBBackend, "temp")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
defer func() {
|
||||
os.RemoveAll("temp")
|
||||
}()
|
||||
|
||||
cms := store.NewCommitMultiStore(db)
|
||||
cms.MountStoreWithDB(authKey, sdk.StoreTypeIAVL, db)
|
||||
cms.MountStoreWithDB(bankKey, sdk.StoreTypeIAVL, db)
|
||||
cms.MountStoreWithDB(paramsKey, sdk.StoreTypeIAVL, db)
|
||||
cms.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db)
|
||||
cms.MountStoreWithDB(paramsTKey, sdk.StoreTypeTransient, db)
|
||||
|
||||
err := cms.LoadLatestVersion()
|
||||
err = cms.LoadLatestVersion()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cdc := newTestCodec()
|
||||
cdc, amino := newTestCodec()
|
||||
|
||||
paramsKeeper := params.NewKeeper(cdc, paramsKey, paramsTKey)
|
||||
paramsKeeper := paramkeeper.NewKeeper(cdc, amino, paramsKey, paramsTKey)
|
||||
|
||||
authSubspace := paramsKeeper.Subspace(auth.DefaultParamspace)
|
||||
evmSubspace := paramsKeeper.Subspace(types.DefaultParamspace).WithKeyTable(ParamKeyTable())
|
||||
authSubspace := paramsKeeper.Subspace(authtypes.ModuleName)
|
||||
bankSubspace := paramsKeeper.Subspace(banktypes.ModuleName)
|
||||
evmSubspace := paramsKeeper.Subspace(ModuleName).WithKeyTable(ParamKeyTable())
|
||||
|
||||
ak := auth.NewAccountKeeper(cdc, authKey, authSubspace, ethermint.ProtoAccount)
|
||||
suite.ctx = sdk.NewContext(cms, abci.Header{ChainID: "ethermint-8"}, false, tmlog.NewNopLogger())
|
||||
suite.stateDB = NewCommitStateDB(suite.ctx, storeKey, evmSubspace, ak).WithContext(suite.ctx)
|
||||
ak := authkeeper.NewAccountKeeper(cdc, authKey, authSubspace, ethermint.ProtoAccount, nil)
|
||||
bk := bankkeeper.NewBaseKeeper(cdc, bankKey, ak, bankSubspace, nil)
|
||||
suite.ctx = sdk.NewContext(cms, tmproto.Header{ChainID: "ethermint-8"}, false, tmlog.NewNopLogger())
|
||||
suite.stateDB = NewCommitStateDB(suite.ctx, storeKey, evmSubspace, ak, bk).WithContext(suite.ctx)
|
||||
suite.stateDB.SetParams(DefaultParams())
|
||||
}
|
||||
|
||||
@@ -149,6 +158,7 @@ func (suite *JournalTestSuite) TestJournal_append_revert() {
|
||||
resetObjectChange{
|
||||
prev: &stateObject{
|
||||
address: suite.address,
|
||||
balance: sdk.OneInt(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+13
-7
@@ -21,13 +21,12 @@ const (
|
||||
|
||||
// KVStore key prefixes
|
||||
var (
|
||||
KeyPrefixBlockHash = []byte{0x01}
|
||||
KeyPrefixBloom = []byte{0x02}
|
||||
KeyPrefixLogs = []byte{0x03}
|
||||
KeyPrefixCode = []byte{0x04}
|
||||
KeyPrefixStorage = []byte{0x05}
|
||||
KeyPrefixChainConfig = []byte{0x06}
|
||||
KeyPrefixHeightHash = []byte{0x07}
|
||||
KeyPrefixBloom = []byte{0x01}
|
||||
KeyPrefixLogs = []byte{0x02}
|
||||
KeyPrefixCode = []byte{0x03}
|
||||
KeyPrefixStorage = []byte{0x04}
|
||||
KeyPrefixChainConfig = []byte{0x05}
|
||||
KeyPrefixHeightHash = []byte{0x06}
|
||||
)
|
||||
|
||||
// HeightHashKey returns the key for the given chain epoch and height.
|
||||
@@ -48,3 +47,10 @@ func BloomKey(height int64) []byte {
|
||||
func AddressStoragePrefix(address ethcmn.Address) []byte {
|
||||
return append(KeyPrefixStorage, address.Bytes()...)
|
||||
}
|
||||
|
||||
// StateKey defines the full key under which an account state is stored.
|
||||
func StateKey(address ethcmn.Address, key []byte) []byte {
|
||||
return append(AddressStoragePrefix(address), key...)
|
||||
}
|
||||
|
||||
// TODO: fix Logs key and append block hash
|
||||
|
||||
+77
-32
@@ -9,32 +9,25 @@ import (
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// TransactionLogs define the logs generated from a transaction execution
|
||||
// with a given hash. It it used for import/export data as transactions are not persisted
|
||||
// on blockchain state after an upgrade.
|
||||
type TransactionLogs struct {
|
||||
Hash string `json:"hash"`
|
||||
Logs []*ethtypes.Log `json:"logs"`
|
||||
}
|
||||
|
||||
// NewTransactionLogs creates a new NewTransactionLogs instance.
|
||||
func NewTransactionLogs(hash ethcmn.Hash, logs []*ethtypes.Log) TransactionLogs { // nolint: interfacer
|
||||
func NewTransactionLogs(hash ethcmn.Hash, logs []*Log) TransactionLogs { // nolint: interfacer
|
||||
return TransactionLogs{
|
||||
Hash: hash.String(),
|
||||
Logs: logs,
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalLogs encodes an array of logs using amino
|
||||
func MarshalLogs(logs []*ethtypes.Log) ([]byte, error) {
|
||||
return ModuleCdc.MarshalBinaryLengthPrefixed(logs)
|
||||
}
|
||||
// NewTransactionLogsFromEth creates a new NewTransactionLogs instance using []*ethtypes.Log.
|
||||
func NewTransactionLogsFromEth(hash ethcmn.Hash, ethlogs []*ethtypes.Log) TransactionLogs { // nolint: interfacer
|
||||
logs := make([]*Log, len(ethlogs))
|
||||
for i := range ethlogs {
|
||||
logs[i] = NewLogFromEth(ethlogs[i])
|
||||
}
|
||||
|
||||
// UnmarshalLogs decodes an amino-encoded byte array into an array of logs
|
||||
func UnmarshalLogs(in []byte) ([]*ethtypes.Log, error) {
|
||||
logs := []*ethtypes.Log{}
|
||||
err := ModuleCdc.UnmarshalBinaryLengthPrefixed(in, &logs)
|
||||
return logs, err
|
||||
return TransactionLogs{
|
||||
Hash: hash.String(),
|
||||
Logs: logs,
|
||||
}
|
||||
}
|
||||
|
||||
// Validate performs a basic validation of a GenesisAccount fields.
|
||||
@@ -44,32 +37,84 @@ func (tx TransactionLogs) Validate() error {
|
||||
}
|
||||
|
||||
for i, log := range tx.Logs {
|
||||
if err := ValidateLog(log); err != nil {
|
||||
if log == nil {
|
||||
return fmt.Errorf("log %d cannot be nil", i)
|
||||
}
|
||||
if err := log.Validate(); err != nil {
|
||||
return fmt.Errorf("invalid log %d: %w", i, err)
|
||||
}
|
||||
if log.TxHash.String() != tx.Hash {
|
||||
return fmt.Errorf("log tx hash mismatch (%s ≠ %s)", log.TxHash.String(), tx.Hash)
|
||||
if log.TxHash != tx.Hash {
|
||||
return fmt.Errorf("log tx hash mismatch (%s ≠ %s)", log.TxHash, tx.Hash)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateLog performs a basic validation of an ethereum Log fields.
|
||||
func ValidateLog(log *ethtypes.Log) error {
|
||||
if log == nil {
|
||||
return errors.New("log cannot be nil")
|
||||
// EthLogs returns the Ethereum type Logs from the Transaction Logs.
|
||||
func (tx TransactionLogs) EthLogs() []*ethtypes.Log {
|
||||
return LogsToEthereum(tx.Logs)
|
||||
}
|
||||
|
||||
// Validate performs a basic validation of an ethereum Log fields.
|
||||
func (log *Log) Validate() error {
|
||||
if ethermint.IsZeroAddress(log.Address) {
|
||||
return fmt.Errorf("log address cannot be empty %s", log.Address)
|
||||
}
|
||||
if ethermint.IsZeroAddress(log.Address.String()) {
|
||||
return fmt.Errorf("log address cannot be empty %s", log.Address.String())
|
||||
}
|
||||
if ethermint.IsEmptyHash(log.BlockHash.String()) {
|
||||
return fmt.Errorf("block hash cannot be the empty %s", log.BlockHash.String())
|
||||
if IsEmptyHash(log.BlockHash) {
|
||||
return fmt.Errorf("block hash cannot be the empty %s", log.BlockHash)
|
||||
}
|
||||
if log.BlockNumber == 0 {
|
||||
return errors.New("block number cannot be zero")
|
||||
}
|
||||
if ethermint.IsEmptyHash(log.TxHash.String()) {
|
||||
return fmt.Errorf("tx hash cannot be the empty %s", log.TxHash.String())
|
||||
if ethermint.IsEmptyHash(log.TxHash) {
|
||||
return fmt.Errorf("tx hash cannot be the empty %s", log.TxHash)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToEthereum returns the Ethereum type Log from a Ethermint-proto compatible Log.
|
||||
func (log *Log) ToEthereum() *ethtypes.Log {
|
||||
topics := make([]ethcmn.Hash, len(log.Topics))
|
||||
for i := range log.Topics {
|
||||
topics[i] = ethcmn.HexToHash(log.Topics[i])
|
||||
}
|
||||
|
||||
return ðtypes.Log{
|
||||
Address: ethcmn.HexToAddress(log.Address),
|
||||
Topics: topics,
|
||||
Data: log.Data,
|
||||
BlockNumber: log.BlockNumber,
|
||||
TxHash: ethcmn.HexToHash(log.TxHash),
|
||||
TxIndex: uint(log.TxIndex),
|
||||
BlockHash: ethcmn.HexToHash(log.BlockHash),
|
||||
Removed: log.Removed,
|
||||
}
|
||||
}
|
||||
|
||||
// LogsToEthereum casts the Ethermint Logs to a slice of Ethereum Logs.
|
||||
func LogsToEthereum(logs []*Log) []*ethtypes.Log {
|
||||
ethLogs := make([]*ethtypes.Log, len(logs))
|
||||
for i := range logs {
|
||||
ethLogs[i] = logs[i].ToEthereum()
|
||||
}
|
||||
return ethLogs
|
||||
}
|
||||
|
||||
// NewLogFromEth creates a new Log instance from a Ethereum type Log.
|
||||
func NewLogFromEth(log *ethtypes.Log) *Log {
|
||||
topics := make([]string, len(log.Topics))
|
||||
for i := range log.Topics {
|
||||
topics[i] = log.Topics[i].String()
|
||||
}
|
||||
|
||||
return &Log{
|
||||
Address: log.Address.String(),
|
||||
Topics: topics,
|
||||
Data: log.Data,
|
||||
BlockNumber: log.BlockNumber,
|
||||
TxHash: log.TxHash.String(),
|
||||
TxIndex: uint64(log.TxIndex),
|
||||
BlockHash: log.BlockHash.String(),
|
||||
Removed: log.Removed,
|
||||
}
|
||||
}
|
||||
|
||||
+25
-26
@@ -2,7 +2,6 @@ package types
|
||||
|
||||
import (
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
func (suite *GenesisTestSuite) TestTransactionLogsValidate() {
|
||||
@@ -15,15 +14,15 @@ func (suite *GenesisTestSuite) TestTransactionLogsValidate() {
|
||||
"valid log",
|
||||
TransactionLogs{
|
||||
Hash: suite.hash.String(),
|
||||
Logs: []*ethtypes.Log{
|
||||
Logs: []*Log{
|
||||
{
|
||||
Address: suite.address,
|
||||
Topics: []ethcmn.Hash{ethcmn.BytesToHash([]byte("topic"))},
|
||||
Topics: []string{suite.hash.String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: suite.hash,
|
||||
TxHash: suite.hash.String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: suite.hash,
|
||||
BlockHash: suite.hash.String(),
|
||||
Index: 1,
|
||||
Removed: false,
|
||||
},
|
||||
@@ -42,7 +41,7 @@ func (suite *GenesisTestSuite) TestTransactionLogsValidate() {
|
||||
"invalid log",
|
||||
TransactionLogs{
|
||||
Hash: suite.hash.String(),
|
||||
Logs: []*ethtypes.Log{nil},
|
||||
Logs: []*Log{nil},
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -50,15 +49,15 @@ func (suite *GenesisTestSuite) TestTransactionLogsValidate() {
|
||||
"hash mismatch log",
|
||||
TransactionLogs{
|
||||
Hash: suite.hash.String(),
|
||||
Logs: []*ethtypes.Log{
|
||||
Logs: []*Log{
|
||||
{
|
||||
Address: suite.address,
|
||||
Topics: []ethcmn.Hash{ethcmn.BytesToHash([]byte("topic"))},
|
||||
Topics: []string{suite.hash.String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: ethcmn.BytesToHash([]byte("other_hash")),
|
||||
TxHash: ethcmn.BytesToHash([]byte("other_hash")).String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: suite.hash,
|
||||
BlockHash: suite.hash.String(),
|
||||
Index: 1,
|
||||
Removed: false,
|
||||
},
|
||||
@@ -82,58 +81,58 @@ func (suite *GenesisTestSuite) TestTransactionLogsValidate() {
|
||||
func (suite *GenesisTestSuite) TestValidateLog() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
log *ethtypes.Log
|
||||
log *Log
|
||||
expPass bool
|
||||
}{
|
||||
{
|
||||
"valid log",
|
||||
ðtypes.Log{
|
||||
&Log{
|
||||
Address: suite.address,
|
||||
Topics: []ethcmn.Hash{ethcmn.BytesToHash([]byte("topic"))},
|
||||
Topics: []string{suite.hash.String()},
|
||||
Data: []byte("data"),
|
||||
BlockNumber: 1,
|
||||
TxHash: suite.hash,
|
||||
TxHash: suite.hash.String(),
|
||||
TxIndex: 1,
|
||||
BlockHash: suite.hash,
|
||||
BlockHash: suite.hash.String(),
|
||||
Index: 1,
|
||||
Removed: false,
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nil log", nil, false,
|
||||
"empty log", &Log{}, false,
|
||||
},
|
||||
{
|
||||
"zero address",
|
||||
ðtypes.Log{
|
||||
Address: ethcmn.Address{},
|
||||
&Log{
|
||||
Address: ethcmn.Address{}.String(),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"empty block hash",
|
||||
ðtypes.Log{
|
||||
&Log{
|
||||
Address: suite.address,
|
||||
BlockHash: ethcmn.Hash{},
|
||||
BlockHash: ethcmn.Hash{}.String(),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"zero block number",
|
||||
ðtypes.Log{
|
||||
&Log{
|
||||
Address: suite.address,
|
||||
BlockHash: suite.hash,
|
||||
BlockHash: suite.hash.String(),
|
||||
BlockNumber: 0,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"empty tx hash",
|
||||
ðtypes.Log{
|
||||
&Log{
|
||||
Address: suite.address,
|
||||
BlockHash: suite.hash,
|
||||
BlockHash: suite.hash.String(),
|
||||
BlockNumber: 1,
|
||||
TxHash: ethcmn.Hash{},
|
||||
TxHash: ethcmn.Hash{}.String(),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -141,7 +140,7 @@ func (suite *GenesisTestSuite) TestValidateLog() {
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
err := ValidateLog(tc.log)
|
||||
err := tc.log.Validate()
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err, tc.name)
|
||||
} else {
|
||||
|
||||
+34
-138
@@ -6,10 +6,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/cosmos/ethermint/types"
|
||||
"gopkg.in/yaml.v2"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
@@ -21,121 +19,23 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
_ sdk.Msg = MsgEthermint{}
|
||||
_ sdk.Msg = MsgEthereumTx{}
|
||||
_ sdk.Tx = MsgEthereumTx{}
|
||||
_ sdk.Msg = &MsgEthereumTx{}
|
||||
_ sdk.Tx = &MsgEthereumTx{}
|
||||
)
|
||||
|
||||
var big8 = big.NewInt(8)
|
||||
|
||||
// message type and route constants
|
||||
const (
|
||||
// TypeMsgEthereumTx defines the type string of an Ethereum tranasction
|
||||
// TypeMsgEthereumTx defines the type string of an Ethereum transaction
|
||||
TypeMsgEthereumTx = "ethereum"
|
||||
// TypeMsgEthermint defines the type string of Ethermint message
|
||||
TypeMsgEthermint = "ethermint"
|
||||
)
|
||||
|
||||
// MsgEthermint implements a cosmos equivalent structure for Ethereum transactions
|
||||
type MsgEthermint struct {
|
||||
AccountNonce uint64 `json:"nonce"`
|
||||
Price sdk.Int `json:"gasPrice"`
|
||||
GasLimit uint64 `json:"gas"`
|
||||
Recipient *sdk.AccAddress `json:"to" rlp:"nil"` // nil means contract creation
|
||||
Amount sdk.Int `json:"value"`
|
||||
Payload []byte `json:"input"`
|
||||
|
||||
// From address (formerly derived from signature)
|
||||
From sdk.AccAddress `json:"from"`
|
||||
}
|
||||
|
||||
// NewMsgEthermint returns a reference to a new Ethermint transaction
|
||||
func NewMsgEthermint(
|
||||
nonce uint64, to *sdk.AccAddress, amount sdk.Int,
|
||||
gasLimit uint64, gasPrice sdk.Int, payload []byte, from sdk.AccAddress,
|
||||
) MsgEthermint {
|
||||
return MsgEthermint{
|
||||
AccountNonce: nonce,
|
||||
Price: gasPrice,
|
||||
GasLimit: gasLimit,
|
||||
Recipient: to,
|
||||
Amount: amount,
|
||||
Payload: payload,
|
||||
From: from,
|
||||
}
|
||||
}
|
||||
|
||||
func (msg MsgEthermint) String() string {
|
||||
return fmt.Sprintf("nonce=%d gasPrice=%d gasLimit=%d recipient=%s amount=%d data=0x%x from=%s",
|
||||
msg.AccountNonce, msg.Price, msg.GasLimit, msg.Recipient, msg.Amount, msg.Payload, msg.From)
|
||||
}
|
||||
|
||||
// Route should return the name of the module
|
||||
func (msg MsgEthermint) Route() string { return RouterKey }
|
||||
|
||||
// Type returns the action of the message
|
||||
func (msg MsgEthermint) Type() string { return TypeMsgEthermint }
|
||||
|
||||
// GetSignBytes encodes the message for signing
|
||||
func (msg MsgEthermint) GetSignBytes() []byte {
|
||||
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg))
|
||||
}
|
||||
|
||||
// ValidateBasic runs stateless checks on the message
|
||||
func (msg MsgEthermint) ValidateBasic() error {
|
||||
if msg.Price.IsZero() {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidValue, "gas price cannot be 0")
|
||||
}
|
||||
|
||||
if msg.Price.Sign() == -1 {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidValue, "gas price cannot be negative %s", msg.Price)
|
||||
}
|
||||
|
||||
// Amount can be 0
|
||||
if msg.Amount.Sign() == -1 {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidValue, "amount cannot be negative %s", msg.Amount)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSigners defines whose signature is required
|
||||
func (msg MsgEthermint) GetSigners() []sdk.AccAddress {
|
||||
return []sdk.AccAddress{msg.From}
|
||||
}
|
||||
|
||||
// To returns the recipient address of the transaction. It returns nil if the
|
||||
// transaction is a contract creation.
|
||||
func (msg MsgEthermint) To() *ethcmn.Address {
|
||||
if msg.Recipient == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
addr := ethcmn.BytesToAddress(msg.Recipient.Bytes())
|
||||
return &addr
|
||||
}
|
||||
|
||||
// MsgEthereumTx encapsulates an Ethereum transaction as an SDK message.
|
||||
type MsgEthereumTx struct {
|
||||
Data TxData
|
||||
|
||||
// caches
|
||||
size atomic.Value
|
||||
from atomic.Value
|
||||
}
|
||||
|
||||
// sigCache is used to cache the derived sender and contains the signer used
|
||||
// to derive it.
|
||||
type sigCache struct {
|
||||
signer ethtypes.Signer
|
||||
from ethcmn.Address
|
||||
}
|
||||
|
||||
// NewMsgEthereumTx returns a reference to a new Ethereum transaction message.
|
||||
func NewMsgEthereumTx(
|
||||
nonce uint64, to *ethcmn.Address, amount *big.Int,
|
||||
gasLimit uint64, gasPrice *big.Int, payload []byte,
|
||||
) MsgEthereumTx {
|
||||
) *MsgEthereumTx {
|
||||
return newMsgEthereumTx(nonce, to, amount, gasLimit, gasPrice, payload)
|
||||
}
|
||||
|
||||
@@ -143,14 +43,14 @@ func NewMsgEthereumTx(
|
||||
// message designated for contract creation.
|
||||
func NewMsgEthereumTxContract(
|
||||
nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, payload []byte,
|
||||
) MsgEthereumTx {
|
||||
) *MsgEthereumTx {
|
||||
return newMsgEthereumTx(nonce, nil, amount, gasLimit, gasPrice, payload)
|
||||
}
|
||||
|
||||
func newMsgEthereumTx(
|
||||
nonce uint64, to *ethcmn.Address, amount *big.Int, // nolint: interfacer
|
||||
gasLimit uint64, gasPrice *big.Int, payload []byte,
|
||||
) MsgEthereumTx {
|
||||
) *MsgEthereumTx {
|
||||
if len(payload) > 0 {
|
||||
payload = ethcmn.CopyBytes(payload)
|
||||
}
|
||||
@@ -160,7 +60,7 @@ func newMsgEthereumTx(
|
||||
recipient = &Recipient{Address: to.String()}
|
||||
}
|
||||
|
||||
txData := TxData{
|
||||
txData := &TxData{
|
||||
AccountNonce: nonce,
|
||||
Recipient: recipient,
|
||||
Payload: payload,
|
||||
@@ -179,12 +79,7 @@ func newMsgEthereumTx(
|
||||
txData.Price = sdk.NewIntFromBigInt(gasPrice)
|
||||
}
|
||||
|
||||
return MsgEthereumTx{Data: txData}
|
||||
}
|
||||
|
||||
func (msg MsgEthereumTx) String() string {
|
||||
out, _ := yaml.Marshal(msg.Data)
|
||||
return string(out)
|
||||
return &MsgEthereumTx{Data: txData}
|
||||
}
|
||||
|
||||
// Route returns the route value of an MsgEthereumTx.
|
||||
@@ -197,16 +92,16 @@ func (msg MsgEthereumTx) Type() string { return TypeMsgEthereumTx }
|
||||
// checks of a Transaction. If returns an error if validation fails.
|
||||
func (msg MsgEthereumTx) ValidateBasic() error {
|
||||
if msg.Data.Price.IsZero() {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidValue, "gas price cannot be 0")
|
||||
return sdkerrors.Wrapf(ethermint.ErrInvalidValue, "gas price cannot be 0")
|
||||
}
|
||||
|
||||
if msg.Data.Price.IsNegative() {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidValue, "gas price cannot be negative %s", msg.Data.Price)
|
||||
return sdkerrors.Wrapf(ethermint.ErrInvalidValue, "gas price cannot be negative %s", msg.Data.Price)
|
||||
}
|
||||
|
||||
// Amount can be 0
|
||||
if msg.Data.Amount.IsNegative() {
|
||||
return sdkerrors.Wrapf(types.ErrInvalidValue, "amount cannot be negative %s", msg.Data.Amount)
|
||||
return sdkerrors.Wrapf(ethermint.ErrInvalidValue, "amount cannot be negative %s", msg.Data.Amount)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -224,7 +119,7 @@ func (msg MsgEthereumTx) To() *ethcmn.Address {
|
||||
}
|
||||
|
||||
// GetMsgs returns a single MsgEthereumTx as an sdk.Msg.
|
||||
func (msg MsgEthereumTx) GetMsgs() []sdk.Msg {
|
||||
func (msg *MsgEthereumTx) GetMsgs() []sdk.Msg {
|
||||
return []sdk.Msg{msg}
|
||||
}
|
||||
|
||||
@@ -233,7 +128,7 @@ func (msg MsgEthereumTx) GetMsgs() []sdk.Msg {
|
||||
//
|
||||
// NOTE: This method panics if 'VerifySig' hasn't been called first.
|
||||
func (msg MsgEthereumTx) GetSigners() []sdk.AccAddress {
|
||||
sender := msg.From()
|
||||
sender := msg.GetFrom()
|
||||
if sender.Empty() {
|
||||
panic("must use 'VerifySig' with a chain ID to get the signer")
|
||||
}
|
||||
@@ -259,7 +154,9 @@ func (msg MsgEthereumTx) RLPSignBytes(chainID *big.Int) ethcmn.Hash {
|
||||
msg.To(),
|
||||
msg.Data.Amount.BigInt(),
|
||||
msg.Data.Payload,
|
||||
chainID, uint(0), uint(0),
|
||||
chainID,
|
||||
uint(0),
|
||||
uint(0),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -339,7 +236,7 @@ func (msg *MsgEthereumTx) DecodeRLP(s *rlp.Stream) error {
|
||||
recipient = &Recipient{Address: data.Recipient.String()}
|
||||
}
|
||||
|
||||
msg.Data = TxData{
|
||||
msg.Data = &TxData{
|
||||
AccountNonce: data.AccountNonce,
|
||||
Price: sdk.NewIntFromBigInt(data.Price),
|
||||
GasLimit: data.GasLimit,
|
||||
@@ -352,7 +249,7 @@ func (msg *MsgEthereumTx) DecodeRLP(s *rlp.Stream) error {
|
||||
Hash: hash,
|
||||
}
|
||||
|
||||
msg.size.Store(ethcmn.StorageSize(rlp.ListSize(size)))
|
||||
msg.Size_ = float64(ethcmn.StorageSize(rlp.ListSize(size)))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -398,12 +295,12 @@ func (msg *MsgEthereumTx) VerifySig(chainID *big.Int) (ethcmn.Address, error) {
|
||||
v, r, s := msg.RawSignatureValues()
|
||||
signer := ethtypes.NewEIP155Signer(chainID)
|
||||
|
||||
if sc := msg.from.Load(); sc != nil {
|
||||
sigCache := sc.(sigCache)
|
||||
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 sigCache.signer.Equal(signer) {
|
||||
return sigCache.from, nil
|
||||
fromSigner := ethtypes.NewEIP155Signer(new(big.Int).SetBytes(msg.From.Signer.chainId))
|
||||
if signer.Equal(fromSigner) {
|
||||
return ethcmn.HexToAddress(msg.From.Address), nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,7 +319,13 @@ func (msg *MsgEthereumTx) VerifySig(chainID *big.Int) (ethcmn.Address, error) {
|
||||
return ethcmn.Address{}, err
|
||||
}
|
||||
|
||||
msg.from.Store(sigCache{signer: signer, from: sender})
|
||||
msg.From = &SigCache{
|
||||
Signer: &EIP155Signer{
|
||||
chainId: chainID.Bytes(),
|
||||
chainIdMul: new(big.Int).Mul(chainID, big.NewInt(2)).Bytes(),
|
||||
},
|
||||
Address: sender.String(),
|
||||
}
|
||||
return sender, nil
|
||||
}
|
||||
|
||||
@@ -459,21 +362,14 @@ func (msg MsgEthereumTx) RawSignatureValues() (v, r, s *big.Int) {
|
||||
new(big.Int).SetBytes(msg.Data.S)
|
||||
}
|
||||
|
||||
// From loads the ethereum sender address from the sigcache and returns an
|
||||
// GetFrom loads the ethereum sender address from the sigcache and returns an
|
||||
// sdk.AccAddress from its bytes
|
||||
func (msg *MsgEthereumTx) From() sdk.AccAddress {
|
||||
sc := msg.from.Load()
|
||||
if sc == nil {
|
||||
func (msg *MsgEthereumTx) GetFrom() sdk.AccAddress {
|
||||
if msg.From == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
sigCache := sc.(sigCache)
|
||||
|
||||
if len(sigCache.from.Bytes()) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return sdk.AccAddress(sigCache.from.Bytes())
|
||||
return sdk.AccAddress(ethcmn.HexToAddress(msg.From.Address).Bytes())
|
||||
}
|
||||
|
||||
// deriveChainID derives the chain id from the given v parameter
|
||||
|
||||
+10
-105
@@ -8,83 +8,22 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||
)
|
||||
|
||||
func TestMsgEthermint(t *testing.T) {
|
||||
addr := newSdkAddress()
|
||||
fromAddr := newSdkAddress()
|
||||
|
||||
msg := NewMsgEthermint(0, &addr, sdk.NewInt(1), 100000, sdk.NewInt(2), []byte("test"), fromAddr)
|
||||
require.NotNil(t, msg)
|
||||
require.Equal(t, msg.Recipient, &addr)
|
||||
|
||||
require.Equal(t, msg.Route(), RouterKey)
|
||||
require.Equal(t, msg.Type(), TypeMsgEthermint)
|
||||
}
|
||||
|
||||
func TestMsgEthermintValidation(t *testing.T) {
|
||||
testCases := []struct {
|
||||
nonce uint64
|
||||
to *sdk.AccAddress
|
||||
amount sdk.Int
|
||||
gasLimit uint64
|
||||
gasPrice sdk.Int
|
||||
payload []byte
|
||||
expectPass bool
|
||||
from sdk.AccAddress
|
||||
}{
|
||||
{amount: sdk.NewInt(100), gasPrice: sdk.NewInt(100000), expectPass: true},
|
||||
{amount: sdk.NewInt(0), gasPrice: sdk.NewInt(100000), expectPass: true},
|
||||
{amount: sdk.NewInt(-1), gasPrice: sdk.NewInt(100000), expectPass: false},
|
||||
{amount: sdk.NewInt(100), gasPrice: sdk.NewInt(-1), expectPass: false},
|
||||
{amount: sdk.NewInt(100), gasPrice: sdk.NewInt(0), expectPass: false},
|
||||
// GenerateEthAddress generates an Ethereum address.
|
||||
func GenerateEthAddress() ethcmn.Address {
|
||||
priv, err := ethsecp256k1.GenerateKey()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for i, tc := range testCases {
|
||||
msg := NewMsgEthermint(tc.nonce, tc.to, tc.amount, tc.gasLimit, tc.gasPrice, tc.payload, tc.from)
|
||||
|
||||
if tc.expectPass {
|
||||
require.Nil(t, msg.ValidateBasic(), "test: %v", i)
|
||||
} else {
|
||||
require.NotNil(t, msg.ValidateBasic(), "test: %v", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMsgEthermintEncodingAndDecoding(t *testing.T) {
|
||||
addr := newSdkAddress()
|
||||
fromAddr := newSdkAddress()
|
||||
|
||||
msg := NewMsgEthermint(0, &addr, sdk.NewInt(1), 100000, sdk.NewInt(2), []byte("test"), fromAddr)
|
||||
|
||||
raw, err := ModuleCdc.MarshalBinaryBare(msg)
|
||||
require.NoError(t, err)
|
||||
|
||||
var msg2 MsgEthermint
|
||||
err = ModuleCdc.UnmarshalBinaryBare(raw, &msg2)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, msg.AccountNonce, msg2.AccountNonce)
|
||||
require.Equal(t, msg.Recipient, msg2.Recipient)
|
||||
require.Equal(t, msg.Amount, msg2.Amount)
|
||||
require.Equal(t, msg.GasLimit, msg2.GasLimit)
|
||||
require.Equal(t, msg.Price, msg2.Price)
|
||||
require.Equal(t, msg.Payload, msg2.Payload)
|
||||
require.Equal(t, msg.From, msg2.From)
|
||||
}
|
||||
|
||||
func newSdkAddress() sdk.AccAddress {
|
||||
tmpKey := secp256k1.GenPrivKey().PubKey()
|
||||
return sdk.AccAddress(tmpKey.Address().Bytes())
|
||||
return ethcmn.BytesToAddress(priv.PubKey().Address().Bytes())
|
||||
}
|
||||
|
||||
func TestMsgEthereumTx(t *testing.T) {
|
||||
@@ -123,10 +62,11 @@ 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.Nil(t, msg.ValidateBasic(), "valid test %d failed: %s", i, tc.msg)
|
||||
require.NoError(t, err, "valid test %d failed: %s", i, tc.msg)
|
||||
} else {
|
||||
require.NotNil(t, msg.ValidateBasic(), "invalid test %d passed: %s", i, tc.msg)
|
||||
require.Error(t, err, "invalid test %d passed: %s", i, tc.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,38 +128,3 @@ func TestMsgEthereumTxSig(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
require.Equal(t, ethcmn.Address{}, signer)
|
||||
}
|
||||
|
||||
func TestMarshalAndUnmarshalLogs(t *testing.T) {
|
||||
var cdc = codec.New()
|
||||
|
||||
logs := []*ethtypes.Log{
|
||||
{
|
||||
Address: ethcmn.BytesToAddress([]byte{0x11}),
|
||||
TxHash: ethcmn.HexToHash("0x01"),
|
||||
// May need to find workaround since Topics is required to unmarshal from JSON
|
||||
Topics: []ethcmn.Hash{},
|
||||
Removed: true,
|
||||
},
|
||||
{Address: ethcmn.BytesToAddress([]byte{0x01, 0x11}), Topics: []ethcmn.Hash{}},
|
||||
}
|
||||
|
||||
raw, err := codec.MarshalJSONIndent(cdc, logs)
|
||||
require.NoError(t, err)
|
||||
|
||||
var logs2 []*ethtypes.Log
|
||||
err = cdc.UnmarshalJSON(raw, &logs2)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, logs2, 2)
|
||||
require.Equal(t, logs[0].Address, logs2[0].Address)
|
||||
require.Equal(t, logs[0].TxHash, logs2[0].TxHash)
|
||||
require.True(t, logs[0].Removed)
|
||||
|
||||
emptyLogs := []*ethtypes.Log{}
|
||||
|
||||
raw, err = codec.MarshalJSONIndent(cdc, emptyLogs)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = cdc.UnmarshalJSON(raw, &logs2)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
+11
-27
@@ -3,20 +3,17 @@ package types
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultParamspace for params keeper
|
||||
DefaultParamspace = ModuleName
|
||||
)
|
||||
var _ paramtypes.ParamSet = &Params{}
|
||||
|
||||
// Parameter keys
|
||||
var (
|
||||
@@ -27,21 +24,8 @@ var (
|
||||
)
|
||||
|
||||
// ParamKeyTable returns the parameter key table.
|
||||
func ParamKeyTable() params.KeyTable {
|
||||
return params.NewKeyTable().RegisterParamSet(&Params{})
|
||||
}
|
||||
|
||||
// Params defines the EVM module parameters
|
||||
type Params struct {
|
||||
// EVMDenom defines the token denomination used for state transitions on the
|
||||
// EVM module.
|
||||
EvmDenom string `json:"evm_denom" yaml:"evm_denom"`
|
||||
// EnableCreate toggles state transitions that use the vm.Create function
|
||||
EnableCreate bool `json:"enable_create" yaml:"enable_create"`
|
||||
// EnableCall toggles state transitions that use the vm.Call function
|
||||
EnableCall bool `json:"enable_call" yaml:"enable_call"`
|
||||
// ExtraEIPs defines the additional EIPs for the vm.Config
|
||||
ExtraEIPs []int64 `json:"extra_eips" yaml:"extra_eips"`
|
||||
func ParamKeyTable() paramtypes.KeyTable {
|
||||
return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
|
||||
}
|
||||
|
||||
// NewParams creates a new Params instance
|
||||
@@ -71,12 +55,12 @@ func (p Params) String() string {
|
||||
}
|
||||
|
||||
// ParamSetPairs returns the parameter set pairs.
|
||||
func (p *Params) ParamSetPairs() params.ParamSetPairs {
|
||||
return params.ParamSetPairs{
|
||||
params.NewParamSetPair(ParamStoreKeyEVMDenom, &p.EvmDenom, validateEVMDenom),
|
||||
params.NewParamSetPair(ParamStoreKeyEnableCreate, &p.EnableCreate, validateBool),
|
||||
params.NewParamSetPair(ParamStoreKeyEnableCall, &p.EnableCall, validateBool),
|
||||
params.NewParamSetPair(ParamStoreKeyExtraEIPs, &p.ExtraEIPs, validateEIPs),
|
||||
func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
|
||||
return paramtypes.ParamSetPairs{
|
||||
paramtypes.NewParamSetPair(ParamStoreKeyEVMDenom, &p.EvmDenom, validateEVMDenom),
|
||||
paramtypes.NewParamSetPair(ParamStoreKeyEnableCreate, &p.EnableCreate, validateBool),
|
||||
paramtypes.NewParamSetPair(ParamStoreKeyEnableCall, &p.EnableCall, validateBool),
|
||||
paramtypes.NewParamSetPair(ParamStoreKeyExtraEIPs, &p.ExtraEIPs, validateEIPs),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// Supported endpoints
|
||||
const (
|
||||
QueryBalance = "balance"
|
||||
QueryBlockNumber = "blockNumber"
|
||||
QueryStorage = "storage"
|
||||
QueryCode = "code"
|
||||
QueryNonce = "nonce"
|
||||
QueryHashToHeight = "hashToHeight"
|
||||
QueryTransactionLogs = "transactionLogs"
|
||||
QueryBloom = "bloom"
|
||||
QueryLogs = "logs"
|
||||
QueryAccount = "account"
|
||||
)
|
||||
|
||||
// QueryResBalance is response type for balance query
|
||||
type QueryResBalance struct {
|
||||
Balance string `json:"balance"`
|
||||
}
|
||||
|
||||
func (q QueryResBalance) String() string {
|
||||
return q.Balance
|
||||
}
|
||||
|
||||
// QueryResBlockNumber is response type for block number query
|
||||
type QueryResBlockNumber struct {
|
||||
Number int64 `json:"blockNumber"`
|
||||
}
|
||||
|
||||
func (q QueryResBlockNumber) String() string {
|
||||
return fmt.Sprint(q.Number)
|
||||
}
|
||||
|
||||
// QueryResStorage is response type for storage query
|
||||
type QueryResStorage struct {
|
||||
Value []byte `json:"value"`
|
||||
}
|
||||
|
||||
func (q QueryResStorage) String() string {
|
||||
return string(q.Value)
|
||||
}
|
||||
|
||||
// QueryResCode is response type for code query
|
||||
type QueryResCode struct {
|
||||
Code []byte
|
||||
}
|
||||
|
||||
func (q QueryResCode) String() string {
|
||||
return string(q.Code)
|
||||
}
|
||||
|
||||
// QueryResNonce is response type for Nonce query
|
||||
type QueryResNonce struct {
|
||||
Nonce uint64 `json:"nonce"`
|
||||
}
|
||||
|
||||
func (q QueryResNonce) String() string {
|
||||
return fmt.Sprint(q.Nonce)
|
||||
}
|
||||
|
||||
// QueryETHLogs is response type for tx logs query
|
||||
type QueryETHLogs struct {
|
||||
Logs []*ethtypes.Log `json:"logs"`
|
||||
}
|
||||
|
||||
func (q QueryETHLogs) String() string {
|
||||
var logsStr string
|
||||
logsLen := len(q.Logs)
|
||||
for i := 0; i < logsLen; i++ {
|
||||
logsStr = fmt.Sprintf("%s%v\n", logsStr, *q.Logs[i])
|
||||
}
|
||||
|
||||
return logsStr
|
||||
}
|
||||
|
||||
// QueryBloomFilter is response type for tx logs query
|
||||
type QueryBloomFilter struct {
|
||||
Bloom ethtypes.Bloom `json:"bloom"`
|
||||
}
|
||||
|
||||
func (q QueryBloomFilter) String() string {
|
||||
return string(q.Bloom.Bytes())
|
||||
}
|
||||
|
||||
// QueryAccount is response type for querying Ethereum state objects
|
||||
type QueryResAccount struct {
|
||||
Balance string `json:"balance"`
|
||||
CodeHash []byte `json:"codeHash"`
|
||||
Nonce uint64 `json:"nonce"`
|
||||
}
|
||||
|
||||
type QueryResExportAccount = GenesisAccount
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,820 @@
|
||||
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||
// source: ethermint/evm/v1alpha1/query.proto
|
||||
|
||||
/*
|
||||
Package types is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/golang/protobuf/descriptor"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/utilities"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Suppress "imported and not used" errors
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
var _ = descriptor.ForMessage
|
||||
|
||||
func request_Query_Account_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryAccountRequest
|
||||
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.Account(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_Account_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryAccountRequest
|
||||
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.Account(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
|
||||
|
||||
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.Balance(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_Balance_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryBalanceRequest
|
||||
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.Balance(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Query_Storage_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryStorageRequest
|
||||
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)
|
||||
}
|
||||
|
||||
val, ok = pathParams["key"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "key")
|
||||
}
|
||||
|
||||
protoReq.Key, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "key", err)
|
||||
}
|
||||
|
||||
msg, err := client.Storage(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_Storage_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryStorageRequest
|
||||
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)
|
||||
}
|
||||
|
||||
val, ok = pathParams["key"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "key")
|
||||
}
|
||||
|
||||
protoReq.Key, err = runtime.String(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "key", err)
|
||||
}
|
||||
|
||||
msg, err := server.Storage(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Query_Code_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryCodeRequest
|
||||
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.Code(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_Code_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryCodeRequest
|
||||
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.Code(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Query_TxLogs_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryTxLogsRequest
|
||||
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.TxLogs(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_TxLogs_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryTxLogsRequest
|
||||
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.TxLogs(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
|
||||
|
||||
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.BlockLogs(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_BlockLogs_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryBlockLogsRequest
|
||||
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.BlockLogs(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
msg, err := client.BlockBloom(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_BlockBloom_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryBlockBloomRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.BlockBloom(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryParamsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq QueryParamsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.Params(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.
|
||||
// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
|
||||
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
|
||||
|
||||
mux.Handle("GET", pattern_Query_Account_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_Account_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_Account_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()
|
||||
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_Balance_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_Balance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_Storage_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_Storage_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_Storage_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_Code_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_Code_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_Code_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_TxLogs_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_TxLogs_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_TxLogs_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()
|
||||
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_BlockLogs_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_BlockLogs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_BlockBloom_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_BlockBloom_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_BlockBloom_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_Params_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_Params_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_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.Dial(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterQueryHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterQueryHandler registers the http handlers for service Query to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn))
|
||||
}
|
||||
|
||||
// RegisterQueryHandlerClient registers the http handlers for service Query
|
||||
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient".
|
||||
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient"
|
||||
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||
// "QueryClient" to call the correct interceptors.
|
||||
func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error {
|
||||
|
||||
mux.Handle("GET", pattern_Query_Account_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_Account_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_Account_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()
|
||||
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_Balance_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_Balance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_Storage_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_Storage_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_Storage_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_Code_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_Code_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_Code_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_TxLogs_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_TxLogs_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_TxLogs_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()
|
||||
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_BlockLogs_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_BlockLogs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_BlockBloom_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_BlockBloom_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_BlockBloom_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_Params_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_Params_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_Params_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_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_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_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_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_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_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_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ethermint", "evm", "v1alpha1", "params"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_Query_Account_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_Balance_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_Storage_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_Code_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_TxLogs_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_BlockLogs_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_BlockBloom_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_Params_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
+16
-19
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
|
||||
@@ -65,6 +65,8 @@ type stateObject struct {
|
||||
dbErr error
|
||||
stateDB *CommitStateDB
|
||||
account *ethermint.EthAccount
|
||||
// balance represents the amount of the EVM denom token that an account holds
|
||||
balance sdk.Int
|
||||
|
||||
keyToOriginStorageIndex map[ethcmn.Hash]int
|
||||
keyToDirtyStorageIndex map[ethcmn.Hash]int
|
||||
@@ -80,8 +82,7 @@ type stateObject struct {
|
||||
deleted bool
|
||||
}
|
||||
|
||||
func newStateObject(db *CommitStateDB, accProto authexported.Account) *stateObject {
|
||||
// func newStateObject(db *CommitStateDB, accProto authexported.Account, balance sdk.Int) *stateObject {
|
||||
func newStateObject(db *CommitStateDB, accProto authtypes.AccountI, balance sdk.Int) *stateObject {
|
||||
ethermintAccount, ok := accProto.(*ethermint.EthAccount)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("invalid account type for state object: %T", accProto))
|
||||
@@ -95,6 +96,7 @@ func newStateObject(db *CommitStateDB, accProto authexported.Account) *stateObje
|
||||
return &stateObject{
|
||||
stateDB: db,
|
||||
account: ethermintAccount,
|
||||
balance: balance,
|
||||
address: ethermintAccount.EthAddress(),
|
||||
originStorage: Storage{},
|
||||
dirtyStorage: Storage{},
|
||||
@@ -176,8 +178,7 @@ func (so *stateObject) AddBalance(amount *big.Int) {
|
||||
return
|
||||
}
|
||||
|
||||
evmDenom := so.stateDB.GetParams().EvmDenom
|
||||
newBalance := so.account.GetCoins().AmountOf(evmDenom).Add(amt)
|
||||
newBalance := so.balance.Add(amt)
|
||||
so.SetBalance(newBalance.BigInt())
|
||||
}
|
||||
|
||||
@@ -189,26 +190,25 @@ func (so *stateObject) SubBalance(amount *big.Int) {
|
||||
return
|
||||
}
|
||||
|
||||
evmDenom := so.stateDB.GetParams().EvmDenom
|
||||
newBalance := so.account.GetCoins().AmountOf(evmDenom).Sub(amt)
|
||||
newBalance := so.balance.Sub(amt)
|
||||
so.SetBalance(newBalance.BigInt())
|
||||
}
|
||||
|
||||
// SetBalance sets the state object's balance.
|
||||
// SetBalance sets the state object's balance. It doesn't perform any validation
|
||||
// on the amount value.
|
||||
func (so *stateObject) SetBalance(amount *big.Int) {
|
||||
amt := sdk.NewIntFromBigInt(amount)
|
||||
|
||||
evmDenom := so.stateDB.GetParams().EvmDenom
|
||||
so.stateDB.journal.append(balanceChange{
|
||||
account: &so.address,
|
||||
prev: so.account.GetCoins().AmountOf(evmDenom),
|
||||
prev: so.balance,
|
||||
})
|
||||
|
||||
so.setBalance(evmDenom, amt)
|
||||
so.setBalance(amt)
|
||||
}
|
||||
|
||||
func (so *stateObject) setBalance(denom string, amount sdk.Int) {
|
||||
so.account.SetBalance(denom, amount)
|
||||
func (so *stateObject) setBalance(amount sdk.Int) {
|
||||
so.balance = amount
|
||||
}
|
||||
|
||||
// SetNonce sets the state object's nonce (i.e sequence number of the account).
|
||||
@@ -298,8 +298,7 @@ func (so stateObject) Address() ethcmn.Address {
|
||||
|
||||
// Balance returns the state object's current balance.
|
||||
func (so *stateObject) Balance() *big.Int {
|
||||
evmDenom := so.stateDB.GetParams().EvmDenom
|
||||
balance := so.account.Balance(evmDenom).BigInt()
|
||||
balance := so.balance.BigInt()
|
||||
if balance == nil {
|
||||
return zeroBalance
|
||||
}
|
||||
@@ -400,7 +399,7 @@ func (so *stateObject) GetCommittedState(_ ethstate.Database, key ethcmn.Hash) e
|
||||
func (so *stateObject) ReturnGas(gas *big.Int) {}
|
||||
|
||||
func (so *stateObject) deepCopy(db *CommitStateDB) *stateObject {
|
||||
newStateObj := newStateObject(db, so.account)
|
||||
newStateObj := newStateObject(db, so.account, so.balance)
|
||||
|
||||
newStateObj.code = so.code
|
||||
newStateObj.dirtyStorage = so.dirtyStorage.Copy()
|
||||
@@ -414,12 +413,10 @@ func (so *stateObject) deepCopy(db *CommitStateDB) *stateObject {
|
||||
|
||||
// empty returns whether the account is considered empty.
|
||||
func (so *stateObject) empty() bool {
|
||||
evmDenom := so.stateDB.GetParams().EvmDenom
|
||||
balace := so.account.Balance(evmDenom)
|
||||
return so.account == nil ||
|
||||
(so.account != nil &&
|
||||
so.account.Sequence == 0 &&
|
||||
(balace.BigInt() == nil || balace.IsZero()) &&
|
||||
(so.balance.BigInt() == nil || so.balance.IsZero()) &&
|
||||
bytes.Equal(so.account.CodeHash, emptyCodeHash))
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@ package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
@@ -41,10 +42,10 @@ type GasInfo struct {
|
||||
|
||||
// ExecutionResult represents what's returned from a transition
|
||||
type ExecutionResult struct {
|
||||
Logs []*ethtypes.Log
|
||||
Bloom *big.Int
|
||||
Result *sdk.Result
|
||||
GasInfo GasInfo
|
||||
Logs []*ethtypes.Log
|
||||
Bloom *big.Int
|
||||
Response *MsgEthereumTxResponse
|
||||
GasInfo GasInfo
|
||||
}
|
||||
|
||||
// GetHashFn implements vm.GetHashFunc for Ethermint. It handles 3 cases:
|
||||
@@ -79,7 +80,7 @@ func (st StateTransition) newEVM(
|
||||
config ChainConfig,
|
||||
extraEIPs []int64,
|
||||
) *vm.EVM {
|
||||
// Create contexts for evm
|
||||
// Create context for evm
|
||||
|
||||
blockCtx := vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
@@ -105,7 +106,6 @@ func (st StateTransition) newEVM(
|
||||
vmConfig := vm.Config{
|
||||
ExtraEips: eips,
|
||||
}
|
||||
|
||||
return vm.NewEVM(blockCtx, txCtx, csdb, config.EthereumConfig(st.ChainID), vmConfig)
|
||||
}
|
||||
|
||||
@@ -153,13 +153,12 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex
|
||||
return nil, errors.New("gas price cannot be nil")
|
||||
}
|
||||
|
||||
evm := st.newEVM(ctx, csdb, gasLimit, gasPrice.Int, config, params.ExtraEIPs)
|
||||
evm := st.newEVM(ctx, csdb, gasLimit, gasPrice.BigInt(), config, params.ExtraEIPs)
|
||||
|
||||
var (
|
||||
ret []byte
|
||||
leftOverGas uint64
|
||||
contractAddress common.Address
|
||||
recipientLog string
|
||||
senderRef = vm.AccountRef(st.Sender)
|
||||
)
|
||||
|
||||
@@ -176,7 +175,7 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex
|
||||
}
|
||||
|
||||
ret, contractAddress, leftOverGas, err = evm.Create(senderRef, st.Payload, gasLimit, st.Amount)
|
||||
recipientLog = fmt.Sprintf("contract address %s", contractAddress.String())
|
||||
|
||||
default:
|
||||
if !params.EnableCall {
|
||||
return nil, ErrCallDisabled
|
||||
@@ -185,7 +184,6 @@ 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)
|
||||
recipientLog = fmt.Sprintf("recipient address %s", st.Recipient.String())
|
||||
}
|
||||
|
||||
gasConsumed := gasLimit - leftOverGas
|
||||
@@ -225,34 +223,20 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex
|
||||
}
|
||||
}
|
||||
|
||||
// Encode all necessary data into slice of bytes to return in sdk result
|
||||
resultData := ResultData{
|
||||
Bloom: bloomFilter,
|
||||
Logs: logs,
|
||||
res := &MsgEthereumTxResponse{
|
||||
Bloom: bloomFilter.Bytes(),
|
||||
TxLogs: NewTransactionLogsFromEth(*st.TxHash, logs),
|
||||
Ret: ret,
|
||||
TxHash: *st.TxHash,
|
||||
}
|
||||
|
||||
if contractCreation {
|
||||
resultData.ContractAddress = contractAddress
|
||||
res.ContractAddress = contractAddress.String()
|
||||
}
|
||||
|
||||
resBz, err := EncodeResultData(resultData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resultLog := fmt.Sprintf(
|
||||
"executed EVM state transition; sender address %s; %s", st.Sender.String(), recipientLog,
|
||||
)
|
||||
|
||||
executionResult := &ExecutionResult{
|
||||
Logs: logs,
|
||||
Bloom: bloomInt,
|
||||
Result: &sdk.Result{
|
||||
Data: resBz,
|
||||
Log: resultLog,
|
||||
},
|
||||
Logs: logs,
|
||||
Bloom: bloomInt,
|
||||
Response: res,
|
||||
GasInfo: GasInfo{
|
||||
GasConsumed: gasConsumed,
|
||||
GasLimit: gasLimit,
|
||||
@@ -268,3 +252,25 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex
|
||||
|
||||
return executionResult, nil
|
||||
}
|
||||
|
||||
// HashFromContext returns the Ethereum Header hash from the context's Tendermint
|
||||
// block header.
|
||||
func HashFromContext(ctx sdk.Context) common.Hash {
|
||||
// cast the ABCI header to tendermint Header type
|
||||
protoHeader := ctx.BlockHeader()
|
||||
tmHeader, err := tmtypes.HeaderFromProto(&protoHeader)
|
||||
if err != nil {
|
||||
return common.Hash{}
|
||||
}
|
||||
|
||||
// get the Tendermint block hash from the current header
|
||||
tmBlockHash := tmHeader.Hash()
|
||||
|
||||
// NOTE: if the validator set hash is missing the hash will be returned as nil,
|
||||
// so we need to check for this case to prevent a panic when calling Bytes()
|
||||
if tmBlockHash == nil {
|
||||
return common.Hash{}
|
||||
}
|
||||
|
||||
return common.BytesToHash(tmBlockHash.Bytes())
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ package types_test
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
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"
|
||||
|
||||
@@ -23,53 +25,60 @@ func (suite *StateDBTestSuite) TestGetHashFn() {
|
||||
malleate func()
|
||||
expEmptyHash bool
|
||||
}{
|
||||
{
|
||||
"valid hash, case 1",
|
||||
1,
|
||||
func() {
|
||||
suite.ctx = suite.ctx.WithBlockHeader(
|
||||
abci.Header{
|
||||
ChainID: "ethermint-1",
|
||||
Height: 1,
|
||||
ValidatorsHash: []byte("val_hash"),
|
||||
},
|
||||
)
|
||||
hash := ethcmn.BytesToHash([]byte("test hash"))
|
||||
suite.stateDB.SetBlockHash(hash)
|
||||
},
|
||||
false,
|
||||
},
|
||||
// {
|
||||
// "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(
|
||||
abci.Header{
|
||||
ChainID: "ethermint-1",
|
||||
Height: 100,
|
||||
ValidatorsHash: []byte("val_hash"),
|
||||
},
|
||||
)
|
||||
hash := ethcmn.BytesToHash([]byte("test hash"))
|
||||
suite.stateDB.WithContext(suite.ctx).SetHeightHash(1, hash)
|
||||
},
|
||||
false,
|
||||
},
|
||||
// {
|
||||
// "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(
|
||||
abci.Header{
|
||||
tmproto.Header{
|
||||
ChainID: "ethermint-1",
|
||||
Height: 100,
|
||||
ValidatorsHash: []byte("val_hash"),
|
||||
Version: version.Consensus{
|
||||
Block: tmversion.BlockProtocol,
|
||||
},
|
||||
},
|
||||
)
|
||||
},
|
||||
@@ -80,10 +89,13 @@ func (suite *StateDBTestSuite) TestGetHashFn() {
|
||||
1000,
|
||||
func() {
|
||||
suite.ctx = suite.ctx.WithBlockHeader(
|
||||
abci.Header{
|
||||
tmproto.Header{
|
||||
ChainID: "ethermint-1",
|
||||
Height: 100,
|
||||
ValidatorsHash: []byte("val_hash"),
|
||||
Version: version.Consensus{
|
||||
Block: tmversion.BlockProtocol,
|
||||
},
|
||||
},
|
||||
)
|
||||
},
|
||||
@@ -113,8 +125,8 @@ func (suite *StateDBTestSuite) TestTransitionDb() {
|
||||
addr := sdk.AccAddress(suite.address.Bytes())
|
||||
balance := ethermint.NewPhotonCoin(sdk.NewInt(5000))
|
||||
acc := suite.app.AccountKeeper.GetAccount(suite.ctx, addr)
|
||||
_ = acc.SetCoins(sdk.NewCoins(balance))
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
suite.app.BankKeeper.SetBalance(suite.ctx, addr, balance)
|
||||
|
||||
priv, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
@@ -198,6 +210,24 @@ func (suite *StateDBTestSuite) TestTransitionDb() {
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"failed to Finalize",
|
||||
func() {},
|
||||
types.StateTransition{
|
||||
AccountNonce: 123,
|
||||
Price: big.NewInt(10),
|
||||
GasLimit: 11,
|
||||
Recipient: &recipient,
|
||||
Amount: big.NewInt(-5000),
|
||||
Payload: []byte("data"),
|
||||
ChainID: big.NewInt(1),
|
||||
Csdb: suite.stateDB,
|
||||
TxHash: ðcmn.Hash{},
|
||||
Sender: suite.address,
|
||||
Simulate: false,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"call disabled",
|
||||
func() {
|
||||
|
||||
+52
-49
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
|
||||
@@ -43,8 +43,9 @@ type CommitStateDB struct {
|
||||
ctx sdk.Context
|
||||
|
||||
storeKey sdk.StoreKey
|
||||
paramSpace params.Subspace
|
||||
paramSpace paramtypes.Subspace
|
||||
accountKeeper AccountKeeper
|
||||
bankKeeper BankKeeper
|
||||
|
||||
// array that hold 'live' objects, which will get modified while processing a
|
||||
// state transition
|
||||
@@ -90,13 +91,15 @@ type CommitStateDB struct {
|
||||
// CONTRACT: Stores used for state must be cache-wrapped as the ordering of the
|
||||
// key/value space matters in determining the merkle root.
|
||||
func NewCommitStateDB(
|
||||
ctx sdk.Context, storeKey sdk.StoreKey, paramSpace params.Subspace, ak AccountKeeper,
|
||||
ctx sdk.Context, storeKey sdk.StoreKey, paramSpace paramtypes.Subspace,
|
||||
ak AccountKeeper, bankKeeper BankKeeper,
|
||||
) *CommitStateDB {
|
||||
return &CommitStateDB{
|
||||
ctx: ctx,
|
||||
storeKey: storeKey,
|
||||
paramSpace: paramSpace,
|
||||
accountKeeper: ak,
|
||||
bankKeeper: bankKeeper,
|
||||
stateObjects: []stateEntry{},
|
||||
addressToObjectIndex: make(map[ethcmn.Address]int),
|
||||
stateObjectsDirty: make(map[ethcmn.Address]struct{}),
|
||||
@@ -132,49 +135,38 @@ 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)
|
||||
if so != nil {
|
||||
so.SetBalance(amount)
|
||||
}
|
||||
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)
|
||||
if so != nil {
|
||||
so.AddBalance(amount)
|
||||
}
|
||||
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)
|
||||
if so != nil {
|
||||
so.SubBalance(amount)
|
||||
}
|
||||
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)
|
||||
if so != nil {
|
||||
so.SetNonce(nonce)
|
||||
}
|
||||
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)
|
||||
if so != nil {
|
||||
so.SetState(nil, key, value)
|
||||
}
|
||||
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)
|
||||
if so != nil {
|
||||
so.SetCode(ethcrypto.Keccak256Hash(code), code)
|
||||
}
|
||||
so.SetCode(ethcrypto.Keccak256Hash(code), code)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -187,7 +179,9 @@ func (csdb *CommitStateDB) SetCode(addr ethcmn.Address, code []byte) {
|
||||
// SetLogs sets the logs for a transaction in the KVStore.
|
||||
func (csdb *CommitStateDB) SetLogs(hash ethcmn.Hash, logs []*ethtypes.Log) error {
|
||||
store := prefix.NewStore(csdb.ctx.KVStore(csdb.storeKey), KeyPrefixLogs)
|
||||
bz, err := MarshalLogs(logs)
|
||||
|
||||
txLogs := NewTransactionLogsFromEth(hash, logs)
|
||||
bz, err := ModuleCdc.MarshalBinaryBare(&txLogs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -306,8 +300,16 @@ 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) {
|
||||
csdb.paramSpace.GetParamSet(csdb.ctx, ¶ms)
|
||||
ps := ¶ms
|
||||
for _, pair := range ps.ParamSetPairs() {
|
||||
if csdb.paramSpace.Has(csdb.ctx, pair.Key) {
|
||||
csdb.paramSpace.Get(csdb.ctx, pair.Key, pair.Value)
|
||||
}
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
@@ -410,7 +412,12 @@ func (csdb *CommitStateDB) GetLogs(hash ethcmn.Hash) ([]*ethtypes.Log, error) {
|
||||
return []*ethtypes.Log{}, nil
|
||||
}
|
||||
|
||||
return UnmarshalLogs(bz)
|
||||
var txLogs TransactionLogs
|
||||
if err := ModuleCdc.UnmarshalBinaryBare(bz, &txLogs); err != nil {
|
||||
return []*ethtypes.Log{}, err
|
||||
}
|
||||
|
||||
return txLogs.EthLogs(), nil
|
||||
}
|
||||
|
||||
// AllLogs returns all the current logs in the state.
|
||||
@@ -421,9 +428,9 @@ func (csdb *CommitStateDB) AllLogs() []*ethtypes.Log {
|
||||
|
||||
allLogs := []*ethtypes.Log{}
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
var logs []*ethtypes.Log
|
||||
ModuleCdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &logs)
|
||||
allLogs = append(allLogs, logs...)
|
||||
var txLogs TransactionLogs
|
||||
ModuleCdc.MustUnmarshalBinaryBare(iterator.Value(), &txLogs)
|
||||
allLogs = append(allLogs, txLogs.EthLogs()...)
|
||||
}
|
||||
|
||||
return allLogs
|
||||
@@ -572,18 +579,11 @@ func (csdb *CommitStateDB) updateStateObject(so *stateObject) error {
|
||||
return fmt.Errorf("invalid balance %s", newBalance)
|
||||
}
|
||||
|
||||
coins := so.account.GetCoins()
|
||||
balance := coins.AmountOf(newBalance.Denom)
|
||||
if balance.IsZero() || !balance.Equal(newBalance.Amount) {
|
||||
coins = coins.Add(newBalance)
|
||||
}
|
||||
|
||||
if err := so.account.SetCoins(coins); err != nil {
|
||||
err := csdb.bankKeeper.SetBalance(csdb.ctx, so.account.GetAddress(), newBalance)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
csdb.accountKeeper.SetAccount(csdb.ctx, so.account)
|
||||
// return csdb.bankKeeper.SetBalance(csdb.ctx, so.account.Address, newBalance)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -703,20 +703,21 @@ func (csdb *CommitStateDB) Reset(_ ethcmn.Hash) error {
|
||||
// UpdateAccounts updates the nonce and coin balances of accounts
|
||||
func (csdb *CommitStateDB) UpdateAccounts() {
|
||||
for _, stateEntry := range csdb.stateObjects {
|
||||
currAcc := csdb.accountKeeper.GetAccount(csdb.ctx, sdk.AccAddress(stateEntry.address.Bytes()))
|
||||
ethermintAcc, ok := currAcc.(*ethermint.EthAccount)
|
||||
address := sdk.AccAddress(stateEntry.address.Bytes())
|
||||
currAccount := csdb.accountKeeper.GetAccount(csdb.ctx, address)
|
||||
ethermintAcc, ok := currAccount.(*ethermint.EthAccount)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
evmDenom := csdb.GetParams().EvmDenom
|
||||
balance := sdk.Coin{
|
||||
Denom: evmDenom,
|
||||
Amount: ethermintAcc.GetCoins().AmountOf(evmDenom),
|
||||
balance := csdb.bankKeeper.GetBalance(csdb.ctx, address, evmDenom)
|
||||
|
||||
if stateEntry.stateObject.Balance() != balance.Amount.BigInt() && balance.IsValid() {
|
||||
stateEntry.stateObject.balance = balance.Amount
|
||||
}
|
||||
|
||||
if stateEntry.stateObject.Balance() != balance.Amount.BigInt() && balance.IsValid() ||
|
||||
stateEntry.stateObject.Nonce() != ethermintAcc.GetSequence() {
|
||||
if stateEntry.stateObject.Nonce() != ethermintAcc.GetSequence() {
|
||||
stateEntry.stateObject.account = ethermintAcc
|
||||
}
|
||||
}
|
||||
@@ -755,8 +756,7 @@ func (csdb *CommitStateDB) Prepare(thash ethcmn.Hash, txi int) {
|
||||
func (csdb *CommitStateDB) CreateAccount(addr ethcmn.Address) {
|
||||
newobj, prevobj := csdb.createObject(addr)
|
||||
if prevobj != nil {
|
||||
evmDenom := csdb.GetParams().EvmDenom
|
||||
newobj.setBalance(evmDenom, sdk.NewIntFromBigInt(prevobj.Balance()))
|
||||
newobj.setBalance(sdk.NewIntFromBigInt(prevobj.Balance()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -780,6 +780,7 @@ func CopyCommitStateDB(from, to *CommitStateDB) {
|
||||
to.storeKey = from.storeKey
|
||||
to.paramSpace = from.paramSpace
|
||||
to.accountKeeper = from.accountKeeper
|
||||
to.bankKeeper = from.bankKeeper
|
||||
to.stateObjects = []stateEntry{}
|
||||
to.addressToObjectIndex = make(map[ethcmn.Address]int)
|
||||
to.stateObjectsDirty = make(map[ethcmn.Address]struct{})
|
||||
@@ -866,8 +867,7 @@ 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 {
|
||||
@@ -884,7 +884,7 @@ func (csdb *CommitStateDB) createObject(addr ethcmn.Address) (newObj, prevObj *s
|
||||
|
||||
acc := csdb.accountKeeper.NewAccountWithAddress(csdb.ctx, sdk.AccAddress(addr.Bytes()))
|
||||
|
||||
newObj = newStateObject(csdb, acc)
|
||||
newObj = newStateObject(csdb, acc, sdk.ZeroInt())
|
||||
newObj.setNonce(0) // sets the object to dirty
|
||||
|
||||
if prevObj == nil {
|
||||
@@ -925,8 +925,11 @@ func (csdb *CommitStateDB) getStateObject(addr ethcmn.Address) (stateObject *sta
|
||||
return nil
|
||||
}
|
||||
|
||||
evmDenom := csdb.GetParams().EvmDenom
|
||||
balance := csdb.bankKeeper.GetBalance(csdb.ctx, acc.GetAddress(), evmDenom)
|
||||
|
||||
// insert the state object into the live set
|
||||
so := newStateObject(csdb, acc)
|
||||
so := newStateObject(csdb, acc, balance.Amount)
|
||||
csdb.setStateObject(so)
|
||||
|
||||
return so
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||
)
|
||||
|
||||
type StateDBTestSuite struct {
|
||||
@@ -40,7 +40,7 @@ func (suite *StateDBTestSuite) SetupTest() {
|
||||
checkTx := false
|
||||
|
||||
suite.app = app.Setup(checkTx)
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "ethermint-1"})
|
||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "ethermint-1"})
|
||||
suite.stateDB = suite.app.EvmKeeper.CommitStateDB.WithContext(suite.ctx)
|
||||
|
||||
privkey, err := ethsecp256k1.GenerateKey()
|
||||
@@ -48,13 +48,16 @@ func (suite *StateDBTestSuite) SetupTest() {
|
||||
|
||||
suite.address = ethcmn.BytesToAddress(privkey.PubKey().Address().Bytes())
|
||||
|
||||
balance := sdk.NewCoins(ethermint.NewPhotonCoin(sdk.ZeroInt()))
|
||||
balance := ethermint.NewPhotonCoin(sdk.ZeroInt())
|
||||
acc := ðermint.EthAccount{
|
||||
BaseAccount: auth.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), balance, nil, 0, 0),
|
||||
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0),
|
||||
CodeHash: ethcrypto.Keccak256(nil),
|
||||
}
|
||||
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
err = suite.app.BankKeeper.SetBalance(suite.ctx, acc.GetAddress(), balance)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.stateObject = suite.stateDB.GetOrNewStateObject(suite.address)
|
||||
}
|
||||
|
||||
@@ -83,7 +86,10 @@ func (suite *StateDBTestSuite) TestBloomFilter() {
|
||||
tHash := ethcmn.BytesToHash([]byte{0x1})
|
||||
suite.stateDB.Prepare(tHash, 0)
|
||||
contractAddress := ethcmn.BigToAddress(big.NewInt(1))
|
||||
log := ethtypes.Log{Address: contractAddress}
|
||||
log := ethtypes.Log{
|
||||
Address: contractAddress,
|
||||
Topics: []ethcmn.Hash{},
|
||||
}
|
||||
|
||||
testCase := []struct {
|
||||
name string
|
||||
@@ -159,6 +165,13 @@ func (suite *StateDBTestSuite) TestStateDB_Balance() {
|
||||
},
|
||||
big.NewInt(200),
|
||||
},
|
||||
{
|
||||
"sub more than balance",
|
||||
func() {
|
||||
suite.stateDB.SubBalance(suite.address, big.NewInt(300))
|
||||
},
|
||||
big.NewInt(-100),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCase {
|
||||
@@ -271,7 +284,7 @@ func (suite *StateDBTestSuite) TestStateDB_Logs() {
|
||||
TxHash: ethcmn.Hash{},
|
||||
TxIndex: 1,
|
||||
BlockHash: ethcmn.Hash{},
|
||||
Index: 1,
|
||||
Index: 0,
|
||||
Removed: false,
|
||||
},
|
||||
},
|
||||
@@ -293,6 +306,7 @@ 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.
|
||||
@@ -441,7 +455,7 @@ func (suite *StateDBTestSuite) TestSuiteDB_CopyState() {
|
||||
TxHash: ethcmn.Hash{},
|
||||
TxIndex: 1,
|
||||
BlockHash: ethcmn.Hash{},
|
||||
Index: 1,
|
||||
Index: 0,
|
||||
Removed: false,
|
||||
},
|
||||
},
|
||||
@@ -542,6 +556,13 @@ func (suite *StateDBTestSuite) TestCommitStateDB_Commit() {
|
||||
},
|
||||
false, true,
|
||||
},
|
||||
{
|
||||
"faled to update state object",
|
||||
func() {
|
||||
suite.stateDB.SubBalance(suite.address, big.NewInt(10))
|
||||
},
|
||||
false, false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCase {
|
||||
@@ -599,6 +620,13 @@ func (suite *StateDBTestSuite) TestCommitStateDB_Finalize() {
|
||||
},
|
||||
false, true,
|
||||
},
|
||||
{
|
||||
"faled to update state object",
|
||||
func() {
|
||||
suite.stateDB.SubBalance(suite.address, big.NewInt(10))
|
||||
},
|
||||
false, false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCase {
|
||||
|
||||
@@ -35,7 +35,7 @@ func (s Storage) Validate() error {
|
||||
func (s Storage) String() string {
|
||||
var str string
|
||||
for _, state := range s {
|
||||
str += fmt.Sprintf("%s: %s\n", state.Key, state.Value)
|
||||
str += fmt.Sprintf("%s\n", state.String())
|
||||
}
|
||||
|
||||
return str
|
||||
@@ -49,12 +49,6 @@ func (s Storage) Copy() Storage {
|
||||
return cpy
|
||||
}
|
||||
|
||||
// State represents a single Storage key value pair item.
|
||||
type State struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// Validate performs a basic validation of the State fields.
|
||||
func (s State) Validate() error {
|
||||
if ethermint.IsEmptyHash(s.Key) {
|
||||
|
||||
@@ -80,6 +80,7 @@ func TestStorageCopy(t *testing.T) {
|
||||
|
||||
func TestStorageString(t *testing.T) {
|
||||
storage := Storage{NewState(ethcmn.BytesToHash([]byte("key")), ethcmn.BytesToHash([]byte("value")))}
|
||||
str := "0x00000000000000000000000000000000000000000000000000000000006b6579: 0x00000000000000000000000000000000000000000000000000000076616c7565\n"
|
||||
str := `key:"0x00000000000000000000000000000000000000000000000000000000006b6579" value:"0x00000000000000000000000000000000000000000000000000000076616c7565"
|
||||
`
|
||||
require.Equal(t, str, storage.String())
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// Recipient is a wrapper of the
|
||||
type Recipient struct {
|
||||
Address string
|
||||
}
|
||||
|
||||
// TxData implements the Ethereum transaction data structure. It is used
|
||||
// solely as intended in Ethereum abiding by the protocol.
|
||||
type TxData struct {
|
||||
AccountNonce uint64 `json:"nonce"`
|
||||
Price sdk.Int `json:"gasPrice"`
|
||||
GasLimit uint64 `json:"gas"`
|
||||
Recipient *Recipient `json:"to" rlp:"nil"` // nil means contract creation
|
||||
Amount sdk.Int `json:"value"`
|
||||
Payload []byte `json:"input"`
|
||||
|
||||
// signature values
|
||||
V []byte `json:"v"`
|
||||
R []byte `json:"r"`
|
||||
S []byte `json:"s"`
|
||||
|
||||
// hash is only used when marshaling to JSON
|
||||
Hash string `json:"hash" rlp:"-"`
|
||||
}
|
||||
+22
-76
@@ -1,35 +1,19 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
)
|
||||
|
||||
// GenerateEthAddress generates an Ethereum address.
|
||||
func GenerateEthAddress() ethcmn.Address {
|
||||
priv, err := ethsecp256k1.GenerateKey()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return ethcrypto.PubkeyToAddress(priv.ToECDSA().PublicKey)
|
||||
}
|
||||
|
||||
// ValidateSigner attempts to validate a signer for a given slice of bytes over
|
||||
// which a signature and signer is given. An error is returned if address
|
||||
// derived from the signature and bytes signed does not match the given signer.
|
||||
@@ -53,73 +37,25 @@ func rlpHash(x interface{}) (hash ethcmn.Hash) {
|
||||
return hash
|
||||
}
|
||||
|
||||
// ResultData represents the data returned in an sdk.Result
|
||||
type ResultData struct {
|
||||
ContractAddress ethcmn.Address `json:"contract_address"`
|
||||
Bloom ethtypes.Bloom `json:"bloom"`
|
||||
Logs []*ethtypes.Log `json:"logs"`
|
||||
Ret []byte `json:"ret"`
|
||||
TxHash ethcmn.Hash `json:"tx_hash"`
|
||||
// EncodeTxResponse takes all of the necessary data from the EVM execution
|
||||
// and returns the data as a byte slice encoded with protobuf.
|
||||
func EncodeTxResponse(res *MsgEthereumTxResponse) ([]byte, error) {
|
||||
return proto.Marshal(res)
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer interface.
|
||||
func (rd ResultData) String() string {
|
||||
var logsStr string
|
||||
logsLen := len(rd.Logs)
|
||||
for i := 0; i < logsLen; i++ {
|
||||
logsStr = fmt.Sprintf("%s\t\t%v\n ", logsStr, *rd.Logs[i])
|
||||
}
|
||||
|
||||
return strings.TrimSpace(fmt.Sprintf(`ResultData:
|
||||
ContractAddress: %s
|
||||
Bloom: %s
|
||||
Ret: %v
|
||||
TxHash: %s
|
||||
Logs:
|
||||
%s`, rd.ContractAddress.String(), rd.Bloom.Big().String(), rd.Ret, rd.TxHash.String(), logsStr))
|
||||
}
|
||||
|
||||
// EncodeResultData takes all of the necessary data from the EVM execution
|
||||
// and returns the data as a byte slice encoded with amino
|
||||
func EncodeResultData(data ResultData) ([]byte, error) {
|
||||
return ModuleCdc.MarshalBinaryLengthPrefixed(data)
|
||||
}
|
||||
|
||||
// DecodeResultData decodes an amino-encoded byte slice into ResultData
|
||||
func DecodeResultData(in []byte) (ResultData, error) {
|
||||
var data ResultData
|
||||
err := ModuleCdc.UnmarshalBinaryLengthPrefixed(in, &data)
|
||||
// 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 ResultData{}, err
|
||||
return MsgEthereumTxResponse{}, err
|
||||
}
|
||||
return data, nil
|
||||
return txResponse, nil
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Auxiliary
|
||||
|
||||
// TxDecoder returns an sdk.TxDecoder that can decode both auth.StdTx and
|
||||
// MsgEthereumTx transactions.
|
||||
func TxDecoder(cdc *codec.Codec) sdk.TxDecoder {
|
||||
return func(txBytes []byte) (sdk.Tx, error) {
|
||||
var tx sdk.Tx
|
||||
|
||||
if len(txBytes) == 0 {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx bytes are empty")
|
||||
}
|
||||
|
||||
// sdk.Tx is an interface. The concrete message types
|
||||
// are registered by MakeTxCodec
|
||||
// TODO: switch to UnmarshalBinaryBare on SDK v0.40.0
|
||||
err := cdc.UnmarshalBinaryLengthPrefixed(txBytes, &tx)
|
||||
if err != nil {
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, err.Error())
|
||||
}
|
||||
|
||||
return tx, nil
|
||||
}
|
||||
}
|
||||
|
||||
// recoverEthSig recovers a signature according to the Ethereum specification and
|
||||
// returns the sender or an error.
|
||||
//
|
||||
@@ -158,3 +94,13 @@ func recoverEthSig(R, S, Vb *big.Int, sigHash ethcmn.Hash) (ethcmn.Address, erro
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// IsEmptyHash returns true if the hash corresponds to an empty ethereum hex hash.
|
||||
func IsEmptyHash(hash string) bool {
|
||||
return bytes.Equal(ethcmn.HexToHash(hash).Bytes(), ethcmn.Hash{}.Bytes())
|
||||
}
|
||||
|
||||
// IsZeroAddress returns true if the address corresponds to an empty ethereum hex address.
|
||||
func IsZeroAddress(address string) bool {
|
||||
return bytes.Equal(ethcmn.HexToAddress(address).Bytes(), ethcmn.Address{}.Bytes())
|
||||
}
|
||||
|
||||
+15
-11
@@ -11,28 +11,32 @@ import (
|
||||
)
|
||||
|
||||
func TestEvmDataEncoding(t *testing.T) {
|
||||
addr := ethcmn.HexToAddress("0x5dE8a020088a2D6d0a23c204FFbeD02790466B49")
|
||||
addr := "0x5dE8a020088a2D6d0a23c204FFbeD02790466B49"
|
||||
bloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
|
||||
ret := []byte{0x5, 0x8}
|
||||
|
||||
data := ResultData{
|
||||
data := &MsgEthereumTxResponse{
|
||||
ContractAddress: addr,
|
||||
Bloom: bloom,
|
||||
Logs: []*ethtypes.Log{{
|
||||
Data: []byte{1, 2, 3, 4},
|
||||
BlockNumber: 17,
|
||||
}},
|
||||
Bloom: bloom.Bytes(),
|
||||
TxLogs: TransactionLogs{
|
||||
Hash: ethcmn.BytesToHash([]byte{1, 2, 3, 4}).String(),
|
||||
Logs: []*Log{{
|
||||
Data: []byte{1, 2, 3, 4},
|
||||
BlockNumber: 17,
|
||||
}},
|
||||
},
|
||||
Ret: ret,
|
||||
}
|
||||
|
||||
enc, err := EncodeResultData(data)
|
||||
enc, err := EncodeTxResponse(data)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := DecodeResultData(enc)
|
||||
res, err := DecodeTxResponse(enc)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, res)
|
||||
require.Equal(t, addr, res.ContractAddress)
|
||||
require.Equal(t, bloom, res.Bloom)
|
||||
require.Equal(t, data.Logs, res.Logs)
|
||||
require.Equal(t, bloom.Bytes(), res.Bloom)
|
||||
require.Equal(t, data.TxLogs, res.TxLogs)
|
||||
require.Equal(t, ret, res.Ret)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user