Merge pull request #35 from vulcanize/sai/upgrade_cosmos_v0.46
upgrade: upgrade to vulcanize cosmos v0.46 SMT
This commit is contained in:
commit
007e27dcbc
23
Makefile
23
Makefile
@ -88,18 +88,23 @@ ifeq (boltdb,$(findstring boltdb,$(COSMOS_BUILD_OPTIONS)))
|
|||||||
ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=boltdb
|
ldflags += -X github.com/cosmos/cosmos-sdk/types.DBBackend=boltdb
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
BUILD_FLAGS := -tags "$(build_tags)" -ldflags '$(ldflags)'
|
||||||
|
|
||||||
|
# Check for debug option
|
||||||
|
ifeq (debug,$(findstring debug,$(COSMOS_BUILD_OPTIONS)))
|
||||||
|
BUILD_FLAGS += -gcflags 'all=-N -l'
|
||||||
|
COSMOS_BUILD_OPTIONS += nostrip
|
||||||
|
endif
|
||||||
|
|
||||||
|
# check for nostrip option
|
||||||
ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS)))
|
ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS)))
|
||||||
|
BUILD_FLAGS += -trimpath
|
||||||
ldflags += -w -s
|
ldflags += -w -s
|
||||||
endif
|
endif
|
||||||
ldflags += $(LDFLAGS)
|
ldflags += $(LDFLAGS)
|
||||||
ldflags := $(strip $(ldflags))
|
ldflags := $(strip $(ldflags))
|
||||||
|
|
||||||
BUILD_FLAGS := -tags "$(build_tags)" -ldflags '$(ldflags)'
|
all: tools build lint test
|
||||||
# check for nostrip option
|
|
||||||
ifeq (,$(findstring nostrip,$(COSMOS_BUILD_OPTIONS)))
|
|
||||||
BUILD_FLAGS += -trimpath
|
|
||||||
endif
|
|
||||||
|
|
||||||
# # The below include contains the tools and runsim targets.
|
# # The below include contains the tools and runsim targets.
|
||||||
# include contrib/devtools/Makefile
|
# include contrib/devtools/Makefile
|
||||||
|
|
||||||
@ -111,14 +116,16 @@ BUILD_TARGETS := build install
|
|||||||
|
|
||||||
build: BUILD_ARGS=-o $(BUILDDIR)/
|
build: BUILD_ARGS=-o $(BUILDDIR)/
|
||||||
build-linux:
|
build-linux:
|
||||||
GOOS=linux GOARCH=amd64 LEDGER_ENABLED=false $(MAKE) build
|
GOOS=linux GOARCH=$(if $(findstring aarch64,$(shell uname -m)) || $(findstring arm64,$(shell uname -m)),arm64,amd64) LEDGER_ENABLED=false $(MAKE) build
|
||||||
|
|
||||||
$(BUILD_TARGETS): go.sum $(BUILDDIR)/
|
$(BUILD_TARGETS): go.sum $(BUILDDIR)/
|
||||||
go $@ $(BUILD_FLAGS) $(BUILD_ARGS) ./...
|
go $@ -mod=readonly $(BUILD_FLAGS) $(BUILD_ARGS) ./...
|
||||||
|
|
||||||
$(BUILDDIR)/:
|
$(BUILDDIR)/:
|
||||||
mkdir -p $(BUILDDIR)/
|
mkdir -p $(BUILDDIR)/
|
||||||
|
|
||||||
|
.PHONY: build build-linux cosmovisor
|
||||||
|
|
||||||
docker-build:
|
docker-build:
|
||||||
# TODO replace with kaniko
|
# TODO replace with kaniko
|
||||||
docker build -t ${DOCKER_IMAGE}:${DOCKER_TAG} .
|
docker build -t ${DOCKER_IMAGE}:${DOCKER_TAG} .
|
||||||
|
103
app/ante/ante.go
103
app/ante/ante.go
@ -1,103 +0,0 @@
|
|||||||
package ante
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"runtime/debug"
|
|
||||||
|
|
||||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
secp256k1VerifyCost uint64 = 21000
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewAnteHandler returns an ante handler responsible for attempting to route an
|
|
||||||
// Ethereum or SDK transaction to an internal ante handler for performing
|
|
||||||
// transaction-level processing (e.g. fee payment, signature verification) before
|
|
||||||
// being passed onto it's respective handler.
|
|
||||||
func NewAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
|
||||||
return func(
|
|
||||||
ctx sdk.Context, tx sdk.Tx, sim bool,
|
|
||||||
) (newCtx sdk.Context, err error) {
|
|
||||||
var anteHandler sdk.AnteHandler
|
|
||||||
|
|
||||||
defer Recover(ctx.Logger(), &err)
|
|
||||||
|
|
||||||
txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
|
|
||||||
if ok {
|
|
||||||
opts := txWithExtensions.GetExtensionOptions()
|
|
||||||
if len(opts) > 0 {
|
|
||||||
switch typeURL := opts[0].GetTypeUrl(); typeURL {
|
|
||||||
case "/ethermint.evm.v1.ExtensionOptionsEthereumTx":
|
|
||||||
// handle as *evmtypes.MsgEthereumTx
|
|
||||||
anteHandler = newEthAnteHandler(options)
|
|
||||||
case "/ethermint.types.v1.ExtensionOptionsWeb3Tx":
|
|
||||||
// handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation
|
|
||||||
anteHandler = newCosmosAnteHandlerEip712(options)
|
|
||||||
default:
|
|
||||||
return ctx, sdkerrors.Wrapf(
|
|
||||||
sdkerrors.ErrUnknownExtensionOptions,
|
|
||||||
"rejecting tx with unsupported extension option: %s", typeURL,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return anteHandler(ctx, tx, sim)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle as totally normal Cosmos SDK tx
|
|
||||||
switch tx.(type) {
|
|
||||||
case sdk.Tx:
|
|
||||||
anteHandler = newCosmosAnteHandler(options)
|
|
||||||
default:
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
return anteHandler(ctx, tx, sim)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Recover(logger tmlog.Logger, err *error) {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
*err = sdkerrors.Wrapf(sdkerrors.ErrPanic, "%v", r)
|
|
||||||
|
|
||||||
if e, ok := r.(error); ok {
|
|
||||||
logger.Error(
|
|
||||||
"ante handler panicked",
|
|
||||||
"error", e,
|
|
||||||
"stack trace", string(debug.Stack()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
logger.Error(
|
|
||||||
"ante handler panicked",
|
|
||||||
"recover", fmt.Sprintf("%v", r),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ authante.SignatureVerificationGasConsumer = DefaultSigVerificationGasConsumer
|
|
||||||
|
|
||||||
// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
|
|
||||||
// for signature verification based upon the public key type. The cost is fetched from the given params and is matched
|
|
||||||
// by the concrete type.
|
|
||||||
func DefaultSigVerificationGasConsumer(
|
|
||||||
meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params,
|
|
||||||
) error {
|
|
||||||
// support for ethereum ECDSA secp256k1 keys
|
|
||||||
_, ok := sig.PubKey.(*ethsecp256k1.PubKey)
|
|
||||||
if ok {
|
|
||||||
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: eth_secp256k1")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return authante.DefaultSigVerificationGasConsumer(meter, sig, params)
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
/*Package ante defines the SDK auth module's AnteHandler as well as an internal
|
|
||||||
AnteHandler for an Ethereum transaction (i.e MsgEthereumTx).
|
|
||||||
|
|
||||||
During CheckTx, the transaction is passed through a series of
|
|
||||||
pre-message execution validation checks such as signature and account
|
|
||||||
verification in addition to minimum fees being checked. Otherwise, during
|
|
||||||
DeliverTx, the transaction is simply passed to the EVM which will also
|
|
||||||
perform the same series of checks. The distinction is made in CheckTx to
|
|
||||||
prevent spam and DoS attacks.
|
|
||||||
*/
|
|
||||||
package ante
|
|
534
app/ante/eth.go
534
app/ante/eth.go
@ -1,534 +0,0 @@
|
|||||||
package ante
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
|
||||||
|
|
||||||
ethermint "github.com/tharsis/ethermint/types"
|
|
||||||
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
|
|
||||||
"github.com/tharsis/ethermint/x/evm/statedb"
|
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EthSigVerificationDecorator validates an ethereum signatures
|
|
||||||
type EthSigVerificationDecorator struct {
|
|
||||||
evmKeeper EVMKeeper
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEthSigVerificationDecorator creates a new EthSigVerificationDecorator
|
|
||||||
func NewEthSigVerificationDecorator(ek EVMKeeper) EthSigVerificationDecorator {
|
|
||||||
return EthSigVerificationDecorator{
|
|
||||||
evmKeeper: ek,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnteHandle validates checks that the registered chain id is the same as the one on the message, and
|
|
||||||
// that the signer address matches the one defined on the message.
|
|
||||||
// It's not skipped for RecheckTx, because it set `From` address which is critical from other ante handler to work.
|
|
||||||
// Failure in RecheckTx will prevent tx to be included into block, especially when CheckTx succeed, in which case user
|
|
||||||
// won't see the error message.
|
|
||||||
func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
|
||||||
chainID := esvd.evmKeeper.ChainID()
|
|
||||||
|
|
||||||
params := esvd.evmKeeper.GetParams(ctx)
|
|
||||||
|
|
||||||
ethCfg := params.ChainConfig.EthereumConfig(chainID)
|
|
||||||
blockNum := big.NewInt(ctx.BlockHeight())
|
|
||||||
signer := ethtypes.MakeSigner(ethCfg, blockNum)
|
|
||||||
|
|
||||||
for _, msg := range tx.GetMsgs() {
|
|
||||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
|
||||||
if !ok {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
sender, err := signer.Sender(msgEthTx.AsTransaction())
|
|
||||||
if err != nil {
|
|
||||||
return ctx, sdkerrors.Wrapf(
|
|
||||||
sdkerrors.ErrorInvalidSigner,
|
|
||||||
"couldn't retrieve sender address ('%s') from the ethereum transaction: %s",
|
|
||||||
msgEthTx.From,
|
|
||||||
err.Error(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// set up the sender to the transaction field if not already
|
|
||||||
msgEthTx.From = sender.Hex()
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EthAccountVerificationDecorator validates an account balance checks
|
|
||||||
type EthAccountVerificationDecorator struct {
|
|
||||||
ak evmtypes.AccountKeeper
|
|
||||||
bankKeeper evmtypes.BankKeeper
|
|
||||||
evmKeeper EVMKeeper
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEthAccountVerificationDecorator creates a new EthAccountVerificationDecorator
|
|
||||||
func NewEthAccountVerificationDecorator(ak evmtypes.AccountKeeper, bankKeeper evmtypes.BankKeeper, ek EVMKeeper) EthAccountVerificationDecorator {
|
|
||||||
return EthAccountVerificationDecorator{
|
|
||||||
ak: ak,
|
|
||||||
bankKeeper: bankKeeper,
|
|
||||||
evmKeeper: ek,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnteHandle validates checks that the sender balance is greater than the total transaction cost.
|
|
||||||
// The account will be set to store if it doesn't exis, i.e cannot be found on store.
|
|
||||||
// This AnteHandler decorator will fail if:
|
|
||||||
// - any of the msgs is not a MsgEthereumTx
|
|
||||||
// - from address is empty
|
|
||||||
// - account balance is lower than the transaction cost
|
|
||||||
func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
|
||||||
if !ctx.IsCheckTx() {
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, msg := range tx.GetMsgs() {
|
|
||||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
|
||||||
if !ok {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
|
||||||
if err != nil {
|
|
||||||
return ctx, sdkerrors.Wrapf(err, "failed to unpack tx data any for tx %d", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sender address should be in the tx cache from the previous AnteHandle call
|
|
||||||
from := msgEthTx.GetFrom()
|
|
||||||
if from.Empty() {
|
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "from address cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// check whether the sender address is EOA
|
|
||||||
fromAddr := common.BytesToAddress(from)
|
|
||||||
acct := avd.evmKeeper.GetAccount(ctx, fromAddr)
|
|
||||||
|
|
||||||
if acct == nil {
|
|
||||||
acc := avd.ak.NewAccountWithAddress(ctx, from)
|
|
||||||
avd.ak.SetAccount(ctx, acc)
|
|
||||||
acct = statedb.NewEmptyAccount()
|
|
||||||
} else if acct.IsContract() {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType,
|
|
||||||
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := evmkeeper.CheckSenderBalance(sdk.NewIntFromBigInt(acct.Balance), txData); err != nil {
|
|
||||||
return ctx, sdkerrors.Wrap(err, "failed to check sender balance")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EthGasConsumeDecorator validates enough intrinsic gas for the transaction and
|
|
||||||
// gas consumption.
|
|
||||||
type EthGasConsumeDecorator struct {
|
|
||||||
evmKeeper EVMKeeper
|
|
||||||
maxGasWanted uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEthGasConsumeDecorator creates a new EthGasConsumeDecorator
|
|
||||||
func NewEthGasConsumeDecorator(
|
|
||||||
evmKeeper EVMKeeper,
|
|
||||||
maxGasWanted uint64,
|
|
||||||
) EthGasConsumeDecorator {
|
|
||||||
return EthGasConsumeDecorator{
|
|
||||||
evmKeeper,
|
|
||||||
maxGasWanted,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnteHandle validates that the Ethereum tx message has enough to cover intrinsic gas
|
|
||||||
// (during CheckTx only) and that the sender has enough balance to pay for the gas cost.
|
|
||||||
//
|
|
||||||
// Intrinsic gas for a transaction is the amount of gas that the transaction uses before the
|
|
||||||
// transaction is executed. The gas is a constant value plus any cost inccured by additional bytes
|
|
||||||
// of data supplied with the transaction.
|
|
||||||
//
|
|
||||||
// This AnteHandler decorator will fail if:
|
|
||||||
// - the message is not a MsgEthereumTx
|
|
||||||
// - sender account cannot be found
|
|
||||||
// - transaction's gas limit is lower than the intrinsic gas
|
|
||||||
// - user doesn't have enough balance to deduct the transaction fees (gas_limit * gas_price)
|
|
||||||
// - transaction or block gas meter runs out of gas
|
|
||||||
// - sets the gas meter limit
|
|
||||||
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
|
||||||
params := egcd.evmKeeper.GetParams(ctx)
|
|
||||||
|
|
||||||
ethCfg := params.ChainConfig.EthereumConfig(egcd.evmKeeper.ChainID())
|
|
||||||
|
|
||||||
blockHeight := big.NewInt(ctx.BlockHeight())
|
|
||||||
homestead := ethCfg.IsHomestead(blockHeight)
|
|
||||||
istanbul := ethCfg.IsIstanbul(blockHeight)
|
|
||||||
london := ethCfg.IsLondon(blockHeight)
|
|
||||||
evmDenom := params.EvmDenom
|
|
||||||
gasWanted := uint64(0)
|
|
||||||
var events sdk.Events
|
|
||||||
|
|
||||||
for _, msg := range tx.GetMsgs() {
|
|
||||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
|
||||||
if !ok {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
|
||||||
if err != nil {
|
|
||||||
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.IsCheckTx() {
|
|
||||||
// We can't trust the tx gas limit, because we'll refund the unused gas.
|
|
||||||
if txData.GetGas() > egcd.maxGasWanted {
|
|
||||||
gasWanted += egcd.maxGasWanted
|
|
||||||
} else {
|
|
||||||
gasWanted += txData.GetGas()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gasWanted += txData.GetGas()
|
|
||||||
}
|
|
||||||
|
|
||||||
fees, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
|
|
||||||
ctx,
|
|
||||||
*msgEthTx,
|
|
||||||
txData,
|
|
||||||
evmDenom,
|
|
||||||
homestead,
|
|
||||||
istanbul,
|
|
||||||
london,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return ctx, sdkerrors.Wrapf(err, "failed to deduct transaction costs from user balance")
|
|
||||||
}
|
|
||||||
|
|
||||||
events = append(events, sdk.NewEvent(sdk.EventTypeTx, sdk.NewAttribute(sdk.AttributeKeyFee, fees.String())))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: change to typed events
|
|
||||||
ctx.EventManager().EmitEvents(events)
|
|
||||||
|
|
||||||
// TODO: deprecate after https://github.com/cosmos/cosmos-sdk/issues/9514 is fixed on SDK
|
|
||||||
blockGasLimit := ethermint.BlockGasLimit(ctx)
|
|
||||||
|
|
||||||
// NOTE: safety check
|
|
||||||
if blockGasLimit > 0 {
|
|
||||||
// generate a copy of the gas pool (i.e block gas meter) to see if we've run out of gas for this block
|
|
||||||
// if current gas consumed is greater than the limit, this funcion panics and the error is recovered on the Baseapp
|
|
||||||
gasPool := sdk.NewGasMeter(blockGasLimit)
|
|
||||||
gasPool.ConsumeGas(ctx.GasMeter().GasConsumedToLimit(), "gas pool check")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set ctx.GasMeter with a limit of GasWanted (gasLimit)
|
|
||||||
gasConsumed := ctx.GasMeter().GasConsumed()
|
|
||||||
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
|
|
||||||
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")
|
|
||||||
|
|
||||||
// we know that we have enough gas on the pool to cover the intrinsic gas
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CanTransferDecorator checks if the sender is allowed to transfer funds according to the EVM block
|
|
||||||
// context rules.
|
|
||||||
type CanTransferDecorator struct {
|
|
||||||
evmKeeper EVMKeeper
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCanTransferDecorator creates a new CanTransferDecorator instance.
|
|
||||||
func NewCanTransferDecorator(evmKeeper EVMKeeper) CanTransferDecorator {
|
|
||||||
return CanTransferDecorator{
|
|
||||||
evmKeeper: evmKeeper,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnteHandle creates an EVM from the message and calls the BlockContext CanTransfer function to
|
|
||||||
// see if the address can execute the transaction.
|
|
||||||
func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
|
||||||
params := ctd.evmKeeper.GetParams(ctx)
|
|
||||||
ethCfg := params.ChainConfig.EthereumConfig(ctd.evmKeeper.ChainID())
|
|
||||||
signer := ethtypes.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight()))
|
|
||||||
|
|
||||||
for _, msg := range tx.GetMsgs() {
|
|
||||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
|
||||||
if !ok {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
baseFee := ctd.evmKeeper.BaseFee(ctx, ethCfg)
|
|
||||||
|
|
||||||
coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
|
|
||||||
if err != nil {
|
|
||||||
return ctx, sdkerrors.Wrapf(
|
|
||||||
err,
|
|
||||||
"failed to create an ethereum core.Message from signer %T", signer,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
|
|
||||||
cfg := &evmtypes.EVMConfig{
|
|
||||||
ChainConfig: ethCfg,
|
|
||||||
Params: params,
|
|
||||||
CoinBase: common.Address{},
|
|
||||||
BaseFee: baseFee,
|
|
||||||
}
|
|
||||||
stateDB := statedb.New(ctx, ctd.evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())))
|
|
||||||
evm := ctd.evmKeeper.NewEVM(ctx, coreMsg, cfg, evmtypes.NewNoOpTracer(), stateDB)
|
|
||||||
|
|
||||||
// check that caller has enough balance to cover asset transfer for **topmost** call
|
|
||||||
// NOTE: here the gas consumed is from the context with the infinite gas meter
|
|
||||||
if coreMsg.Value().Sign() > 0 && !evm.Context.CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
|
|
||||||
return ctx, sdkerrors.Wrapf(
|
|
||||||
sdkerrors.ErrInsufficientFunds,
|
|
||||||
"failed to transfer %s from address %s using the EVM block context transfer function",
|
|
||||||
coreMsg.Value(),
|
|
||||||
coreMsg.From(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
|
|
||||||
if baseFee == nil {
|
|
||||||
return ctx, sdkerrors.Wrap(
|
|
||||||
evmtypes.ErrInvalidBaseFee,
|
|
||||||
"base fee is supported but evm block context value is nil",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
|
|
||||||
return ctx, sdkerrors.Wrapf(
|
|
||||||
sdkerrors.ErrInsufficientFee,
|
|
||||||
"max fee per gas less than block base fee (%s < %s)",
|
|
||||||
coreMsg.GasFeeCap(), baseFee,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EthIncrementSenderSequenceDecorator increments the sequence of the signers.
|
|
||||||
type EthIncrementSenderSequenceDecorator struct {
|
|
||||||
ak evmtypes.AccountKeeper
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEthIncrementSenderSequenceDecorator creates a new EthIncrementSenderSequenceDecorator.
|
|
||||||
func NewEthIncrementSenderSequenceDecorator(ak evmtypes.AccountKeeper) EthIncrementSenderSequenceDecorator {
|
|
||||||
return EthIncrementSenderSequenceDecorator{
|
|
||||||
ak: ak,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnteHandle handles incrementing the sequence of the signer (i.e sender). If the transaction is a
|
|
||||||
// contract creation, the nonce will be incremented during the transaction execution and not within
|
|
||||||
// this AnteHandler decorator.
|
|
||||||
func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
|
||||||
for _, msg := range tx.GetMsgs() {
|
|
||||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
|
||||||
if !ok {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
|
||||||
if err != nil {
|
|
||||||
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
|
|
||||||
}
|
|
||||||
|
|
||||||
// increase sequence of sender
|
|
||||||
acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom())
|
|
||||||
if acc == nil {
|
|
||||||
return ctx, sdkerrors.Wrapf(
|
|
||||||
sdkerrors.ErrUnknownAddress,
|
|
||||||
"account %s is nil", common.BytesToAddress(msgEthTx.GetFrom().Bytes()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
nonce := acc.GetSequence()
|
|
||||||
|
|
||||||
// we merged the nonce verification to nonce increment, so when tx includes multiple messages
|
|
||||||
// with same sender, they'll be accepted.
|
|
||||||
if txData.GetNonce() != nonce {
|
|
||||||
return ctx, sdkerrors.Wrapf(
|
|
||||||
sdkerrors.ErrInvalidSequence,
|
|
||||||
"invalid nonce; got %d, expected %d", txData.GetNonce(), nonce,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := acc.SetSequence(nonce + 1); err != nil {
|
|
||||||
return ctx, sdkerrors.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
|
|
||||||
}
|
|
||||||
|
|
||||||
issd.ak.SetAccount(ctx, acc)
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EthValidateBasicDecorator is adapted from ValidateBasicDecorator from cosmos-sdk, it ignores ErrNoSignatures
|
|
||||||
type EthValidateBasicDecorator struct {
|
|
||||||
evmKeeper EVMKeeper
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewEthValidateBasicDecorator creates a new EthValidateBasicDecorator
|
|
||||||
func NewEthValidateBasicDecorator(ek EVMKeeper) EthValidateBasicDecorator {
|
|
||||||
return EthValidateBasicDecorator{
|
|
||||||
evmKeeper: ek,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnteHandle handles basic validation of tx
|
|
||||||
func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
|
||||||
// no need to validate basic on recheck tx, call next antehandler
|
|
||||||
if ctx.IsReCheckTx() {
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := tx.ValidateBasic()
|
|
||||||
// ErrNoSignatures is fine with eth tx
|
|
||||||
if err != nil && !errors.Is(err, sdkerrors.ErrNoSignatures) {
|
|
||||||
return ctx, sdkerrors.Wrap(err, "tx basic validation failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// For eth type cosmos tx, some fields should be veified as zero values,
|
|
||||||
// since we will only verify the signature against the hash of the MsgEthereumTx.Data
|
|
||||||
if wrapperTx, ok := tx.(protoTxProvider); ok {
|
|
||||||
protoTx := wrapperTx.GetProtoTx()
|
|
||||||
body := protoTx.Body
|
|
||||||
if body.Memo != "" || body.TimeoutHeight != uint64(0) || len(body.NonCriticalExtensionOptions) > 0 {
|
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
|
||||||
"for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(body.ExtensionOptions) != 1 {
|
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1")
|
|
||||||
}
|
|
||||||
|
|
||||||
txFee := sdk.Coins{}
|
|
||||||
txGasLimit := uint64(0)
|
|
||||||
|
|
||||||
for _, msg := range protoTx.GetMsgs() {
|
|
||||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
|
||||||
if !ok {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
|
||||||
}
|
|
||||||
txGasLimit += msgEthTx.GetGas()
|
|
||||||
|
|
||||||
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
|
||||||
if err != nil {
|
|
||||||
return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data")
|
|
||||||
}
|
|
||||||
|
|
||||||
params := vbd.evmKeeper.GetParams(ctx)
|
|
||||||
chainID := vbd.evmKeeper.ChainID()
|
|
||||||
ethCfg := params.ChainConfig.EthereumConfig(chainID)
|
|
||||||
baseFee := vbd.evmKeeper.BaseFee(ctx, ethCfg)
|
|
||||||
if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
|
|
||||||
return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
txFee = txFee.Add(sdk.NewCoin(params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee())))
|
|
||||||
}
|
|
||||||
|
|
||||||
authInfo := protoTx.AuthInfo
|
|
||||||
if len(authInfo.SignerInfos) > 0 {
|
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if authInfo.Fee.Payer != "" || authInfo.Fee.Granter != "" {
|
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo Fee payer and granter should be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !authInfo.Fee.Amount.IsEqual(txFee) {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee Amount (%s != %s)", authInfo.Fee.Amount, txFee)
|
|
||||||
}
|
|
||||||
|
|
||||||
if authInfo.Fee.GasLimit != txGasLimit {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee GasLimit (%d != %d)", authInfo.Fee.GasLimit, txGasLimit)
|
|
||||||
}
|
|
||||||
|
|
||||||
sigs := protoTx.Signatures
|
|
||||||
if len(sigs) > 0 {
|
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx Signatures should be empty")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EthSetupContextDecorator is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption
|
|
||||||
// by setting the gas meter to infinite
|
|
||||||
type EthSetupContextDecorator struct {
|
|
||||||
evmKeeper EVMKeeper
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEthSetUpContextDecorator(evmKeeper EVMKeeper) EthSetupContextDecorator {
|
|
||||||
return EthSetupContextDecorator{
|
|
||||||
evmKeeper: evmKeeper,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (esc EthSetupContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
|
||||||
// all transactions must implement GasTx
|
|
||||||
_, ok := tx.(authante.GasTx)
|
|
||||||
if !ok {
|
|
||||||
return newCtx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
|
|
||||||
}
|
|
||||||
|
|
||||||
newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
|
||||||
// Reset transient gas used to prepare the execution of current cosmos tx.
|
|
||||||
// Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs.
|
|
||||||
esc.evmKeeper.ResetTransientGasUsed(ctx)
|
|
||||||
return next(newCtx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EthMempoolFeeDecorator will check if the transaction's effective fee is at least as large
|
|
||||||
// as the local validator's minimum gasFee (defined in validator config).
|
|
||||||
// If fee is too low, decorator returns error and tx is rejected from mempool.
|
|
||||||
// Note this only applies when ctx.CheckTx = true
|
|
||||||
// If fee is high enough or not CheckTx, then call next AnteHandler
|
|
||||||
// CONTRACT: Tx must implement FeeTx to use MempoolFeeDecorator
|
|
||||||
type EthMempoolFeeDecorator struct {
|
|
||||||
evmKeeper EVMKeeper
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEthMempoolFeeDecorator(ek EVMKeeper) EthMempoolFeeDecorator {
|
|
||||||
return EthMempoolFeeDecorator{
|
|
||||||
evmKeeper: ek,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AnteHandle ensures that the provided fees meet a minimum threshold for the validator,
|
|
||||||
// if this is a CheckTx. This is only for local mempool purposes, and thus
|
|
||||||
// is only ran on check tx.
|
|
||||||
// It only do the check if london hardfork not enabled or feemarket not enabled, because in that case feemarket will take over the task.
|
|
||||||
func (mfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
|
||||||
if ctx.IsCheckTx() && !simulate {
|
|
||||||
params := mfd.evmKeeper.GetParams(ctx)
|
|
||||||
ethCfg := params.ChainConfig.EthereumConfig(mfd.evmKeeper.ChainID())
|
|
||||||
baseFee := mfd.evmKeeper.BaseFee(ctx, ethCfg)
|
|
||||||
if baseFee == nil {
|
|
||||||
for _, msg := range tx.GetMsgs() {
|
|
||||||
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
|
||||||
if !ok {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
evmDenom := params.EvmDenom
|
|
||||||
feeAmt := ethMsg.GetFee()
|
|
||||||
glDec := sdk.NewDec(int64(ethMsg.GetGas()))
|
|
||||||
requiredFee := ctx.MinGasPrices().AmountOf(evmDenom).Mul(glDec)
|
|
||||||
if sdk.NewDecFromBigInt(feeAmt).LT(requiredFee) {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeAmt, requiredFee)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
package ante
|
|
||||||
|
|
||||||
import (
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
|
||||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
|
||||||
|
|
||||||
ibcante "github.com/cosmos/ibc-go/v3/modules/core/ante"
|
|
||||||
ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper"
|
|
||||||
|
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC
|
|
||||||
// channel keeper, EVM Keeper and Fee Market Keeper.
|
|
||||||
type HandlerOptions struct {
|
|
||||||
AccountKeeper evmtypes.AccountKeeper
|
|
||||||
BankKeeper evmtypes.BankKeeper
|
|
||||||
IBCKeeper *ibckeeper.Keeper
|
|
||||||
FeeMarketKeeper evmtypes.FeeMarketKeeper
|
|
||||||
EvmKeeper EVMKeeper
|
|
||||||
FeegrantKeeper ante.FeegrantKeeper
|
|
||||||
SignModeHandler authsigning.SignModeHandler
|
|
||||||
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params) error
|
|
||||||
MaxTxGasWanted uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (options HandlerOptions) Validate() error {
|
|
||||||
if options.AccountKeeper == nil {
|
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for AnteHandler")
|
|
||||||
}
|
|
||||||
if options.BankKeeper == nil {
|
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for AnteHandler")
|
|
||||||
}
|
|
||||||
if options.SignModeHandler == nil {
|
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
|
|
||||||
}
|
|
||||||
if options.FeeMarketKeeper == nil {
|
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for AnteHandler")
|
|
||||||
}
|
|
||||||
if options.EvmKeeper == nil {
|
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for AnteHandler")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
|
||||||
return sdk.ChainAnteDecorators(
|
|
||||||
NewEthSetUpContextDecorator(options.EvmKeeper), // outermost AnteDecorator. SetUpContext must be called first
|
|
||||||
NewEthMempoolFeeDecorator(options.EvmKeeper), // Check eth effective gas price against minimal-gas-prices
|
|
||||||
NewEthValidateBasicDecorator(options.EvmKeeper),
|
|
||||||
NewEthSigVerificationDecorator(options.EvmKeeper),
|
|
||||||
NewEthAccountVerificationDecorator(options.AccountKeeper, options.BankKeeper, options.EvmKeeper),
|
|
||||||
NewEthGasConsumeDecorator(options.EvmKeeper, options.MaxTxGasWanted),
|
|
||||||
NewCanTransferDecorator(options.EvmKeeper),
|
|
||||||
NewEthIncrementSenderSequenceDecorator(options.AccountKeeper), // innermost AnteDecorator.
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
|
|
||||||
return sdk.ChainAnteDecorators(
|
|
||||||
RejectMessagesDecorator{}, // reject MsgEthereumTxs
|
|
||||||
ante.NewSetUpContextDecorator(),
|
|
||||||
ante.NewRejectExtensionOptionsDecorator(),
|
|
||||||
ante.NewMempoolFeeDecorator(),
|
|
||||||
ante.NewValidateBasicDecorator(),
|
|
||||||
ante.NewTxTimeoutHeightDecorator(),
|
|
||||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
|
||||||
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
|
||||||
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
|
|
||||||
// SetPubKeyDecorator must be called before all signature verification decorators
|
|
||||||
ante.NewSetPubKeyDecorator(options.AccountKeeper),
|
|
||||||
ante.NewValidateSigCountDecorator(options.AccountKeeper),
|
|
||||||
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
|
|
||||||
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
|
|
||||||
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
|
|
||||||
ibcante.NewAnteDecorator(options.IBCKeeper),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
|
|
||||||
return sdk.ChainAnteDecorators(
|
|
||||||
RejectMessagesDecorator{}, // reject MsgEthereumTxs
|
|
||||||
ante.NewSetUpContextDecorator(),
|
|
||||||
// NOTE: extensions option decorator removed
|
|
||||||
// ante.NewRejectExtensionOptionsDecorator(),
|
|
||||||
ante.NewMempoolFeeDecorator(),
|
|
||||||
ante.NewValidateBasicDecorator(),
|
|
||||||
ante.NewTxTimeoutHeightDecorator(),
|
|
||||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
|
||||||
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
|
||||||
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
|
|
||||||
// SetPubKeyDecorator must be called before all signature verification decorators
|
|
||||||
ante.NewSetPubKeyDecorator(options.AccountKeeper),
|
|
||||||
ante.NewValidateSigCountDecorator(options.AccountKeeper),
|
|
||||||
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
|
|
||||||
// Note: signature verification uses EIP instead of the cosmos signature validator
|
|
||||||
NewEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
|
|
||||||
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
|
|
||||||
ibcante.NewAnteDecorator(options.IBCKeeper),
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package ante
|
|
||||||
|
|
||||||
import (
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RejectMessagesDecorator prevents invalid msg types from being executed
|
|
||||||
type RejectMessagesDecorator struct{}
|
|
||||||
|
|
||||||
// AnteHandle rejects messages that requires ethereum-specific authentication.
|
|
||||||
// For example `MsgEthereumTx` requires fee to be deducted in the antehandler in
|
|
||||||
// order to perform the refund.
|
|
||||||
func (rmd RejectMessagesDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
|
||||||
for _, msg := range tx.GetMsgs() {
|
|
||||||
if _, ok := msg.(*evmtypes.MsgEthereumTx); ok {
|
|
||||||
return ctx, sdkerrors.Wrapf(
|
|
||||||
sdkerrors.ErrInvalidType,
|
|
||||||
"MsgEthereumTx needs to be contained within a tx with 'ExtensionOptionsEthereumTx' option",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
242
app/app.go
242
app/app.go
@ -11,27 +11,32 @@ import (
|
|||||||
"github.com/rakyll/statik/fs"
|
"github.com/rakyll/statik/fs"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
"github.com/tharsis/ethermint/app/middleware"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
tmos "github.com/tendermint/tendermint/libs/os"
|
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
||||||
"github.com/cosmos/cosmos-sdk/client/rpc"
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/db"
|
||||||
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
"github.com/cosmos/cosmos-sdk/server/api"
|
"github.com/cosmos/cosmos-sdk/server/api"
|
||||||
"github.com/cosmos/cosmos-sdk/server/config"
|
"github.com/cosmos/cosmos-sdk/server/config"
|
||||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
|
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||||
|
|
||||||
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
||||||
|
"github.com/cosmos/cosmos-sdk/store/streaming"
|
||||||
|
storetypes "github.com/cosmos/cosmos-sdk/store/v2alpha1"
|
||||||
|
"github.com/cosmos/cosmos-sdk/store/v2alpha1/multi"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/types/module"
|
"github.com/cosmos/cosmos-sdk/types/module"
|
||||||
"github.com/cosmos/cosmos-sdk/version"
|
"github.com/cosmos/cosmos-sdk/version"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||||
|
authmiddleware "github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
||||||
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
||||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
@ -62,8 +67,10 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||||
|
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
|
||||||
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
|
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
|
||||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||||
|
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
||||||
"github.com/cosmos/cosmos-sdk/x/mint"
|
"github.com/cosmos/cosmos-sdk/x/mint"
|
||||||
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
|
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
|
||||||
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||||
@ -83,6 +90,10 @@ import (
|
|||||||
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
|
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
|
||||||
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
||||||
|
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
|
tmos "github.com/tendermint/tendermint/libs/os"
|
||||||
|
|
||||||
"github.com/cosmos/ibc-go/v3/modules/apps/transfer"
|
"github.com/cosmos/ibc-go/v3/modules/apps/transfer"
|
||||||
ibctransferkeeper "github.com/cosmos/ibc-go/v3/modules/apps/transfer/keeper"
|
ibctransferkeeper "github.com/cosmos/ibc-go/v3/modules/apps/transfer/keeper"
|
||||||
ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types"
|
ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types"
|
||||||
@ -96,13 +107,12 @@ import (
|
|||||||
// unnamed import of statik for swagger UI support
|
// unnamed import of statik for swagger UI support
|
||||||
_ "github.com/tharsis/ethermint/client/docs/statik"
|
_ "github.com/tharsis/ethermint/client/docs/statik"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/app/ante"
|
|
||||||
srvflags "github.com/tharsis/ethermint/server/flags"
|
srvflags "github.com/tharsis/ethermint/server/flags"
|
||||||
ethermint "github.com/tharsis/ethermint/types"
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
"github.com/tharsis/ethermint/x/evm"
|
"github.com/tharsis/ethermint/x/evm"
|
||||||
evmrest "github.com/tharsis/ethermint/x/evm/client/rest"
|
|
||||||
|
// evmrest "github.com/tharsis/ethermint/x/evm/client/rest"
|
||||||
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
|
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
|
||||||
"github.com/tharsis/ethermint/x/feemarket"
|
"github.com/tharsis/ethermint/x/feemarket"
|
||||||
feemarketkeeper "github.com/tharsis/ethermint/x/feemarket/keeper"
|
feemarketkeeper "github.com/tharsis/ethermint/x/feemarket/keeper"
|
||||||
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
||||||
@ -149,8 +159,8 @@ var (
|
|||||||
mint.AppModuleBasic{},
|
mint.AppModuleBasic{},
|
||||||
distr.AppModuleBasic{},
|
distr.AppModuleBasic{},
|
||||||
gov.NewAppModuleBasic(
|
gov.NewAppModuleBasic(
|
||||||
paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler,
|
[]govclient.ProposalHandler{paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.LegacyProposalHandler, upgradeclient.LegacyCancelProposalHandler,
|
||||||
ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler,
|
ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler},
|
||||||
),
|
),
|
||||||
params.AppModuleBasic{},
|
params.AppModuleBasic{},
|
||||||
crisis.AppModuleBasic{},
|
crisis.AppModuleBasic{},
|
||||||
@ -173,15 +183,14 @@ var (
|
|||||||
|
|
||||||
// module account permissions
|
// module account permissions
|
||||||
maccPerms = map[string][]string{
|
maccPerms = map[string][]string{
|
||||||
authtypes.FeeCollectorName: nil,
|
authtypes.FeeCollectorName: nil,
|
||||||
distrtypes.ModuleName: nil,
|
distrtypes.ModuleName: nil,
|
||||||
minttypes.ModuleName: {authtypes.Minter},
|
minttypes.ModuleName: {authtypes.Minter},
|
||||||
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
|
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
|
||||||
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
|
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
|
||||||
govtypes.ModuleName: {authtypes.Burner},
|
govtypes.ModuleName: {authtypes.Burner},
|
||||||
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
|
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
|
||||||
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
|
evmtypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for secure addition and subtraction of balance using module account
|
||||||
|
|
||||||
auctiontypes.ModuleName: nil,
|
auctiontypes.ModuleName: nil,
|
||||||
auctiontypes.AuctionBurnModuleAccountName: nil,
|
auctiontypes.AuctionBurnModuleAccountName: nil,
|
||||||
nameservicetypes.ModuleName: nil,
|
nameservicetypes.ModuleName: nil,
|
||||||
@ -210,13 +219,14 @@ type EthermintApp struct {
|
|||||||
cdc *codec.LegacyAmino
|
cdc *codec.LegacyAmino
|
||||||
appCodec codec.Codec
|
appCodec codec.Codec
|
||||||
interfaceRegistry types.InterfaceRegistry
|
interfaceRegistry types.InterfaceRegistry
|
||||||
|
MsgSvcRouter *authmiddleware.MsgServiceRouter
|
||||||
invCheckPeriod uint
|
LegacyRouter sdk.Router
|
||||||
|
invCheckPeriod uint
|
||||||
|
|
||||||
// keys to access the substores
|
// keys to access the substores
|
||||||
keys map[string]*sdk.KVStoreKey
|
keys map[string]*storetypes.KVStoreKey
|
||||||
tkeys map[string]*sdk.TransientStoreKey
|
tkeys map[string]*storetypes.TransientStoreKey
|
||||||
memKeys map[string]*sdk.MemoryStoreKey
|
memKeys map[string]*storetypes.MemoryStoreKey
|
||||||
|
|
||||||
// keepers
|
// keepers
|
||||||
AccountKeeper authkeeper.AccountKeeper
|
AccountKeeper authkeeper.AccountKeeper
|
||||||
@ -263,7 +273,7 @@ type EthermintApp struct {
|
|||||||
// NewEthermintApp returns a reference to a new initialized Ethermint application.
|
// NewEthermintApp returns a reference to a new initialized Ethermint application.
|
||||||
func NewEthermintApp(
|
func NewEthermintApp(
|
||||||
logger log.Logger,
|
logger log.Logger,
|
||||||
db dbm.DB,
|
db db.DBConnection,
|
||||||
traceStore io.Writer,
|
traceStore io.Writer,
|
||||||
loadLatest bool,
|
loadLatest bool,
|
||||||
skipUpgradeHeights map[int64]bool,
|
skipUpgradeHeights map[int64]bool,
|
||||||
@ -271,31 +281,19 @@ func NewEthermintApp(
|
|||||||
invCheckPeriod uint,
|
invCheckPeriod uint,
|
||||||
encodingConfig simappparams.EncodingConfig,
|
encodingConfig simappparams.EncodingConfig,
|
||||||
appOpts servertypes.AppOptions,
|
appOpts servertypes.AppOptions,
|
||||||
baseAppOptions ...func(*baseapp.BaseApp),
|
baseAppOptions ...baseapp.AppOption,
|
||||||
) *EthermintApp {
|
) *EthermintApp {
|
||||||
appCodec := encodingConfig.Marshaler
|
appCodec := encodingConfig.Codec
|
||||||
cdc := encodingConfig.Amino
|
cdc := encodingConfig.Amino
|
||||||
interfaceRegistry := encodingConfig.InterfaceRegistry
|
interfaceRegistry := encodingConfig.InterfaceRegistry
|
||||||
|
|
||||||
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
|
|
||||||
bApp := baseapp.NewBaseApp(
|
|
||||||
appName,
|
|
||||||
logger,
|
|
||||||
db,
|
|
||||||
encodingConfig.TxConfig.TxDecoder(),
|
|
||||||
baseAppOptions...,
|
|
||||||
)
|
|
||||||
bApp.SetCommitMultiStoreTracer(traceStore)
|
|
||||||
bApp.SetVersion(version.Version)
|
|
||||||
bApp.SetInterfaceRegistry(interfaceRegistry)
|
|
||||||
|
|
||||||
keys := sdk.NewKVStoreKeys(
|
keys := sdk.NewKVStoreKeys(
|
||||||
// SDK keys
|
// SDK keys
|
||||||
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
|
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
|
||||||
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
|
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
|
||||||
govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey,
|
govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey,
|
||||||
evidencetypes.StoreKey, capabilitytypes.StoreKey,
|
evidencetypes.StoreKey, capabilitytypes.StoreKey,
|
||||||
feegrant.StoreKey, authzkeeper.StoreKey,
|
authzkeeper.StoreKey,
|
||||||
// ibc keys
|
// ibc keys
|
||||||
ibchost.StoreKey, ibctransfertypes.StoreKey,
|
ibchost.StoreKey, ibctransfertypes.StoreKey,
|
||||||
// ethermint keys
|
// ethermint keys
|
||||||
@ -310,12 +308,67 @@ func NewEthermintApp(
|
|||||||
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey)
|
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey)
|
||||||
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
||||||
|
|
||||||
|
// initialize stores
|
||||||
|
setNamespaces := func(config *multi.StoreParams, ver uint64) error {
|
||||||
|
for _, key := range keys {
|
||||||
|
typ, err := storetypes.StoreKeyToType(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = config.RegisterSubstore(key, typ); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, key := range memKeys {
|
||||||
|
typ, err := storetypes.StoreKeyToType(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = config.RegisterSubstore(key, typ); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, key := range tkeys {
|
||||||
|
typ, err := storetypes.StoreKeyToType(key)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = config.RegisterSubstore(key, typ); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
baseAppOptions = append(baseAppOptions, baseapp.StoreOption(setNamespaces))
|
||||||
|
|
||||||
|
// NOTE we use custom transaction decoder that supports the sdk.Tx interface instead of sdk.StdTx
|
||||||
|
bApp := baseapp.NewBaseApp(
|
||||||
|
appName,
|
||||||
|
logger,
|
||||||
|
db,
|
||||||
|
baseAppOptions...,
|
||||||
|
)
|
||||||
|
bApp.SetCommitMultiStoreTracer(traceStore)
|
||||||
|
bApp.SetVersion(version.Version)
|
||||||
|
|
||||||
|
evmtypes.RegisterInterfaces(interfaceRegistry)
|
||||||
|
bApp.SetInterfaceRegistry(interfaceRegistry)
|
||||||
|
|
||||||
|
// configure state listening capabilities using AppOptions
|
||||||
|
// we are doing nothing with the returned streamingServices and waitGroup in this case
|
||||||
|
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, keys); err != nil {
|
||||||
|
tmos.Exit(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
app := &EthermintApp{
|
app := &EthermintApp{
|
||||||
BaseApp: bApp,
|
BaseApp: bApp,
|
||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
appCodec: appCodec,
|
appCodec: appCodec,
|
||||||
interfaceRegistry: interfaceRegistry,
|
interfaceRegistry: interfaceRegistry,
|
||||||
invCheckPeriod: invCheckPeriod,
|
invCheckPeriod: invCheckPeriod,
|
||||||
|
LegacyRouter: authmiddleware.NewLegacyRouter(),
|
||||||
|
MsgSvcRouter: authmiddleware.NewMsgServiceRouter(interfaceRegistry),
|
||||||
keys: keys,
|
keys: keys,
|
||||||
tkeys: tkeys,
|
tkeys: tkeys,
|
||||||
memKeys: memKeys,
|
memKeys: memKeys,
|
||||||
@ -324,7 +377,7 @@ func NewEthermintApp(
|
|||||||
// init params keeper and subspaces
|
// init params keeper and subspaces
|
||||||
app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
|
app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
|
||||||
// set the BaseApp's parameter store
|
// set the BaseApp's parameter store
|
||||||
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramskeeper.ConsensusParamsKeyTable()))
|
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramstypes.ConsensusParamsKeyTable()))
|
||||||
|
|
||||||
// add capability keeper and ScopeToModule for ibc module
|
// add capability keeper and ScopeToModule for ibc module
|
||||||
app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
|
app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
|
||||||
@ -338,7 +391,7 @@ func NewEthermintApp(
|
|||||||
|
|
||||||
// use custom Ethermint account for contracts
|
// use custom Ethermint account for contracts
|
||||||
app.AccountKeeper = authkeeper.NewAccountKeeper(
|
app.AccountKeeper = authkeeper.NewAccountKeeper(
|
||||||
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms,
|
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms, sdk.Bech32MainPrefix,
|
||||||
)
|
)
|
||||||
app.BankKeeper = bankkeeper.NewBaseKeeper(
|
app.BankKeeper = bankkeeper.NewBaseKeeper(
|
||||||
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(),
|
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(),
|
||||||
@ -352,7 +405,7 @@ func NewEthermintApp(
|
|||||||
)
|
)
|
||||||
app.DistrKeeper = distrkeeper.NewKeeper(
|
app.DistrKeeper = distrkeeper.NewKeeper(
|
||||||
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
||||||
&stakingKeeper, authtypes.FeeCollectorName, app.ModuleAccountAddrs(),
|
&stakingKeeper, authtypes.FeeCollectorName,
|
||||||
)
|
)
|
||||||
app.SlashingKeeper = slashingkeeper.NewKeeper(
|
app.SlashingKeeper = slashingkeeper.NewKeeper(
|
||||||
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
|
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
|
||||||
@ -361,7 +414,7 @@ func NewEthermintApp(
|
|||||||
app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName,
|
app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName,
|
||||||
)
|
)
|
||||||
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
|
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
|
||||||
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp)
|
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String())
|
||||||
|
|
||||||
// register the staking hooks
|
// register the staking hooks
|
||||||
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
|
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
|
||||||
@ -369,7 +422,7 @@ func NewEthermintApp(
|
|||||||
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
|
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
|
||||||
)
|
)
|
||||||
|
|
||||||
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.BaseApp.MsgServiceRouter())
|
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.MsgSvcRouter, app.AccountKeeper)
|
||||||
|
|
||||||
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
|
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
|
||||||
|
|
||||||
@ -411,16 +464,22 @@ func NewEthermintApp(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// register the proposal types
|
// register the proposal types
|
||||||
govRouter := govtypes.NewRouter()
|
govRouter := govv1beta1.NewRouter()
|
||||||
govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler).
|
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
|
||||||
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
|
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
|
||||||
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
|
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
|
||||||
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
|
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
|
||||||
AddRoute(ibchost.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))
|
AddRoute(ibchost.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))
|
||||||
|
|
||||||
|
govConfig := govtypes.DefaultConfig()
|
||||||
|
/*
|
||||||
|
Example of setting gov params:
|
||||||
|
govConfig.MaxMetadataLen = 10000
|
||||||
|
*/
|
||||||
|
|
||||||
govKeeper := govkeeper.NewKeeper(
|
govKeeper := govkeeper.NewKeeper(
|
||||||
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
||||||
&stakingKeeper, govRouter,
|
&stakingKeeper, govRouter, app.MsgSvcRouter, govConfig,
|
||||||
)
|
)
|
||||||
|
|
||||||
app.GovKeeper = *govKeeper.SetHooks(
|
app.GovKeeper = *govKeeper.SetHooks(
|
||||||
@ -438,7 +497,7 @@ func NewEthermintApp(
|
|||||||
transferModule := transfer.NewAppModule(app.TransferKeeper)
|
transferModule := transfer.NewAppModule(app.TransferKeeper)
|
||||||
transferIBCModule := transfer.NewIBCModule(app.TransferKeeper)
|
transferIBCModule := transfer.NewIBCModule(app.TransferKeeper)
|
||||||
|
|
||||||
// Create static IBC router, add transfer route, then set and seal it
|
//Create static IBC router, add transfer route, then set and seal it
|
||||||
ibcRouter := porttypes.NewRouter()
|
ibcRouter := porttypes.NewRouter()
|
||||||
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferIBCModule)
|
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferIBCModule)
|
||||||
app.IBCKeeper.SetRouter(ibcRouter)
|
app.IBCKeeper.SetRouter(ibcRouter)
|
||||||
@ -470,7 +529,7 @@ func NewEthermintApp(
|
|||||||
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
||||||
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
|
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
|
||||||
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
||||||
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper),
|
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
|
||||||
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||||
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||||
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
||||||
@ -479,7 +538,6 @@ func NewEthermintApp(
|
|||||||
params.NewAppModule(app.ParamsKeeper),
|
params.NewAppModule(app.ParamsKeeper),
|
||||||
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
|
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
|
||||||
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
|
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
|
||||||
|
|
||||||
// ibc modules
|
// ibc modules
|
||||||
ibc.NewAppModule(app.IBCKeeper),
|
ibc.NewAppModule(app.IBCKeeper),
|
||||||
transferModule,
|
transferModule,
|
||||||
@ -592,8 +650,8 @@ func NewEthermintApp(
|
|||||||
)
|
)
|
||||||
|
|
||||||
app.mm.RegisterInvariants(&app.CrisisKeeper)
|
app.mm.RegisterInvariants(&app.CrisisKeeper)
|
||||||
app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
|
app.mm.RegisterRoutes(app.LegacyRouter, app.QueryRouter(), encodingConfig.Amino)
|
||||||
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
|
app.configurator = module.NewConfigurator(app.appCodec, app.MsgSvcRouter, app.GRPCQueryRouter())
|
||||||
app.mm.RegisterServices(app.configurator)
|
app.mm.RegisterServices(app.configurator)
|
||||||
|
|
||||||
// add test gRPC service for testing gRPC queries in isolation
|
// add test gRPC service for testing gRPC queries in isolation
|
||||||
@ -608,7 +666,7 @@ func NewEthermintApp(
|
|||||||
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
|
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
|
||||||
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
||||||
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
||||||
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper),
|
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
|
||||||
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
||||||
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||||
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
||||||
@ -624,49 +682,48 @@ func NewEthermintApp(
|
|||||||
|
|
||||||
app.sm.RegisterStoreDecoders()
|
app.sm.RegisterStoreDecoders()
|
||||||
|
|
||||||
// initialize stores
|
|
||||||
app.MountKVStores(keys)
|
|
||||||
app.MountTransientStores(tkeys)
|
|
||||||
app.MountMemoryStores(memKeys)
|
|
||||||
|
|
||||||
// initialize BaseApp
|
// initialize BaseApp
|
||||||
app.SetInitChainer(app.InitChainer)
|
app.SetInitChainer(app.InitChainer)
|
||||||
app.SetBeginBlocker(app.BeginBlocker)
|
app.SetBeginBlocker(app.BeginBlocker)
|
||||||
|
|
||||||
// use Ethermint's custom AnteHandler
|
|
||||||
|
|
||||||
maxGasWanted := cast.ToUint64(appOpts.Get(srvflags.EVMMaxTxGasWanted))
|
maxGasWanted := cast.ToUint64(appOpts.Get(srvflags.EVMMaxTxGasWanted))
|
||||||
options := ante.HandlerOptions{
|
options := middleware.HandlerOptions{
|
||||||
AccountKeeper: app.AccountKeeper,
|
Codec: app.appCodec,
|
||||||
BankKeeper: app.BankKeeper,
|
Debug: app.Trace(),
|
||||||
EvmKeeper: app.EvmKeeper,
|
LegacyRouter: app.LegacyRouter,
|
||||||
FeegrantKeeper: app.FeeGrantKeeper,
|
MsgServiceRouter: app.MsgSvcRouter,
|
||||||
IBCKeeper: app.IBCKeeper,
|
AccountKeeper: app.AccountKeeper,
|
||||||
FeeMarketKeeper: app.FeeMarketKeeper,
|
BankKeeper: app.BankKeeper,
|
||||||
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
|
EvmKeeper: app.EvmKeeper,
|
||||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
FeegrantKeeper: app.FeeGrantKeeper,
|
||||||
MaxTxGasWanted: maxGasWanted,
|
FeeMarketKeeper: app.FeeMarketKeeper,
|
||||||
|
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
|
||||||
|
SigGasConsumer: middleware.DefaultSigVerificationGasConsumer,
|
||||||
|
MaxTxGasWanted: maxGasWanted,
|
||||||
|
TxDecoder: encodingConfig.TxConfig.TxDecoder(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := options.Validate(); err != nil {
|
app.setTxHandler(options, encodingConfig.TxConfig, cast.ToStringSlice(appOpts.Get(server.FlagIndexEvents)))
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
app.SetAnteHandler(ante.NewAnteHandler(options))
|
|
||||||
app.SetEndBlocker(app.EndBlocker)
|
app.SetEndBlocker(app.EndBlocker)
|
||||||
|
|
||||||
if loadLatest {
|
|
||||||
if err := app.LoadLatestVersion(); err != nil {
|
|
||||||
tmos.Exit(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
app.ScopedIBCKeeper = scopedIBCKeeper
|
app.ScopedIBCKeeper = scopedIBCKeeper
|
||||||
app.ScopedTransferKeeper = scopedTransferKeeper
|
app.ScopedTransferKeeper = scopedTransferKeeper
|
||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *EthermintApp) setTxHandler(options middleware.HandlerOptions, txConfig client.TxConfig, indexEventsStr []string) {
|
||||||
|
indexEvents := map[string]struct{}{}
|
||||||
|
for _, e := range indexEventsStr {
|
||||||
|
indexEvents[e] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
options.IndexEvents = indexEvents
|
||||||
|
|
||||||
|
txHandler := middleware.NewTxHandler(options)
|
||||||
|
app.SetTxHandler(txHandler)
|
||||||
|
}
|
||||||
|
|
||||||
// Name returns the name of the App
|
// Name returns the name of the App
|
||||||
func (app *EthermintApp) Name() string { return app.BaseApp.Name() }
|
func (app *EthermintApp) Name() string { return app.BaseApp.Name() }
|
||||||
|
|
||||||
@ -692,7 +749,8 @@ func (app *EthermintApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain)
|
|||||||
|
|
||||||
// LoadHeight loads state at a particular height
|
// LoadHeight loads state at a particular height
|
||||||
func (app *EthermintApp) LoadHeight(height int64) error {
|
func (app *EthermintApp) LoadHeight(height int64) error {
|
||||||
return app.LoadVersion(height)
|
// return app.LoadVersion(height)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModuleAccountAddrs returns all the app's module account addresses.
|
// ModuleAccountAddrs returns all the app's module account addresses.
|
||||||
@ -740,21 +798,21 @@ func (app *EthermintApp) InterfaceRegistry() types.InterfaceRegistry {
|
|||||||
// GetKey returns the KVStoreKey for the provided store key.
|
// GetKey returns the KVStoreKey for the provided store key.
|
||||||
//
|
//
|
||||||
// NOTE: This is solely to be used for testing purposes.
|
// NOTE: This is solely to be used for testing purposes.
|
||||||
func (app *EthermintApp) GetKey(storeKey string) *sdk.KVStoreKey {
|
func (app *EthermintApp) GetKey(storeKey string) *storetypes.KVStoreKey {
|
||||||
return app.keys[storeKey]
|
return app.keys[storeKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTKey returns the TransientStoreKey for the provided store key.
|
// GetTKey returns the TransientStoreKey for the provided store key.
|
||||||
//
|
//
|
||||||
// NOTE: This is solely to be used for testing purposes.
|
// NOTE: This is solely to be used for testing purposes.
|
||||||
func (app *EthermintApp) GetTKey(storeKey string) *sdk.TransientStoreKey {
|
func (app *EthermintApp) GetTKey(storeKey string) *storetypes.TransientStoreKey {
|
||||||
return app.tkeys[storeKey]
|
return app.tkeys[storeKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMemKey returns the MemStoreKey for the provided mem key.
|
// GetMemKey returns the MemStoreKey for the provided mem key.
|
||||||
//
|
//
|
||||||
// NOTE: This is solely used for testing purposes.
|
// NOTE: This is solely used for testing purposes.
|
||||||
func (app *EthermintApp) GetMemKey(storeKey string) *sdk.MemoryStoreKey {
|
func (app *EthermintApp) GetMemKey(storeKey string) *storetypes.MemoryStoreKey {
|
||||||
return app.memKeys[storeKey]
|
return app.memKeys[storeKey]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -775,9 +833,9 @@ func (app *EthermintApp) SimulationManager() *module.SimulationManager {
|
|||||||
// API server.
|
// API server.
|
||||||
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
||||||
clientCtx := apiSvr.ClientCtx
|
clientCtx := apiSvr.ClientCtx
|
||||||
rpc.RegisterRoutes(clientCtx, apiSvr.Router)
|
// NOTE: in v0.46 legacy routes are removed
|
||||||
|
// rpc.RegisterRoutes(clientCtx, apiSvr.Router)
|
||||||
evmrest.RegisterTxRoutes(clientCtx, apiSvr.Router)
|
// evmrest.RegisterTxRoutes(clientCtx, apiSvr.Router)
|
||||||
|
|
||||||
// Register new tx routes from grpc-gateway.
|
// Register new tx routes from grpc-gateway.
|
||||||
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
||||||
@ -825,7 +883,7 @@ func GetMaccPerms() map[string][]string {
|
|||||||
|
|
||||||
// initParamsKeeper init params keeper and its subspaces
|
// initParamsKeeper init params keeper and its subspaces
|
||||||
func initParamsKeeper(
|
func initParamsKeeper(
|
||||||
appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey,
|
appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey storetypes.StoreKey,
|
||||||
) paramskeeper.Keeper {
|
) paramskeeper.Keeper {
|
||||||
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
|
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
|
||||||
|
|
||||||
@ -836,7 +894,7 @@ func initParamsKeeper(
|
|||||||
paramsKeeper.Subspace(minttypes.ModuleName)
|
paramsKeeper.Subspace(minttypes.ModuleName)
|
||||||
paramsKeeper.Subspace(distrtypes.ModuleName)
|
paramsKeeper.Subspace(distrtypes.ModuleName)
|
||||||
paramsKeeper.Subspace(slashingtypes.ModuleName)
|
paramsKeeper.Subspace(slashingtypes.ModuleName)
|
||||||
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable())
|
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govv1.ParamKeyTable())
|
||||||
paramsKeeper.Subspace(crisistypes.ModuleName)
|
paramsKeeper.Subspace(crisistypes.ModuleName)
|
||||||
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
|
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
|
||||||
paramsKeeper.Subspace(ibchost.ModuleName)
|
paramsKeeper.Subspace(ibchost.ModuleName)
|
||||||
|
@ -1,41 +1,45 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
memdb "github.com/cosmos/cosmos-sdk/db/memdb"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/encoding"
|
"github.com/tharsis/ethermint/encoding"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEthermintAppExport(t *testing.T) {
|
func TestEthermintAppExport(t *testing.T) {
|
||||||
db := dbm.NewMemDB()
|
encCfg := encoding.MakeConfig(ModuleBasics)
|
||||||
app := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
db := memdb.NewDB()
|
||||||
|
logger, _ := log.NewDefaultLogger("plain", "info", false)
|
||||||
|
app := NewTestAppWithCustomOptions(t, false, SetupOptions{
|
||||||
|
Logger: logger,
|
||||||
|
DB: db,
|
||||||
|
InvCheckPeriod: 0,
|
||||||
|
EncConfig: encCfg,
|
||||||
|
HomePath: DefaultNodeHome,
|
||||||
|
SkipUpgradeHeights: map[int64]bool{},
|
||||||
|
AppOpts: EmptyAppOptions{},
|
||||||
|
})
|
||||||
|
|
||||||
genesisState := NewDefaultGenesisState()
|
for acc := range allowedReceivingModAcc {
|
||||||
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
// check module account is not blocked in bank
|
||||||
require.NoError(t, err)
|
require.False(
|
||||||
|
t,
|
||||||
|
app.BankKeeper.BlockedAddr(app.AccountKeeper.GetModuleAddress(acc)),
|
||||||
|
"ensure that blocked addresses %s are properly set in bank keeper",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize the chain
|
|
||||||
app.InitChain(
|
|
||||||
abci.RequestInitChain{
|
|
||||||
ChainId: "ethermint_9000-1",
|
|
||||||
Validators: []abci.ValidatorUpdate{},
|
|
||||||
AppStateBytes: stateBytes,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
app.Commit()
|
app.Commit()
|
||||||
|
logger2, _ := log.NewDefaultLogger("plain", "info", false)
|
||||||
|
|
||||||
// Making a new app object with the db, so that initchain hasn't been called
|
// Making a new app object with the db, so that initchain hasn't been called
|
||||||
app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
app2 := NewEthermintApp(logger2, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{})
|
||||||
_, err = app2.ExportAppStateAndValidators(false, []string{})
|
require.NoError(t, app2.Init())
|
||||||
|
_, err := app2.ExportAppStateAndValidators(false, []string{})
|
||||||
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
|
require.NoError(t, err, "ExportAppStateAndValidators should not have an error")
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,21 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/db/memdb"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
"github.com/tharsis/ethermint/encoding"
|
"github.com/tharsis/ethermint/encoding"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
|
func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
|
||||||
db := dbm.NewMemDB()
|
db := memdb.NewDB()
|
||||||
app := NewEthermintApp(log.NewTMLogger(io.Discard), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
logger, _ := log.NewDefaultLogger("plain", "info", false)
|
||||||
|
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
||||||
|
|
||||||
genesisState := NewDefaultGenesisState()
|
genesisState := NewDefaultGenesisState(app.appCodec)
|
||||||
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
@ -36,7 +36,7 @@ func BenchmarkEthermintApp_ExportAppStateAndValidators(b *testing.B) {
|
|||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
// Making a new app object with the db, so that initchain hasn't been called
|
// Making a new app object with the db, so that initchain hasn't been called
|
||||||
app2 := NewEthermintApp(log.NewTMLogger(log.NewSyncWriter(io.Discard)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
app2 := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
||||||
if _, err := app2.ExportAppStateAndValidators(false, []string{}); err != nil {
|
if _, err := app2.ExportAppStateAndValidators(false, []string{}); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -6,20 +6,18 @@ import (
|
|||||||
|
|
||||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/encoding"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewDefaultGenesisState generates the default state for the application.
|
// NewDefaultGenesisState generates the default state for the application.
|
||||||
func NewDefaultGenesisState() simapp.GenesisState {
|
func NewDefaultGenesisState(cdc codec.JSONCodec) simapp.GenesisState {
|
||||||
encCfg := encoding.MakeConfig(ModuleBasics)
|
return ModuleBasics.DefaultGenesis(cdc)
|
||||||
return ModuleBasics.DefaultGenesis(encCfg.Marshaler)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportAppStateAndValidators exports the state of the application for a genesis
|
// ExportAppStateAndValidators exports the state of the application for a genesis
|
||||||
|
@ -1,107 +1,104 @@
|
|||||||
package ante
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
context "context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
|
||||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
|
|
||||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||||
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
|
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
|
||||||
"github.com/tharsis/ethermint/ethereum/eip712"
|
"github.com/tharsis/ethermint/ethereum/eip712"
|
||||||
ethermint "github.com/tharsis/ethermint/types"
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ethermintCodec codec.ProtoCodecMarshaler
|
// Eip712SigVerificationMiddleware Verify all signatures for a tx and return an error if any are invalid. Note,
|
||||||
|
// the Eip712SigVerificationMiddleware middleware will not get executed on ReCheck.
|
||||||
func init() {
|
|
||||||
registry := codectypes.NewInterfaceRegistry()
|
|
||||||
ethermint.RegisterInterfaces(registry)
|
|
||||||
ethermintCodec = codec.NewProtoCodec(registry)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Eip712SigVerificationDecorator Verify all signatures for a tx and return an error if any are invalid. Note,
|
|
||||||
// the Eip712SigVerificationDecorator decorator will not get executed on ReCheck.
|
|
||||||
//
|
//
|
||||||
// CONTRACT: Pubkeys are set in context for all signers before this decorator runs
|
// CONTRACT: Pubkeys are set in context for all signers before this middleware runs
|
||||||
// CONTRACT: Tx must implement SigVerifiableTx interface
|
// CONTRACT: Tx must implement SigVerifiableTx interface
|
||||||
type Eip712SigVerificationDecorator struct {
|
type Eip712SigVerificationMiddleware struct {
|
||||||
|
appCodec codec.Codec
|
||||||
|
next tx.Handler
|
||||||
ak evmtypes.AccountKeeper
|
ak evmtypes.AccountKeeper
|
||||||
signModeHandler authsigning.SignModeHandler
|
signModeHandler authsigning.SignModeHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEip712SigVerificationDecorator creates a new Eip712SigVerificationDecorator
|
var _ tx.Handler = Eip712SigVerificationMiddleware{}
|
||||||
func NewEip712SigVerificationDecorator(ak evmtypes.AccountKeeper, signModeHandler authsigning.SignModeHandler) Eip712SigVerificationDecorator {
|
|
||||||
return Eip712SigVerificationDecorator{
|
// NewEip712SigVerificationMiddleware creates a new Eip712SigVerificationMiddleware
|
||||||
ak: ak,
|
func NewEip712SigVerificationMiddleware(appCodec codec.Codec, ak evmtypes.AccountKeeper, signModeHandler authsigning.SignModeHandler) tx.Middleware {
|
||||||
signModeHandler: signModeHandler,
|
return func(h tx.Handler) tx.Handler {
|
||||||
|
return Eip712SigVerificationMiddleware{
|
||||||
|
appCodec: appCodec,
|
||||||
|
next: h,
|
||||||
|
ak: ak,
|
||||||
|
signModeHandler: signModeHandler,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnteHandle handles validation of EIP712 signed cosmos txs.
|
func eipSigVerification(svd Eip712SigVerificationMiddleware, cx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
// it is not run on RecheckTx
|
ctx := sdk.UnwrapSDKContext(cx)
|
||||||
func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
reqTx := req.Tx
|
||||||
// no need to verify signatures on recheck tx
|
|
||||||
if ctx.IsReCheckTx() {
|
sigTx, ok := reqTx.(authsigning.SigVerifiableTx)
|
||||||
return next(ctx, tx, simulate)
|
if !ok {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement authsigning.SigVerifiableTx", reqTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
authSignTx, ok := reqTx.(authsigning.Tx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement authsigning.SigVerifiableTx", tx)
|
return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement the authsigning.Tx interface", reqTx)
|
||||||
}
|
|
||||||
|
|
||||||
authSignTx, ok := tx.(authsigning.Tx)
|
|
||||||
if !ok {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "tx %T doesn't implement the authsigning.Tx interface", tx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// stdSigs contains the sequence number, account number, and signatures.
|
// stdSigs contains the sequence number, account number, and signatures.
|
||||||
// When simulating, this would just be a 0-length slice.
|
// When simulating, this would just be a 0-length slice.
|
||||||
sigs, err := sigTx.GetSignaturesV2()
|
sigs, err := sigTx.GetSignaturesV2()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, err
|
return tx.Response{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
signerAddrs := sigTx.GetSigners()
|
signerAddrs := sigTx.GetSigners()
|
||||||
|
|
||||||
// EIP712 allows just one signature
|
// EIP712 allows just one signature
|
||||||
if len(sigs) != 1 {
|
if len(sigs) != 1 {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signers (%d); EIP712 signatures allows just one signature", len(sigs))
|
return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signers (%d); EIP712 signatures allows just one signature", len(sigs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that signer length and signature length are the same
|
// check that signer length and signature length are the same
|
||||||
if len(sigs) != len(signerAddrs) {
|
if len(sigs) != len(signerAddrs) {
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs))
|
return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs))
|
||||||
}
|
}
|
||||||
|
|
||||||
// EIP712 has just one signature, avoid looping here and only read index 0
|
// EIP712 has just one signature, avoid looping here and only read index 0
|
||||||
i := 0
|
i := 0
|
||||||
sig := sigs[i]
|
sig := sigs[i]
|
||||||
|
|
||||||
acc, err := authante.GetSignerAcc(ctx, svd.ak, signerAddrs[i])
|
acc, err := middleware.GetSignerAcc(ctx, svd.ak, signerAddrs[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctx, err
|
return tx.Response{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// retrieve pubkey
|
// retrieve pubkey
|
||||||
pubKey := acc.GetPubKey()
|
pubKey := acc.GetPubKey()
|
||||||
if !simulate && pubKey == nil {
|
if pubKey == nil {
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set")
|
return tx.Response{}, sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check account sequence number.
|
// Check account sequence number.
|
||||||
if sig.Sequence != acc.GetSequence() {
|
if sig.Sequence != acc.GetSequence() {
|
||||||
return ctx, sdkerrors.Wrapf(
|
return tx.Response{}, sdkerrors.Wrapf(
|
||||||
sdkerrors.ErrWrongSequence,
|
sdkerrors.ErrWrongSequence,
|
||||||
"account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence,
|
"account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence,
|
||||||
)
|
)
|
||||||
@ -122,21 +119,45 @@ func (svd Eip712SigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx,
|
|||||||
Sequence: acc.GetSequence(),
|
Sequence: acc.GetSequence(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if simulate {
|
if err := VerifySignature(svd.appCodec, pubKey, signerData, sig.Data, svd.signModeHandler, authSignTx); err != nil {
|
||||||
return next(ctx, tx, simulate)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := VerifySignature(pubKey, signerData, sig.Data, svd.signModeHandler, authSignTx); err != nil {
|
|
||||||
errMsg := fmt.Errorf("signature verification failed; please verify account number (%d) and chain-id (%s): %w", accNum, chainID, err)
|
errMsg := fmt.Errorf("signature verification failed; please verify account number (%d) and chain-id (%s): %w", accNum, chainID, err)
|
||||||
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, errMsg.Error())
|
return tx.Response{}, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, errMsg.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return next(ctx, tx, simulate)
|
return tx.Response{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (svd Eip712SigVerificationMiddleware) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
if _, err := eipSigVerification(svd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return svd.next.CheckTx(ctx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (svd Eip712SigVerificationMiddleware) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
if _, err := eipSigVerification(svd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return svd.next.DeliverTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (svd Eip712SigVerificationMiddleware) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
if _, err := eipSigVerification(svd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return svd.next.SimulateTx(ctx, req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifySignature verifies a transaction signature contained in SignatureData abstracting over different signing modes
|
// VerifySignature verifies a transaction signature contained in SignatureData abstracting over different signing modes
|
||||||
// and single vs multi-signatures.
|
// and single vs multi-signatures.
|
||||||
func VerifySignature(
|
func VerifySignature(
|
||||||
|
appCodec codec.Codec,
|
||||||
pubKey cryptotypes.PubKey,
|
pubKey cryptotypes.PubKey,
|
||||||
signerData authsigning.SignerData,
|
signerData authsigning.SignerData,
|
||||||
sigData signing.SignatureData,
|
sigData signing.SignatureData,
|
||||||
@ -171,7 +192,7 @@ func VerifySignature(
|
|||||||
Amount: tx.GetFee(),
|
Amount: tx.GetFee(),
|
||||||
Gas: tx.GetGas(),
|
Gas: tx.GetGas(),
|
||||||
},
|
},
|
||||||
msgs, tx.GetMemo(),
|
msgs, tx.GetMemo(), tx.GetTip(),
|
||||||
)
|
)
|
||||||
|
|
||||||
signerChainID, err := ethermint.ParseChainID(signerData.ChainID)
|
signerChainID, err := ethermint.ParseChainID(signerData.ChainID)
|
||||||
@ -179,7 +200,7 @@ func VerifySignature(
|
|||||||
return sdkerrors.Wrapf(err, "failed to parse chainID: %s", signerData.ChainID)
|
return sdkerrors.Wrapf(err, "failed to parse chainID: %s", signerData.ChainID)
|
||||||
}
|
}
|
||||||
|
|
||||||
txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
|
txWithExtensions, ok := tx.(middleware.HasExtensionOptionsTx)
|
||||||
if !ok {
|
if !ok {
|
||||||
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "tx doesnt contain any extensions")
|
return sdkerrors.Wrap(sdkerrors.ErrUnknownExtensionOptions, "tx doesnt contain any extensions")
|
||||||
}
|
}
|
||||||
@ -190,7 +211,7 @@ func VerifySignature(
|
|||||||
|
|
||||||
var optIface ethermint.ExtensionOptionsWeb3TxI
|
var optIface ethermint.ExtensionOptionsWeb3TxI
|
||||||
|
|
||||||
if err := ethermintCodec.UnpackAny(opts[0], &optIface); err != nil {
|
if err := appCodec.UnpackAny(opts[0], &optIface); err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed to proto-unpack ExtensionOptionsWeb3Tx")
|
return sdkerrors.Wrap(err, "failed to proto-unpack ExtensionOptionsWeb3Tx")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +236,7 @@ func VerifySignature(
|
|||||||
FeePayer: feePayer,
|
FeePayer: feePayer,
|
||||||
}
|
}
|
||||||
|
|
||||||
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, extOpt.TypedDataChainID, msgs[0], txBytes, feeDelegation)
|
typedData, err := eip712.WrapTxToTypedData(appCodec, extOpt.TypedDataChainID, msgs[0], txBytes, feeDelegation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sdkerrors.Wrap(err, "failed to pack tx data in EIP712 object")
|
return sdkerrors.Wrap(err, "failed to pack tx data in EIP712 object")
|
||||||
}
|
}
|
757
app/middleware/eth.go
Normal file
757
app/middleware/eth.go
Normal file
@ -0,0 +1,757 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
|
evmkeeper "github.com/tharsis/ethermint/x/evm/keeper"
|
||||||
|
"github.com/tharsis/ethermint/x/evm/statedb"
|
||||||
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EthSetupContextMiddleware is adapted from SetUpContextMiddleware from cosmos-sdk, it ignores gas consumption
|
||||||
|
// by setting the gas meter to infinite
|
||||||
|
type EthSetupContextMiddleware struct {
|
||||||
|
next tx.Handler
|
||||||
|
evmKeeper EVMKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
// gasContext returns a new context with a gas meter set from a given context.
|
||||||
|
func gasContext(ctx sdk.Context, tx sdk.Tx, isSimulate bool) (sdk.Context, error) {
|
||||||
|
// all transactions must implement GasTx
|
||||||
|
gasTx, ok := tx.(middleware.GasTx)
|
||||||
|
if !ok {
|
||||||
|
// Set a gas meter with limit 0 as to prevent an infinite gas meter attack
|
||||||
|
// during runTx.
|
||||||
|
newCtx := setGasMeter(ctx, 0, isSimulate)
|
||||||
|
return newCtx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
|
||||||
|
}
|
||||||
|
|
||||||
|
return setGasMeter(ctx, gasTx.GetGas(), isSimulate), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// setGasMeter returns a new context with a gas meter set from a given context.
|
||||||
|
func setGasMeter(ctx sdk.Context, gasLimit uint64, simulate bool) sdk.Context {
|
||||||
|
// In various cases such as simulation and during the genesis block, we do not
|
||||||
|
// meter any gas utilization.
|
||||||
|
if simulate || ctx.BlockHeight() == 0 {
|
||||||
|
return ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasLimit))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (esc EthSetupContextMiddleware) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), req.Tx, false)
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset transient gas used to prepare the execution of current cosmos tx.
|
||||||
|
// Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs.
|
||||||
|
esc.evmKeeper.ResetTransientGasUsed(sdkCtx)
|
||||||
|
return esc.next.CheckTx(sdkCtx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (esc EthSetupContextMiddleware) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), req.Tx, false)
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset transient gas used to prepare the execution of current cosmos tx.
|
||||||
|
// Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs.
|
||||||
|
esc.evmKeeper.ResetTransientGasUsed(sdkCtx)
|
||||||
|
return esc.next.DeliverTx(sdkCtx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (esc EthSetupContextMiddleware) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
sdkCtx, err := gasContext(sdk.UnwrapSDKContext(ctx), req.Tx, false)
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset transient gas used to prepare the execution of current cosmos tx.
|
||||||
|
// Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs.
|
||||||
|
esc.evmKeeper.ResetTransientGasUsed(sdkCtx)
|
||||||
|
return esc.next.SimulateTx(sdkCtx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = EthSetupContextMiddleware{}
|
||||||
|
|
||||||
|
func NewEthSetUpContextMiddleware(evmKeeper EVMKeeper) tx.Middleware {
|
||||||
|
return func(txh tx.Handler) tx.Handler {
|
||||||
|
return EthSetupContextMiddleware{
|
||||||
|
next: txh,
|
||||||
|
evmKeeper: evmKeeper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EthMempoolFeeMiddleware will check if the transaction's effective fee is at least as large
|
||||||
|
// as the local validator's minimum gasFee (defined in validator config).
|
||||||
|
// If fee is too low, Middleware returns error and tx is rejected from mempool.
|
||||||
|
// Note this only applies when ctx.CheckTx = true
|
||||||
|
// If fee is high enough or not CheckTx, then call next AnteHandler
|
||||||
|
// CONTRACT: Tx must implement FeeTx to use MempoolFeeMiddleware
|
||||||
|
type EthMempoolFeeMiddleware struct {
|
||||||
|
next tx.Handler
|
||||||
|
evmKeeper EVMKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (mfd EthMempoolFeeMiddleware) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
|
||||||
|
sdkCtx := sdk.UnwrapSDKContext(ctx)
|
||||||
|
params := mfd.evmKeeper.GetParams(sdkCtx)
|
||||||
|
ethCfg := params.ChainConfig.EthereumConfig(mfd.evmKeeper.ChainID())
|
||||||
|
baseFee := mfd.evmKeeper.BaseFee(sdkCtx, ethCfg)
|
||||||
|
if baseFee == nil {
|
||||||
|
for _, msg := range req.Tx.GetMsgs() {
|
||||||
|
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
|
if !ok {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
evmDenom := params.EvmDenom
|
||||||
|
feeAmt := ethMsg.GetFee()
|
||||||
|
glDec := sdk.NewDec(int64(ethMsg.GetGas()))
|
||||||
|
requiredFee := sdkCtx.MinGasPrices().AmountOf(evmDenom).Mul(glDec)
|
||||||
|
if sdk.NewDecFromBigInt(feeAmt).LT(requiredFee) {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeAmt, requiredFee)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mfd.next.CheckTx(ctx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (mfd EthMempoolFeeMiddleware) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
return mfd.next.DeliverTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (mfd EthMempoolFeeMiddleware) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
return mfd.next.SimulateTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = EthMempoolFeeMiddleware{}
|
||||||
|
|
||||||
|
func NewEthMempoolFeeMiddleware(ek EVMKeeper) tx.Middleware {
|
||||||
|
return func(txh tx.Handler) tx.Handler {
|
||||||
|
return EthMempoolFeeMiddleware{
|
||||||
|
next: txh,
|
||||||
|
evmKeeper: ek,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EthValidateBasicMiddleware is adapted from ValidateBasicMiddleware from cosmos-sdk, it ignores ErrNoSignatures
|
||||||
|
type EthValidateBasicMiddleware struct {
|
||||||
|
next tx.Handler
|
||||||
|
evmKeeper EVMKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (vbd EthValidateBasicMiddleware) CheckTx(cx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(cx)
|
||||||
|
reqTx := req.Tx
|
||||||
|
|
||||||
|
// no need to validate basic on recheck tx, call next antehandler
|
||||||
|
if ctx.IsReCheckTx() {
|
||||||
|
return vbd.next.CheckTx(ctx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := reqTx.ValidateBasic()
|
||||||
|
// ErrNoSignatures is fine with eth tx
|
||||||
|
if err != nil && !errors.Is(err, sdkerrors.ErrNoSignatures) {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(err, "tx basic validation failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// For eth type cosmos tx, some fields should be verified as zero values,
|
||||||
|
// since we will only verify the signature against the hash of the MsgEthereumTx.Data
|
||||||
|
if wrapperTx, ok := reqTx.(protoTxProvider); ok {
|
||||||
|
protoTx := wrapperTx.GetProtoTx()
|
||||||
|
body := protoTx.Body
|
||||||
|
if body.Memo != "" || body.TimeoutHeight != uint64(0) || len(body.NonCriticalExtensionOptions) > 0 {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest,
|
||||||
|
"for eth tx body Memo TimeoutHeight NonCriticalExtensionOptions should be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(body.ExtensionOptions) != 1 {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx length of ExtensionOptions should be 1")
|
||||||
|
}
|
||||||
|
|
||||||
|
txFee := sdk.Coins{}
|
||||||
|
txGasLimit := uint64(0)
|
||||||
|
|
||||||
|
for _, msg := range protoTx.GetMsgs() {
|
||||||
|
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
|
if !ok {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
|
}
|
||||||
|
txGasLimit += msgEthTx.GetGas()
|
||||||
|
|
||||||
|
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data")
|
||||||
|
}
|
||||||
|
|
||||||
|
params := vbd.evmKeeper.GetParams(ctx)
|
||||||
|
chainID := vbd.evmKeeper.ChainID()
|
||||||
|
ethCfg := params.ChainConfig.EthereumConfig(chainID)
|
||||||
|
baseFee := vbd.evmKeeper.BaseFee(ctx, ethCfg)
|
||||||
|
if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
txFee = txFee.Add(sdk.NewCoin(params.EvmDenom, sdk.NewIntFromBigInt(txData.Fee())))
|
||||||
|
}
|
||||||
|
|
||||||
|
authInfo := protoTx.AuthInfo
|
||||||
|
if len(authInfo.SignerInfos) > 0 {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo SignerInfos should be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if authInfo.Fee.Payer != "" || authInfo.Fee.Granter != "" {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx AuthInfo Fee payer and granter should be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !authInfo.Fee.Amount.IsEqual(txFee) {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee Amount (%s != %s)", authInfo.Fee.Amount, txFee)
|
||||||
|
}
|
||||||
|
|
||||||
|
if authInfo.Fee.GasLimit != txGasLimit {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "invalid AuthInfo Fee GasLimit (%d != %d)", authInfo.Fee.GasLimit, txGasLimit)
|
||||||
|
}
|
||||||
|
|
||||||
|
sigs := protoTx.Signatures
|
||||||
|
if len(sigs) > 0 {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "for eth tx Signatures should be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vbd.next.CheckTx(ctx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (vbd EthValidateBasicMiddleware) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
return vbd.next.DeliverTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (vbd EthValidateBasicMiddleware) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
return vbd.next.SimulateTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = EthValidateBasicMiddleware{}
|
||||||
|
|
||||||
|
// NewEthValidateBasicMiddleware creates a new EthValidateBasicMiddleware
|
||||||
|
func NewEthValidateBasicMiddleware(ek EVMKeeper) tx.Middleware {
|
||||||
|
return func(h tx.Handler) tx.Handler {
|
||||||
|
return EthValidateBasicMiddleware{
|
||||||
|
next: h,
|
||||||
|
evmKeeper: ek,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// EthSigVerificationMiddleware validates an ethereum signatures
|
||||||
|
type EthSigVerificationMiddleware struct {
|
||||||
|
next tx.Handler
|
||||||
|
evmKeeper EVMKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func ethSigVerificationMiddleware(esvd EthSigVerificationMiddleware, cx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
chainID := esvd.evmKeeper.ChainID()
|
||||||
|
ctx := sdk.UnwrapSDKContext(cx)
|
||||||
|
reqTx := req.Tx
|
||||||
|
|
||||||
|
params := esvd.evmKeeper.GetParams(ctx)
|
||||||
|
|
||||||
|
ethCfg := params.ChainConfig.EthereumConfig(chainID)
|
||||||
|
blockNum := big.NewInt(ctx.BlockHeight())
|
||||||
|
signer := ethtypes.MakeSigner(ethCfg, blockNum)
|
||||||
|
|
||||||
|
for _, msg := range reqTx.GetMsgs() {
|
||||||
|
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
|
if !ok {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
sender, err := signer.Sender(msgEthTx.AsTransaction())
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(
|
||||||
|
sdkerrors.ErrorInvalidSigner,
|
||||||
|
"couldn't retrieve sender address ('%s') from the ethereum transaction: %s",
|
||||||
|
msgEthTx.From,
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up the sender to the transaction field if not already
|
||||||
|
msgEthTx.From = sender.Hex()
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Response{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (esvd EthSigVerificationMiddleware) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
if _, err := ethSigVerificationMiddleware(esvd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return esvd.next.CheckTx(ctx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (esvd EthSigVerificationMiddleware) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
if _, err := ethSigVerificationMiddleware(esvd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return esvd.next.DeliverTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (esvd EthSigVerificationMiddleware) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
if _, err := ethSigVerificationMiddleware(esvd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return esvd.next.SimulateTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = EthSigVerificationMiddleware{}
|
||||||
|
|
||||||
|
// NewEthSigVerificationMiddleware creates a new EthSigVerificationMiddleware
|
||||||
|
func NewEthSigVerificationMiddleware(ek EVMKeeper) tx.Middleware {
|
||||||
|
return func(h tx.Handler) tx.Handler {
|
||||||
|
return EthSigVerificationMiddleware{
|
||||||
|
next: h,
|
||||||
|
evmKeeper: ek,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EthAccountVerificationMiddleware validates an account balance checks
|
||||||
|
type EthAccountVerificationMiddleware struct {
|
||||||
|
next tx.Handler
|
||||||
|
ak evmtypes.AccountKeeper
|
||||||
|
bankKeeper evmtypes.BankKeeper
|
||||||
|
evmKeeper EVMKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (avd EthAccountVerificationMiddleware) CheckTx(cx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
reqTx := req.Tx
|
||||||
|
ctx := sdk.UnwrapSDKContext(cx)
|
||||||
|
if !ctx.IsCheckTx() {
|
||||||
|
return avd.next.CheckTx(cx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, msg := range reqTx.GetMsgs() {
|
||||||
|
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
|
if !ok {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(err, "failed to unpack tx data any for tx %d", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sender address should be in the tx cache from the previous AnteHandle call
|
||||||
|
from := msgEthTx.GetFrom()
|
||||||
|
if from.Empty() {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "from address cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether the sender address is EOA
|
||||||
|
fromAddr := common.BytesToAddress(from)
|
||||||
|
acct := avd.evmKeeper.GetAccount(ctx, fromAddr)
|
||||||
|
|
||||||
|
if acct == nil {
|
||||||
|
acc := avd.ak.NewAccountWithAddress(ctx, from)
|
||||||
|
avd.ak.SetAccount(ctx, acc)
|
||||||
|
acct = statedb.NewEmptyAccount()
|
||||||
|
} else if acct.IsContract() {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidType,
|
||||||
|
"the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := evmkeeper.CheckSenderBalance(sdk.NewIntFromBigInt(acct.Balance), txData); err != nil {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, sdkerrors.Wrap(err, "failed to check sender balance")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return avd.next.CheckTx(ctx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (avd EthAccountVerificationMiddleware) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
return avd.next.DeliverTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (avd EthAccountVerificationMiddleware) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
return avd.next.SimulateTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = EthAccountVerificationMiddleware{}
|
||||||
|
|
||||||
|
// NewEthAccountVerificationMiddleware creates a new EthAccountVerificationMiddleware
|
||||||
|
func NewEthAccountVerificationMiddleware(ak evmtypes.AccountKeeper, bankKeeper evmtypes.BankKeeper, ek EVMKeeper) tx.Middleware {
|
||||||
|
return func(h tx.Handler) tx.Handler {
|
||||||
|
return EthAccountVerificationMiddleware{
|
||||||
|
next: h,
|
||||||
|
ak: ak,
|
||||||
|
bankKeeper: bankKeeper,
|
||||||
|
evmKeeper: ek,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EthGasConsumeMiddleware validates enough intrinsic gas for the transaction and
|
||||||
|
// gas consumption.
|
||||||
|
type EthGasConsumeMiddleware struct {
|
||||||
|
next tx.Handler
|
||||||
|
evmKeeper EVMKeeper
|
||||||
|
maxGasWanted uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func ethGasMiddleware(egcd EthGasConsumeMiddleware, cx context.Context, req tx.Request) (context.Context, tx.Response, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(cx)
|
||||||
|
reqTx := req.Tx
|
||||||
|
|
||||||
|
params := egcd.evmKeeper.GetParams(ctx)
|
||||||
|
|
||||||
|
ethCfg := params.ChainConfig.EthereumConfig(egcd.evmKeeper.ChainID())
|
||||||
|
|
||||||
|
blockHeight := big.NewInt(ctx.BlockHeight())
|
||||||
|
homestead := ethCfg.IsHomestead(blockHeight)
|
||||||
|
istanbul := ethCfg.IsIstanbul(blockHeight)
|
||||||
|
london := ethCfg.IsLondon(blockHeight)
|
||||||
|
evmDenom := params.EvmDenom
|
||||||
|
gasWanted := uint64(0)
|
||||||
|
var events sdk.Events
|
||||||
|
|
||||||
|
for _, msg := range reqTx.GetMsgs() {
|
||||||
|
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
|
if !ok {
|
||||||
|
return ctx, tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||||
|
if err != nil {
|
||||||
|
return ctx, tx.Response{}, sdkerrors.Wrap(err, "failed to unpack tx data")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.IsCheckTx() {
|
||||||
|
// We can't trust the tx gas limit, because we'll refund the unused gas.
|
||||||
|
if txData.GetGas() > egcd.maxGasWanted {
|
||||||
|
gasWanted += egcd.maxGasWanted
|
||||||
|
} else {
|
||||||
|
gasWanted += txData.GetGas()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gasWanted += txData.GetGas()
|
||||||
|
}
|
||||||
|
|
||||||
|
fees, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
|
||||||
|
ctx,
|
||||||
|
*msgEthTx,
|
||||||
|
txData,
|
||||||
|
evmDenom,
|
||||||
|
homestead,
|
||||||
|
istanbul,
|
||||||
|
london,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return ctx, tx.Response{}, sdkerrors.Wrapf(err, "failed to deduct transaction costs from user balance")
|
||||||
|
}
|
||||||
|
|
||||||
|
events = append(events, sdk.NewEvent(sdk.EventTypeTx, sdk.NewAttribute(sdk.AttributeKeyFee, fees.String())))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: change to typed events
|
||||||
|
ctx.EventManager().EmitEvents(events)
|
||||||
|
|
||||||
|
// TODO: deprecate after https://github.com/cosmos/cosmos-sdk/issues/9514 is fixed on SDK
|
||||||
|
blockGasLimit := ethermint.BlockGasLimit(ctx)
|
||||||
|
|
||||||
|
// NOTE: safety check
|
||||||
|
if blockGasLimit > 0 {
|
||||||
|
// generate a copy of the gas pool (i.e block gas meter) to see if we've run out of gas for this block
|
||||||
|
// if current gas consumed is greater than the limit, this funcion panics and the error is recovered on the Baseapp
|
||||||
|
gasPool := sdk.NewGasMeter(blockGasLimit)
|
||||||
|
gasPool.ConsumeGas(ctx.GasMeter().GasConsumedToLimit(), "gas pool check")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set ctx.GasMeter with a limit of GasWanted (gasLimit)
|
||||||
|
gasConsumed := ctx.GasMeter().GasConsumed()
|
||||||
|
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
|
||||||
|
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")
|
||||||
|
|
||||||
|
return ctx, tx.Response{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (egcd EthGasConsumeMiddleware) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
newCtx, _, err := ethGasMiddleware(egcd, ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return egcd.next.CheckTx(newCtx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (egcd EthGasConsumeMiddleware) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
newCtx, _, err := ethGasMiddleware(egcd, ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return egcd.next.DeliverTx(newCtx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (egcd EthGasConsumeMiddleware) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
newCtx, _, err := ethGasMiddleware(egcd, ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return egcd.next.SimulateTx(newCtx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = EthGasConsumeMiddleware{}
|
||||||
|
|
||||||
|
// NewEthGasConsumeMiddleware creates a new EthGasConsumeMiddleware
|
||||||
|
func NewEthGasConsumeMiddleware(
|
||||||
|
evmKeeper EVMKeeper,
|
||||||
|
maxGasWanted uint64,
|
||||||
|
) tx.Middleware {
|
||||||
|
return func(h tx.Handler) tx.Handler {
|
||||||
|
return EthGasConsumeMiddleware{
|
||||||
|
h,
|
||||||
|
evmKeeper,
|
||||||
|
maxGasWanted,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanTransferMiddleware checks if the sender is allowed to transfer funds according to the EVM block
|
||||||
|
// context rules.
|
||||||
|
type CanTransferMiddleware struct {
|
||||||
|
next tx.Handler
|
||||||
|
evmKeeper EVMKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func canTransfer(ctd CanTransferMiddleware, cx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(cx)
|
||||||
|
reqTx := req.Tx
|
||||||
|
params := ctd.evmKeeper.GetParams(ctx)
|
||||||
|
ethCfg := params.ChainConfig.EthereumConfig(ctd.evmKeeper.ChainID())
|
||||||
|
signer := ethtypes.MakeSigner(ethCfg, big.NewInt(ctx.BlockHeight()))
|
||||||
|
|
||||||
|
for _, msg := range reqTx.GetMsgs() {
|
||||||
|
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
|
if !ok {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
baseFee := ctd.evmKeeper.BaseFee(ctx, ethCfg)
|
||||||
|
|
||||||
|
coreMsg, err := msgEthTx.AsMessage(signer, baseFee)
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(
|
||||||
|
err,
|
||||||
|
"failed to create an ethereum core.Message from signer %T", signer,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: pass in an empty coinbase address and nil tracer as we don't need them for the check below
|
||||||
|
cfg := &evmtypes.EVMConfig{
|
||||||
|
ChainConfig: ethCfg,
|
||||||
|
Params: params,
|
||||||
|
CoinBase: common.Address{},
|
||||||
|
BaseFee: baseFee,
|
||||||
|
}
|
||||||
|
stateDB := statedb.New(ctx, ctd.evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())))
|
||||||
|
evm := ctd.evmKeeper.NewEVM(ctx, coreMsg, cfg, evmtypes.NewNoOpTracer(), stateDB)
|
||||||
|
|
||||||
|
// check that caller has enough balance to cover asset transfer for **topmost** call
|
||||||
|
// NOTE: here the gas consumed is from the context with the infinite gas meter
|
||||||
|
if coreMsg.Value().Sign() > 0 && !evm.Context.CanTransfer(stateDB, coreMsg.From(), coreMsg.Value()) {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(
|
||||||
|
sdkerrors.ErrInsufficientFunds,
|
||||||
|
"failed to transfer %s from address %s using the EVM block context transfer function",
|
||||||
|
coreMsg.Value(),
|
||||||
|
coreMsg.From(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
|
||||||
|
if baseFee == nil {
|
||||||
|
return tx.Response{}, sdkerrors.Wrap(
|
||||||
|
evmtypes.ErrInvalidBaseFee,
|
||||||
|
"base fee is supported but evm block context value is nil",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if coreMsg.GasFeeCap().Cmp(baseFee) < 0 {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(
|
||||||
|
sdkerrors.ErrInsufficientFee,
|
||||||
|
"max fee per gas less than block base fee (%s < %s)",
|
||||||
|
coreMsg.GasFeeCap(), baseFee,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Response{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (ctd CanTransferMiddleware) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
if _, err := canTransfer(ctd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctd.next.CheckTx(ctx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (ctd CanTransferMiddleware) DeliverTx(cx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(cx)
|
||||||
|
if _, err := canTransfer(ctd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctd.next.DeliverTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (ctd CanTransferMiddleware) SimulateTx(cx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(cx)
|
||||||
|
if _, err := canTransfer(ctd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctd.next.SimulateTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = CanTransferMiddleware{}
|
||||||
|
|
||||||
|
// NewCanTransferMiddleware creates a new CanTransferMiddleware instance.
|
||||||
|
func NewCanTransferMiddleware(evmKeeper EVMKeeper) tx.Middleware {
|
||||||
|
return func(h tx.Handler) tx.Handler {
|
||||||
|
return CanTransferMiddleware{
|
||||||
|
next: h,
|
||||||
|
evmKeeper: evmKeeper,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EthIncrementSenderSequenceMiddleware increments the sequence of the signers.
|
||||||
|
type EthIncrementSenderSequenceMiddleware struct {
|
||||||
|
next tx.Handler
|
||||||
|
ak evmtypes.AccountKeeper
|
||||||
|
}
|
||||||
|
|
||||||
|
func ethIncrementSenderSequence(issd EthIncrementSenderSequenceMiddleware, cx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
ctx := sdk.UnwrapSDKContext(cx)
|
||||||
|
reqTx := req.Tx
|
||||||
|
|
||||||
|
for _, msg := range reqTx.GetMsgs() {
|
||||||
|
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||||
|
if !ok {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
|
||||||
|
if err != nil {
|
||||||
|
return tx.Response{}, sdkerrors.Wrap(err, "failed to unpack tx data")
|
||||||
|
}
|
||||||
|
|
||||||
|
// increase sequence of sender
|
||||||
|
acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom())
|
||||||
|
if acc == nil {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(
|
||||||
|
sdkerrors.ErrUnknownAddress,
|
||||||
|
"account %s is nil", common.BytesToAddress(msgEthTx.GetFrom().Bytes()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
nonce := acc.GetSequence()
|
||||||
|
|
||||||
|
// we merged the nonce verification to nonce increment, so when tx includes multiple messages
|
||||||
|
// with same sender, they'll be accepted.
|
||||||
|
if txData.GetNonce() != nonce {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(
|
||||||
|
sdkerrors.ErrInvalidSequence,
|
||||||
|
"invalid nonce; got %d, expected %d", txData.GetNonce(), nonce,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := acc.SetSequence(nonce + 1); err != nil {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(err, "failed to set sequence to %d", acc.GetSequence()+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
issd.ak.SetAccount(ctx, acc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Response{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (issd EthIncrementSenderSequenceMiddleware) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
if _, err := ethIncrementSenderSequence(issd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return issd.next.CheckTx(ctx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (issd EthIncrementSenderSequenceMiddleware) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
if _, err := ethIncrementSenderSequence(issd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return issd.next.DeliverTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (issd EthIncrementSenderSequenceMiddleware) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
if _, err := ethIncrementSenderSequence(issd, ctx, req); err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return issd.next.SimulateTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = EthIncrementSenderSequenceMiddleware{}
|
||||||
|
|
||||||
|
// NewEthIncrementSenderSequenceMiddleware creates a new EthIncrementSenderSequenceMiddleware.
|
||||||
|
func NewEthIncrementSenderSequenceMiddleware(ak evmtypes.AccountKeeper) tx.Middleware {
|
||||||
|
return func(h tx.Handler) tx.Handler {
|
||||||
|
return EthIncrementSenderSequenceMiddleware{
|
||||||
|
next: h,
|
||||||
|
ak: ak,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,13 @@
|
|||||||
package ante_test
|
package middleware_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/app/ante"
|
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
||||||
|
ante "github.com/tharsis/ethermint/app/middleware"
|
||||||
"github.com/tharsis/ethermint/server/config"
|
"github.com/tharsis/ethermint/server/config"
|
||||||
"github.com/tharsis/ethermint/tests"
|
"github.com/tharsis/ethermint/tests"
|
||||||
"github.com/tharsis/ethermint/x/evm/statedb"
|
"github.com/tharsis/ethermint/x/evm/statedb"
|
||||||
@ -14,12 +16,8 @@ import (
|
|||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func nextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
|
func (suite MiddlewareTestSuite) TestEthSigVerificationDecorator() {
|
||||||
return ctx, nil
|
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthSigVerificationMiddleware(suite.app.EvmKeeper))
|
||||||
}
|
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
|
|
||||||
dec := ante.NewEthSigVerificationDecorator(suite.app.EvmKeeper)
|
|
||||||
addr, privKey := tests.NewAddrKey()
|
addr, privKey := tests.NewAddrKey()
|
||||||
|
|
||||||
signedTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
signedTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||||
@ -46,7 +44,7 @@ func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
suite.Run(tc.name, func() {
|
suite.Run(tc.name, func() {
|
||||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, nextFn)
|
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
@ -57,10 +55,10 @@ func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
|
func (suite MiddlewareTestSuite) TestNewEthAccountVerificationDecorator() {
|
||||||
dec := ante.NewEthAccountVerificationDecorator(
|
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthAccountVerificationMiddleware(
|
||||||
suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.EvmKeeper,
|
suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.EvmKeeper,
|
||||||
)
|
))
|
||||||
|
|
||||||
addr := tests.GenerateAddress()
|
addr := tests.GenerateAddress()
|
||||||
|
|
||||||
@ -134,8 +132,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
|
|||||||
tc.malleate()
|
tc.malleate()
|
||||||
suite.Require().NoError(vmdb.Commit())
|
suite.Require().NoError(vmdb.Commit())
|
||||||
|
|
||||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(tc.checkTx), tc.tx, false, nextFn)
|
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx.WithIsCheckTx(tc.checkTx)), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
||||||
@ -145,10 +142,9 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestEthNonceVerificationDecorator() {
|
func (suite MiddlewareTestSuite) TestEthNonceVerificationDecorator() {
|
||||||
suite.SetupTest()
|
suite.SetupTest()
|
||||||
dec := ante.NewEthIncrementSenderSequenceDecorator(suite.app.AccountKeeper)
|
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthIncrementSenderSequenceMiddleware(suite.app.AccountKeeper))
|
||||||
|
|
||||||
addr := tests.GenerateAddress()
|
addr := tests.GenerateAddress()
|
||||||
|
|
||||||
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||||
@ -190,7 +186,7 @@ func (suite AnteTestSuite) TestEthNonceVerificationDecorator() {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
suite.Run(tc.name, func() {
|
suite.Run(tc.name, func() {
|
||||||
tc.malleate()
|
tc.malleate()
|
||||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, nextFn)
|
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
@ -201,8 +197,8 @@ func (suite AnteTestSuite) TestEthNonceVerificationDecorator() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
func (suite MiddlewareTestSuite) TestEthGasConsumeDecorator() {
|
||||||
dec := ante.NewEthGasConsumeDecorator(suite.app.EvmKeeper, config.DefaultMaxTxGasWanted)
|
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthGasConsumeMiddleware(suite.app.EvmKeeper, config.DefaultMaxTxGasWanted))
|
||||||
|
|
||||||
addr := tests.GenerateAddress()
|
addr := tests.GenerateAddress()
|
||||||
|
|
||||||
@ -287,24 +283,24 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
|||||||
|
|
||||||
if tc.expPanic {
|
if tc.expPanic {
|
||||||
suite.Require().Panics(func() {
|
suite.Require().Panics(func() {
|
||||||
_, _ = dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewGasMeter(1)), tc.tx, false, nextFn)
|
_, _, _ = txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewGasMeter(1))), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter()), tc.tx, false, nextFn)
|
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter())), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err)
|
suite.Require().Error(err)
|
||||||
}
|
}
|
||||||
suite.Require().Equal(tc.gasLimit, ctx.GasMeter().Limit())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestCanTransferDecorator() {
|
func (suite MiddlewareTestSuite) TestCanTransferDecorator() {
|
||||||
dec := ante.NewCanTransferDecorator(suite.app.EvmKeeper)
|
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewCanTransferMiddleware(suite.app.EvmKeeper))
|
||||||
|
|
||||||
addr, privKey := tests.NewAddrKey()
|
addr, privKey := tests.NewAddrKey()
|
||||||
|
|
||||||
@ -376,8 +372,7 @@ func (suite AnteTestSuite) TestCanTransferDecorator() {
|
|||||||
tc.malleate()
|
tc.malleate()
|
||||||
suite.Require().NoError(vmdb.Commit())
|
suite.Require().NoError(vmdb.Commit())
|
||||||
|
|
||||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
|
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx.WithIsCheckTx(true)), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
||||||
@ -387,8 +382,8 @@ func (suite AnteTestSuite) TestCanTransferDecorator() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
|
func (suite MiddlewareTestSuite) TestEthIncrementSenderSequenceDecorator() {
|
||||||
dec := ante.NewEthIncrementSenderSequenceDecorator(suite.app.AccountKeeper)
|
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthIncrementSenderSequenceMiddleware(suite.app.AccountKeeper))
|
||||||
addr, privKey := tests.NewAddrKey()
|
addr, privKey := tests.NewAddrKey()
|
||||||
|
|
||||||
contract := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 0, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
contract := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 0, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||||
@ -455,12 +450,17 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
|
|||||||
|
|
||||||
if tc.expPanic {
|
if tc.expPanic {
|
||||||
suite.Require().Panics(func() {
|
suite.Require().Panics(func() {
|
||||||
_, _ = dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
|
_, _, _ = txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
|
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
@ -478,8 +478,8 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestEthSetupContextDecorator() {
|
func (suite MiddlewareTestSuite) TestEthSetupContextDecorator() {
|
||||||
dec := ante.NewEthSetUpContextDecorator(suite.app.EvmKeeper)
|
txHandler := middleware.ComposeMiddlewares(noopTxHandler, ante.NewEthSetUpContextMiddleware(suite.app.EvmKeeper))
|
||||||
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
@ -497,8 +497,7 @@ func (suite AnteTestSuite) TestEthSetupContextDecorator() {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
suite.Run(tc.name, func() {
|
suite.Run(tc.name, func() {
|
||||||
_, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
|
_, _, err := txHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.tx}, txtypes.RequestCheckTx{})
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
@ -1,4 +1,4 @@
|
|||||||
package ante
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
116
app/middleware/middleware.go
Normal file
116
app/middleware/middleware.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
authmiddleware "github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
||||||
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
secp256k1VerifyCost uint64 = 21000
|
||||||
|
)
|
||||||
|
|
||||||
|
type txRouter struct {
|
||||||
|
eth, cosmos, eip712 tx.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = txRouter{}
|
||||||
|
|
||||||
|
func NewTxHandler(options HandlerOptions) tx.Handler {
|
||||||
|
return authmiddleware.ComposeMiddlewares(
|
||||||
|
authmiddleware.NewRunMsgsTxHandler(options.MsgServiceRouter, options.LegacyRouter),
|
||||||
|
authmiddleware.NewTxDecoderMiddleware(options.TxDecoder),
|
||||||
|
NewTxRouterMiddleware(options),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTxRouterMiddleware(options HandlerOptions) tx.Middleware {
|
||||||
|
ethMiddleware := newEthAuthMiddleware(options)
|
||||||
|
cosmoseip712 := newCosmosMiddlewareEip712(options)
|
||||||
|
cosmosMiddleware := newCosmosAuthMiddleware(options)
|
||||||
|
return func(txh tx.Handler) tx.Handler {
|
||||||
|
return txRouter{
|
||||||
|
eth: ethMiddleware(txh),
|
||||||
|
cosmos: cosmosMiddleware(txh),
|
||||||
|
eip712: cosmoseip712(txh),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (txh txRouter) route(req tx.Request) (tx.Handler, error) {
|
||||||
|
txWithExtensions, ok := req.Tx.(authmiddleware.HasExtensionOptionsTx)
|
||||||
|
if ok {
|
||||||
|
opts := txWithExtensions.GetExtensionOptions()
|
||||||
|
if len(opts) > 0 {
|
||||||
|
var next tx.Handler
|
||||||
|
switch typeURL := opts[0].GetTypeUrl(); typeURL {
|
||||||
|
case "/ethermint.evm.v1.ExtensionOptionsEthereumTx":
|
||||||
|
// handle as *evmtypes.MsgEthereumTx
|
||||||
|
next = txh.eth
|
||||||
|
case "/ethermint.types.v1.ExtensionOptionsWeb3Tx":
|
||||||
|
// handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation
|
||||||
|
next = txh.eip712
|
||||||
|
default:
|
||||||
|
return nil, sdkerrors.Wrapf(
|
||||||
|
sdkerrors.ErrUnknownExtensionOptions,
|
||||||
|
"rejecting tx with unsupported extension option: %s", typeURL,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return next, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// handle as totally normal Cosmos SDK tx
|
||||||
|
return txh.cosmos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (txh txRouter) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (res tx.Response, rct tx.ResponseCheckTx, err error) {
|
||||||
|
next, err := txh.route(req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return next.CheckTx(ctx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (txh txRouter) DeliverTx(ctx context.Context, req tx.Request) (res tx.Response, err error) {
|
||||||
|
next, err := txh.route(req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return next.DeliverTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (txh txRouter) SimulateTx(ctx context.Context, req tx.Request) (res tx.Response, err error) {
|
||||||
|
next, err := txh.route(req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return next.SimulateTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = DefaultSigVerificationGasConsumer
|
||||||
|
|
||||||
|
// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
|
||||||
|
// for signature verification based upon the public key type. The cost is fetched from the given params and is matched
|
||||||
|
// by the concrete type.
|
||||||
|
func DefaultSigVerificationGasConsumer(
|
||||||
|
meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params,
|
||||||
|
) error {
|
||||||
|
// support for ethereum ECDSA secp256k1 keys
|
||||||
|
_, ok := sig.PubKey.(*ethsecp256k1.PubKey)
|
||||||
|
if ok {
|
||||||
|
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: eth_secp256k1")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return authmiddleware.DefaultSigVerificationGasConsumer(meter, sig, params)
|
||||||
|
}
|
@ -1,10 +1,13 @@
|
|||||||
package ante_test
|
package middleware_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
|
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
@ -13,7 +16,7 @@ import (
|
|||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestAnteHandler() {
|
func (suite MiddlewareTestSuite) TestAnteHandler() {
|
||||||
suite.enableFeemarket = false
|
suite.enableFeemarket = false
|
||||||
suite.SetupTest() // reset
|
suite.SetupTest() // reset
|
||||||
|
|
||||||
@ -297,7 +300,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
"success - DeliverTx EIP712 signed Cosmos Tx with MsgSend",
|
"success - DeliverTx EIP712 signed Cosmos Tx with MsgSend",
|
||||||
func() sdk.Tx {
|
func() sdk.Tx {
|
||||||
from := acc.GetAddress()
|
from := acc.GetAddress()
|
||||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
|
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(200000)))
|
||||||
gas := uint64(200000)
|
gas := uint64(200000)
|
||||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9000-1", gas, amount)
|
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
return txBuilder.GetTx()
|
return txBuilder.GetTx()
|
||||||
@ -307,7 +310,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
"success - DeliverTx EIP712 signed Cosmos Tx with DelegateMsg",
|
"success - DeliverTx EIP712 signed Cosmos Tx with DelegateMsg",
|
||||||
func() sdk.Tx {
|
func() sdk.Tx {
|
||||||
from := acc.GetAddress()
|
from := acc.GetAddress()
|
||||||
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20))
|
coinAmount := sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(200000))
|
||||||
amount := sdk.NewCoins(coinAmount)
|
amount := sdk.NewCoins(coinAmount)
|
||||||
gas := uint64(200000)
|
gas := uint64(200000)
|
||||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgDelegate(from, privKey, "ethermint_9000-1", gas, amount)
|
txBuilder := suite.CreateTestEIP712TxBuilderMsgDelegate(from, privKey, "ethermint_9000-1", gas, amount)
|
||||||
@ -318,7 +321,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
"fails - DeliverTx EIP712 signed Cosmos Tx with wrong Chain ID",
|
"fails - DeliverTx EIP712 signed Cosmos Tx with wrong Chain ID",
|
||||||
func() sdk.Tx {
|
func() sdk.Tx {
|
||||||
from := acc.GetAddress()
|
from := acc.GetAddress()
|
||||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
|
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(200000)))
|
||||||
gas := uint64(200000)
|
gas := uint64(200000)
|
||||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9002-1", gas, amount)
|
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9002-1", gas, amount)
|
||||||
return txBuilder.GetTx()
|
return txBuilder.GetTx()
|
||||||
@ -328,7 +331,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
"fails - DeliverTx EIP712 signed Cosmos Tx with different gas fees",
|
"fails - DeliverTx EIP712 signed Cosmos Tx with different gas fees",
|
||||||
func() sdk.Tx {
|
func() sdk.Tx {
|
||||||
from := acc.GetAddress()
|
from := acc.GetAddress()
|
||||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
|
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(200000)))
|
||||||
gas := uint64(200000)
|
gas := uint64(200000)
|
||||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
||||||
txBuilder.SetGasLimit(uint64(300000))
|
txBuilder.SetGasLimit(uint64(300000))
|
||||||
@ -340,7 +343,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
"fails - DeliverTx EIP712 signed Cosmos Tx with empty signature",
|
"fails - DeliverTx EIP712 signed Cosmos Tx with empty signature",
|
||||||
func() sdk.Tx {
|
func() sdk.Tx {
|
||||||
from := acc.GetAddress()
|
from := acc.GetAddress()
|
||||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
|
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(200000)))
|
||||||
gas := uint64(200000)
|
gas := uint64(200000)
|
||||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
||||||
sigsV2 := signing.SignatureV2{}
|
sigsV2 := signing.SignatureV2{}
|
||||||
@ -352,7 +355,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
"fails - DeliverTx EIP712 signed Cosmos Tx with invalid sequence",
|
"fails - DeliverTx EIP712 signed Cosmos Tx with invalid sequence",
|
||||||
func() sdk.Tx {
|
func() sdk.Tx {
|
||||||
from := acc.GetAddress()
|
from := acc.GetAddress()
|
||||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
|
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(200000)))
|
||||||
gas := uint64(200000)
|
gas := uint64(200000)
|
||||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
||||||
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
|
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
|
||||||
@ -372,7 +375,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
"fails - DeliverTx EIP712 signed Cosmos Tx with invalid signMode",
|
"fails - DeliverTx EIP712 signed Cosmos Tx with invalid signMode",
|
||||||
func() sdk.Tx {
|
func() sdk.Tx {
|
||||||
from := acc.GetAddress()
|
from := acc.GetAddress()
|
||||||
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
|
amount := sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(200000)))
|
||||||
gas := uint64(200000)
|
gas := uint64(200000)
|
||||||
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
txBuilder := suite.CreateTestEIP712TxBuilderMsgSend(from, privKey, "ethermint_9001-1", gas, amount)
|
||||||
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
|
nonce, err := suite.app.AccountKeeper.GetSequence(suite.ctx, acc.GetAddress())
|
||||||
@ -395,8 +398,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx)
|
suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx)
|
||||||
|
|
||||||
// expConsumed := params.TxGasContractCreation + params.TxGas
|
// expConsumed := params.TxGasContractCreation + params.TxGas
|
||||||
_, err := suite.anteHandler(suite.ctx, tc.txFn(), false)
|
_, _, err := suite.anteHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.txFn()}, tx.RequestCheckTx{})
|
||||||
|
|
||||||
// suite.Require().Equal(consumed, ctx.GasMeter().GasConsumed())
|
// suite.Require().Equal(consumed, ctx.GasMeter().GasConsumed())
|
||||||
|
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
@ -409,7 +411,7 @@ func (suite AnteTestSuite) TestAnteHandler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
func (suite MiddlewareTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
||||||
addr, privKey := tests.NewAddrKey()
|
addr, privKey := tests.NewAddrKey()
|
||||||
to := tests.GenerateAddress()
|
to := tests.GenerateAddress()
|
||||||
|
|
||||||
@ -674,7 +676,7 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
|
|||||||
|
|
||||||
suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx)
|
suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx)
|
||||||
suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt((ethparams.InitialBaseFee+10)*100000))
|
suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt((ethparams.InitialBaseFee+10)*100000))
|
||||||
_, err := suite.anteHandler(suite.ctx, tc.txFn(), false)
|
_, _, err := suite.anteHandler.CheckTx(sdk.WrapSDKContext(suite.ctx), txtypes.Request{Tx: tc.txFn()}, tx.RequestCheckTx{})
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
} else {
|
} else {
|
178
app/middleware/options.go
Normal file
178
app/middleware/options.go
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
authmiddleware "github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
||||||
|
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandlerOptions extend the SDK's TxHandler options by requiring the IBC
|
||||||
|
// channel keeper, EVM Keeper and Fee Market Keeper.
|
||||||
|
type HandlerOptions struct {
|
||||||
|
Debug bool
|
||||||
|
|
||||||
|
Codec codec.Codec
|
||||||
|
// TxDecoder is used to decode the raw tx bytes into a sdk.Tx.
|
||||||
|
TxDecoder sdk.TxDecoder
|
||||||
|
|
||||||
|
// IndexEvents defines the set of events in the form {eventType}.{attributeKey},
|
||||||
|
// which informs Tendermint what to index. If empty, all events will be indexed.
|
||||||
|
IndexEvents map[string]struct{}
|
||||||
|
|
||||||
|
LegacyRouter sdk.Router
|
||||||
|
MsgServiceRouter *authmiddleware.MsgServiceRouter
|
||||||
|
|
||||||
|
ExtensionOptionChecker authmiddleware.ExtensionOptionChecker
|
||||||
|
TxFeeChecker authmiddleware.TxFeeChecker
|
||||||
|
|
||||||
|
AccountKeeper evmtypes.AccountKeeper
|
||||||
|
BankKeeper evmtypes.BankKeeper
|
||||||
|
FeeMarketKeeper evmtypes.FeeMarketKeeper
|
||||||
|
EvmKeeper EVMKeeper
|
||||||
|
FeegrantKeeper authmiddleware.FeegrantKeeper
|
||||||
|
SignModeHandler authsigning.SignModeHandler
|
||||||
|
SigGasConsumer func(meter sdk.GasMeter, sig signing.SignatureV2, params authtypes.Params) error
|
||||||
|
MaxTxGasWanted uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (options HandlerOptions) Validate() error {
|
||||||
|
if options.TxDecoder == nil {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrLogic, "txDecoder is required for middlewares")
|
||||||
|
}
|
||||||
|
if options.SignModeHandler == nil {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for middlewares")
|
||||||
|
}
|
||||||
|
if options.AccountKeeper == nil {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for middlewares")
|
||||||
|
}
|
||||||
|
if options.BankKeeper == nil {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for middlewares")
|
||||||
|
}
|
||||||
|
if options.SignModeHandler == nil {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for middlewares")
|
||||||
|
}
|
||||||
|
if options.FeeMarketKeeper == nil {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrLogic, "fee market keeper is required for middlewares")
|
||||||
|
}
|
||||||
|
if options.EvmKeeper == nil {
|
||||||
|
return sdkerrors.Wrap(sdkerrors.ErrLogic, "evm keeper is required for middlewares")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newEthAuthMiddleware(options HandlerOptions) tx.Middleware {
|
||||||
|
stack := []tx.Middleware{
|
||||||
|
NewEthSetUpContextMiddleware(options.EvmKeeper),
|
||||||
|
NewEthMempoolFeeMiddleware(options.EvmKeeper),
|
||||||
|
authmiddleware.NewIndexEventsTxMiddleware(options.IndexEvents),
|
||||||
|
NewEthValidateBasicMiddleware(options.EvmKeeper),
|
||||||
|
NewEthSigVerificationMiddleware(options.EvmKeeper),
|
||||||
|
NewEthAccountVerificationMiddleware(options.AccountKeeper, options.BankKeeper, options.EvmKeeper),
|
||||||
|
NewEthGasConsumeMiddleware(options.EvmKeeper, options.MaxTxGasWanted),
|
||||||
|
NewCanTransferMiddleware(options.EvmKeeper),
|
||||||
|
NewEthIncrementSenderSequenceMiddleware(options.AccountKeeper),
|
||||||
|
}
|
||||||
|
return func(txh tx.Handler) tx.Handler {
|
||||||
|
return authmiddleware.ComposeMiddlewares(txh, stack...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCosmosAuthMiddleware(options HandlerOptions) tx.Middleware {
|
||||||
|
stack := []tx.Middleware{
|
||||||
|
NewRejectMessagesMiddleware,
|
||||||
|
// Set a new GasMeter on sdk.Context.
|
||||||
|
//
|
||||||
|
// Make sure the Gas middleware is outside of all other middlewares
|
||||||
|
// that reads the GasMeter. In our case, the Recovery middleware reads
|
||||||
|
// the GasMeter to populate GasInfo.
|
||||||
|
authmiddleware.GasTxMiddleware,
|
||||||
|
// Recover from panics. Panics outside of this middleware won't be
|
||||||
|
// caught, be careful!
|
||||||
|
authmiddleware.RecoveryTxMiddleware,
|
||||||
|
// Choose which events to index in Tendermint. Make sure no events are
|
||||||
|
// emitted outside of this middleware.
|
||||||
|
authmiddleware.NewIndexEventsTxMiddleware(options.IndexEvents),
|
||||||
|
// Reject all extension options other than the ones needed by the feemarket.
|
||||||
|
authmiddleware.NewExtensionOptionsMiddleware(options.ExtensionOptionChecker),
|
||||||
|
authmiddleware.ValidateBasicMiddleware,
|
||||||
|
authmiddleware.TxTimeoutHeightMiddleware,
|
||||||
|
authmiddleware.ValidateMemoMiddleware(options.AccountKeeper),
|
||||||
|
authmiddleware.ConsumeTxSizeGasMiddleware(options.AccountKeeper),
|
||||||
|
// No gas should be consumed in any middleware above in a "post" handler part. See
|
||||||
|
// ComposeMiddlewares godoc for details.
|
||||||
|
// `DeductFeeMiddleware` and `IncrementSequenceMiddleware` should be put outside of `WithBranchedStore` middleware,
|
||||||
|
// so their storage writes are not discarded when tx fails.
|
||||||
|
authmiddleware.DeductFeeMiddleware(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
||||||
|
authmiddleware.SetPubKeyMiddleware(options.AccountKeeper),
|
||||||
|
authmiddleware.ValidateSigCountMiddleware(options.AccountKeeper),
|
||||||
|
authmiddleware.SigGasConsumeMiddleware(options.AccountKeeper, options.SigGasConsumer),
|
||||||
|
authmiddleware.SigVerificationMiddleware(options.AccountKeeper, options.SignModeHandler),
|
||||||
|
authmiddleware.IncrementSequenceMiddleware(options.AccountKeeper),
|
||||||
|
// Creates a new MultiStore branch, discards downstream writes if the downstream returns error.
|
||||||
|
// These kinds of middlewares should be put under this:
|
||||||
|
// - Could return error after messages executed succesfully.
|
||||||
|
// - Storage writes should be discarded together when tx failed.
|
||||||
|
authmiddleware.WithBranchedStore,
|
||||||
|
// Consume block gas. All middlewares whose gas consumption after their `next` handler
|
||||||
|
// should be accounted for, should go below this middleware.
|
||||||
|
authmiddleware.ConsumeBlockGasMiddleware,
|
||||||
|
authmiddleware.NewTipMiddleware(options.BankKeeper),
|
||||||
|
}
|
||||||
|
return func(txh tx.Handler) tx.Handler {
|
||||||
|
return authmiddleware.ComposeMiddlewares(txh, stack...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCosmosMiddlewareEip712(options HandlerOptions) tx.Middleware {
|
||||||
|
stack := []tx.Middleware{
|
||||||
|
NewRejectMessagesMiddleware,
|
||||||
|
// Set a new GasMeter on sdk.Context.
|
||||||
|
//
|
||||||
|
// Make sure the Gas middleware is outside of all other middlewares
|
||||||
|
// that reads the GasMeter. In our case, the Recovery middleware reads
|
||||||
|
// the GasMeter to populate GasInfo.
|
||||||
|
authmiddleware.GasTxMiddleware,
|
||||||
|
// Recover from panics. Panics outside of this middleware won't be
|
||||||
|
// caught, be careful!
|
||||||
|
authmiddleware.RecoveryTxMiddleware,
|
||||||
|
// Choose which events to index in Tendermint. Make sure no events are
|
||||||
|
// emitted outside of this middleware.
|
||||||
|
authmiddleware.NewIndexEventsTxMiddleware(options.IndexEvents),
|
||||||
|
// Reject all extension options other than the ones needed by the feemarket.
|
||||||
|
// authmiddleware.NewExtensionOptionsMiddleware(options.ExtensionOptionChecker),
|
||||||
|
authmiddleware.ValidateBasicMiddleware,
|
||||||
|
authmiddleware.TxTimeoutHeightMiddleware,
|
||||||
|
authmiddleware.ValidateMemoMiddleware(options.AccountKeeper),
|
||||||
|
authmiddleware.ConsumeTxSizeGasMiddleware(options.AccountKeeper),
|
||||||
|
// No gas should be consumed in any middleware above in a "post" handler part. See
|
||||||
|
// ComposeMiddlewares godoc for details.
|
||||||
|
// `DeductFeeMiddleware` and `IncrementSequenceMiddleware` should be put outside of `WithBranchedStore` middleware,
|
||||||
|
// so their storage writes are not discarded when tx fails.
|
||||||
|
authmiddleware.DeductFeeMiddleware(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
||||||
|
authmiddleware.SetPubKeyMiddleware(options.AccountKeeper),
|
||||||
|
authmiddleware.ValidateSigCountMiddleware(options.AccountKeeper),
|
||||||
|
authmiddleware.SigGasConsumeMiddleware(options.AccountKeeper, options.SigGasConsumer),
|
||||||
|
// Note: signature verification uses EIP instead of the cosmos signature validator
|
||||||
|
NewEip712SigVerificationMiddleware(options.Codec, options.AccountKeeper, options.SignModeHandler),
|
||||||
|
authmiddleware.IncrementSequenceMiddleware(options.AccountKeeper),
|
||||||
|
// Creates a new MultiStore branch, discards downstream writes if the downstream returns error.
|
||||||
|
// These kinds of middlewares should be put under this:
|
||||||
|
// - Could return error after messages executed succesfully.
|
||||||
|
// - Storage writes should be discarded together when tx failed.
|
||||||
|
authmiddleware.WithBranchedStore,
|
||||||
|
// Consume block gas. All middlewares whose gas consumption after their `next` handler
|
||||||
|
// should be accounted for, should go below this middleware.
|
||||||
|
authmiddleware.ConsumeBlockGasMiddleware,
|
||||||
|
authmiddleware.NewTipMiddleware(options.BankKeeper),
|
||||||
|
}
|
||||||
|
return func(txh tx.Handler) tx.Handler {
|
||||||
|
return authmiddleware.ComposeMiddlewares(txh, stack...)
|
||||||
|
}
|
||||||
|
}
|
67
app/middleware/reject.go
Normal file
67
app/middleware/reject.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RejectMessagesMiddleware prevents invalid msg types from being executed
|
||||||
|
type RejectMessagesMiddleware struct {
|
||||||
|
next tx.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRejectMessagesMiddleware(txh tx.Handler) tx.Handler {
|
||||||
|
return RejectMessagesMiddleware{
|
||||||
|
next: txh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Middleware rejects messages that requires ethereum-specific authentication.
|
||||||
|
// For example `MsgEthereumTx` requires fee to be deducted in the antehandler in
|
||||||
|
// order to perform the refund.
|
||||||
|
|
||||||
|
// CheckTx implements tx.Handler
|
||||||
|
func (rmd RejectMessagesMiddleware) CheckTx(ctx context.Context, req tx.Request, checkReq tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
if _, err := reject(req); err != nil {
|
||||||
|
return tx.Response{}, tx.ResponseCheckTx{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rmd.next.CheckTx(ctx, req, checkReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeliverTx implements tx.Handler
|
||||||
|
func (rmd RejectMessagesMiddleware) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
if _, err := reject(req); err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rmd.next.DeliverTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateTx implements tx.Handler
|
||||||
|
func (rmd RejectMessagesMiddleware) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
if _, err := reject(req); err != nil {
|
||||||
|
return tx.Response{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rmd.next.SimulateTx(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func reject(req tx.Request) (tx.Response, error) {
|
||||||
|
reqTx := req.Tx
|
||||||
|
for _, msg := range reqTx.GetMsgs() {
|
||||||
|
if _, ok := msg.(*evmtypes.MsgEthereumTx); ok {
|
||||||
|
return tx.Response{}, sdkerrors.Wrapf(
|
||||||
|
sdkerrors.ErrInvalidType,
|
||||||
|
"MsgEthereumTx needs to be contained within a tx with 'ExtensionOptionsEthereumTx' option",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.Response{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = RejectMessagesMiddleware{}
|
@ -1,4 +1,4 @@
|
|||||||
package ante_test
|
package middleware_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
@ -8,7 +8,7 @@ import (
|
|||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (suite AnteTestSuite) TestSignatures() {
|
func (suite MiddlewareTestSuite) TestSignatures() {
|
||||||
suite.enableFeemarket = false
|
suite.enableFeemarket = false
|
||||||
suite.SetupTest() // reset
|
suite.SetupTest() // reset
|
||||||
|
|
@ -1,16 +1,21 @@
|
|||||||
package ante_test
|
package middleware_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
context "context"
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
clientTx "github.com/cosmos/cosmos-sdk/client/tx"
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
|
"github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx"
|
||||||
types2 "github.com/cosmos/cosmos-sdk/x/bank/types"
|
types2 "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
types3 "github.com/cosmos/cosmos-sdk/x/staking/types"
|
types3 "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
"github.com/tharsis/ethermint/app/middleware"
|
||||||
"github.com/tharsis/ethermint/ethereum/eip712"
|
"github.com/tharsis/ethermint/ethereum/eip712"
|
||||||
|
"github.com/tharsis/ethermint/server/config"
|
||||||
"github.com/tharsis/ethermint/types"
|
"github.com/tharsis/ethermint/types"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -19,48 +24,69 @@ import (
|
|||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/tx"
|
|
||||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
|
||||||
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
"github.com/tharsis/ethermint/app"
|
"github.com/tharsis/ethermint/app"
|
||||||
ante "github.com/tharsis/ethermint/app/ante"
|
|
||||||
"github.com/tharsis/ethermint/encoding"
|
"github.com/tharsis/ethermint/encoding"
|
||||||
"github.com/tharsis/ethermint/tests"
|
"github.com/tharsis/ethermint/tests"
|
||||||
"github.com/tharsis/ethermint/x/evm/statedb"
|
"github.com/tharsis/ethermint/x/evm/statedb"
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
||||||
|
|
||||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AnteTestSuite struct {
|
// customTxHandler is a test middleware that will run a custom function.
|
||||||
|
type customTxHandler struct {
|
||||||
|
fn func(context.Context, tx.Request) (tx.Response, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ tx.Handler = customTxHandler{}
|
||||||
|
|
||||||
|
func (h customTxHandler) DeliverTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
return h.fn(ctx, req)
|
||||||
|
}
|
||||||
|
func (h customTxHandler) CheckTx(ctx context.Context, req tx.Request, _ tx.RequestCheckTx) (tx.Response, tx.ResponseCheckTx, error) {
|
||||||
|
res, err := h.fn(ctx, req)
|
||||||
|
return res, tx.ResponseCheckTx{}, err
|
||||||
|
}
|
||||||
|
func (h customTxHandler) SimulateTx(ctx context.Context, req tx.Request) (tx.Response, error) {
|
||||||
|
return h.fn(ctx, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// noopTxHandler is a test middleware that returns an empty response.
|
||||||
|
var noopTxHandler = customTxHandler{func(_ context.Context, _ tx.Request) (tx.Response, error) {
|
||||||
|
return tx.Response{}, nil
|
||||||
|
}}
|
||||||
|
|
||||||
|
type MiddlewareTestSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
|
|
||||||
ctx sdk.Context
|
ctx sdk.Context
|
||||||
app *app.EthermintApp
|
app *app.EthermintApp
|
||||||
clientCtx client.Context
|
clientCtx client.Context
|
||||||
anteHandler sdk.AnteHandler
|
anteHandler tx.Handler
|
||||||
ethSigner ethtypes.Signer
|
ethSigner ethtypes.Signer
|
||||||
enableFeemarket bool
|
enableFeemarket bool
|
||||||
enableLondonHF bool
|
enableLondonHF bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) StateDB() *statedb.StateDB {
|
func (suite *MiddlewareTestSuite) StateDB() *statedb.StateDB {
|
||||||
return statedb.New(suite.ctx, suite.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(suite.ctx.HeaderHash().Bytes())))
|
return statedb.New(suite.ctx, suite.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(suite.ctx.HeaderHash().Bytes())))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) SetupTest() {
|
func (suite *MiddlewareTestSuite) SetupTest() {
|
||||||
checkTx := false
|
checkTx := false
|
||||||
|
|
||||||
suite.app = app.Setup(checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
suite.app = app.Setup(suite.T(), checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
||||||
if suite.enableFeemarket {
|
if suite.enableFeemarket {
|
||||||
// setup feemarketGenesis params
|
// setup feemarketGenesis params
|
||||||
feemarketGenesis := feemarkettypes.DefaultGenesisState()
|
feemarketGenesis := feemarkettypes.DefaultGenesisState()
|
||||||
@ -95,32 +121,37 @@ func (suite *AnteTestSuite) SetupTest() {
|
|||||||
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
|
encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
|
||||||
|
|
||||||
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
|
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
|
||||||
|
maxGasWanted := cast.ToUint64(config.DefaultMaxTxGasWanted)
|
||||||
|
|
||||||
options := ante.HandlerOptions{
|
options := middleware.HandlerOptions{
|
||||||
AccountKeeper: suite.app.AccountKeeper,
|
TxDecoder: suite.clientCtx.TxConfig.TxDecoder(),
|
||||||
BankKeeper: suite.app.BankKeeper,
|
AccountKeeper: suite.app.AccountKeeper,
|
||||||
EvmKeeper: suite.app.EvmKeeper,
|
BankKeeper: suite.app.BankKeeper,
|
||||||
FeegrantKeeper: suite.app.FeeGrantKeeper,
|
EvmKeeper: suite.app.EvmKeeper,
|
||||||
IBCKeeper: suite.app.IBCKeeper,
|
FeegrantKeeper: suite.app.FeeGrantKeeper,
|
||||||
FeeMarketKeeper: suite.app.FeeMarketKeeper,
|
Codec: suite.app.AppCodec(),
|
||||||
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
|
Debug: suite.app.Trace(),
|
||||||
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
LegacyRouter: suite.app.LegacyRouter,
|
||||||
|
MsgServiceRouter: suite.app.MsgSvcRouter,
|
||||||
|
FeeMarketKeeper: suite.app.FeeMarketKeeper,
|
||||||
|
SignModeHandler: suite.clientCtx.TxConfig.SignModeHandler(),
|
||||||
|
SigGasConsumer: middleware.DefaultSigVerificationGasConsumer,
|
||||||
|
MaxTxGasWanted: maxGasWanted,
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Require().NoError(options.Validate())
|
suite.Require().NoError(options.Validate())
|
||||||
|
suite.anteHandler = middleware.NewTxHandler(options)
|
||||||
suite.anteHandler = ante.NewAnteHandler(options)
|
|
||||||
suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
|
suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAnteTestSuite(t *testing.T) {
|
func TestMiddlewareTestSuite(t *testing.T) {
|
||||||
suite.Run(t, &AnteTestSuite{
|
suite.Run(t, &MiddlewareTestSuite{
|
||||||
enableLondonHF: true,
|
enableLondonHF: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateTestTx is a helper function to create a tx given multiple inputs.
|
// CreateTestTx is a helper function to create a tx given multiple inputs.
|
||||||
func (suite *AnteTestSuite) CreateTestTx(
|
func (suite *MiddlewareTestSuite) CreateTestTx(
|
||||||
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool,
|
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool,
|
||||||
unsetExtensionOptions ...bool,
|
unsetExtensionOptions ...bool,
|
||||||
) authsigning.Tx {
|
) authsigning.Tx {
|
||||||
@ -128,7 +159,7 @@ func (suite *AnteTestSuite) CreateTestTx(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateTestTxBuilder is a helper function to create a tx builder given multiple inputs.
|
// CreateTestTxBuilder is a helper function to create a tx builder given multiple inputs.
|
||||||
func (suite *AnteTestSuite) CreateTestTxBuilder(
|
func (suite *MiddlewareTestSuite) CreateTestTxBuilder(
|
||||||
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool,
|
msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey, accNum uint64, signCosmosTx bool,
|
||||||
unsetExtensionOptions ...bool,
|
unsetExtensionOptions ...bool,
|
||||||
) client.TxBuilder {
|
) client.TxBuilder {
|
||||||
@ -184,7 +215,7 @@ func (suite *AnteTestSuite) CreateTestTxBuilder(
|
|||||||
AccountNumber: accNum,
|
AccountNumber: accNum,
|
||||||
Sequence: txData.GetNonce(),
|
Sequence: txData.GetNonce(),
|
||||||
}
|
}
|
||||||
sigV2, err = tx.SignWithPrivKey(
|
sigV2, err = clientTx.SignWithPrivKey(
|
||||||
suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData,
|
suite.clientCtx.TxConfig.SignModeHandler().DefaultMode(), signerData,
|
||||||
txBuilder, priv, suite.clientCtx.TxConfig, txData.GetNonce(),
|
txBuilder, priv, suite.clientCtx.TxConfig, txData.GetNonce(),
|
||||||
)
|
)
|
||||||
@ -199,22 +230,22 @@ func (suite *AnteTestSuite) CreateTestTxBuilder(
|
|||||||
return txBuilder
|
return txBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
func (suite *MiddlewareTestSuite) CreateTestEIP712TxBuilderMsgSend(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
// Build MsgSend
|
// Build MsgSend
|
||||||
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
recipient := sdk.AccAddress(common.Address{}.Bytes())
|
||||||
msgSend := types2.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(1))))
|
msgSend := types2.NewMsgSend(from, recipient, sdk.NewCoins(sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(1))))
|
||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
func (suite *MiddlewareTestSuite) CreateTestEIP712TxBuilderMsgDelegate(from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins) client.TxBuilder {
|
||||||
// Build MsgSend
|
// Build MsgSend
|
||||||
valEthAddr := tests.GenerateAddress()
|
valEthAddr := tests.GenerateAddress()
|
||||||
valAddr := sdk.ValAddress(valEthAddr.Bytes())
|
valAddr := sdk.ValAddress(valEthAddr.Bytes())
|
||||||
msgSend := types3.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(20)))
|
msgSend := types3.NewMsgDelegate(from, valAddr, sdk.NewCoin(evmtypes.DefaultEVMDenom, sdk.NewInt(200000)))
|
||||||
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
return suite.CreateTestEIP712CosmosTxBuilder(from, priv, chainId, gas, gasAmount, msgSend)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
func (suite *MiddlewareTestSuite) CreateTestEIP712CosmosTxBuilder(
|
||||||
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msg sdk.Msg,
|
from sdk.AccAddress, priv cryptotypes.PrivKey, chainId string, gas uint64, gasAmount sdk.Coins, msg sdk.Msg,
|
||||||
) client.TxBuilder {
|
) client.TxBuilder {
|
||||||
var err error
|
var err error
|
||||||
@ -231,7 +262,7 @@ func (suite *AnteTestSuite) CreateTestEIP712CosmosTxBuilder(
|
|||||||
fee := legacytx.NewStdFee(gas, gasAmount)
|
fee := legacytx.NewStdFee(gas, gasAmount)
|
||||||
accNumber := suite.app.AccountKeeper.GetAccount(suite.ctx, from).GetAccountNumber()
|
accNumber := suite.app.AccountKeeper.GetAccount(suite.ctx, from).GetAccountNumber()
|
||||||
|
|
||||||
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, []sdk.Msg{msg}, "")
|
data := legacytx.StdSignBytes(chainId, accNumber, nonce, 0, fee, []sdk.Msg{msg}, "", nil)
|
||||||
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msg, data, &eip712.FeeDelegationOptions{
|
typedData, err := eip712.WrapTxToTypedData(ethermintCodec, ethChainId, msg, data, &eip712.FeeDelegationOptions{
|
||||||
FeePayer: from,
|
FeePayer: from,
|
||||||
})
|
})
|
@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||||
"github.com/cosmos/cosmos-sdk/store"
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
@ -27,12 +26,14 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/x/simulation"
|
"github.com/cosmos/cosmos-sdk/x/simulation"
|
||||||
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
||||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/db/memdb"
|
||||||
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||||
ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types"
|
ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types"
|
||||||
ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host"
|
ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
evmenc "github.com/tharsis/ethermint/encoding"
|
evmenc "github.com/tharsis/ethermint/encoding"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,21 +49,22 @@ func init() {
|
|||||||
const SimAppChainID = "simulation_777-1"
|
const SimAppChainID = "simulation_777-1"
|
||||||
|
|
||||||
type storeKeysPrefixes struct {
|
type storeKeysPrefixes struct {
|
||||||
A sdk.StoreKey
|
A storetypes.StoreKey
|
||||||
B sdk.StoreKey
|
B storetypes.StoreKey
|
||||||
Prefixes [][]byte
|
Prefixes [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
|
// fauxMerkleModeOpt returns a BaseApp option to use a dbStoreAdapter instead of
|
||||||
// an IAVLStore for faster simulation speed.
|
// an IAVLStore for faster simulation speed.
|
||||||
func fauxMerkleModeOpt(bapp *baseapp.BaseApp) {
|
var fauxMerkleModeOpt = baseapp.AppOptionFunc(func(bapp *baseapp.BaseApp) {
|
||||||
bapp.SetFauxMerkleMode()
|
bapp.SetFauxMerkleMode()
|
||||||
}
|
})
|
||||||
|
|
||||||
// interBlockCacheOpt returns a BaseApp option function that sets the persistent
|
// interBlockCacheOpt returns a BaseApp option function that sets the persistent
|
||||||
// inter-block write-through cache.
|
// inter-block write-through cache.
|
||||||
func interBlockCacheOpt() func(*baseapp.BaseApp) {
|
// TODO: implement this cache as enhancement to v2 multistore
|
||||||
return baseapp.SetInterBlockCache(store.NewCommitKVStoreCacheManager())
|
func interBlockCacheOpt() baseapp.AppOptionFunc {
|
||||||
|
return func(*baseapp.BaseApp) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFullAppSimulation(t *testing.T) {
|
func TestFullAppSimulation(t *testing.T) {
|
||||||
@ -310,7 +312,7 @@ func TestAppStateDeterminism(t *testing.T) {
|
|||||||
logger = log.NewNopLogger()
|
logger = log.NewNopLogger()
|
||||||
}
|
}
|
||||||
|
|
||||||
db := dbm.NewMemDB()
|
db := memdb.NewDB()
|
||||||
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, interBlockCacheOpt())
|
app := NewEthermintApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, simapp.FlagPeriodValue, MakeEncodingConfig(), simapp.EmptyAppOptions{}, interBlockCacheOpt())
|
||||||
|
|
||||||
fmt.Printf(
|
fmt.Printf(
|
||||||
|
@ -1,26 +1,50 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
|
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||||
|
"github.com/cosmos/cosmos-sdk/server/types"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
"github.com/tharsis/ethermint/encoding"
|
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
tmjson "github.com/tendermint/tendermint/libs/json"
|
||||||
|
"github.com/tharsis/ethermint/crypto/ethsecp256k1"
|
||||||
|
"github.com/tharsis/ethermint/encoding"
|
||||||
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/db/memdb"
|
||||||
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GenesisState of the blockchain is represented here as a map of raw json
|
||||||
|
// messages key'd by a identifier string.
|
||||||
|
// The identifier is used to determine which module genesis information belongs
|
||||||
|
// to so it may be appropriately routed during init chain.
|
||||||
|
// Within this application default genesis information is retrieved from
|
||||||
|
// the ModuleBasicManager which populates json from each BasicModule
|
||||||
|
// object provided to it during init.
|
||||||
|
|
||||||
// DefaultConsensusParams defines the default Tendermint consensus params used in
|
// DefaultConsensusParams defines the default Tendermint consensus params used in
|
||||||
// EthermintApp testing.
|
// EthermintApp testing.
|
||||||
var DefaultConsensusParams = &abci.ConsensusParams{
|
var DefaultConsensusParams = &tmproto.ConsensusParams{
|
||||||
Block: &abci.BlockParams{
|
Block: &tmproto.BlockParams{
|
||||||
MaxBytes: 200000,
|
MaxBytes: 200000,
|
||||||
MaxGas: -1, // no limit
|
MaxGas: -1, // no limit
|
||||||
},
|
},
|
||||||
@ -36,21 +60,50 @@ var DefaultConsensusParams = &abci.ConsensusParams{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp.
|
// SetupOptions defines arguments that are passed into `Simapp` constructor.
|
||||||
func Setup(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState) *EthermintApp {
|
type SetupOptions struct {
|
||||||
db := dbm.NewMemDB()
|
Logger log.Logger
|
||||||
app := NewEthermintApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5, encoding.MakeConfig(ModuleBasics), simapp.EmptyAppOptions{})
|
DB *memdb.MemDB
|
||||||
|
InvCheckPeriod uint
|
||||||
|
HomePath string
|
||||||
|
SkipUpgradeHeights map[int64]bool
|
||||||
|
EncConfig params.EncodingConfig
|
||||||
|
AppOpts types.AppOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTestAppWithCustomOptions(t *testing.T, isCheckTx bool, options SetupOptions) *EthermintApp {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
privVal := mock.NewPV()
|
||||||
|
pubKey, err := privVal.GetPubKey(context.TODO())
|
||||||
|
require.NoError(t, err)
|
||||||
|
// create validator set with single validator
|
||||||
|
validator := tmtypes.NewValidator(pubKey, 1)
|
||||||
|
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
|
||||||
|
|
||||||
|
// generate genesis account
|
||||||
|
priv, err := ethsecp256k1.GenerateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
|
||||||
|
|
||||||
|
acc := ðermint.EthAccount{
|
||||||
|
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(address.Bytes()), nil, 0, 0),
|
||||||
|
CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(),
|
||||||
|
}
|
||||||
|
|
||||||
|
balance := banktypes.Balance{
|
||||||
|
Address: acc.GetAddress().String(),
|
||||||
|
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
|
||||||
|
}
|
||||||
|
|
||||||
|
app := NewEthermintApp(options.Logger, options.DB, nil, true, options.SkipUpgradeHeights, options.HomePath, options.InvCheckPeriod, options.EncConfig, options.AppOpts)
|
||||||
|
genesisState := NewDefaultGenesisState(app.appCodec)
|
||||||
|
genesisState = genesisStateWithValSet(t, app, genesisState, valSet, []authtypes.GenesisAccount{acc}, balance)
|
||||||
|
|
||||||
if !isCheckTx {
|
if !isCheckTx {
|
||||||
// init chain must be called to stop deliverState from being nil
|
// init chain must be called to stop deliverState from being nil
|
||||||
genesisState := NewDefaultGenesisState()
|
stateBytes, err := tmjson.MarshalIndent(genesisState, "", " ")
|
||||||
if patchGenesis != nil {
|
require.NoError(t, err)
|
||||||
genesisState = patchGenesis(app, genesisState)
|
|
||||||
}
|
|
||||||
|
|
||||||
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the chain
|
// Initialize the chain
|
||||||
app.InitChain(
|
app.InitChain(
|
||||||
@ -66,6 +119,149 @@ func Setup(isCheckTx bool, patchGenesis func(*EthermintApp, simapp.GenesisState)
|
|||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup initializes a new EthermintApp. A Nop logger is set in EthermintApp.
|
||||||
|
func Setup(t *testing.T, isCheckTx bool, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState) *EthermintApp {
|
||||||
|
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
privVal := mock.NewPV()
|
||||||
|
pubKey, err := privVal.GetPubKey(context.TODO())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// create validator set with single validator
|
||||||
|
validator := tmtypes.NewValidator(pubKey, 1)
|
||||||
|
valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator})
|
||||||
|
|
||||||
|
priv, err := ethsecp256k1.GenerateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
address := common.BytesToAddress(priv.PubKey().Address().Bytes())
|
||||||
|
|
||||||
|
acc := ðermint.EthAccount{
|
||||||
|
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(address.Bytes()), nil, 0, 0),
|
||||||
|
CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(),
|
||||||
|
}
|
||||||
|
|
||||||
|
balance := banktypes.Balance{
|
||||||
|
Address: acc.GetAddress().String(),
|
||||||
|
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100000000000000))),
|
||||||
|
}
|
||||||
|
|
||||||
|
app := SetupWithGenesisValSet(t, valSet, patchGenesis, []authtypes.GenesisAccount{acc}, balance)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func setup(withGenesis bool, invCheckPeriod uint, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState) (*EthermintApp, simapp.GenesisState) {
|
||||||
|
encCdc := encoding.MakeConfig(ModuleBasics)
|
||||||
|
app := NewEthermintApp(log.NewNopLogger(), memdb.NewDB(), nil, true, map[int64]bool{}, DefaultNodeHome, invCheckPeriod, encCdc, EmptyAppOptions{})
|
||||||
|
if withGenesis {
|
||||||
|
genesisState := NewDefaultGenesisState(encCdc.Codec)
|
||||||
|
if patchGenesis != nil {
|
||||||
|
genesisState = patchGenesis(app, genesisState)
|
||||||
|
}
|
||||||
|
return app, genesisState
|
||||||
|
}
|
||||||
|
|
||||||
|
return app, simapp.GenesisState{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetupWithGenesisValSet initializes a new SimApp with a validator set and genesis accounts
|
||||||
|
// that also act as delegators. For simplicity, each validator is bonded with a delegation
|
||||||
|
// of one consensus engine unit in the default token of the simapp from first genesis
|
||||||
|
// account. A Nop logger is set in SimApp.
|
||||||
|
func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, patchGenesis func(*EthermintApp, simapp.GenesisState) simapp.GenesisState, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *EthermintApp {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
app, genesisState := setup(true, 5, patchGenesis)
|
||||||
|
genesisState = genesisStateWithValSet(t, app, genesisState, valSet, genAccs, balances...)
|
||||||
|
|
||||||
|
stateBytes, err := json.MarshalIndent(genesisState, "", " ")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// init chain will set the validator set and initialize the genesis accounts
|
||||||
|
app.InitChain(
|
||||||
|
abci.RequestInitChain{
|
||||||
|
ChainId: "ethermint_9000-1",
|
||||||
|
Validators: []abci.ValidatorUpdate{},
|
||||||
|
ConsensusParams: DefaultConsensusParams,
|
||||||
|
AppStateBytes: stateBytes,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// commit genesis changes
|
||||||
|
// app.Commit()
|
||||||
|
// app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{
|
||||||
|
// ChainID: "ethermint_9000-1",
|
||||||
|
// Height: app.LastBlockHeight() + 1,
|
||||||
|
// AppHash: app.LastCommitID().Hash,
|
||||||
|
// ValidatorsHash: valSet.Hash(),
|
||||||
|
// NextValidatorsHash: valSet.Hash(),
|
||||||
|
// }})
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func genesisStateWithValSet(t *testing.T, app *EthermintApp, genesisState simapp.GenesisState,
|
||||||
|
valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) simapp.GenesisState {
|
||||||
|
// set genesis accounts
|
||||||
|
authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
|
||||||
|
genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis)
|
||||||
|
|
||||||
|
validators := make([]stakingtypes.Validator, 0, len(valSet.Validators))
|
||||||
|
delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators))
|
||||||
|
|
||||||
|
bondAmt := sdk.DefaultPowerReduction
|
||||||
|
|
||||||
|
for _, val := range valSet.Validators {
|
||||||
|
pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey)
|
||||||
|
require.NoError(t, err)
|
||||||
|
pkAny, err := codectypes.NewAnyWithValue(pk)
|
||||||
|
require.NoError(t, err)
|
||||||
|
validator := stakingtypes.Validator{
|
||||||
|
OperatorAddress: sdk.ValAddress(val.Address).String(),
|
||||||
|
ConsensusPubkey: pkAny,
|
||||||
|
Jailed: false,
|
||||||
|
Status: stakingtypes.Bonded,
|
||||||
|
Tokens: bondAmt,
|
||||||
|
DelegatorShares: sdk.OneDec(),
|
||||||
|
Description: stakingtypes.Description{},
|
||||||
|
UnbondingHeight: int64(0),
|
||||||
|
UnbondingTime: time.Unix(0, 0).UTC(),
|
||||||
|
Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
|
||||||
|
MinSelfDelegation: sdk.ZeroInt(),
|
||||||
|
}
|
||||||
|
validators = append(validators, validator)
|
||||||
|
delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec()))
|
||||||
|
|
||||||
|
}
|
||||||
|
// set validators and delegations
|
||||||
|
stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations)
|
||||||
|
genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(stakingGenesis)
|
||||||
|
|
||||||
|
totalSupply := sdk.NewCoins()
|
||||||
|
for _, b := range balances {
|
||||||
|
// add genesis acc tokens to total supply
|
||||||
|
totalSupply = totalSupply.Add(b.Coins...)
|
||||||
|
}
|
||||||
|
|
||||||
|
for range delegations {
|
||||||
|
// add delegated tokens to total supply
|
||||||
|
totalSupply = totalSupply.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt))
|
||||||
|
}
|
||||||
|
|
||||||
|
// add bonded amount to bonded pool module account
|
||||||
|
balances = append(balances, banktypes.Balance{
|
||||||
|
Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(),
|
||||||
|
Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)},
|
||||||
|
})
|
||||||
|
|
||||||
|
// update total supply
|
||||||
|
bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{})
|
||||||
|
genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis)
|
||||||
|
|
||||||
|
return genesisState
|
||||||
|
}
|
||||||
|
|
||||||
// CreateRandomAccounts will generate random accounts
|
// CreateRandomAccounts will generate random accounts
|
||||||
func CreateRandomAccounts(accNum int) []sdk.AccAddress {
|
func CreateRandomAccounts(accNum int) []sdk.AccAddress {
|
||||||
// createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
|
// createRandomAccounts is a strategy used by addTestAddrs() in order to generated addresses in random order.
|
||||||
@ -77,3 +273,11 @@ func CreateRandomAccounts(accNum int) []sdk.AccAddress {
|
|||||||
|
|
||||||
return testAddrs
|
return testAddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmptyAppOptions is a stub implementing AppOptions
|
||||||
|
type EmptyAppOptions struct{}
|
||||||
|
|
||||||
|
// Get implements AppOptions
|
||||||
|
func (ao EmptyAppOptions) Get(o string) interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
"github.com/cosmos/cosmos-sdk/client/input"
|
"github.com/cosmos/cosmos-sdk/client/input"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto"
|
"github.com/cosmos/cosmos-sdk/crypto"
|
||||||
@ -30,12 +31,13 @@ func UnsafeExportEthKeyCommand() *cobra.Command {
|
|||||||
|
|
||||||
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
|
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
|
||||||
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
|
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
|
||||||
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||||
kr, err := keyring.New(
|
kr, err := keyring.New(
|
||||||
sdk.KeyringServiceName(),
|
sdk.KeyringServiceName(),
|
||||||
keyringBackend,
|
keyringBackend,
|
||||||
rootDir,
|
rootDir,
|
||||||
inBuf,
|
inBuf,
|
||||||
|
clientCtx.Codec,
|
||||||
hd.EthSecp256k1Option(),
|
hd.EthSecp256k1Option(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
"github.com/cosmos/cosmos-sdk/client/input"
|
"github.com/cosmos/cosmos-sdk/client/input"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto"
|
"github.com/cosmos/cosmos-sdk/crypto"
|
||||||
@ -31,12 +32,14 @@ func runImportCmd(cmd *cobra.Command, args []string) error {
|
|||||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||||
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
|
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
|
||||||
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
|
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
|
||||||
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
||||||
|
|
||||||
kb, err := keyring.New(
|
kb, err := keyring.New(
|
||||||
sdk.KeyringServiceName(),
|
sdk.KeyringServiceName(),
|
||||||
keyringBackend,
|
keyringBackend,
|
||||||
rootDir,
|
rootDir,
|
||||||
inBuf,
|
inBuf,
|
||||||
|
clientCtx.Codec,
|
||||||
hd.EthSecp256k1Option(),
|
hd.EthSecp256k1Option(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -92,7 +92,7 @@ func runAddCmd(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun)
|
dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun)
|
||||||
if dryRun {
|
if dryRun {
|
||||||
kr, err = keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, clientCtx.KeyringDir, buf, hd.EthSecp256k1Option())
|
kr, err = keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, clientCtx.KeyringDir, buf, clientCtx.Codec, hd.EthSecp256k1Option())
|
||||||
clientCtx = clientCtx.WithKeyring(kr)
|
clientCtx = clientCtx.WithKeyring(kr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
|
|||||||
|
|
||||||
if dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun); dryRun {
|
if dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun); dryRun {
|
||||||
// use in memory keybase
|
// use in memory keybase
|
||||||
kb = keyring.NewInMemory(etherminthd.EthSecp256k1Option())
|
kb = keyring.NewInMemory(ctx.Codec, etherminthd.EthSecp256k1Option())
|
||||||
} else {
|
} else {
|
||||||
_, err = kb.Key(name)
|
_, err = kb.Key(name)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -156,7 +156,9 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pks[i] = k.GetPubKey()
|
if pks[i], err = k.GetPubKey(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if noSort, _ := cmd.Flags().GetBool(flagNoSort); !noSort {
|
if noSort, _ := cmd.Flags().GetBool(flagNoSort); !noSort {
|
||||||
@ -183,7 +185,7 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := kb.SavePubKey(name, pk, algo.Name())
|
info, err := kb.SaveOfflineKey(name, pk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -289,7 +291,7 @@ func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
|
|||||||
return printCreate(cmd, info, showMnemonic, mnemonic, outputFormat)
|
return printCreate(cmd, info, showMnemonic, mnemonic, outputFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printCreate(cmd *cobra.Command, info keyring.Info, showMnemonic bool, mnemonic, outputFormat string) error {
|
func printCreate(cmd *cobra.Command, info *keyring.Record, showMnemonic bool, mnemonic, outputFormat string) error {
|
||||||
switch outputFormat {
|
switch outputFormat {
|
||||||
case OutputFormatText:
|
case OutputFormatText:
|
||||||
cmd.PrintErrln()
|
cmd.PrintErrln()
|
||||||
|
@ -3,7 +3,6 @@ package keys
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
|
||||||
@ -20,19 +19,9 @@ const (
|
|||||||
defaultKeyDBName = "keys"
|
defaultKeyDBName = "keys"
|
||||||
)
|
)
|
||||||
|
|
||||||
type bechKeyOutFn func(keyInfo cryptokeyring.Info) (cryptokeyring.KeyOutput, error)
|
type bechKeyOutFn func(keyInfo *cryptokeyring.Record) (cryptokeyring.KeyOutput, error)
|
||||||
|
|
||||||
// NewLegacyKeyBaseFromDir initializes a legacy keybase at the rootDir directory. Keybase
|
func printKeyInfo(w io.Writer, keyInfo *cryptokeyring.Record, bechKeyOut bechKeyOutFn, output string) {
|
||||||
// options can be applied when generating this new Keybase.
|
|
||||||
func NewLegacyKeyBaseFromDir(rootDir string, opts ...cryptokeyring.KeybaseOption) (cryptokeyring.LegacyKeybase, error) {
|
|
||||||
return getLegacyKeyBaseFromDir(rootDir, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLegacyKeyBaseFromDir(rootDir string, opts ...cryptokeyring.KeybaseOption) (cryptokeyring.LegacyKeybase, error) {
|
|
||||||
return cryptokeyring.NewLegacy(defaultKeyDBName, filepath.Join(rootDir, "keys"), opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func printKeyInfo(w io.Writer, keyInfo cryptokeyring.Info, bechKeyOut bechKeyOutFn, output string) {
|
|
||||||
ko, err := bechKeyOut(keyInfo)
|
ko, err := bechKeyOut(keyInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -6,17 +6,18 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
tmcfg "github.com/tendermint/tendermint/config"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
tmconfig "github.com/tendermint/tendermint/config"
|
tmconfig "github.com/tendermint/tendermint/config"
|
||||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
tmtime "github.com/tendermint/tendermint/types/time"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
@ -34,6 +35,8 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||||
|
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||||
|
|
||||||
mintypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
mintypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
|
|
||||||
@ -209,7 +212,7 @@ func initTestnetFiles(
|
|||||||
args initArgs,
|
args initArgs,
|
||||||
) error {
|
) error {
|
||||||
if args.chainID == "" {
|
if args.chainID == "" {
|
||||||
args.chainID = fmt.Sprintf("ethermint_%d-1", tmrand.Int63n(9999999999999)+1)
|
args.chainID = fmt.Sprintf("ethermint_%d-1", rand.Int63n(9999999999999)+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeIDs := make([]string, args.numValidators)
|
nodeIDs := make([]string, args.numValidators)
|
||||||
@ -261,7 +264,7 @@ func initTestnetFiles(
|
|||||||
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
|
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
|
||||||
genFiles = append(genFiles, nodeConfig.GenesisFile())
|
genFiles = append(genFiles, nodeConfig.GenesisFile())
|
||||||
|
|
||||||
kb, err := keyring.New(sdk.KeyringServiceName(), args.keyringBackend, nodeDir, inBuf, hd.EthSecp256k1Option())
|
kb, err := keyring.New(sdk.KeyringServiceName(), args.keyringBackend, nodeDir, inBuf, clientCtx.Codec, hd.EthSecp256k1Option())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -343,7 +346,8 @@ func initTestnetFiles(
|
|||||||
|
|
||||||
customAppTemplate, customAppConfig := config.AppConfig(ethermint.AttoPhoton)
|
customAppTemplate, customAppConfig := config.AppConfig(ethermint.AttoPhoton)
|
||||||
srvconfig.SetConfigTemplate(customAppTemplate)
|
srvconfig.SetConfigTemplate(customAppTemplate)
|
||||||
if err := sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig); err != nil {
|
customTmConfig := tmcfg.DefaultConfig()
|
||||||
|
if err := sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customTmConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +406,7 @@ func initGenFiles(
|
|||||||
stakingGenState.Params.BondDenom = coinDenom
|
stakingGenState.Params.BondDenom = coinDenom
|
||||||
appGenState[stakingtypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&stakingGenState)
|
appGenState[stakingtypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&stakingGenState)
|
||||||
|
|
||||||
var govGenState govtypes.GenesisState
|
var govGenState v1.GenesisState
|
||||||
clientCtx.Codec.MustUnmarshalJSON(appGenState[govtypes.ModuleName], &govGenState)
|
clientCtx.Codec.MustUnmarshalJSON(appGenState[govtypes.ModuleName], &govGenState)
|
||||||
|
|
||||||
govGenState.DepositParams.MinDeposit[0].Denom = coinDenom
|
govGenState.DepositParams.MinDeposit[0].Denom = coinDenom
|
||||||
@ -452,7 +456,7 @@ func collectGenFiles(
|
|||||||
outputDir, nodeDirPrefix, nodeDaemonHome string, genBalIterator banktypes.GenesisBalancesIterator,
|
outputDir, nodeDirPrefix, nodeDaemonHome string, genBalIterator banktypes.GenesisBalancesIterator,
|
||||||
) error {
|
) error {
|
||||||
var appState json.RawMessage
|
var appState json.RawMessage
|
||||||
genTime := tmtime.Now()
|
genTime := time.Now()
|
||||||
|
|
||||||
for i := 0; i < numValidators; i++ {
|
for i := 0; i < numValidators; i++ {
|
||||||
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
|
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
|
||||||
|
@ -23,6 +23,6 @@ func TestInitCmd(t *testing.T) {
|
|||||||
fmt.Sprintf("--%s=%s", flags.FlagChainID, "ethermint_9000-1"),
|
fmt.Sprintf("--%s=%s", flags.FlagChainID, "ethermint_9000-1"),
|
||||||
})
|
})
|
||||||
|
|
||||||
err := svrcmd.Execute(rootCmd, app.DefaultNodeHome)
|
err := svrcmd.Execute(rootCmd, chibaclonkd.EnvPrefix, app.DefaultNodeHome)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
|
|||||||
keyringBackend,
|
keyringBackend,
|
||||||
clientCtx.HomeDir,
|
clientCtx.HomeDir,
|
||||||
inBuf,
|
inBuf,
|
||||||
|
clientCtx.Codec,
|
||||||
hd.EthSecp256k1Option(),
|
hd.EthSecp256k1Option(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -77,7 +78,10 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
|
|||||||
return fmt.Errorf("failed to get address from Keyring: %w", err)
|
return fmt.Errorf("failed to get address from Keyring: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = info.GetAddress()
|
addr, err = info.GetAddress()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get address from Keyring: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
coins, err := sdk.ParseCoinsNormalized(args[1])
|
coins, err := sdk.ParseCoinsNormalized(args[1])
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
rootCmd, _ := NewRootCmd()
|
rootCmd, _ := NewRootCmd()
|
||||||
|
|
||||||
if err := svrcmd.Execute(rootCmd, app.DefaultNodeHome); err != nil {
|
if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil {
|
||||||
switch e := err.(type) {
|
switch e := err.(type) {
|
||||||
case server.ErrorCode:
|
case server.ErrorCode:
|
||||||
os.Exit(e.Code)
|
os.Exit(e.Code)
|
||||||
|
@ -6,18 +6,13 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/spf13/cast"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
tmcli "github.com/tendermint/tendermint/libs/cli"
|
|
||||||
tmlog "github.com/tendermint/tendermint/libs/log"
|
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/config"
|
"github.com/cosmos/cosmos-sdk/client/config"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
"github.com/cosmos/cosmos-sdk/client/rpc"
|
"github.com/cosmos/cosmos-sdk/client/rpc"
|
||||||
|
dbm "github.com/cosmos/cosmos-sdk/db"
|
||||||
|
"github.com/cosmos/cosmos-sdk/db/badgerdb"
|
||||||
sdkserver "github.com/cosmos/cosmos-sdk/server"
|
sdkserver "github.com/cosmos/cosmos-sdk/server"
|
||||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||||
@ -29,6 +24,11 @@ import (
|
|||||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/crisis"
|
"github.com/cosmos/cosmos-sdk/x/crisis"
|
||||||
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
tmcfg "github.com/tendermint/tendermint/config"
|
||||||
|
tmcli "github.com/tendermint/tendermint/libs/cli"
|
||||||
|
tmlog "github.com/tendermint/tendermint/libs/log"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/app"
|
"github.com/tharsis/ethermint/app"
|
||||||
ethermintclient "github.com/tharsis/ethermint/client"
|
ethermintclient "github.com/tharsis/ethermint/client"
|
||||||
@ -48,7 +48,7 @@ const EnvPrefix = "CHIBACLONK"
|
|||||||
func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
||||||
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
||||||
initClientCtx := client.Context{}.
|
initClientCtx := client.Context{}.
|
||||||
WithCodec(encodingConfig.Marshaler).
|
WithCodec(encodingConfig.Codec).
|
||||||
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
|
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
|
||||||
WithTxConfig(encodingConfig.TxConfig).
|
WithTxConfig(encodingConfig.TxConfig).
|
||||||
WithLegacyAmino(encodingConfig.Amino).
|
WithLegacyAmino(encodingConfig.Amino).
|
||||||
@ -83,8 +83,9 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
|||||||
|
|
||||||
// FIXME: replace AttoPhoton with bond denom
|
// FIXME: replace AttoPhoton with bond denom
|
||||||
customAppTemplate, customAppConfig := servercfg.AppConfig(ethermint.AttoPhoton)
|
customAppTemplate, customAppConfig := servercfg.AppConfig(ethermint.AttoPhoton)
|
||||||
|
customTMConfig := initTendermintConfig()
|
||||||
|
|
||||||
return sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig)
|
return sdkserver.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customTMConfig)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +127,7 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add rosetta
|
// add rosetta
|
||||||
rootCmd.AddCommand(sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler))
|
rootCmd.AddCommand(sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Codec))
|
||||||
|
|
||||||
// Add flags for GQL server.
|
// Add flags for GQL server.
|
||||||
rootCmd = srvflags.AddGQLFlags(rootCmd)
|
rootCmd = srvflags.AddGQLFlags(rootCmd)
|
||||||
@ -138,6 +139,18 @@ func addModuleInitFlags(startCmd *cobra.Command) {
|
|||||||
crisis.AddModuleInitFlags(startCmd)
|
crisis.AddModuleInitFlags(startCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initTendermintConfig helps to override default Tendermint Config values.
|
||||||
|
// return tmcfg.DefaultConfig if no custom configuration is required for the application.
|
||||||
|
func initTendermintConfig() *tmcfg.Config {
|
||||||
|
cfg := tmcfg.DefaultConfig()
|
||||||
|
|
||||||
|
// these values put a higher strain on node memory
|
||||||
|
// cfg.P2P.MaxNumInboundPeers = 100
|
||||||
|
// cfg.P2P.MaxNumOutboundPeers = 40
|
||||||
|
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
func queryCommand() *cobra.Command {
|
func queryCommand() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "query",
|
Use: "query",
|
||||||
@ -193,7 +206,7 @@ type appCreator struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newApp is an appCreator
|
// newApp is an appCreator
|
||||||
func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application {
|
func (a appCreator) newApp(logger tmlog.Logger, db dbm.DBConnection, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application {
|
||||||
var cache sdk.MultiStorePersistentCache
|
var cache sdk.MultiStorePersistentCache
|
||||||
|
|
||||||
if cast.ToBool(appOpts.Get(sdkserver.FlagInterBlockCache)) {
|
if cast.ToBool(appOpts.Get(sdkserver.FlagInterBlockCache)) {
|
||||||
@ -211,7 +224,7 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots")
|
snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots")
|
||||||
snapshotDB, err := sdk.NewLevelDB("metadata", snapshotDir)
|
snapshotDB, err := badgerdb.NewDB(filepath.Join(snapshotDir, "metadata"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -245,7 +258,7 @@ func (a appCreator) newApp(logger tmlog.Logger, db dbm.DB, traceStore io.Writer,
|
|||||||
// appExport creates a new simapp (optionally at a given height)
|
// appExport creates a new simapp (optionally at a given height)
|
||||||
// and exports state.
|
// and exports state.
|
||||||
func (a appCreator) appExport(
|
func (a appCreator) appExport(
|
||||||
logger tmlog.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string,
|
logger tmlog.Logger, db dbm.DBConnection, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string,
|
||||||
appOpts servertypes.AppOptions,
|
appOpts servertypes.AppOptions,
|
||||||
) (servertypes.ExportedApp, error) {
|
) (servertypes.ExportedApp, error) {
|
||||||
var ethermintApp *app.EthermintApp
|
var ethermintApp *app.EthermintApp
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Bech32Prefix defines the Bech32 prefix used for EthAccounts
|
// Bech32Prefix defines the Bech32 prefix used for EthAccounts
|
||||||
Bech32Prefix = "ethm"
|
Bech32Prefix = ethermint.Bech32MainPrefix
|
||||||
|
|
||||||
// Bech32PrefixAccAddr defines the Bech32 prefix of an account's address
|
// Bech32PrefixAccAddr defines the Bech32 prefix of an account's address
|
||||||
Bech32PrefixAccAddr = Bech32Prefix
|
Bech32PrefixAccAddr = Bech32Prefix
|
||||||
|
@ -10,4 +10,5 @@ import (
|
|||||||
// RegisterInterfaces register the Ethermint key concrete types.
|
// RegisterInterfaces register the Ethermint key concrete types.
|
||||||
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
||||||
registry.RegisterImplementations((*cryptotypes.PubKey)(nil), ðsecp256k1.PubKey{})
|
registry.RegisterImplementations((*cryptotypes.PubKey)(nil), ðsecp256k1.PubKey{})
|
||||||
|
registry.RegisterImplementations((*cryptotypes.PrivKey)(nil), ðsecp256k1.PrivKey{})
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -12,12 +13,14 @@ import (
|
|||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
|
|
||||||
cryptocodec "github.com/tharsis/ethermint/crypto/codec"
|
cryptocodec "github.com/tharsis/ethermint/crypto/codec"
|
||||||
ethermint "github.com/tharsis/ethermint/types"
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var protoCodec codec.Codec
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
protoCodec = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
|
||||||
amino := codec.NewLegacyAmino()
|
amino := codec.NewLegacyAmino()
|
||||||
cryptocodec.RegisterCrypto(amino)
|
cryptocodec.RegisterCrypto(amino)
|
||||||
}
|
}
|
||||||
@ -28,7 +31,7 @@ func TestKeyring(t *testing.T) {
|
|||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
mockIn := strings.NewReader("")
|
mockIn := strings.NewReader("")
|
||||||
|
|
||||||
kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, EthSecp256k1Option())
|
kr, err := keyring.New("ethermint", keyring.BackendTest, dir, mockIn, protoCodec, EthSecp256k1Option())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// fail in retrieving key
|
// fail in retrieving key
|
||||||
@ -40,9 +43,8 @@ func TestKeyring(t *testing.T) {
|
|||||||
info, mnemonic, err := kr.NewMnemonic("foo", keyring.English, ethermint.BIP44HDPath, keyring.DefaultBIP39Passphrase, EthSecp256k1)
|
info, mnemonic, err := kr.NewMnemonic("foo", keyring.English, ethermint.BIP44HDPath, keyring.DefaultBIP39Passphrase, EthSecp256k1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, mnemonic)
|
require.NotEmpty(t, mnemonic)
|
||||||
require.Equal(t, "foo", info.GetName())
|
require.Equal(t, "foo", info.Name)
|
||||||
require.Equal(t, "local", info.GetType().String())
|
require.Equal(t, "local", info.GetType().String())
|
||||||
require.Equal(t, EthSecp256k1Type, info.GetAlgo())
|
|
||||||
|
|
||||||
hdPath := ethermint.BIP44HDPath
|
hdPath := ethermint.BIP44HDPath
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
"github.com/cosmos/cosmos-sdk/std"
|
"github.com/cosmos/cosmos-sdk/std"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
|
|
||||||
cryptocodec "github.com/tharsis/ethermint/crypto/codec"
|
cryptocodec "github.com/tharsis/ethermint/crypto/codec"
|
||||||
ethermint "github.com/tharsis/ethermint/types"
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
@ -12,9 +11,7 @@ import (
|
|||||||
|
|
||||||
// RegisterLegacyAminoCodec registers Interfaces from types, crypto, and SDK std.
|
// RegisterLegacyAminoCodec registers Interfaces from types, crypto, and SDK std.
|
||||||
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
|
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
|
||||||
sdk.RegisterLegacyAminoCodec(cdc)
|
std.RegisterLegacyAminoCodec(cdc)
|
||||||
cryptocodec.RegisterCrypto(cdc)
|
|
||||||
codec.RegisterEvidences(cdc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterInterfaces registers Interfaces from types, crypto, and SDK std.
|
// RegisterInterfaces registers Interfaces from types, crypto, and SDK std.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package encoding
|
package encoding
|
||||||
|
|
||||||
import (
|
import (
|
||||||
amino "github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||||
"github.com/cosmos/cosmos-sdk/types/module"
|
"github.com/cosmos/cosmos-sdk/types/module"
|
||||||
@ -12,15 +12,16 @@ import (
|
|||||||
|
|
||||||
// MakeConfig creates an EncodingConfig for testing
|
// MakeConfig creates an EncodingConfig for testing
|
||||||
func MakeConfig(mb module.BasicManager) params.EncodingConfig {
|
func MakeConfig(mb module.BasicManager) params.EncodingConfig {
|
||||||
cdc := amino.NewLegacyAmino()
|
amino := codec.NewLegacyAmino()
|
||||||
interfaceRegistry := types.NewInterfaceRegistry()
|
interfaceRegistry := types.NewInterfaceRegistry()
|
||||||
marshaler := amino.NewProtoCodec(interfaceRegistry)
|
marshaler := codec.NewProtoCodec(interfaceRegistry)
|
||||||
|
txCfg := tx.NewTxConfig(marshaler, tx.DefaultSignModes)
|
||||||
|
|
||||||
encodingConfig := params.EncodingConfig{
|
encodingConfig := params.EncodingConfig{
|
||||||
InterfaceRegistry: interfaceRegistry,
|
InterfaceRegistry: interfaceRegistry,
|
||||||
Marshaler: marshaler,
|
Codec: marshaler,
|
||||||
TxConfig: tx.NewTxConfig(marshaler, tx.DefaultSignModes),
|
TxConfig: txCfg,
|
||||||
Amino: cdc,
|
Amino: amino,
|
||||||
}
|
}
|
||||||
|
|
||||||
enccodec.RegisterLegacyAminoCodec(encodingConfig.Amino)
|
enccodec.RegisterLegacyAminoCodec(encodingConfig.Amino)
|
||||||
|
108
go.mod
108
go.mod
@ -6,12 +6,13 @@ require (
|
|||||||
github.com/99designs/gqlgen v0.17.2
|
github.com/99designs/gqlgen v0.17.2
|
||||||
github.com/btcsuite/btcd v0.22.0-beta
|
github.com/btcsuite/btcd v0.22.0-beta
|
||||||
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
|
||||||
github.com/cosmos/cosmos-sdk v0.45.1
|
github.com/cosmos/cosmos-sdk v0.46.0-beta2
|
||||||
|
github.com/cosmos/cosmos-sdk/db v1.0.0-beta.1
|
||||||
github.com/cosmos/go-bip39 v1.0.0
|
github.com/cosmos/go-bip39 v1.0.0
|
||||||
github.com/cosmos/ibc-go/v3 v3.0.0
|
github.com/cosmos/ibc-go/v3 v3.0.0-alpha1.0.20220517190049-c4ce2b908a1e
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/deckarep/golang-set v1.8.0
|
github.com/deckarep/golang-set v1.8.0
|
||||||
github.com/ethereum/go-ethereum v1.10.16
|
github.com/ethereum/go-ethereum v1.10.17
|
||||||
github.com/gibson042/canonicaljson-go v1.0.3
|
github.com/gibson042/canonicaljson-go v1.0.3
|
||||||
github.com/gogo/protobuf v1.3.3
|
github.com/gogo/protobuf v1.3.3
|
||||||
github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf v1.5.2
|
||||||
@ -28,13 +29,13 @@ require (
|
|||||||
github.com/rakyll/statik v0.1.7
|
github.com/rakyll/statik v0.1.7
|
||||||
github.com/regen-network/cosmos-proto v0.3.1
|
github.com/regen-network/cosmos-proto v0.3.1
|
||||||
github.com/rs/cors v1.8.2
|
github.com/rs/cors v1.8.2
|
||||||
|
github.com/rs/zerolog v1.26.1
|
||||||
github.com/spf13/cast v1.4.1
|
github.com/spf13/cast v1.4.1
|
||||||
github.com/spf13/cobra v1.4.0
|
github.com/spf13/cobra v1.4.0
|
||||||
github.com/spf13/viper v1.10.1
|
github.com/spf13/viper v1.10.1
|
||||||
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
|
github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969
|
||||||
github.com/stretchr/testify v1.7.1
|
github.com/stretchr/testify v1.7.1
|
||||||
github.com/tendermint/tendermint v0.34.14
|
github.com/tendermint/tendermint v0.35.2
|
||||||
github.com/tendermint/tm-db v0.6.7
|
|
||||||
github.com/tyler-smith/go-bip39 v1.1.0
|
github.com/tyler-smith/go-bip39 v1.1.0
|
||||||
github.com/vektah/gqlparser/v2 v2.4.1
|
github.com/vektah/gqlparser/v2 v2.4.1
|
||||||
google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de
|
google.golang.org/genproto v0.0.0-20220401170504-314d38edb7de
|
||||||
@ -45,31 +46,40 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
filippo.io/edwards25519 v1.0.0-beta.2 // indirect
|
cloud.google.com/go v0.99.0 // indirect
|
||||||
|
cloud.google.com/go/storage v1.14.0 // indirect
|
||||||
|
filippo.io/edwards25519 v1.0.0-rc.1 // indirect
|
||||||
github.com/99designs/keyring v1.1.6 // indirect
|
github.com/99designs/keyring v1.1.6 // indirect
|
||||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
|
|
||||||
github.com/DataDog/zstd v1.4.5 // indirect
|
|
||||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
||||||
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
|
github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
|
||||||
github.com/Workiva/go-datastructures v1.0.52 // indirect
|
github.com/Workiva/go-datastructures v1.0.53 // indirect
|
||||||
github.com/agnivade/levenshtein v1.1.0 // indirect
|
github.com/agnivade/levenshtein v1.1.0 // indirect
|
||||||
github.com/armon/go-metrics v0.3.10 // indirect
|
github.com/armon/go-metrics v0.3.10 // indirect
|
||||||
|
github.com/aws/aws-sdk-go v1.40.45 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||||
github.com/bgentry/speakeasy v0.1.0 // indirect
|
github.com/bgentry/speakeasy v0.1.0 // indirect
|
||||||
|
github.com/btcsuite/btcd/btcec/v2 v2.1.2 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
|
||||||
github.com/cespare/xxhash v1.1.0 // indirect
|
github.com/cespare/xxhash v1.1.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect
|
github.com/cockroachdb/apd/v2 v2.0.2 // indirect
|
||||||
|
github.com/coinbase/rosetta-sdk-go v0.7.7 // indirect
|
||||||
github.com/confio/ics23/go v0.7.0 // indirect
|
github.com/confio/ics23/go v0.7.0 // indirect
|
||||||
github.com/cosmos/btcutil v1.0.4 // indirect
|
github.com/cosmos/btcutil v1.0.4 // indirect
|
||||||
|
github.com/cosmos/cosmos-proto v1.0.0-alpha7 // indirect
|
||||||
|
github.com/cosmos/cosmos-sdk/api v0.1.0 // indirect
|
||||||
|
github.com/cosmos/cosmos-sdk/errors v1.0.0-beta.3 // indirect
|
||||||
github.com/cosmos/gorocksdb v1.2.0 // indirect
|
github.com/cosmos/gorocksdb v1.2.0 // indirect
|
||||||
github.com/cosmos/iavl v0.17.3 // indirect
|
github.com/cosmos/iavl v0.18.0 // indirect
|
||||||
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
|
github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
|
||||||
github.com/cosmos/ledger-go v0.9.2 // indirect
|
github.com/cosmos/ledger-go v0.9.2 // indirect
|
||||||
github.com/danieljoos/wincred v1.0.2 // indirect
|
github.com/danieljoos/wincred v1.0.2 // indirect
|
||||||
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||||
github.com/dgraph-io/badger/v2 v2.2007.2 // indirect
|
github.com/dgraph-io/badger/v2 v2.2007.4 // indirect
|
||||||
github.com/dgraph-io/ristretto v0.0.3 // indirect
|
github.com/dgraph-io/badger/v3 v3.2103.2 // indirect
|
||||||
|
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
||||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||||
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect
|
github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect
|
||||||
@ -77,49 +87,58 @@ require (
|
|||||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
|
||||||
github.com/go-kit/kit v0.10.0 // indirect
|
github.com/go-kit/kit v0.12.0 // indirect
|
||||||
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.1 // indirect
|
|
||||||
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
github.com/go-playground/validator/v10 v10.4.1 // indirect
|
||||||
github.com/go-stack/stack v1.8.0 // indirect
|
github.com/go-stack/stack v1.8.0 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||||
github.com/gogo/gateway v1.1.0 // indirect
|
github.com/gogo/gateway v1.1.0 // indirect
|
||||||
|
github.com/golang/glog v1.0.0 // indirect
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/btree v1.0.0 // indirect
|
github.com/google/btree v1.0.1 // indirect
|
||||||
|
github.com/google/flatbuffers v2.0.0+incompatible // indirect
|
||||||
github.com/google/orderedcode v0.0.1 // indirect
|
github.com/google/orderedcode v0.0.1 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
|
github.com/googleapis/gax-go/v2 v2.1.1 // indirect
|
||||||
github.com/gorilla/handlers v1.5.1 // indirect
|
github.com/gorilla/handlers v1.5.1 // indirect
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
|
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
|
||||||
github.com/gtank/merlin v0.1.1 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/gtank/ristretto255 v0.1.2 // indirect
|
github.com/hashicorp/go-getter v1.5.11 // indirect
|
||||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||||
|
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||||
|
github.com/hashicorp/go-version v1.2.1 // indirect
|
||||||
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
|
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect
|
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect
|
||||||
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
|
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
|
||||||
github.com/huin/goupnp v1.0.2 // indirect
|
github.com/huin/goupnp v1.0.3-0.20220313090229-ca81a64b4204 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
github.com/ipfs/go-block-format v0.0.2 // indirect
|
github.com/ipfs/go-block-format v0.0.2 // indirect
|
||||||
github.com/ipfs/go-cid v0.0.3 // indirect
|
github.com/ipfs/go-cid v0.0.3 // indirect
|
||||||
github.com/ipfs/go-ipfs-util v0.0.1 // indirect
|
github.com/ipfs/go-ipfs-util v0.0.1 // indirect
|
||||||
github.com/ipfs/go-ipld-format v0.0.1 // indirect
|
github.com/ipfs/go-ipld-format v0.0.1 // indirect
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||||
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
|
github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect
|
||||||
github.com/klauspost/compress v1.11.7 // indirect
|
github.com/klauspost/compress v1.13.6 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||||
github.com/lib/pq v1.10.2 // indirect
|
github.com/lazyledger/smt v0.2.1-0.20210709230900-03ea40719554 // indirect
|
||||||
|
github.com/lib/pq v1.10.4 // indirect
|
||||||
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
|
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
|
||||||
github.com/magiconair/properties v1.8.5 // indirect
|
github.com/magiconair/properties v1.8.6 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||||
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
|
|
||||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
|
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
|
||||||
github.com/minio/highwayhash v1.0.1 // indirect
|
github.com/minio/highwayhash v1.0.2 // indirect
|
||||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
|
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||||
github.com/mtibben/percent v0.2.1 // indirect
|
github.com/mtibben/percent v0.2.1 // indirect
|
||||||
@ -127,23 +146,23 @@ require (
|
|||||||
github.com/multiformats/go-multibase v0.0.1 // indirect
|
github.com/multiformats/go-multibase v0.0.1 // indirect
|
||||||
github.com/multiformats/go-varint v0.0.6 // indirect
|
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||||
github.com/nxadm/tail v1.4.8 // indirect
|
github.com/nxadm/tail v1.4.8 // indirect
|
||||||
|
github.com/oasisprotocol/curve25519-voi v0.0.0-20210609091139-0a56a4bca00b // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992 // indirect
|
github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992 // indirect
|
||||||
github.com/prometheus/client_golang v1.11.0 // indirect
|
github.com/prometheus/client_golang v1.12.1 // indirect
|
||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.29.0 // indirect
|
github.com/prometheus/common v0.33.0 // indirect
|
||||||
github.com/prometheus/procfs v0.6.0 // indirect
|
github.com/prometheus/procfs v0.7.3 // indirect
|
||||||
github.com/prometheus/tsdb v0.7.1 // indirect
|
github.com/prometheus/tsdb v0.7.1 // indirect
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
|
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
|
||||||
github.com/rjeczalik/notify v0.9.1 // indirect
|
github.com/rjeczalik/notify v0.9.1 // indirect
|
||||||
github.com/rs/zerolog v1.23.0 // indirect
|
|
||||||
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect
|
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect
|
||||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
||||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
github.com/spf13/afero v1.6.0 // indirect
|
github.com/spf13/afero v1.8.0 // indirect
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.2.0 // indirect
|
github.com/subosito/gotenv v1.2.0 // indirect
|
||||||
@ -151,29 +170,40 @@ require (
|
|||||||
github.com/tendermint/btcd v0.1.1 // indirect
|
github.com/tendermint/btcd v0.1.1 // indirect
|
||||||
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect
|
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect
|
||||||
github.com/tendermint/go-amino v0.16.0 // indirect
|
github.com/tendermint/go-amino v0.16.0 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.5 // indirect
|
github.com/tendermint/tm-db v0.6.7 // indirect
|
||||||
github.com/tklauser/numcpus v0.2.2 // indirect
|
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||||
|
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||||
|
github.com/ulikunitz/xz v0.5.8 // indirect
|
||||||
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 // indirect
|
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158 // indirect
|
||||||
github.com/zondax/hid v0.9.0 // indirect
|
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 // indirect
|
||||||
go.etcd.io/bbolt v1.3.6 // indirect
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
|
go.opencensus.io v0.23.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect
|
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||||
|
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 // indirect
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/tools v0.1.9 // indirect
|
golang.org/x/tools v0.1.9 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
google.golang.org/api v0.63.0 // indirect
|
||||||
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.66.3 // indirect
|
||||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
|
||||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect
|
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
lukechampine.com/blake3 v1.1.6 // indirect
|
lukechampine.com/blake3 v1.1.6 // indirect
|
||||||
nhooyr.io/websocket v1.8.6 // indirect
|
nhooyr.io/websocket v1.8.6 // indirect
|
||||||
|
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace (
|
replace (
|
||||||
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
|
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
|
||||||
|
|
||||||
|
// replace cosmos
|
||||||
|
github.com/cosmos/cosmos-sdk => github.com/vulcanize/cosmos-sdk v0.46.0-smt-0.0.3-alpha
|
||||||
|
github.com/cosmos/cosmos-sdk/db => github.com/vulcanize/cosmos-sdk/db v1.0.0-beta.1
|
||||||
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
|
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
|
||||||
google.golang.org/grpc => google.golang.org/grpc v1.33.2
|
google.golang.org/grpc => google.golang.org/grpc v1.44.0
|
||||||
)
|
)
|
||||||
|
@ -49,17 +49,17 @@ func getNetInfo(client client.Context) (string, []*PeerInfo, error) {
|
|||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
peers := netInfo.Peers
|
peersInfo := make([]*PeerInfo, netInfo.NPeers)
|
||||||
peersInfo := make([]*PeerInfo, len(peers))
|
// TODO: find a way to get the peer information from nodeClient
|
||||||
for index, peer := range peers {
|
for index, peer := range netInfo.Peers {
|
||||||
peersInfo[index] = &PeerInfo{
|
peersInfo[index] = &PeerInfo{
|
||||||
Node: &NodeInfo{
|
Node: &NodeInfo{
|
||||||
ID: string(peer.NodeInfo.ID()),
|
ID: string(peer.ID),
|
||||||
Moniker: peer.NodeInfo.Moniker,
|
// Moniker: peer.Node.Moniker,
|
||||||
Network: peer.NodeInfo.Network,
|
// Network: peer.Node.Network,
|
||||||
},
|
},
|
||||||
IsOutbound: peer.IsOutbound,
|
// IsOutbound: peer.IsOutbound,
|
||||||
RemoteIP: peer.RemoteIP,
|
// RemoteIP: peer.RemoteIP,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
117
rpc/apis.go
117
rpc/apis.go
@ -3,6 +3,8 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/server"
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
|
|
||||||
@ -35,92 +37,96 @@ const (
|
|||||||
apiVersion = "1.0"
|
apiVersion = "1.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetRPCAPIs returns the list of all APIs
|
// APICreator creates the json-rpc api implementations.
|
||||||
func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient, selectedAPIs []string) []rpc.API {
|
type APICreator = func(*server.Context, client.Context, *rpcclient.WSClient) []rpc.API
|
||||||
nonceLock := new(types.AddrLocker)
|
|
||||||
evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx)
|
|
||||||
|
|
||||||
var apis []rpc.API
|
// apiCreators defines the json-rpc api namespaces.
|
||||||
// remove duplicates
|
var apiCreators map[string]APICreator
|
||||||
selectedAPIs = unique(selectedAPIs)
|
|
||||||
|
|
||||||
for index := range selectedAPIs {
|
func init() {
|
||||||
switch selectedAPIs[index] {
|
apiCreators = map[string]APICreator{
|
||||||
case EthNamespace:
|
EthNamespace: func(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient) []rpc.API {
|
||||||
apis = append(apis,
|
nonceLock := new(types.AddrLocker)
|
||||||
rpc.API{
|
evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx)
|
||||||
|
return []rpc.API{
|
||||||
|
{
|
||||||
Namespace: EthNamespace,
|
Namespace: EthNamespace,
|
||||||
Version: apiVersion,
|
Version: apiVersion,
|
||||||
Service: eth.NewPublicAPI(ctx.Logger, clientCtx, evmBackend, nonceLock),
|
Service: eth.NewPublicAPI(ctx.Logger, clientCtx, evmBackend, nonceLock),
|
||||||
Public: true,
|
Public: true,
|
||||||
},
|
},
|
||||||
rpc.API{
|
{
|
||||||
Namespace: EthNamespace,
|
Namespace: EthNamespace,
|
||||||
Version: apiVersion,
|
Version: apiVersion,
|
||||||
Service: filters.NewPublicAPI(ctx.Logger, clientCtx, tmWSClient, evmBackend),
|
Service: filters.NewPublicAPI(ctx.Logger, clientCtx, tmWSClient, evmBackend),
|
||||||
Public: true,
|
Public: true,
|
||||||
},
|
},
|
||||||
)
|
}
|
||||||
case Web3Namespace:
|
},
|
||||||
apis = append(apis,
|
Web3Namespace: func(*server.Context, client.Context, *rpcclient.WSClient) []rpc.API {
|
||||||
rpc.API{
|
return []rpc.API{
|
||||||
|
{
|
||||||
Namespace: Web3Namespace,
|
Namespace: Web3Namespace,
|
||||||
Version: apiVersion,
|
Version: apiVersion,
|
||||||
Service: web3.NewPublicAPI(),
|
Service: web3.NewPublicAPI(),
|
||||||
Public: true,
|
Public: true,
|
||||||
},
|
},
|
||||||
)
|
}
|
||||||
case NetNamespace:
|
},
|
||||||
apis = append(apis,
|
NetNamespace: func(_ *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API {
|
||||||
rpc.API{
|
return []rpc.API{
|
||||||
|
{
|
||||||
Namespace: NetNamespace,
|
Namespace: NetNamespace,
|
||||||
Version: apiVersion,
|
Version: apiVersion,
|
||||||
Service: net.NewPublicAPI(clientCtx),
|
Service: net.NewPublicAPI(clientCtx),
|
||||||
Public: true,
|
Public: true,
|
||||||
},
|
},
|
||||||
)
|
}
|
||||||
case PersonalNamespace:
|
},
|
||||||
apis = append(apis,
|
PersonalNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API {
|
||||||
rpc.API{
|
evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx)
|
||||||
|
return []rpc.API{
|
||||||
|
{
|
||||||
Namespace: PersonalNamespace,
|
Namespace: PersonalNamespace,
|
||||||
Version: apiVersion,
|
Version: apiVersion,
|
||||||
Service: personal.NewAPI(ctx.Logger, clientCtx, evmBackend),
|
Service: personal.NewAPI(ctx.Logger, clientCtx, evmBackend),
|
||||||
Public: false,
|
Public: false,
|
||||||
},
|
},
|
||||||
)
|
}
|
||||||
case TxPoolNamespace:
|
},
|
||||||
apis = append(apis,
|
TxPoolNamespace: func(ctx *server.Context, _ client.Context, _ *rpcclient.WSClient) []rpc.API {
|
||||||
rpc.API{
|
return []rpc.API{
|
||||||
|
{
|
||||||
Namespace: TxPoolNamespace,
|
Namespace: TxPoolNamespace,
|
||||||
Version: apiVersion,
|
Version: apiVersion,
|
||||||
Service: txpool.NewPublicAPI(ctx.Logger),
|
Service: txpool.NewPublicAPI(ctx.Logger),
|
||||||
Public: true,
|
Public: true,
|
||||||
},
|
},
|
||||||
)
|
}
|
||||||
case DebugNamespace:
|
},
|
||||||
apis = append(apis,
|
DebugNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API {
|
||||||
rpc.API{
|
evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx)
|
||||||
|
return []rpc.API{
|
||||||
|
{
|
||||||
Namespace: DebugNamespace,
|
Namespace: DebugNamespace,
|
||||||
Version: apiVersion,
|
Version: apiVersion,
|
||||||
Service: debug.NewAPI(ctx, evmBackend, clientCtx),
|
Service: debug.NewAPI(ctx, evmBackend, clientCtx),
|
||||||
Public: true,
|
Public: true,
|
||||||
},
|
},
|
||||||
)
|
}
|
||||||
case MinerNamespace:
|
},
|
||||||
apis = append(apis,
|
MinerNamespace: func(ctx *server.Context, clientCtx client.Context, _ *rpcclient.WSClient) []rpc.API {
|
||||||
rpc.API{
|
evmBackend := backend.NewEVMBackend(ctx, ctx.Logger, clientCtx)
|
||||||
|
return []rpc.API{
|
||||||
|
{
|
||||||
Namespace: MinerNamespace,
|
Namespace: MinerNamespace,
|
||||||
Version: apiVersion,
|
Version: apiVersion,
|
||||||
Service: miner.NewPrivateAPI(ctx, clientCtx, evmBackend),
|
Service: miner.NewPrivateAPI(ctx, clientCtx, evmBackend),
|
||||||
Public: false,
|
Public: false,
|
||||||
},
|
},
|
||||||
)
|
}
|
||||||
default:
|
},
|
||||||
ctx.Logger.Error("invalid namespace value", "namespace", selectedAPIs[index])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return apis
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func unique(intSlice []string) []string {
|
func unique(intSlice []string) []string {
|
||||||
@ -134,3 +140,28 @@ func unique(intSlice []string) []string {
|
|||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRPCAPIs returns the list of all APIs
|
||||||
|
func GetRPCAPIs(ctx *server.Context, clientCtx client.Context, tmWSClient *rpcclient.WSClient, selectedAPIs []string) []rpc.API {
|
||||||
|
var apis []rpc.API
|
||||||
|
|
||||||
|
for _, ns := range selectedAPIs {
|
||||||
|
if creator, ok := apiCreators[ns]; ok {
|
||||||
|
apis = append(apis, creator(ctx, clientCtx, tmWSClient)...)
|
||||||
|
} else {
|
||||||
|
ctx.Logger.Error("invalid namespace value", "namespace", ns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return apis
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterAPINamespace registers a new API namespace with the API creator.
|
||||||
|
// This function fails if the namespace is already registered.
|
||||||
|
func RegisterAPINamespace(ns string, creator APICreator) error {
|
||||||
|
if _, ok := apiCreators[ns]; ok {
|
||||||
|
return fmt.Errorf("duplicated api namespace %s", ns)
|
||||||
|
}
|
||||||
|
apiCreators[ns] = creator
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package backend
|
package backend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -15,7 +14,8 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
|
||||||
|
tmrpctypes "github.com/tendermint/tendermint/rpc/coretypes"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
@ -334,8 +334,8 @@ func (e *EVMBackend) BlockBloom(height *int64) (ethtypes.Bloom, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, attr := range event.Attributes {
|
for _, attr := range event.Attributes {
|
||||||
if bytes.Equal(attr.Key, bAttributeKeyEthereumBloom) {
|
if attr.Key == string(bAttributeKeyEthereumBloom) {
|
||||||
return ethtypes.BytesToBloom(attr.Value), nil
|
return ethtypes.BytesToBloom([]byte(attr.Value)), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
tmrpctypes "github.com/tendermint/tendermint/rpc/coretypes"
|
||||||
rpctypes "github.com/tharsis/ethermint/rpc/ethereum/types"
|
rpctypes "github.com/tharsis/ethermint/rpc/ethereum/types"
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
)
|
)
|
||||||
|
@ -238,12 +238,12 @@ func TxLogsFromEvents(events []abci.Event, msgIndex int) ([]*ethtypes.Log, error
|
|||||||
func ParseTxLogsFromEvent(event abci.Event) ([]*ethtypes.Log, error) {
|
func ParseTxLogsFromEvent(event abci.Event) ([]*ethtypes.Log, error) {
|
||||||
logs := make([]*evmtypes.Log, 0, len(event.Attributes))
|
logs := make([]*evmtypes.Log, 0, len(event.Attributes))
|
||||||
for _, attr := range event.Attributes {
|
for _, attr := range event.Attributes {
|
||||||
if !bytes.Equal(attr.Key, []byte(evmtypes.AttributeKeyTxLog)) {
|
if !bytes.Equal([]byte(attr.Key), []byte(evmtypes.AttributeKeyTxLog)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var log evmtypes.Log
|
var log evmtypes.Log
|
||||||
if err := json.Unmarshal(attr.Value, &log); err != nil {
|
if err := json.Unmarshal([]byte(attr.Value), &log); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
tmrpctypes "github.com/tendermint/tendermint/rpc/coretypes"
|
||||||
|
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
tmrpctypes "github.com/tendermint/tendermint/rpc/coretypes"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
@ -74,6 +74,7 @@ func NewPublicAPI(
|
|||||||
viper.GetString(flags.FlagKeyringBackend),
|
viper.GetString(flags.FlagKeyringBackend),
|
||||||
clientCtx.KeyringDir,
|
clientCtx.KeyringDir,
|
||||||
clientCtx.Input,
|
clientCtx.Input,
|
||||||
|
clientCtx.Codec,
|
||||||
hd.EthSecp256k1Option(),
|
hd.EthSecp256k1Option(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -242,7 +243,11 @@ func (e *PublicAPI) Accounts() ([]common.Address, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, info := range infos {
|
for _, info := range infos {
|
||||||
addressBytes := info.GetPubKey().Address().Bytes()
|
pubKey, err := info.GetPubKey()
|
||||||
|
if err != nil {
|
||||||
|
return addresses, err
|
||||||
|
}
|
||||||
|
addressBytes := pubKey.Address().Bytes()
|
||||||
addresses = append(addresses, common.BytesToAddress(addressBytes))
|
addresses = append(addresses, common.BytesToAddress(addressBytes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
|
|
||||||
coretypes "github.com/tendermint/tendermint/rpc/core/types"
|
coretypes "github.com/tendermint/tendermint/rpc/coretypes"
|
||||||
rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client"
|
rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
@ -371,7 +371,13 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit filters.FilterCriteri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// filter only events from EVM module txs
|
// filter only events from EVM module txs
|
||||||
_, isMsgEthereumTx := ev.Events[evmtypes.TypeMsgEthereumTx]
|
var isMsgEthereumTx bool
|
||||||
|
|
||||||
|
for _, event := range ev.Events {
|
||||||
|
if event.Type == evmtypes.TypeMsgEthereumTx {
|
||||||
|
isMsgEthereumTx = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !isMsgEthereumTx {
|
if !isMsgEthereumTx {
|
||||||
// ignore transaction as it's not from the evm module
|
// ignore transaction as it's not from the evm module
|
||||||
@ -385,7 +391,7 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit filters.FilterCriteri
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data)
|
txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data, api.clientCtx.Codec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -461,7 +467,7 @@ func (api *PublicFilterAPI) NewFilter(criteria filters.FilterCriteria) (rpc.ID,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data)
|
txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data, api.clientCtx.Codec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
tmjson "github.com/tendermint/tendermint/libs/json"
|
tmjson "github.com/tendermint/tendermint/libs/json"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
tmquery "github.com/tendermint/tendermint/libs/pubsub/query"
|
tmquery "github.com/tendermint/tendermint/libs/pubsub/query"
|
||||||
coretypes "github.com/tendermint/tendermint/rpc/core/types"
|
coretypes "github.com/tendermint/tendermint/rpc/coretypes"
|
||||||
rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client"
|
rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
@ -27,9 +27,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
txEvents = tmtypes.QueryForEvent(tmtypes.EventTx).String()
|
txEvents = tmtypes.QueryForEvent(tmtypes.EventTxValue).String()
|
||||||
evmEvents = tmquery.MustParse(fmt.Sprintf("%s='%s' AND %s.%s='%s'", tmtypes.EventTypeKey, tmtypes.EventTx, sdk.EventTypeMessage, sdk.AttributeKeyModule, evmtypes.ModuleName)).String()
|
evmEvents = tmquery.MustCompile(fmt.Sprintf("%s='%s' AND %s.%s='%s'", tmtypes.EventTypeKey, tmtypes.EventTxValue, sdk.EventTypeMessage, sdk.AttributeKeyModule, evmtypes.ModuleName)).String()
|
||||||
headerEvents = tmtypes.QueryForEvent(tmtypes.EventNewBlockHeader).String()
|
headerEvents = tmtypes.QueryForEvent(tmtypes.EventNewBlockHeaderValue).String()
|
||||||
)
|
)
|
||||||
|
|
||||||
// EventSystem creates subscriptions, processes events and broadcasts them to the
|
// EventSystem creates subscriptions, processes events and broadcasts them to the
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/eth/filters"
|
"github.com/ethereum/go-ethereum/eth/filters"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
coretypes "github.com/tendermint/tendermint/rpc/core/types"
|
coretypes "github.com/tendermint/tendermint/rpc/coretypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Subscription defines a wrapper for the private subscription
|
// Subscription defines a wrapper for the private subscription
|
||||||
|
@ -124,7 +124,7 @@ func (api *API) SetEtherbase(etherbase common.Address) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tx.Sign(txFactory, keyInfo.GetName(), builder, false); err != nil {
|
if err := tx.Sign(txFactory, keyInfo.Name, builder, false); err != nil {
|
||||||
api.logger.Debug("failed to sign tx", "error", err.Error())
|
api.logger.Debug("failed to sign tx", "error", err.Error())
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,11 @@ func (api *PrivateAccountAPI) ListAccounts() ([]common.Address, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, info := range list {
|
for _, info := range list {
|
||||||
addrs = append(addrs, common.BytesToAddress(info.GetPubKey().Address()))
|
pubKey, err := info.GetPubKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
addrs = append(addrs, common.BytesToAddress(pubKey.Address()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return addrs, nil
|
return addrs, nil
|
||||||
@ -131,7 +135,8 @@ func (api *PrivateAccountAPI) NewAccount(password string) (common.Address, error
|
|||||||
return common.Address{}, err
|
return common.Address{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := common.BytesToAddress(info.GetPubKey().Address().Bytes())
|
pubKeyAddr, err := info.GetAddress()
|
||||||
|
addr := common.BytesToAddress(pubKeyAddr.Bytes())
|
||||||
api.logger.Info("Your new key was generated", "address", addr.String())
|
api.logger.Info("Your new key was generated", "address", addr.String())
|
||||||
api.logger.Info("Please backup your key file!", "path", os.Getenv("HOME")+"/.ethermint/"+name) // TODO: pass the correct binary
|
api.logger.Info("Please backup your key file!", "path", os.Getenv("HOME")+"/.ethermint/"+name) // TODO: pass the correct binary
|
||||||
api.logger.Info("Please remember your password!")
|
api.logger.Info("Please remember your password!")
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
coretypes "github.com/tendermint/tendermint/rpc/core/types"
|
coretypes "github.com/tendermint/tendermint/rpc/coretypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UnsubscribeFunc func()
|
type UnsubscribeFunc func()
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
coretypes "github.com/tendermint/tendermint/rpc/core/types"
|
coretypes "github.com/tendermint/tendermint/rpc/coretypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAddTopic(t *testing.T) {
|
func TestAddTopic(t *testing.T) {
|
||||||
|
@ -242,7 +242,7 @@ func BaseFeeFromEvents(events []abci.Event) *big.Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, attr := range event.Attributes {
|
for _, attr := range event.Attributes {
|
||||||
if bytes.Equal(attr.Key, []byte(feemarkettypes.AttributeKeyBaseFee)) {
|
if attr.Key == feemarkettypes.AttributeKeyBaseFee {
|
||||||
result, success := new(big.Int).SetString(string(attr.Value), 10)
|
result, success := new(big.Int).SetString(string(attr.Value), 10)
|
||||||
if success {
|
if success {
|
||||||
return result
|
return result
|
||||||
@ -250,6 +250,14 @@ func BaseFeeFromEvents(events []abci.Event) *big.Int {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// if bytes.Equal(attr.Key, []byte(feemarkettypes.AttributeKeyBaseFee)) {
|
||||||
|
// result, success := new(big.Int).SetString(string(attr.Value), 10)
|
||||||
|
// if success {
|
||||||
|
// return result
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -310,10 +318,10 @@ func FindTxAttributesByIndex(events []abci.Event, txIndex uint64) int {
|
|||||||
// FindAttribute find event attribute with specified key, if not found returns nil.
|
// FindAttribute find event attribute with specified key, if not found returns nil.
|
||||||
func FindAttribute(attrs []abci.EventAttribute, key []byte) []byte {
|
func FindAttribute(attrs []abci.EventAttribute, key []byte) []byte {
|
||||||
for _, attr := range attrs {
|
for _, attr := range attrs {
|
||||||
if !bytes.Equal(attr.Key, key) {
|
if !bytes.Equal([]byte(attr.Key), key) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return attr.Value
|
return []byte(attr.Value)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -536,7 +536,7 @@ func (api *pubSubAPI) subscribeLogs(wsConn *wsConn, subID rpc.ID, extra interfac
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data)
|
txResponse, err := evmtypes.DecodeTxResponse(dataTx.TxResult.Result.Data, api.clientCtx.Codec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.logger.Error("failed to decode tx response", "error", err.Error())
|
api.logger.Error("failed to decode tx response", "error", err.Error())
|
||||||
return
|
return
|
||||||
|
@ -35,7 +35,7 @@ cat $HOME/.chibaclonkd/config/genesis.json | jq '.app_state["mint"]["params"]["m
|
|||||||
"$PWD"/build/chibaclonkd validate-genesis
|
"$PWD"/build/chibaclonkd validate-genesis
|
||||||
|
|
||||||
# Start the node (remove the --pruning=nothing flag if historical queries are not needed) in background and log to file
|
# Start the node (remove the --pruning=nothing flag if historical queries are not needed) in background and log to file
|
||||||
"$PWD"/build/chibaclonkd start --pruning=nothing --rpc.unsafe --json-rpc.address="0.0.0.0:8545" --keyring-backend test > ethermintd.log 2>&1 &
|
"$PWD"/build/chibaclonkd start --pruning=nothing --mode validator --rpc.unsafe --json-rpc.address="0.0.0.0:8545" --keyring-backend test > ethermintd.log 2>&1 &
|
||||||
|
|
||||||
# Give ethermintd node enough time to launch
|
# Give ethermintd node enough time to launch
|
||||||
sleep 5
|
sleep 5
|
||||||
|
@ -17,10 +17,10 @@ RPC_PORT="854"
|
|||||||
IP_ADDR="0.0.0.0"
|
IP_ADDR="0.0.0.0"
|
||||||
|
|
||||||
KEY="mykey"
|
KEY="mykey"
|
||||||
CHAINID="ethermint_9000-1"
|
CHAINID="chibaclonk_9000-1"
|
||||||
MONIKER="mymoniker"
|
MONIKER="mymoniker"
|
||||||
|
|
||||||
## default port prefixes for ethermintd
|
## default port prefixes for chibaclonkd
|
||||||
NODE_P2P_PORT="2660"
|
NODE_P2P_PORT="2660"
|
||||||
NODE_PORT="2663"
|
NODE_PORT="2663"
|
||||||
NODE_RPC_PORT="2666"
|
NODE_RPC_PORT="2666"
|
||||||
@ -32,6 +32,7 @@ usage() {
|
|||||||
echo "-q <number> -- Quantity of nodes to run. eg: 3"
|
echo "-q <number> -- Quantity of nodes to run. eg: 3"
|
||||||
echo "-z <number> -- Quantity of nodes to run tests against eg: 3"
|
echo "-z <number> -- Quantity of nodes to run tests against eg: 3"
|
||||||
echo "-s <number> -- Sleep between operations in secs. eg: 5"
|
echo "-s <number> -- Sleep between operations in secs. eg: 5"
|
||||||
|
echo "-m <string> -- Mode for testing. eg: rpc"
|
||||||
echo "-r <string> -- Remove test dir after, eg: true, default is false"
|
echo "-r <string> -- Remove test dir after, eg: true, default is false"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@ -52,15 +53,15 @@ done
|
|||||||
|
|
||||||
set -euxo pipefail
|
set -euxo pipefail
|
||||||
|
|
||||||
DATA_DIR=$(mktemp -d -t ethermint-datadir.XXXXX)
|
|
||||||
|
|
||||||
|
DATA_DIR=$(mktemp -d -t chibaclonk-datadir.XXXXX)
|
||||||
if [[ ! "$DATA_DIR" ]]; then
|
if [[ ! "$DATA_DIR" ]]; then
|
||||||
echo "Could not create $DATA_DIR"
|
echo "Could not create $DATA_DIR"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Compile ethermint
|
# Compile chibaclonk
|
||||||
echo "compiling ethermint"
|
echo "compiling chibaclonk"
|
||||||
make build
|
make build
|
||||||
|
|
||||||
# PID array declaration
|
# PID array declaration
|
||||||
@ -103,18 +104,22 @@ init_func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
start_func() {
|
start_func() {
|
||||||
echo "starting ethermint node $i in background ..."
|
echo "starting chibaclonk node $i in background ..."
|
||||||
"$PWD"/build/chibaclonkd start --pruning=nothing --rpc.unsafe \
|
"$PWD"/build/chibaclonkd start \
|
||||||
--p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" --address tcp://$IP_ADDR:$NODE_PORT"$i" --rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
|
--pruning=nothing --rpc.unsafe \
|
||||||
--json-rpc.address=$IP_ADDR:$RPC_PORT"$i" \
|
--p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" \
|
||||||
--json-rpc.api="eth,txpool,personal,net,debug,web3" \
|
--address tcp://$IP_ADDR:$NODE_PORT"$i" \
|
||||||
--keyring-backend test --home "$DATA_DIR$i" \
|
--rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
|
||||||
|
--json-rpc.address=$IP_ADDR:$RPC_PORT"$i" \
|
||||||
|
--json-rpc.api="eth,txpool,personal,net,debug,web3" \
|
||||||
|
--keyring-backend test --mode validator --home "$DATA_DIR$i" \
|
||||||
|
--log_level debug \
|
||||||
>"$DATA_DIR"/node"$i".log 2>&1 & disown
|
>"$DATA_DIR"/node"$i".log 2>&1 & disown
|
||||||
|
|
||||||
ETHERMINT_PID=$!
|
CHIBACLONK_PID=$!
|
||||||
echo "started ethermint node, pid=$ETHERMINT_PID"
|
echo "started chibaclonk node, pid=$CHIBACLONK_PID"
|
||||||
# add PID to array
|
# add PID to array
|
||||||
arr+=("$ETHERMINT_PID")
|
arr+=("$CHIBACLONK_PID")
|
||||||
|
|
||||||
if [[ $MODE == "pending" ]]; then
|
if [[ $MODE == "pending" ]]; then
|
||||||
echo "waiting for the first block..."
|
echo "waiting for the first block..."
|
||||||
@ -144,7 +149,7 @@ if [[ -z $TEST || $TEST == "integration" ]] ; then
|
|||||||
|
|
||||||
for i in $(seq 1 "$TEST_QTD"); do
|
for i in $(seq 1 "$TEST_QTD"); do
|
||||||
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
|
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
|
||||||
echo "going to test ethermint node $HOST_RPC ..."
|
echo "going to test chibaclonk node $HOST_RPC ..."
|
||||||
MODE=$MODE HOST=$HOST_RPC go test ./tests/e2e/... -timeout=$time_out -v -short
|
MODE=$MODE HOST=$HOST_RPC go test ./tests/e2e/... -timeout=$time_out -v -short
|
||||||
TEST_FAIL=$?
|
TEST_FAIL=$?
|
||||||
done
|
done
|
||||||
@ -158,21 +163,20 @@ if [[ -z $TEST || $TEST == "rpc" || $TEST == "pending" ]]; then
|
|||||||
|
|
||||||
for i in $(seq 1 "$TEST_QTD"); do
|
for i in $(seq 1 "$TEST_QTD"); do
|
||||||
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
|
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
|
||||||
echo "going to test ethermint node $HOST_RPC ..."
|
echo "going to test chibaclonk node $HOST_RPC ..."
|
||||||
MODE=$MODE HOST=$HOST_RPC go test ./tests/rpc/... -timeout=$time_out -v -short
|
MODE=$MODE HOST=$HOST_RPC go test ./tests/rpc/... -timeout=$time_out -v -short
|
||||||
|
|
||||||
TEST_FAIL=$?
|
TEST_FAIL=$?
|
||||||
done
|
done
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
stop_func() {
|
stop_func() {
|
||||||
ETHERMINT_PID=$i
|
CHIBACLONK_PID=$i
|
||||||
echo "shutting down node, pid=$ETHERMINT_PID ..."
|
echo "shutting down node, pid=$CHIBACLONK_PID ..."
|
||||||
|
|
||||||
# Shutdown ethermint node
|
# Shutdown chibaclonk node
|
||||||
kill -9 "$ETHERMINT_PID"
|
kill -9 "$CHIBACLONK_PID"
|
||||||
wait "$ETHERMINT_PID"
|
wait "$CHIBACLONK_PID"
|
||||||
|
|
||||||
if [ $REMOVE_DATA_DIR == "true" ]
|
if [ $REMOVE_DATA_DIR == "true" ]
|
||||||
then
|
then
|
||||||
|
@ -3,7 +3,7 @@ export GOPATH=~/go
|
|||||||
export PATH=$PATH:$GOPATH/bin
|
export PATH=$PATH:$GOPATH/bin
|
||||||
|
|
||||||
# remove existing daemon
|
# remove existing daemon
|
||||||
rm -rf ~/.ethermintd
|
rm -rf ~/.chibaclonk*
|
||||||
|
|
||||||
# build ethermint binary
|
# build ethermint binary
|
||||||
make install
|
make install
|
||||||
|
@ -6,7 +6,8 @@ chibaclonkd validate-genesis --home /chibaclonk
|
|||||||
echo "starting chibaclonk node $ID in background ..."
|
echo "starting chibaclonk node $ID in background ..."
|
||||||
chibaclonkd start \
|
chibaclonkd start \
|
||||||
--home /chibaclonk \
|
--home /chibaclonk \
|
||||||
--keyring-backend test
|
--keyring-backend test \
|
||||||
|
--mode validator
|
||||||
|
|
||||||
echo "started ethermint node"
|
echo "started ethermint node"
|
||||||
tail -f /dev/null
|
tail -f /dev/null
|
@ -61,8 +61,8 @@ if [[ ! "$DATA_CLI_DIR" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Compile ethermint
|
# Compile chibaclonk
|
||||||
echo "compiling ethermint"
|
echo "compiling chibaclonk"
|
||||||
make build
|
make build
|
||||||
|
|
||||||
# PID array declaration
|
# PID array declaration
|
||||||
@ -89,15 +89,15 @@ init_func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
start_func() {
|
start_func() {
|
||||||
echo "starting ethermint node $i in background ..."
|
echo "starting chibaclonk node $i in background ..."
|
||||||
"$PWD"/build/chibaclonkd start --pruning=nothing --rpc.unsafe \
|
"$PWD"/build/chibaclonkd start --pruning=nothing --rpc.unsafe \
|
||||||
--p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" --address tcp://$IP_ADDR:$NODE_PORT"$i" --rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
|
--p2p.laddr tcp://$IP_ADDR:$NODE_P2P_PORT"$i" --address tcp://$IP_ADDR:$NODE_PORT"$i" --rpc.laddr tcp://$IP_ADDR:$NODE_RPC_PORT"$i" \
|
||||||
--json-rpc.address=$IP_ADDR:$RPC_PORT"$i" \
|
--json-rpc.address=$IP_ADDR:$RPC_PORT"$i" \
|
||||||
--keyring-backend test --home "$DATA_DIR$i" \
|
--keyring-backend test --mode validator --home "$DATA_DIR$i" \
|
||||||
>"$DATA_DIR"/node"$i".log 2>&1 & disown
|
>"$DATA_DIR"/node"$i".log 2>&1 & disown
|
||||||
|
|
||||||
ETHERMINT_PID=$!
|
ETHERMINT_PID=$!
|
||||||
echo "started ethermint node, pid=$ETHERMINT_PID"
|
echo "started chibaclonk node, pid=$ETHERMINT_PID"
|
||||||
# add PID to array
|
# add PID to array
|
||||||
arr+=("$ETHERMINT_PID")
|
arr+=("$ETHERMINT_PID")
|
||||||
}
|
}
|
||||||
@ -123,7 +123,7 @@ if [[ -z $TEST || $TEST == "rpc" ]]; then
|
|||||||
|
|
||||||
for i in $(seq 1 "$TEST_QTD"); do
|
for i in $(seq 1 "$TEST_QTD"); do
|
||||||
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
|
HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i"
|
||||||
echo "going to test ethermint node $HOST_RPC ..."
|
echo "going to test chibaclonk node $HOST_RPC ..."
|
||||||
MODE=$MODE HOST=$HOST_RPC go test ./tests/e2e/... -timeout=300s -v -short
|
MODE=$MODE HOST=$HOST_RPC go test ./tests/e2e/... -timeout=300s -v -short
|
||||||
MODE=$MODE HOST=$HOST_RPC go test ./tests/rpc/... -timeout=300s -v -short
|
MODE=$MODE HOST=$HOST_RPC go test ./tests/rpc/... -timeout=300s -v -short
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ stop_func() {
|
|||||||
ETHERMINT_PID=$i
|
ETHERMINT_PID=$i
|
||||||
echo "shutting down node, pid=$ETHERMINT_PID ..."
|
echo "shutting down node, pid=$ETHERMINT_PID ..."
|
||||||
|
|
||||||
# Shutdown ethermint node
|
# Shutdown chibaclonk node
|
||||||
kill -9 "$ETHERMINT_PID"
|
kill -9 "$ETHERMINT_PID"
|
||||||
wait "$ETHERMINT_PID"
|
wait "$ETHERMINT_PID"
|
||||||
}
|
}
|
||||||
|
@ -16,30 +16,27 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
tmservice "github.com/tendermint/tendermint/libs/service"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
abciserver "github.com/tendermint/tendermint/abci/server"
|
|
||||||
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
|
|
||||||
tmos "github.com/tendermint/tendermint/libs/os"
|
|
||||||
"github.com/tendermint/tendermint/node"
|
|
||||||
"github.com/tendermint/tendermint/p2p"
|
|
||||||
pvm "github.com/tendermint/tendermint/privval"
|
|
||||||
"github.com/tendermint/tendermint/proxy"
|
|
||||||
"github.com/tendermint/tendermint/rpc/client/local"
|
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/server/rosetta"
|
|
||||||
crgserver "github.com/cosmos/cosmos-sdk/server/rosetta/lib/server"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||||
|
dbm "github.com/cosmos/cosmos-sdk/db"
|
||||||
"github.com/cosmos/cosmos-sdk/server"
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
"github.com/cosmos/cosmos-sdk/server/api"
|
"github.com/cosmos/cosmos-sdk/server/api"
|
||||||
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
|
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||||
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
|
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
|
||||||
|
"github.com/cosmos/cosmos-sdk/server/rosetta"
|
||||||
|
crgserver "github.com/cosmos/cosmos-sdk/server/rosetta/lib/server"
|
||||||
"github.com/cosmos/cosmos-sdk/server/types"
|
"github.com/cosmos/cosmos-sdk/server/types"
|
||||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
abciclient "github.com/tendermint/tendermint/abci/client"
|
||||||
|
abciserver "github.com/tendermint/tendermint/abci/server"
|
||||||
|
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
|
||||||
|
tmos "github.com/tendermint/tendermint/libs/os"
|
||||||
|
"github.com/tendermint/tendermint/node"
|
||||||
|
"github.com/tendermint/tendermint/rpc/client/local"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
ethdebug "github.com/tharsis/ethermint/rpc/ethereum/namespaces/debug"
|
ethdebug "github.com/tharsis/ethermint/rpc/ethereum/namespaces/debug"
|
||||||
"github.com/tharsis/ethermint/server/config"
|
"github.com/tharsis/ethermint/server/config"
|
||||||
@ -48,6 +45,16 @@ import (
|
|||||||
"github.com/tharsis/ethermint/gql"
|
"github.com/tharsis/ethermint/gql"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
|
||||||
|
// gRPC-related flags
|
||||||
|
flagGRPCOnly = "grpc-only"
|
||||||
|
flagGRPCEnable = "grpc.enable"
|
||||||
|
flagGRPCAddress = "grpc.address"
|
||||||
|
flagGRPCWebEnable = "grpc-web.enable"
|
||||||
|
flagGRPCWebAddress = "grpc-web.address"
|
||||||
|
)
|
||||||
|
|
||||||
// StartCmd runs the service passed in, either stand-alone or in-process with
|
// StartCmd runs the service passed in, either stand-alone or in-process with
|
||||||
// Tendermint.
|
// Tendermint.
|
||||||
func StartCmd(appCreator types.AppCreator, defaultNodeHome string) *cobra.Command {
|
func StartCmd(appCreator types.AppCreator, defaultNodeHome string) *cobra.Command {
|
||||||
@ -141,7 +148,6 @@ which accepts a path for the resulting pprof file.
|
|||||||
cmd.Flags().Bool(server.FlagTrace, false, "Provide full stack traces for errors in ABCI Log")
|
cmd.Flags().Bool(server.FlagTrace, false, "Provide full stack traces for errors in ABCI Log")
|
||||||
cmd.Flags().String(server.FlagPruning, storetypes.PruningOptionDefault, "Pruning strategy (default|nothing|everything|custom)")
|
cmd.Flags().String(server.FlagPruning, storetypes.PruningOptionDefault, "Pruning strategy (default|nothing|everything|custom)")
|
||||||
cmd.Flags().Uint64(server.FlagPruningKeepRecent, 0, "Number of recent heights to keep on disk (ignored if pruning is not 'custom')")
|
cmd.Flags().Uint64(server.FlagPruningKeepRecent, 0, "Number of recent heights to keep on disk (ignored if pruning is not 'custom')")
|
||||||
cmd.Flags().Uint64(server.FlagPruningKeepEvery, 0, "Offset heights to keep on disk after 'keep-every' (ignored if pruning is not 'custom')")
|
|
||||||
cmd.Flags().Uint64(server.FlagPruningInterval, 0, "Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom')")
|
cmd.Flags().Uint64(server.FlagPruningInterval, 0, "Height interval at which pruned heights are removed from disk (ignored if pruning is not 'custom')")
|
||||||
cmd.Flags().Uint(server.FlagInvCheckPeriod, 0, "Assert registered invariants every N blocks")
|
cmd.Flags().Uint(server.FlagInvCheckPeriod, 0, "Assert registered invariants every N blocks")
|
||||||
cmd.Flags().Uint64(server.FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune Tendermint blocks")
|
cmd.Flags().Uint64(server.FlagMinRetainBlocks, 0, "Minimum block height offset during ABCI commit to prune Tendermint blocks")
|
||||||
@ -186,10 +192,11 @@ func startStandAlone(ctx *server.Context, appCreator types.AppCreator) error {
|
|||||||
transport := ctx.Viper.GetString(srvflags.Transport)
|
transport := ctx.Viper.GetString(srvflags.Transport)
|
||||||
home := ctx.Viper.GetString(flags.FlagHome)
|
home := ctx.Viper.GetString(flags.FlagHome)
|
||||||
|
|
||||||
db, err := openDB(home)
|
db, err := openDB(home, server.GetAppDBBackend((ctx.Viper)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := db.Close(); err != nil {
|
if err := db.Close(); err != nil {
|
||||||
ctx.Logger.With("error", err).Error("error closing db")
|
ctx.Logger.With("error", err).Error("error closing db")
|
||||||
@ -261,9 +268,8 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
traceWriterFile := ctx.Viper.GetString(srvflags.TraceStore)
|
traceWriterFile := ctx.Viper.GetString(srvflags.TraceStore)
|
||||||
db, err := openDB(home)
|
db, err := openDB(home, server.GetAppDBBackend(ctx.Viper))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to open DB", "error", err.Error())
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -294,38 +300,46 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
|||||||
|
|
||||||
app := appCreator(ctx.Logger, db, traceWriter, ctx.Viper)
|
app := appCreator(ctx.Logger, db, traceWriter, ctx.Viper)
|
||||||
|
|
||||||
nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile())
|
genDoc, err := tmtypes.GenesisDocFromFile(cfg.GenesisFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed load or gen node key", "error", err.Error())
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
genDocProvider := node.DefaultGenesisDocProviderFunc(cfg)
|
var (
|
||||||
tmNode, err := node.NewNode(
|
tmNode tmservice.Service
|
||||||
cfg,
|
gRPCOnly = ctx.Viper.GetBool(flagGRPCOnly)
|
||||||
pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()),
|
|
||||||
nodeKey,
|
|
||||||
proxy.NewLocalClientCreator(app),
|
|
||||||
genDocProvider,
|
|
||||||
node.DefaultDBProvider,
|
|
||||||
node.DefaultMetricsProvider(cfg.Instrumentation),
|
|
||||||
ctx.Logger.With("server", "node"),
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if gRPCOnly {
|
||||||
logger.Error("failed init node", "error", err.Error())
|
ctx.Logger.Info("starting node in gRPC only mode; Tendermint is disabled")
|
||||||
return err
|
config.GRPC.Enable = true
|
||||||
}
|
} else {
|
||||||
|
ctx.Logger.Info("starting node with ABCI Tendermint in-process")
|
||||||
|
|
||||||
if err := tmNode.Start(); err != nil {
|
tmNode, err = node.New(cfg, ctx.Logger, abciclient.NewLocalCreator(app), genDoc)
|
||||||
logger.Error("failed start tendermint server", "error", err.Error())
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tmNode.Start(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the tx service to the gRPC router. We only need to register this
|
// Add the tx service to the gRPC router. We only need to register this
|
||||||
// service if API or gRPC or JSONRPC is enabled, and avoid doing so in the general
|
// service if API or gRPC or JSONRPC is enabled, and avoid doing so in the general
|
||||||
// case, because it spawns a new local tendermint RPC client.
|
// case, because it spawns a new local tendermint RPC client.
|
||||||
if config.API.Enable || config.GRPC.Enable || config.JSONRPC.Enable {
|
if config.API.Enable || config.GRPC.Enable || config.JSONRPC.Enable {
|
||||||
clientCtx = clientCtx.WithClient(local.New(tmNode))
|
node, ok := tmNode.(local.NodeService)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("unable to set node type; please try re-installing the binary")
|
||||||
|
}
|
||||||
|
|
||||||
|
localNode, err := local.New(node)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
clientCtx = clientCtx.WithClient(localNode)
|
||||||
|
|
||||||
app.RegisterTxService(clientCtx)
|
app.RegisterTxService(clientCtx)
|
||||||
app.RegisterTendermintService(clientCtx)
|
app.RegisterTendermintService(clientCtx)
|
||||||
@ -333,7 +347,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
|||||||
|
|
||||||
var apiSrv *api.Server
|
var apiSrv *api.Server
|
||||||
if config.API.Enable {
|
if config.API.Enable {
|
||||||
genDoc, err := genDocProvider()
|
genDoc, err := tmtypes.GenesisDocFromFile(cfg.GenesisFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -419,7 +433,7 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
|||||||
)
|
)
|
||||||
|
|
||||||
if config.JSONRPC.Enable {
|
if config.JSONRPC.Enable {
|
||||||
genDoc, err := genDocProvider()
|
genDoc, err := tmtypes.GenesisDocFromFile(cfg.GenesisFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -481,9 +495,9 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, appCreator ty
|
|||||||
return server.WaitForQuitSignals()
|
return server.WaitForQuitSignals()
|
||||||
}
|
}
|
||||||
|
|
||||||
func openDB(rootDir string) (dbm.DB, error) {
|
func openDB(rootDir string, backendType dbm.BackendType) (dbm.DBConnection, error) {
|
||||||
dataDir := filepath.Join(rootDir, "data")
|
dataDir := filepath.Join(rootDir, "data")
|
||||||
return sdk.NewLevelDB("application", dataDir)
|
return dbm.NewDB("application", backendType, dataDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
func openTraceWriter(traceWriterFile string) (w io.Writer, err error) {
|
func openTraceWriter(traceWriterFile string) (w io.Writer, err error) {
|
||||||
|
@ -43,15 +43,16 @@ func AddCommands(rootCmd *cobra.Command, defaultNodeHome string, appCreator type
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ConnectTmWS(tmRPCAddr, tmEndpoint string, logger tmlog.Logger) *rpcclient.WSClient {
|
func ConnectTmWS(tmRPCAddr, tmEndpoint string, logger tmlog.Logger) *rpcclient.WSClient {
|
||||||
tmWsClient, err := rpcclient.NewWS(tmRPCAddr, tmEndpoint,
|
tmWsClient, err := rpcclient.NewWSWithOptions(tmRPCAddr, tmEndpoint, rpcclient.WSOptions{
|
||||||
rpcclient.MaxReconnectAttempts(256),
|
MaxReconnectAttempts: 256, // first: 2 sec, last: 17 min.
|
||||||
rpcclient.ReadWait(120*time.Second),
|
WriteWait: 120 * time.Second,
|
||||||
rpcclient.WriteWait(120*time.Second),
|
ReadWait: 120 * time.Second,
|
||||||
rpcclient.PingPeriod(50*time.Second),
|
PingPeriod: 50 * time.Second,
|
||||||
rpcclient.OnReconnect(func() {
|
})
|
||||||
logger.Debug("EVM RPC reconnects to Tendermint WS", "address", tmRPCAddr+tmEndpoint)
|
|
||||||
}),
|
tmWsClient.OnReconnect(func() {
|
||||||
)
|
logger.Debug("EVM RPC reconnects to Tendermint WS", "address", tmRPCAddr+tmEndpoint)
|
||||||
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(
|
logger.Error(
|
||||||
@ -59,7 +60,7 @@ func ConnectTmWS(tmRPCAddr, tmEndpoint string, logger tmlog.Logger) *rpcclient.W
|
|||||||
"address", tmRPCAddr+tmEndpoint,
|
"address", tmRPCAddr+tmEndpoint,
|
||||||
"error", err,
|
"error", err,
|
||||||
)
|
)
|
||||||
} else if err := tmWsClient.OnStart(); err != nil {
|
} else if err := tmWsClient.Start(); err != nil {
|
||||||
logger.Error(
|
logger.Error(
|
||||||
"Tendermint WS client could not start",
|
"Tendermint WS client could not start",
|
||||||
"address", tmRPCAddr+tmEndpoint,
|
"address", tmRPCAddr+tmEndpoint,
|
||||||
|
@ -59,7 +59,7 @@ type ImporterTestSuite struct {
|
|||||||
/// DoSetupTest setup test environment, it uses`require.TestingT` to support both `testing.T` and `testing.B`.
|
/// DoSetupTest setup test environment, it uses`require.TestingT` to support both `testing.T` and `testing.B`.
|
||||||
func (suite *ImporterTestSuite) DoSetupTest(t require.TestingT) {
|
func (suite *ImporterTestSuite) DoSetupTest(t require.TestingT) {
|
||||||
checkTx := false
|
checkTx := false
|
||||||
suite.app = app.Setup(checkTx, nil)
|
suite.app = app.Setup(suite.T(), checkTx, nil)
|
||||||
// consensus key
|
// consensus key
|
||||||
priv, err := ethsecp256k1.GenerateKey()
|
priv, err := ethsecp256k1.GenerateKey()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -301,17 +301,6 @@ func deployTestContract(t *testing.T) (hexutil.Bytes, map[string]interface{}) {
|
|||||||
return hash, receipt
|
return hash, receipt
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTransactionReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} {
|
|
||||||
param := []string{hash.String()}
|
|
||||||
rpcRes := call(t, "eth_getTransactionReceipt", param)
|
|
||||||
|
|
||||||
receipt := make(map[string]interface{})
|
|
||||||
err := json.Unmarshal(rpcRes.Result, &receipt)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
return receipt
|
|
||||||
}
|
|
||||||
|
|
||||||
func waitForReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} {
|
func waitForReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} {
|
||||||
timeout := time.After(12 * time.Second)
|
timeout := time.After(12 * time.Second)
|
||||||
ticker := time.Tick(500 * time.Millisecond)
|
ticker := time.Tick(500 * time.Millisecond)
|
||||||
@ -321,7 +310,7 @@ func waitForReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} {
|
|||||||
case <-timeout:
|
case <-timeout:
|
||||||
return nil
|
return nil
|
||||||
case <-ticker:
|
case <-ticker:
|
||||||
receipt := getTransactionReceipt(t, hash)
|
receipt := GetTransactionReceipt(t, hash)
|
||||||
if receipt != nil {
|
if receipt != nil {
|
||||||
return receipt
|
return receipt
|
||||||
}
|
}
|
||||||
|
@ -58,4 +58,4 @@ chibaclonkd collect-gentxs
|
|||||||
chibaclonkd validate-genesis
|
chibaclonkd validate-genesis
|
||||||
|
|
||||||
# Start the node (remove the --pruning=nothing flag if historical queries are not needed)
|
# Start the node (remove the --pruning=nothing flag if historical queries are not needed)
|
||||||
chibaclonkd start --pruning=nothing --rpc.unsafe --keyring-backend test --log_level info --json-rpc.api eth,txpool,personal,net,debug,web3 --api.enable
|
chibaclonkd start --pruning=nothing --rpc.unsafe --keyring-backend test --log_level info --json-rpc.api eth,txpool,personal,net,debug,web3 --api.enable --mode validator
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -15,16 +16,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
tmcfg "github.com/tendermint/tendermint/config"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
tmcfg "github.com/tendermint/tendermint/config"
|
"github.com/tendermint/tendermint/libs/service"
|
||||||
tmflags "github.com/tendermint/tendermint/libs/cli/flags"
|
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
|
||||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
|
||||||
"github.com/tendermint/tendermint/node"
|
|
||||||
tmclient "github.com/tendermint/tendermint/rpc/client"
|
tmclient "github.com/tendermint/tendermint/rpc/client"
|
||||||
dbm "github.com/tendermint/tm-db"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
@ -34,6 +33,7 @@ import (
|
|||||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/db/memdb"
|
||||||
"github.com/cosmos/cosmos-sdk/server"
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
"github.com/cosmos/cosmos-sdk/server/api"
|
"github.com/cosmos/cosmos-sdk/server/api"
|
||||||
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
|
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||||
@ -68,7 +68,7 @@ type AppConstructor = func(val Validator) servertypes.Application
|
|||||||
func NewAppConstructor(encodingCfg params.EncodingConfig) AppConstructor {
|
func NewAppConstructor(encodingCfg params.EncodingConfig) AppConstructor {
|
||||||
return func(val Validator) servertypes.Application {
|
return func(val Validator) servertypes.Application {
|
||||||
return app.NewEthermintApp(
|
return app.NewEthermintApp(
|
||||||
val.Ctx.Logger, dbm.NewMemDB(), nil, true, make(map[int64]bool), val.Ctx.Config.RootDir, 0,
|
val.Ctx.Logger, memdb.NewDB(), nil, true, make(map[int64]bool), val.Ctx.Config.RootDir, 0,
|
||||||
encodingCfg,
|
encodingCfg,
|
||||||
simapp.EmptyAppOptions{},
|
simapp.EmptyAppOptions{},
|
||||||
baseapp.SetPruning(storetypes.NewPruningOptionsFromString(val.AppConfig.Pruning)),
|
baseapp.SetPruning(storetypes.NewPruningOptionsFromString(val.AppConfig.Pruning)),
|
||||||
@ -113,15 +113,15 @@ func DefaultConfig() Config {
|
|||||||
encCfg := encoding.MakeConfig(app.ModuleBasics)
|
encCfg := encoding.MakeConfig(app.ModuleBasics)
|
||||||
|
|
||||||
return Config{
|
return Config{
|
||||||
Codec: encCfg.Marshaler,
|
Codec: encCfg.Codec,
|
||||||
TxConfig: encCfg.TxConfig,
|
TxConfig: encCfg.TxConfig,
|
||||||
LegacyAmino: encCfg.Amino,
|
LegacyAmino: encCfg.Amino,
|
||||||
InterfaceRegistry: encCfg.InterfaceRegistry,
|
InterfaceRegistry: encCfg.InterfaceRegistry,
|
||||||
AccountRetriever: authtypes.AccountRetriever{},
|
AccountRetriever: authtypes.AccountRetriever{},
|
||||||
AppConstructor: NewAppConstructor(encCfg),
|
AppConstructor: NewAppConstructor(encCfg),
|
||||||
GenesisState: app.ModuleBasics.DefaultGenesis(encCfg.Marshaler),
|
GenesisState: app.ModuleBasics.DefaultGenesis(encCfg.Codec),
|
||||||
TimeoutCommit: 2 * time.Second,
|
TimeoutCommit: 2 * time.Second,
|
||||||
ChainID: fmt.Sprintf("ethermint_%d-1", tmrand.Int63n(9999999999999)+1),
|
ChainID: fmt.Sprintf("ethermint_%d-1", rand.Int63n(9999999999999)+1),
|
||||||
NumValidators: 4,
|
NumValidators: 4,
|
||||||
BondDenom: ethermint.AttoPhoton,
|
BondDenom: ethermint.AttoPhoton,
|
||||||
MinGasPrices: fmt.Sprintf("0.000006%s", ethermint.AttoPhoton),
|
MinGasPrices: fmt.Sprintf("0.000006%s", ethermint.AttoPhoton),
|
||||||
@ -174,7 +174,7 @@ type (
|
|||||||
RPCClient tmclient.Client
|
RPCClient tmclient.Client
|
||||||
JSONRPCClient *ethclient.Client
|
JSONRPCClient *ethclient.Client
|
||||||
|
|
||||||
tmNode *node.Node
|
tmNode service.Service
|
||||||
api *api.Server
|
api *api.Server
|
||||||
grpc *grpc.Server
|
grpc *grpc.Server
|
||||||
grpcWeb *http.Server
|
grpcWeb *http.Server
|
||||||
@ -255,6 +255,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) {
|
|||||||
ctx := server.NewDefaultContext()
|
ctx := server.NewDefaultContext()
|
||||||
tmCfg := ctx.Config
|
tmCfg := ctx.Config
|
||||||
tmCfg.Consensus.TimeoutCommit = cfg.TimeoutCommit
|
tmCfg.Consensus.TimeoutCommit = cfg.TimeoutCommit
|
||||||
|
tmCfg.Mode = tmcfg.ModeValidator
|
||||||
|
|
||||||
// Only allow the first validator to expose an RPC, API and gRPC
|
// Only allow the first validator to expose an RPC, API and gRPC
|
||||||
// server/client due to Tendermint in-process constraints.
|
// server/client due to Tendermint in-process constraints.
|
||||||
@ -322,17 +323,18 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) {
|
|||||||
appCfg.JSONRPC.API = config.GetAPINamespaces()
|
appCfg.JSONRPC.API = config.GetAPINamespaces()
|
||||||
}
|
}
|
||||||
|
|
||||||
logger := log.NewNopLogger()
|
logger := server.ZeroLogWrapper{Logger: zerolog.Nop()}
|
||||||
if cfg.EnableTMLogging {
|
if cfg.EnableTMLogging {
|
||||||
logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
logWriter := zerolog.ConsoleWriter{Out: os.Stderr}
|
||||||
logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel)
|
logger = server.ZeroLogWrapper{Logger: zerolog.New(logWriter).Level(zerolog.InfoLevel).With().Timestamp().Logger()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.Logger = logger
|
||||||
ctx.Logger = logger
|
ctx.Logger = logger
|
||||||
|
|
||||||
nodeDirName := fmt.Sprintf("node%d", i)
|
nodeDirName := fmt.Sprintf("node%d", i)
|
||||||
nodeDir := filepath.Join(network.BaseDir, nodeDirName, "evmosd")
|
nodeDir := filepath.Join(network.BaseDir, nodeDirName, "chibaclonkd")
|
||||||
clientDir := filepath.Join(network.BaseDir, nodeDirName, "evmoscli")
|
clientDir := filepath.Join(network.BaseDir, nodeDirName, "chibaclonkcli")
|
||||||
gentxsDir := filepath.Join(network.BaseDir, "gentxs")
|
gentxsDir := filepath.Join(network.BaseDir, "gentxs")
|
||||||
|
|
||||||
err := os.MkdirAll(filepath.Join(nodeDir, "config"), 0o750)
|
err := os.MkdirAll(filepath.Join(nodeDir, "config"), 0o750)
|
||||||
@ -370,7 +372,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) {
|
|||||||
nodeIDs[i] = nodeID
|
nodeIDs[i] = nodeID
|
||||||
valPubKeys[i] = pubKey
|
valPubKeys[i] = pubKey
|
||||||
|
|
||||||
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.KeyringOptions...)
|
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.Codec, cfg.KeyringOptions...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -527,6 +529,13 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) {
|
|||||||
|
|
||||||
l.Log("started test network")
|
l.Log("started test network")
|
||||||
|
|
||||||
|
height, err := network.LatestHeight()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Log("started test network at height:", height)
|
||||||
|
|
||||||
// Ensure we cleanup incase any test was abruptly halted (e.g. SIGINT) as any
|
// Ensure we cleanup incase any test was abruptly halted (e.g. SIGINT) as any
|
||||||
// defer in a test would not be called.
|
// defer in a test would not be called.
|
||||||
server.TrapSignal(network.Cleanup)
|
server.TrapSignal(network.Cleanup)
|
||||||
@ -560,22 +569,22 @@ func (n *Network) WaitForHeight(h int64) (int64, error) {
|
|||||||
// provide a custom timeout.
|
// provide a custom timeout.
|
||||||
func (n *Network) WaitForHeightWithTimeout(h int64, t time.Duration) (int64, error) {
|
func (n *Network) WaitForHeightWithTimeout(h int64, t time.Duration) (int64, error) {
|
||||||
ticker := time.NewTicker(time.Second)
|
ticker := time.NewTicker(time.Second)
|
||||||
timeout := time.After(t)
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
timeout := time.NewTimer(t)
|
||||||
|
defer timeout.Stop()
|
||||||
|
|
||||||
if len(n.Validators) == 0 {
|
if len(n.Validators) == 0 {
|
||||||
return 0, errors.New("no validators available")
|
return 0, errors.New("no validators available")
|
||||||
}
|
}
|
||||||
|
|
||||||
var latestHeight int64
|
var latestHeight int64
|
||||||
val := n.Validators[0]
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-timeout:
|
case <-timeout.C:
|
||||||
ticker.Stop()
|
|
||||||
return latestHeight, errors.New("timeout exceeded waiting for block")
|
return latestHeight, errors.New("timeout exceeded waiting for block")
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
status, err := val.RPCClient.Status(context.Background())
|
status, err := n.Validators[0].RPCClient.Status(context.Background())
|
||||||
if err == nil && status != nil {
|
if err == nil && status != nil {
|
||||||
latestHeight = status.SyncInfo.LatestBlockHeight
|
latestHeight = status.SyncInfo.LatestBlockHeight
|
||||||
if latestHeight >= h {
|
if latestHeight >= h {
|
||||||
@ -629,21 +638,6 @@ func (n *Network) Cleanup() {
|
|||||||
_ = v.grpcWeb.Close()
|
_ = v.grpcWeb.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.jsonrpc != nil {
|
|
||||||
shutdownCtx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second)
|
|
||||||
defer cancelFn()
|
|
||||||
|
|
||||||
if err := v.jsonrpc.Shutdown(shutdownCtx); err != nil {
|
|
||||||
v.tmNode.Logger.Error("HTTP server shutdown produced a warning", "error", err.Error())
|
|
||||||
} else {
|
|
||||||
v.tmNode.Logger.Info("HTTP server shut down, waiting 5 sec")
|
|
||||||
select {
|
|
||||||
case <-time.Tick(5 * time.Second):
|
|
||||||
case <-v.jsonrpcDone:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Config.CleanupDir {
|
if n.Config.CleanupDir {
|
||||||
|
@ -3,18 +3,17 @@ package network
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
|
abciclient "github.com/tendermint/tendermint/abci/client"
|
||||||
tmos "github.com/tendermint/tendermint/libs/os"
|
tmos "github.com/tendermint/tendermint/libs/os"
|
||||||
|
tmtime "github.com/tendermint/tendermint/libs/time"
|
||||||
"github.com/tendermint/tendermint/node"
|
"github.com/tendermint/tendermint/node"
|
||||||
"github.com/tendermint/tendermint/p2p"
|
|
||||||
pvm "github.com/tendermint/tendermint/privval"
|
|
||||||
"github.com/tendermint/tendermint/proxy"
|
|
||||||
"github.com/tendermint/tendermint/rpc/client/local"
|
"github.com/tendermint/tendermint/rpc/client/local"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
tmtime "github.com/tendermint/tendermint/types/time"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/server/api"
|
"github.com/cosmos/cosmos-sdk/server/api"
|
||||||
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
|
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
|
||||||
@ -25,9 +24,9 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||||
|
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||||
mintypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
mintypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/server"
|
"github.com/tharsis/ethermint/server"
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
)
|
)
|
||||||
@ -41,36 +40,35 @@ func startInProcess(cfg Config, val *Validator) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeKey, err := p2p.LoadOrGenNodeKey(tmCfg.NodeKeyFile())
|
app := cfg.AppConstructor(*val)
|
||||||
|
genDoc, err := types.GenesisDocFromFile(tmCfg.GenesisFile())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
app := cfg.AppConstructor(*val)
|
val.tmNode, err = node.New(
|
||||||
|
|
||||||
genDocProvider := node.DefaultGenesisDocProviderFunc(tmCfg)
|
|
||||||
tmNode, err := node.NewNode(
|
|
||||||
tmCfg,
|
tmCfg,
|
||||||
pvm.LoadOrGenFilePV(tmCfg.PrivValidatorKeyFile(), tmCfg.PrivValidatorStateFile()),
|
|
||||||
nodeKey,
|
|
||||||
proxy.NewLocalClientCreator(app),
|
|
||||||
genDocProvider,
|
|
||||||
node.DefaultDBProvider,
|
|
||||||
node.DefaultMetricsProvider(tmCfg.Instrumentation),
|
|
||||||
logger.With("module", val.Moniker),
|
logger.With("module", val.Moniker),
|
||||||
|
abciclient.NewLocalCreator(app),
|
||||||
|
genDoc,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tmNode.Start(); err != nil {
|
if err := val.tmNode.Start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
val.tmNode = tmNode
|
|
||||||
|
|
||||||
if val.RPCAddress != "" {
|
if val.RPCAddress != "" {
|
||||||
val.RPCClient = local.New(tmNode)
|
node, ok := val.tmNode.(local.NodeService)
|
||||||
|
if !ok {
|
||||||
|
panic("can't cast service.Service to NodeService")
|
||||||
|
}
|
||||||
|
val.RPCClient, err = local.New(node)
|
||||||
|
if err != nil {
|
||||||
|
panic("cant create a local node")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll need a RPC client if the validator exposes a gRPC or REST endpoint.
|
// We'll need a RPC client if the validator exposes a gRPC or REST endpoint.
|
||||||
@ -152,7 +150,7 @@ func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error {
|
|||||||
for i := 0; i < cfg.NumValidators; i++ {
|
for i := 0; i < cfg.NumValidators; i++ {
|
||||||
tmCfg := vals[i].Ctx.Config
|
tmCfg := vals[i].Ctx.Config
|
||||||
|
|
||||||
nodeDir := filepath.Join(outputDir, vals[i].Moniker, "evmosd")
|
nodeDir := filepath.Join(outputDir, vals[i].Moniker, "chibaclonkd")
|
||||||
gentxsDir := filepath.Join(outputDir, "gentxs")
|
gentxsDir := filepath.Join(outputDir, "gentxs")
|
||||||
|
|
||||||
tmCfg.Moniker = vals[i].Moniker
|
tmCfg.Moniker = vals[i].Moniker
|
||||||
@ -206,7 +204,7 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance
|
|||||||
stakingGenState.Params.BondDenom = cfg.BondDenom
|
stakingGenState.Params.BondDenom = cfg.BondDenom
|
||||||
cfg.GenesisState[stakingtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&stakingGenState)
|
cfg.GenesisState[stakingtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&stakingGenState)
|
||||||
|
|
||||||
var govGenState govtypes.GenesisState
|
var govGenState v1.GenesisState
|
||||||
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[govtypes.ModuleName], &govGenState)
|
cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[govtypes.ModuleName], &govGenState)
|
||||||
|
|
||||||
govGenState.DepositParams.MinDeposit[0].Denom = cfg.BondDenom
|
govGenState.DepositParams.MinDeposit[0].Denom = cfg.BondDenom
|
||||||
@ -252,12 +250,18 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance
|
|||||||
}
|
}
|
||||||
|
|
||||||
func WriteFile(name string, dir string, contents []byte) error {
|
func WriteFile(name string, dir string, contents []byte) error {
|
||||||
file := filepath.Join(dir, name)
|
writePath := filepath.Join(dir)
|
||||||
|
file := filepath.Join(writePath, name)
|
||||||
|
|
||||||
err := tmos.EnsureDir(dir, 0o755)
|
err := tmos.EnsureDir(writePath, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmos.WriteFile(file, contents, 0o644)
|
err = ioutil.WriteFile(file, contents, 0644) // nolint: gosec
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
6
types/address.go
Normal file
6
types/address.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Bech32MainPrefix defines the main SDK Bech32 prefix of an account's address
|
||||||
|
Bech32MainPrefix = "ethm"
|
||||||
|
)
|
@ -19,7 +19,7 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
|||||||
&EthAccount{},
|
&EthAccount{},
|
||||||
)
|
)
|
||||||
registry.RegisterInterface(
|
registry.RegisterInterface(
|
||||||
"ethermint.v1.ExtensionOptionsWeb3Tx",
|
"ethermint.types.v1.ExtensionOptionsWeb3Tx",
|
||||||
(*ExtensionOptionsWeb3TxI)(nil),
|
(*ExtensionOptionsWeb3TxI)(nil),
|
||||||
&ExtensionOptionsWeb3Tx{},
|
&ExtensionOptionsWeb3Tx{},
|
||||||
)
|
)
|
||||||
|
@ -26,7 +26,7 @@ type infiniteGasMeterWithLimit struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewInfiniteGasMeterWithLimit returns a reference to a new infiniteGasMeter.
|
// NewInfiniteGasMeterWithLimit returns a reference to a new infiniteGasMeter.
|
||||||
func NewInfiniteGasMeterWithLimit(limit sdk.Gas) sdk.GasMeter {
|
func NewInfiniteGasMeterWithLimit(limit sdk.Gas) *infiniteGasMeterWithLimit {
|
||||||
return &infiniteGasMeterWithLimit{
|
return &infiniteGasMeterWithLimit{
|
||||||
consumed: 0,
|
consumed: 0,
|
||||||
limit: limit,
|
limit: limit,
|
||||||
@ -45,6 +45,14 @@ func (g *infiniteGasMeterWithLimit) Limit() sdk.Gas {
|
|||||||
return g.limit
|
return g.limit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GasRemaining returns the gas left in the GasMeter.
|
||||||
|
func (g *infiniteGasMeterWithLimit) GasRemaining() sdk.Gas {
|
||||||
|
if g.IsPastLimit() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return g.limit - g.consumed
|
||||||
|
}
|
||||||
|
|
||||||
// addUint64Overflow performs the addition operation on two uint64 integers and
|
// addUint64Overflow performs the addition operation on two uint64 integers and
|
||||||
// returns a boolean on whether or not the result overflows.
|
// returns a boolean on whether or not the result overflows.
|
||||||
func addUint64Overflow(a, b uint64) (uint64, bool) {
|
func addUint64Overflow(a, b uint64) (uint64, bool) {
|
||||||
@ -67,7 +75,7 @@ func (g *infiniteGasMeterWithLimit) ConsumeGas(amount sdk.Gas, descriptor string
|
|||||||
// RefundGas will deduct the given amount from the gas consumed. If the amount is greater than the
|
// RefundGas will deduct the given amount from the gas consumed. If the amount is greater than the
|
||||||
// gas consumed, the function will panic.
|
// gas consumed, the function will panic.
|
||||||
//
|
//
|
||||||
// Use case: This functionality enables refunding gas to the trasaction or block gas pools so that
|
// Use case: This functionality enables refunding gas to the transaction or block gas pools so that
|
||||||
// EVM-compatible chains can fully support the go-ethereum StateDb interface.
|
// EVM-compatible chains can fully support the go-ethereum StateDb interface.
|
||||||
// See https://github.com/cosmos/cosmos-sdk/pull/9403 for reference.
|
// See https://github.com/cosmos/cosmos-sdk/pull/9403 for reference.
|
||||||
func (g *infiniteGasMeterWithLimit) RefundGas(amount sdk.Gas, descriptor string) {
|
func (g *infiniteGasMeterWithLimit) RefundGas(amount sdk.Gas, descriptor string) {
|
||||||
|
@ -36,6 +36,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
|
|||||||
s.T().Log("setting up integration test suite")
|
s.T().Log("setting up integration test suite")
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
|
s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg)
|
||||||
s.Require().NoError(err)
|
s.Require().NoError(err)
|
||||||
|
|
||||||
@ -61,9 +62,7 @@ func (s *IntegrationTestSuite) createAccountWithBalance(accountName string, acco
|
|||||||
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.EthSecp256k1)
|
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.EthSecp256k1)
|
||||||
sr.NoError(err)
|
sr.NoError(err)
|
||||||
|
|
||||||
val.ClientCtx.Keyring.SavePubKey(accountName, info.GetPubKey(), hd.EthSecp256k1Type)
|
newAddr, _ := info.GetAddress()
|
||||||
|
|
||||||
newAddr := sdk.AccAddress(info.GetPubKey().Address())
|
|
||||||
_, err = banktestutil.MsgSendExec(
|
_, err = banktestutil.MsgSendExec(
|
||||||
val.ClientCtx,
|
val.ClientCtx,
|
||||||
val.Address,
|
val.Address,
|
||||||
|
@ -3,7 +3,7 @@ package testutil
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/types/rest"
|
"github.com/cosmos/cosmos-sdk/testutil/rest"
|
||||||
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
|
auctiontypes "github.com/tharsis/ethermint/x/auction/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||||
"github.com/tharsis/ethermint/app"
|
"github.com/tharsis/ethermint/app"
|
||||||
"github.com/tharsis/ethermint/x/auction/types"
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
)
|
)
|
||||||
@ -40,7 +40,7 @@ func (suite *KeeperTestSuite) TestGrpcGetAllAuctions() {
|
|||||||
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
suite.Run(fmt.Sprintf("Case %s", test.msg), func() {
|
||||||
if test.createAuctions {
|
if test.createAuctions {
|
||||||
account := app.CreateRandomAccounts(1)[0]
|
account := app.CreateRandomAccounts(1)[0]
|
||||||
err := simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(
|
err := testutil.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(
|
||||||
sdk.Coin{Amount: sdk.NewInt(100), Denom: sdk.DefaultBondDenom},
|
sdk.Coin{Amount: sdk.NewInt(100), Denom: sdk.DefaultBondDenom},
|
||||||
))
|
))
|
||||||
|
|
||||||
@ -329,7 +329,7 @@ func (suite *KeeperTestSuite) createAuctionAndCommitBid(commitBid bool) (*types.
|
|||||||
|
|
||||||
accounts := app.CreateRandomAccounts(accCount)
|
accounts := app.CreateRandomAccounts(accCount)
|
||||||
for _, account := range accounts {
|
for _, account := range accounts {
|
||||||
err := simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(
|
err := testutil.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(
|
||||||
sdk.Coin{Amount: sdk.NewInt(100), Denom: sdk.DefaultBondDenom},
|
sdk.Coin{Amount: sdk.NewInt(100), Denom: sdk.DefaultBondDenom},
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -7,12 +7,12 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
auth "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
auth "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||||
bank "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
bank "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
||||||
params "github.com/cosmos/cosmos-sdk/x/params/types"
|
params "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/x/auction/types"
|
"github.com/tharsis/ethermint/x/auction/types"
|
||||||
|
|
||||||
wnsUtils "github.com/tharsis/ethermint/utils"
|
wnsUtils "github.com/tharsis/ethermint/utils"
|
||||||
@ -43,7 +43,7 @@ type Keeper struct {
|
|||||||
// Track auction usage in other cosmos-sdk modules (more like a usage tracker).
|
// Track auction usage in other cosmos-sdk modules (more like a usage tracker).
|
||||||
usageKeepers []types.AuctionUsageKeeper
|
usageKeepers []types.AuctionUsageKeeper
|
||||||
|
|
||||||
storeKey sdk.StoreKey // Unexposed key to access store from sdk.Context
|
storeKey storetypes.StoreKey // Unexposed key to access store from sdk.Context
|
||||||
|
|
||||||
cdc codec.BinaryCodec // The wire codec for binary encoding/decoding.
|
cdc codec.BinaryCodec // The wire codec for binary encoding/decoding.
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ type AuctionClientKeeper interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewKeeper creates new instances of the auction Keeper
|
// NewKeeper creates new instances of the auction Keeper
|
||||||
func NewKeeper(accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper, storeKey sdk.StoreKey, cdc codec.BinaryCodec, ps params.Subspace) Keeper {
|
func NewKeeper(accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper, storeKey storetypes.StoreKey, cdc codec.BinaryCodec, ps params.Subspace) Keeper {
|
||||||
if !ps.HasKeyTable() {
|
if !ps.HasKeyTable() {
|
||||||
ps = ps.WithKeyTable(types.ParamKeyTable())
|
ps = ps.WithKeyTable(types.ParamKeyTable())
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ type KeeperTestSuite struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) SetupTest() {
|
func (suite *KeeperTestSuite) SetupTest() {
|
||||||
testApp := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
testApp := app.Setup(suite.T(), false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
||||||
return genesis
|
return genesis
|
||||||
})
|
})
|
||||||
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
|
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
|
||||||
@ -37,7 +37,7 @@ func (suite *KeeperTestSuite) SetupTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestParams(t *testing.T) {
|
func TestParams(t *testing.T) {
|
||||||
testApp := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
testApp := app.Setup(t, false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
||||||
return genesis
|
return genesis
|
||||||
})
|
})
|
||||||
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
|
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
|
||||||
|
@ -2,8 +2,9 @@ package testutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||||
"github.com/cosmos/cosmos-sdk/types/rest"
|
"github.com/cosmos/cosmos-sdk/testutil/rest"
|
||||||
tmcli "github.com/tendermint/tendermint/libs/cli"
|
tmcli "github.com/tendermint/tendermint/libs/cli"
|
||||||
"github.com/tharsis/ethermint/x/bond/client/cli"
|
"github.com/tharsis/ethermint/x/bond/client/cli"
|
||||||
bondtypes "github.com/tharsis/ethermint/x/bond/types"
|
bondtypes "github.com/tharsis/ethermint/x/bond/types"
|
||||||
|
@ -89,7 +89,7 @@ func (s *IntegrationTestSuite) createAccountWithBalance(accountName string) {
|
|||||||
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
|
||||||
sr.NoError(err)
|
sr.NoError(err)
|
||||||
|
|
||||||
newAddr := sdk.AccAddress(info.GetPubKey().Address())
|
newAddr, _ := info.GetAddress()
|
||||||
_, err = banktestutil.MsgSendExec(
|
_, err = banktestutil.MsgSendExec(
|
||||||
val.ClientCtx,
|
val.ClientCtx,
|
||||||
val.Address,
|
val.Address,
|
||||||
@ -175,7 +175,7 @@ func (s *IntegrationTestSuite) TestGetQueryBondById() {
|
|||||||
{
|
{
|
||||||
"invalid bond id",
|
"invalid bond id",
|
||||||
[]string{
|
[]string{
|
||||||
fmt.Sprint("not_found_bond_id"),
|
"not_found_bond_id",
|
||||||
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
@ -246,7 +246,7 @@ func (s *IntegrationTestSuite) TestGetQueryBondListsByOwner() {
|
|||||||
{
|
{
|
||||||
"invalid owner address",
|
"invalid owner address",
|
||||||
[]string{
|
[]string{
|
||||||
fmt.Sprint("not_found_bond_id"),
|
"not_found_bond_id",
|
||||||
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
|
@ -3,8 +3,9 @@ package keeper_test
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||||
"github.com/tharsis/ethermint/app"
|
"github.com/tharsis/ethermint/app"
|
||||||
"github.com/tharsis/ethermint/x/bond/types"
|
"github.com/tharsis/ethermint/x/bond/types"
|
||||||
)
|
)
|
||||||
@ -39,7 +40,7 @@ func (suite *KeeperTestSuite) TestGrpcQueryBondsList() {
|
|||||||
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||||
if test.createBonds {
|
if test.createBonds {
|
||||||
account := app.CreateRandomAccounts(1)[0]
|
account := app.CreateRandomAccounts(1)[0]
|
||||||
err := simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
|
err := testutil.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
|
||||||
Denom: sdk.DefaultBondDenom,
|
Denom: sdk.DefaultBondDenom,
|
||||||
Amount: sdk.NewInt(1000),
|
Amount: sdk.NewInt(1000),
|
||||||
}))
|
}))
|
||||||
@ -102,7 +103,7 @@ func (suite *KeeperTestSuite) TestGrpcQueryBondBondId() {
|
|||||||
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||||
if test.createBonds {
|
if test.createBonds {
|
||||||
account := app.CreateRandomAccounts(1)[0]
|
account := app.CreateRandomAccounts(1)[0]
|
||||||
err := simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
|
err := testutil.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
|
||||||
Denom: sdk.DefaultBondDenom,
|
Denom: sdk.DefaultBondDenom,
|
||||||
Amount: sdk.NewInt(1000),
|
Amount: sdk.NewInt(1000),
|
||||||
}))
|
}))
|
||||||
@ -156,7 +157,7 @@ func (suite *KeeperTestSuite) TestGrpcGetBondsByOwner() {
|
|||||||
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||||
if test.createBonds {
|
if test.createBonds {
|
||||||
account := app.CreateRandomAccounts(1)[0]
|
account := app.CreateRandomAccounts(1)[0]
|
||||||
_ = simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
|
_ = testutil.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
|
||||||
Denom: sdk.DefaultBondDenom,
|
Denom: sdk.DefaultBondDenom,
|
||||||
Amount: sdk.NewInt(1000),
|
Amount: sdk.NewInt(1000),
|
||||||
}))
|
}))
|
||||||
@ -200,7 +201,7 @@ func (suite *KeeperTestSuite) TestGrpcGetModuleBalance() {
|
|||||||
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
suite.Run(fmt.Sprintf("Case %s ", test.msg), func() {
|
||||||
if test.createBonds {
|
if test.createBonds {
|
||||||
account := app.CreateRandomAccounts(1)[0]
|
account := app.CreateRandomAccounts(1)[0]
|
||||||
_ = simapp.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
|
_ = testutil.FundAccount(suite.app.BankKeeper, ctx, account, sdk.NewCoins(sdk.Coin{
|
||||||
Denom: sdk.DefaultBondDenom,
|
Denom: sdk.DefaultBondDenom,
|
||||||
Amount: sdk.NewInt(1000),
|
Amount: sdk.NewInt(1000),
|
||||||
}))
|
}))
|
||||||
|
@ -4,7 +4,9 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
auth "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
auth "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||||
@ -29,7 +31,7 @@ type Keeper struct {
|
|||||||
// Track bond usage in other cosmos-sdk modules (more like a usage tracker).
|
// Track bond usage in other cosmos-sdk modules (more like a usage tracker).
|
||||||
usageKeepers []types.BondUsageKeeper
|
usageKeepers []types.BondUsageKeeper
|
||||||
|
|
||||||
storeKey sdk.StoreKey
|
storeKey storetypes.StoreKey
|
||||||
|
|
||||||
cdc codec.BinaryCodec
|
cdc codec.BinaryCodec
|
||||||
|
|
||||||
@ -37,7 +39,7 @@ type Keeper struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewKeeper creates new instances of the bond Keeper
|
// NewKeeper creates new instances of the bond Keeper
|
||||||
func NewKeeper(cdc codec.BinaryCodec, accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper, usageKeepers []types.BondUsageKeeper, storeKey sdk.StoreKey, ps paramtypes.Subspace) Keeper {
|
func NewKeeper(cdc codec.BinaryCodec, accountKeeper auth.AccountKeeper, bankKeeper bank.Keeper, usageKeepers []types.BondUsageKeeper, storeKey storetypes.StoreKey, ps paramtypes.Subspace) Keeper {
|
||||||
// set KeyTable if it has not already been set
|
// set KeyTable if it has not already been set
|
||||||
if !ps.HasKeyTable() {
|
if !ps.HasKeyTable() {
|
||||||
ps = ps.WithKeyTable(types.ParamKeyTable())
|
ps = ps.WithKeyTable(types.ParamKeyTable())
|
||||||
|
@ -22,7 +22,7 @@ type KeeperTestSuite struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) SetupTest() {
|
func (suite *KeeperTestSuite) SetupTest() {
|
||||||
testApp := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
testApp := app.Setup(suite.T(), false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
||||||
return genesis
|
return genesis
|
||||||
})
|
})
|
||||||
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
|
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
|
||||||
@ -37,7 +37,7 @@ func (suite *KeeperTestSuite) SetupTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestParams(t *testing.T) {
|
func TestParams(t *testing.T) {
|
||||||
testApp := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
testApp := app.Setup(t, false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
||||||
return genesis
|
return genesis
|
||||||
})
|
})
|
||||||
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
|
ctx := testApp.BaseApp.NewContext(false, tmproto.Header{})
|
||||||
|
@ -5,23 +5,17 @@ import (
|
|||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
abcitypes "github.com/tendermint/tendermint/abci/types"
|
|
||||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
app "github.com/tharsis/ethermint/app"
|
app "github.com/tharsis/ethermint/app"
|
||||||
bondtypes "github.com/tharsis/ethermint/x/bond/types"
|
bondtypes "github.com/tharsis/ethermint/x/bond/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestItCreatesModuleAccountOnInitBlock(t *testing.T) {
|
func TestItCreatesModuleAccountOnInitBlock(t *testing.T) {
|
||||||
app := app.Setup(false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
app := app.Setup(t, false, func(ea *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
||||||
return genesis
|
return genesis
|
||||||
})
|
})
|
||||||
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
ctx := app.BaseApp.NewContext(false, tmproto.Header{})
|
||||||
|
|
||||||
app.InitChain(abcitypes.RequestInitChain{
|
|
||||||
AppStateBytes: []byte("{}"),
|
|
||||||
ChainId: "test-chain-id",
|
|
||||||
})
|
|
||||||
|
|
||||||
acc := app.AccountKeeper.GetModuleAccount(ctx, bondtypes.ModuleName)
|
acc := app.AccountKeeper.GetModuleAccount(ctx, bondtypes.ModuleName)
|
||||||
require.NotNil(t, acc)
|
require.NotNil(t, acc)
|
||||||
}
|
}
|
||||||
|
@ -1,116 +1,98 @@
|
|||||||
package rest
|
package rest
|
||||||
|
|
||||||
import (
|
// clientrest "github.com/cosmos/cosmos-sdk/client/rest"
|
||||||
"context"
|
// "github.com/cosmos/cosmos-sdk/types/rest"
|
||||||
"encoding/hex"
|
// authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"math/big"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
// // RegisterTxRoutes - Central function to define routes that get registered by the main application
|
||||||
|
// func RegisterTxRoutes(clientCtx client.Context, rtr *mux.Router) {
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
// r := testutil.GetRequestWithHeaders(rtr)
|
||||||
clientrest "github.com/cosmos/cosmos-sdk/client/rest"
|
// r.HandleFunc("/txs/{hash}", QueryTxRequestHandlerFn(clientCtx)).Methods("GET")
|
||||||
"github.com/cosmos/cosmos-sdk/types/rest"
|
// r.HandleFunc("/txs", testutil.QueryTxsRequestHandlerFn(clientCtx)).Methods("GET")
|
||||||
authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
|
// r.HandleFunc("/txs/decode", testutil.DecodeTxRequestHandlerFn(clientCtx)).Methods("POST")
|
||||||
|
// }
|
||||||
rpctypes "github.com/tharsis/ethermint/rpc/ethereum/types"
|
|
||||||
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 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/decode", authrest.DecodeTxRequestHandlerFn(clientCtx)).Methods("POST")
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryTxRequestHandlerFn implements a REST handler that queries a transaction
|
// QueryTxRequestHandlerFn implements a REST handler that queries a transaction
|
||||||
// by hash in a committed block.
|
// by hash in a committed block.
|
||||||
func QueryTxRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
|
// func QueryTxRequestHandlerFn(clientCtx client.Context) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
// return func(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
// vars := mux.Vars(r)
|
||||||
hashHexStr := vars["hash"]
|
// hashHexStr := vars["hash"]
|
||||||
|
|
||||||
clientCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, clientCtx, r)
|
// clientCtx, ok := testutil.ParseQueryHeightOrReturnBadRequest(w, clientCtx, r)
|
||||||
if !ok {
|
// if !ok {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
ethHashPrefix := "0x"
|
// ethHashPrefix := "0x"
|
||||||
if !strings.HasPrefix(hashHexStr, ethHashPrefix) {
|
// // if !strings.HasPrefix(hashHexStr, ethHashPrefix) {
|
||||||
authrest.QueryTxRequestHandlerFn(clientCtx)
|
// // authrest.QueryTxRequestHandlerFn(clientCtx)
|
||||||
return
|
// // return
|
||||||
}
|
// // }
|
||||||
|
|
||||||
// eth Tx
|
// // eth Tx
|
||||||
ethHashPrefixLength := len(ethHashPrefix)
|
// ethHashPrefixLength := len(ethHashPrefix)
|
||||||
output, err := getEthTransactionByHash(clientCtx, hashHexStr[ethHashPrefixLength:])
|
// output, err := getEthTransactionByHash(clientCtx, hashHexStr[ethHashPrefixLength:])
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
// rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
rest.PostProcessResponseBare(w, clientCtx, output)
|
// rest.PostProcessResponseBare(w, clientCtx, output)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// GetTransactionByHash returns the transaction identified by hash.
|
// // GetTransactionByHash returns the transaction identified by hash.
|
||||||
func getEthTransactionByHash(clientCtx client.Context, hashHex string) ([]byte, error) {
|
// func getEthTransactionByHash(clientCtx client.Context, hashHex string) ([]byte, error) {
|
||||||
hash, err := hex.DecodeString(hashHex)
|
// hash, err := hex.DecodeString(hashHex)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
node, err := clientCtx.GetNode()
|
// node, err := clientCtx.GetNode()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
|
|
||||||
tx, err := node.Tx(context.Background(), hash, false)
|
// tx, err := node.Tx(context.Background(), hash, false)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Can either cache or just leave this out if not necessary
|
// // Can either cache or just leave this out if not necessary
|
||||||
block, err := node.Block(context.Background(), &tx.Height)
|
// block, err := node.Block(context.Background(), &tx.Height)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
|
|
||||||
client := feemarkettypes.NewQueryClient(clientCtx)
|
// client := feemarkettypes.NewQueryClient(clientCtx)
|
||||||
res, err := client.BaseFee(context.Background(), &feemarkettypes.QueryBaseFeeRequest{})
|
// res, err := client.BaseFee(context.Background(), &feemarkettypes.QueryBaseFeeRequest{})
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
|
|
||||||
var baseFee *big.Int
|
// var baseFee *big.Int
|
||||||
if res.BaseFee != nil {
|
// if res.BaseFee != nil {
|
||||||
baseFee = res.BaseFee.BigInt()
|
// baseFee = res.BaseFee.BigInt()
|
||||||
}
|
// }
|
||||||
|
|
||||||
blockHash := common.BytesToHash(block.Block.Header.Hash())
|
// blockHash := common.BytesToHash(block.Block.Header.Hash())
|
||||||
|
|
||||||
ethTxs, err := rpctypes.RawTxToEthTx(clientCtx, tx.Tx)
|
// ethTxs, err := rpctypes.RawTxToEthTx(clientCtx, tx.Tx)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
|
|
||||||
height := uint64(tx.Height)
|
// height := uint64(tx.Height)
|
||||||
|
|
||||||
for _, ethTx := range ethTxs {
|
// for _, ethTx := range ethTxs {
|
||||||
if common.HexToHash(ethTx.Hash) == common.BytesToHash(hash) {
|
// if common.HexToHash(ethTx.Hash) == common.BytesToHash(hash) {
|
||||||
rpcTx, err := rpctypes.NewRPCTransaction(ethTx.AsTransaction(), blockHash, height, uint64(tx.Index), baseFee)
|
// rpcTx, err := rpctypes.NewRPCTransaction(ethTx.AsTransaction(), blockHash, height, uint64(tx.Index), baseFee)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
return nil, err
|
// return nil, err
|
||||||
}
|
// }
|
||||||
return json.Marshal(rpcTx)
|
// return json.Marshal(rpcTx)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return nil, errors.New("eth tx not found")
|
// return nil, errors.New("eth tx not found")
|
||||||
}
|
// }
|
||||||
|
@ -8,12 +8,9 @@ import (
|
|||||||
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
tmjson "github.com/tendermint/tendermint/libs/json"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||||
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
||||||
|
|
||||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
@ -75,7 +72,7 @@ func (suite *EvmTestSuite) DoSetupTest(t require.TestingT) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
consAddress := sdk.ConsAddress(priv.PubKey().Address())
|
consAddress := sdk.ConsAddress(priv.PubKey().Address())
|
||||||
|
|
||||||
suite.app = app.Setup(checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
suite.app = app.Setup(suite.T(), checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
||||||
if suite.dynamicTxFee {
|
if suite.dynamicTxFee {
|
||||||
feemarketGenesis := feemarkettypes.DefaultGenesisState()
|
feemarketGenesis := feemarkettypes.DefaultGenesisState()
|
||||||
feemarketGenesis.Params.EnableHeight = 1
|
feemarketGenesis.Params.EnableHeight = 1
|
||||||
@ -85,36 +82,6 @@ func (suite *EvmTestSuite) DoSetupTest(t require.TestingT) {
|
|||||||
return genesis
|
return genesis
|
||||||
})
|
})
|
||||||
|
|
||||||
coins := sdk.NewCoins(sdk.NewCoin(types.DefaultEVMDenom, sdk.NewInt(100000000000000)))
|
|
||||||
genesisState := app.ModuleBasics.DefaultGenesis(suite.app.AppCodec())
|
|
||||||
b32address := sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), priv.PubKey().Address().Bytes())
|
|
||||||
balances := []banktypes.Balance{
|
|
||||||
{
|
|
||||||
Address: b32address,
|
|
||||||
Coins: coins,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Address: suite.app.AccountKeeper.GetModuleAddress(authtypes.FeeCollectorName).String(),
|
|
||||||
Coins: coins,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// update total supply
|
|
||||||
bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, sdk.NewCoins(sdk.NewCoin(types.DefaultEVMDenom, sdk.NewInt(200000000000000))), []banktypes.Metadata{})
|
|
||||||
genesisState[banktypes.ModuleName] = suite.app.AppCodec().MustMarshalJSON(bankGenesis)
|
|
||||||
|
|
||||||
stateBytes, err := tmjson.MarshalIndent(genesisState, "", " ")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Initialize the chain
|
|
||||||
suite.app.InitChain(
|
|
||||||
abci.RequestInitChain{
|
|
||||||
ChainId: "ethermint_9000-1",
|
|
||||||
Validators: []abci.ValidatorUpdate{},
|
|
||||||
ConsensusParams: simapp.DefaultConsensusParams,
|
|
||||||
AppStateBytes: stateBytes,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{
|
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{
|
||||||
Height: 1,
|
Height: 1,
|
||||||
ChainID: "ethermint_9000-1",
|
ChainID: "ethermint_9000-1",
|
||||||
@ -139,10 +106,25 @@ func (suite *EvmTestSuite) DoSetupTest(t require.TestingT) {
|
|||||||
LastResultsHash: tmhash.Sum([]byte("last_result")),
|
LastResultsHash: tmhash.Sum([]byte("last_result")),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
coins := sdk.NewCoins(sdk.NewCoin(types.DefaultEVMDenom, sdk.NewInt(100000000000000)))
|
||||||
|
b32address := sdk.MustBech32ifyAddressBytes(sdk.GetConfig().GetBech32AccountAddrPrefix(), priv.PubKey().Address().Bytes())
|
||||||
|
accAddr, err := sdk.AccAddressFromBech32(b32address)
|
||||||
|
require.NoError(t, err)
|
||||||
|
acc := ðermint.EthAccount{
|
||||||
|
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(accAddr.Bytes()), nil, 0, 0),
|
||||||
|
CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = testutil.FundAccount(suite.app.BankKeeper, suite.ctx, accAddr, coins)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = testutil.FundModuleAccount(suite.app.BankKeeper, suite.ctx, authtypes.FeeCollectorName, coins)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
|
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
|
||||||
types.RegisterQueryServer(queryHelper, suite.app.EvmKeeper)
|
types.RegisterQueryServer(queryHelper, suite.app.EvmKeeper)
|
||||||
|
|
||||||
acc := ðermint.EthAccount{
|
acc = ðermint.EthAccount{
|
||||||
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(address.Bytes()), nil, 0, 0),
|
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(address.Bytes()), nil, 0, 0),
|
||||||
CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(),
|
CodeHash: common.BytesToHash(crypto.Keccak256(nil)).String(),
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
||||||
|
authmiddleware "github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
ethermint "github.com/tharsis/ethermint/types"
|
ethermint "github.com/tharsis/ethermint/types"
|
||||||
"github.com/tharsis/ethermint/x/evm/types"
|
"github.com/tharsis/ethermint/x/evm/types"
|
||||||
@ -67,7 +67,7 @@ func DoBenchmark(b *testing.B, txBuilder TxBuilder) {
|
|||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
||||||
fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdk.NewIntFromBigInt(txData.Fee()))}
|
fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdk.NewIntFromBigInt(txData.Fee()))}
|
||||||
err = authante.DeductFees(suite.app.BankKeeper, suite.ctx, suite.app.AccountKeeper.GetAccount(ctx, msg.GetFrom()), fees)
|
err = authmiddleware.DeductFees(suite.app.BankKeeper, suite.ctx, suite.app.AccountKeeper.GetAccount(ctx, msg.GetFrom()), fees)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
||||||
rsp, err := suite.app.EvmKeeper.EthereumTx(sdk.WrapSDKContext(ctx), msg)
|
rsp, err := suite.app.EvmKeeper.EthereumTx(sdk.WrapSDKContext(ctx), msg)
|
||||||
@ -134,7 +134,7 @@ func BenchmarkMessageCall(b *testing.B) {
|
|||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
||||||
fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdk.NewIntFromBigInt(txData.Fee()))}
|
fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdk.NewIntFromBigInt(txData.Fee()))}
|
||||||
err = authante.DeductFees(suite.app.BankKeeper, suite.ctx, suite.app.AccountKeeper.GetAccount(ctx, msg.GetFrom()), fees)
|
err = authmiddleware.DeductFees(suite.app.BankKeeper, suite.ctx, suite.app.AccountKeeper.GetAccount(ctx, msg.GetFrom()), fees)
|
||||||
require.NoError(b, err)
|
require.NoError(b, err)
|
||||||
|
|
||||||
rsp, err := suite.app.EvmKeeper.EthereumTx(sdk.WrapSDKContext(ctx), msg)
|
rsp, err := suite.app.EvmKeeper.EthereumTx(sdk.WrapSDKContext(ctx), msg)
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||||
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||||
@ -29,10 +30,10 @@ type Keeper struct {
|
|||||||
// - storing account's Code
|
// - storing account's Code
|
||||||
// - storing transaction Logs
|
// - storing transaction Logs
|
||||||
// - storing Bloom filters by block height. Needed for the Web3 API.
|
// - storing Bloom filters by block height. Needed for the Web3 API.
|
||||||
storeKey sdk.StoreKey
|
storeKey storetypes.StoreKey
|
||||||
|
|
||||||
// key to access the transient store, which is reset on every block during Commit
|
// key to access the transient store, which is reset on every block during Commit
|
||||||
transientKey sdk.StoreKey
|
transientKey storetypes.StoreKey
|
||||||
|
|
||||||
// module specific parameter space that can be configured through governance
|
// module specific parameter space that can be configured through governance
|
||||||
paramSpace paramtypes.Subspace
|
paramSpace paramtypes.Subspace
|
||||||
@ -58,7 +59,7 @@ type Keeper struct {
|
|||||||
// NewKeeper generates new evm module keeper
|
// NewKeeper generates new evm module keeper
|
||||||
func NewKeeper(
|
func NewKeeper(
|
||||||
cdc codec.BinaryCodec,
|
cdc codec.BinaryCodec,
|
||||||
storeKey, transientKey sdk.StoreKey, paramSpace paramtypes.Subspace,
|
storeKey, transientKey storetypes.StoreKey, paramSpace paramtypes.Subspace,
|
||||||
ak types.AccountKeeper, bankKeeper types.BankKeeper, sk types.StakingKeeper,
|
ak types.AccountKeeper, bankKeeper types.BankKeeper, sk types.StakingKeeper,
|
||||||
fmk types.FeeMarketKeeper,
|
fmk types.FeeMarketKeeper,
|
||||||
tracer string,
|
tracer string,
|
||||||
|
@ -18,9 +18,8 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/simapp"
|
"github.com/cosmos/cosmos-sdk/simapp"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
"github.com/cosmos/cosmos-sdk/x/bank/testutil"
|
||||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
tmjson "github.com/tendermint/tendermint/libs/json"
|
|
||||||
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/app"
|
"github.com/tharsis/ethermint/app"
|
||||||
@ -86,7 +85,7 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
suite.consAddress = sdk.ConsAddress(priv.PubKey().Address())
|
suite.consAddress = sdk.ConsAddress(priv.PubKey().Address())
|
||||||
|
|
||||||
suite.app = app.Setup(checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
suite.app = app.Setup(suite.T(), checkTx, func(app *app.EthermintApp, genesis simapp.GenesisState) simapp.GenesisState {
|
||||||
feemarketGenesis := feemarkettypes.DefaultGenesisState()
|
feemarketGenesis := feemarkettypes.DefaultGenesisState()
|
||||||
if suite.enableFeemarket {
|
if suite.enableFeemarket {
|
||||||
feemarketGenesis.Params.EnableHeight = 1
|
feemarketGenesis.Params.EnableHeight = 1
|
||||||
@ -106,37 +105,6 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
|
|||||||
return genesis
|
return genesis
|
||||||
})
|
})
|
||||||
|
|
||||||
if suite.mintFeeCollector {
|
|
||||||
// mint some coin to fee collector
|
|
||||||
coins := sdk.NewCoins(sdk.NewCoin(types.DefaultEVMDenom, sdk.NewInt(int64(params.TxGas)-1)))
|
|
||||||
genesisState := app.ModuleBasics.DefaultGenesis(suite.app.AppCodec())
|
|
||||||
balances := []banktypes.Balance{
|
|
||||||
{
|
|
||||||
Address: suite.app.AccountKeeper.GetModuleAddress(authtypes.FeeCollectorName).String(),
|
|
||||||
Coins: coins,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// update total supply
|
|
||||||
bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, sdk.NewCoins(sdk.NewCoin(types.DefaultEVMDenom, sdk.NewInt((int64(params.TxGas)-1)))), []banktypes.Metadata{})
|
|
||||||
bz := suite.app.AppCodec().MustMarshalJSON(bankGenesis)
|
|
||||||
require.NotNil(t, bz)
|
|
||||||
genesisState[banktypes.ModuleName] = suite.app.AppCodec().MustMarshalJSON(bankGenesis)
|
|
||||||
|
|
||||||
// we marshal the genesisState of all module to a byte array
|
|
||||||
stateBytes, err := tmjson.MarshalIndent(genesisState, "", " ")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// Initialize the chain
|
|
||||||
suite.app.InitChain(
|
|
||||||
abci.RequestInitChain{
|
|
||||||
ChainId: "ethermint_9000-1",
|
|
||||||
Validators: []abci.ValidatorUpdate{},
|
|
||||||
ConsensusParams: simapp.DefaultConsensusParams,
|
|
||||||
AppStateBytes: stateBytes,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{
|
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{
|
||||||
Height: 1,
|
Height: 1,
|
||||||
ChainID: "ethermint_9000-1",
|
ChainID: "ethermint_9000-1",
|
||||||
@ -161,6 +129,12 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
|
|||||||
LastResultsHash: tmhash.Sum([]byte("last_result")),
|
LastResultsHash: tmhash.Sum([]byte("last_result")),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if suite.mintFeeCollector {
|
||||||
|
// mint some coin to fee collector
|
||||||
|
coins := sdk.NewCoins(sdk.NewCoin(types.DefaultEVMDenom, sdk.NewInt(int64(params.TxGas)-1)))
|
||||||
|
testutil.FundModuleAccount(suite.app.BankKeeper, suite.ctx, authtypes.FeeCollectorName, coins)
|
||||||
|
}
|
||||||
|
|
||||||
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
|
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
|
||||||
types.RegisterQueryServer(queryHelper, suite.app.EvmKeeper)
|
types.RegisterQueryServer(queryHelper, suite.app.EvmKeeper)
|
||||||
suite.queryClient = types.NewQueryClient(queryHelper)
|
suite.queryClient = types.NewQueryClient(queryHelper)
|
||||||
@ -183,7 +157,7 @@ func (suite *KeeperTestSuite) DoSetupTest(t require.TestingT) {
|
|||||||
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
||||||
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
|
suite.clientCtx = client.Context{}.WithTxConfig(encodingConfig.TxConfig)
|
||||||
suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
|
suite.ethSigner = ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())
|
||||||
suite.appCodec = encodingConfig.Marshaler
|
suite.appCodec = encodingConfig.Codec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) SetupTest() {
|
func (suite *KeeperTestSuite) SetupTest() {
|
||||||
|
@ -19,8 +19,7 @@ var _ types.MsgServer = &Keeper{}
|
|||||||
|
|
||||||
// EthereumTx implements the gRPC MsgServer interface. It receives a transaction which is then
|
// EthereumTx implements the gRPC MsgServer interface. It receives a transaction which is then
|
||||||
// executed (i.e applied) against the go-ethereum EVM. The provided SDK Context is set to the Keeper
|
// executed (i.e applied) against the go-ethereum EVM. The provided SDK Context is set to the Keeper
|
||||||
// so that it can implements and call the StateDB methods without receiving it as a function
|
// so that it can call the StateDB methods without receiving it as a function parameter.
|
||||||
// parameter.
|
|
||||||
func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*types.MsgEthereumTxResponse, error) {
|
func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*types.MsgEthereumTxResponse, error) {
|
||||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ import (
|
|||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
|
|
||||||
|
authmiddleware "github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
||||||
|
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ func (k Keeper) DeductTxCostsFromUserBalance(
|
|||||||
isContractCreation := txData.GetTo() == nil
|
isContractCreation := txData.GetTo() == nil
|
||||||
|
|
||||||
// fetch sender account from signature
|
// fetch sender account from signature
|
||||||
signerAcc, err := authante.GetSignerAcc(ctx, k.accountKeeper, msgEthTx.GetFrom())
|
signerAcc, err := authmiddleware.GetSignerAcc(ctx, k.accountKeeper, msgEthTx.GetFrom())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdkerrors.Wrapf(err, "account not found for sender %s", msgEthTx.From)
|
return nil, sdkerrors.Wrapf(err, "account not found for sender %s", msgEthTx.From)
|
||||||
}
|
}
|
||||||
@ -74,7 +75,7 @@ func (k Keeper) DeductTxCostsFromUserBalance(
|
|||||||
fees := sdk.Coins{sdk.NewCoin(denom, sdk.NewIntFromBigInt(feeAmt))}
|
fees := sdk.Coins{sdk.NewCoin(denom, sdk.NewIntFromBigInt(feeAmt))}
|
||||||
|
|
||||||
// deduct the full gas cost from the user balance
|
// deduct the full gas cost from the user balance
|
||||||
if err := authante.DeductFees(k.bankKeeper, ctx, signerAcc, fees); err != nil {
|
if err := authmiddleware.DeductFees(k.bankKeeper, ctx, signerAcc, fees); err != nil {
|
||||||
return nil, sdkerrors.Wrapf(
|
return nil, sdkerrors.Wrapf(
|
||||||
err,
|
err,
|
||||||
"failed to deduct full gas cost %s from the user %s balance",
|
"failed to deduct full gas cost %s from the user %s balance",
|
||||||
|
@ -170,11 +170,13 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw
|
|||||||
|
|
||||||
// RandomizedParams creates randomized evm param changes for the simulator.
|
// RandomizedParams creates randomized evm param changes for the simulator.
|
||||||
func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange {
|
func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange {
|
||||||
return nil
|
return simulation.ParamChanges(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterStoreDecoder registers a decoder for evm module's types
|
// RegisterStoreDecoder registers a decoder for evm module's types
|
||||||
func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {}
|
func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) {
|
||||||
|
sdr[types.StoreKey] = simulation.NewDecodeStore()
|
||||||
|
}
|
||||||
|
|
||||||
// ProposalContents doesn't return any content functions for governance proposals.
|
// ProposalContents doesn't return any content functions for governance proposals.
|
||||||
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
|
func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent {
|
||||||
@ -188,5 +190,7 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) {
|
|||||||
|
|
||||||
// WeightedOperations returns the all the evm module operations with their respective weights.
|
// WeightedOperations returns the all the evm module operations with their respective weights.
|
||||||
func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
|
func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation {
|
||||||
return nil
|
return simulation.WeightedOperations(
|
||||||
|
simState.AppParams, simState.Cdc, am.ak, am.keeper,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
31
x/evm/simulation/decoder.go
Normal file
31
x/evm/simulation/decoder.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package simulation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/kv"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/tharsis/ethermint/x/evm/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's
|
||||||
|
// Value to the corresponding evm type.
|
||||||
|
func NewDecodeStore() func(kvA, kvB kv.Pair) string {
|
||||||
|
return func(kvA, kvB kv.Pair) string {
|
||||||
|
switch {
|
||||||
|
case bytes.Equal(kvA.Key[:1], types.KeyPrefixStorage):
|
||||||
|
storageHashA := common.BytesToHash(kvA.Value).Hex()
|
||||||
|
storageHashB := common.BytesToHash(kvB.Value).Hex()
|
||||||
|
|
||||||
|
return fmt.Sprintf("%v\n%v", storageHashA, storageHashB)
|
||||||
|
case bytes.Equal(kvA.Key[:1], types.KeyPrefixCode):
|
||||||
|
codeHashA := common.BytesToHash(kvA.Value).Hex()
|
||||||
|
codeHashB := common.BytesToHash(kvB.Value).Hex()
|
||||||
|
|
||||||
|
return fmt.Sprintf("%v\n%v", codeHashA, codeHashB)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("invalid evm key prefix %X", kvA.Key[:1]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,12 +3,22 @@ package simulation
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/types/module"
|
"github.com/cosmos/cosmos-sdk/types/module"
|
||||||
|
|
||||||
"github.com/tharsis/ethermint/x/evm/types"
|
"github.com/tharsis/ethermint/x/evm/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GenExtraEIPs randomly generates specific extra eips or not.
|
||||||
|
func genExtraEIPs(r *rand.Rand) []int64 {
|
||||||
|
var extraEIPs []int64
|
||||||
|
if r.Uint32()%2 == 0 {
|
||||||
|
extraEIPs = []int64{1344, 1884, 2200, 2929, 3198, 3529}
|
||||||
|
}
|
||||||
|
return extraEIPs
|
||||||
|
}
|
||||||
|
|
||||||
// RandomizedGenState generates a random GenesisState for nft
|
// RandomizedGenState generates a random GenesisState for nft
|
||||||
func RandomizedGenState(simState *module.SimulationState) {
|
func RandomizedGenState(simState *module.SimulationState) {
|
||||||
params := types.NewParams(types.DefaultEVMDenom, true, true, types.DefaultChainConfig())
|
params := types.NewParams(types.DefaultEVMDenom, true, true, types.DefaultChainConfig())
|
||||||
|
302
x/evm/simulation/operations.go
Normal file
302
x/evm/simulation/operations.go
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
package simulation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||||
|
"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"
|
||||||
|
sdktx "github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/module"
|
||||||
|
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/simulation"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
||||||
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
|
|
||||||
|
"github.com/tharsis/ethermint/encoding"
|
||||||
|
"github.com/tharsis/ethermint/server/config"
|
||||||
|
"github.com/tharsis/ethermint/tests"
|
||||||
|
"github.com/tharsis/ethermint/x/evm/keeper"
|
||||||
|
"github.com/tharsis/ethermint/x/evm/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
/* #nosec */
|
||||||
|
OpWeightMsgEthSimpleTransfer = "op_weight_msg_eth_simple_transfer"
|
||||||
|
/* #nosec */
|
||||||
|
OpWeightMsgEthCreateContract = "op_weight_msg_eth_create_contract"
|
||||||
|
/* #nosec */
|
||||||
|
OpWeightMsgEthCallContract = "op_weight_msg_eth_call_contract"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
WeightMsgEthSimpleTransfer = 50
|
||||||
|
WeightMsgEthCreateContract = 50
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrNoEnoughBalance = fmt.Errorf("no enough balance")
|
||||||
|
|
||||||
|
var maxWaitSeconds = 10
|
||||||
|
|
||||||
|
type simulateContext struct {
|
||||||
|
context sdk.Context
|
||||||
|
bapp *baseapp.BaseApp
|
||||||
|
rand *rand.Rand
|
||||||
|
keeper *keeper.Keeper
|
||||||
|
}
|
||||||
|
|
||||||
|
// WeightedOperations generate Two kinds of operations: SimulateEthSimpleTransfer, SimulateEthCreateContract.
|
||||||
|
// Contract call operations work as the future operations of SimulateEthCreateContract.
|
||||||
|
func WeightedOperations(
|
||||||
|
appParams simtypes.AppParams, cdc codec.JSONCodec, ak types.AccountKeeper, k *keeper.Keeper,
|
||||||
|
) simulation.WeightedOperations {
|
||||||
|
var (
|
||||||
|
weightMsgEthSimpleTransfer int
|
||||||
|
weightMsgEthCreateContract int
|
||||||
|
)
|
||||||
|
|
||||||
|
appParams.GetOrGenerate(cdc, OpWeightMsgEthSimpleTransfer, &weightMsgEthSimpleTransfer, nil,
|
||||||
|
func(_ *rand.Rand) {
|
||||||
|
weightMsgEthSimpleTransfer = WeightMsgEthSimpleTransfer
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
appParams.GetOrGenerate(cdc, OpWeightMsgEthCreateContract, &weightMsgEthCreateContract, nil,
|
||||||
|
func(_ *rand.Rand) {
|
||||||
|
weightMsgEthCreateContract = WeightMsgEthCreateContract
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return simulation.WeightedOperations{
|
||||||
|
simulation.NewWeightedOperation(
|
||||||
|
weightMsgEthSimpleTransfer,
|
||||||
|
SimulateEthSimpleTransfer(ak, k),
|
||||||
|
),
|
||||||
|
simulation.NewWeightedOperation(
|
||||||
|
weightMsgEthCreateContract,
|
||||||
|
SimulateEthCreateContract(ak, k),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateEthSimpleTransfer simulate simple eth account transferring gas token.
|
||||||
|
// It randomly choose sender, recipient and transferable amount.
|
||||||
|
// Other tx details like nonce, gasprice, gaslimit are calculated to get valid value.
|
||||||
|
func SimulateEthSimpleTransfer(ak types.AccountKeeper, k *keeper.Keeper) simtypes.Operation {
|
||||||
|
return func(
|
||||||
|
r *rand.Rand, bapp *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
|
||||||
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
||||||
|
simAccount, _ := simtypes.RandomAcc(r, accs)
|
||||||
|
var recipient simtypes.Account
|
||||||
|
if r.Intn(2) == 1 {
|
||||||
|
recipient, _ = simtypes.RandomAcc(r, accs)
|
||||||
|
} else {
|
||||||
|
recipient = simtypes.RandomAccounts(r, 1)[0]
|
||||||
|
}
|
||||||
|
from := common.BytesToAddress(simAccount.Address)
|
||||||
|
to := common.BytesToAddress(recipient.Address)
|
||||||
|
|
||||||
|
simulateContext := &simulateContext{ctx, bapp, r, k}
|
||||||
|
|
||||||
|
return SimulateEthTx(simulateContext, &from, &to, nil, (*hexutil.Bytes)(&[]byte{}), simAccount.PrivKey, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateEthCreateContract simulate create an ERC20 contract.
|
||||||
|
// It makes operationSimulateEthCallContract the future operations of SimulateEthCreateContract to ensure valid contract call.
|
||||||
|
func SimulateEthCreateContract(ak types.AccountKeeper, k *keeper.Keeper) simtypes.Operation {
|
||||||
|
return func(
|
||||||
|
r *rand.Rand, bapp *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
|
||||||
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
||||||
|
simAccount, _ := simtypes.RandomAcc(r, accs)
|
||||||
|
|
||||||
|
from := common.BytesToAddress(simAccount.Address)
|
||||||
|
nonce := k.GetNonce(ctx, from)
|
||||||
|
|
||||||
|
ctorArgs, err := types.ERC20Contract.ABI.Pack("", from, sdk.NewIntWithDecimal(1000, 18).BigInt())
|
||||||
|
if err != nil {
|
||||||
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "can not pack owner and supply"), nil, err
|
||||||
|
}
|
||||||
|
data := types.ERC20Contract.Bin
|
||||||
|
data = append(data, ctorArgs...)
|
||||||
|
|
||||||
|
simulateContext := &simulateContext{ctx, bapp, r, k}
|
||||||
|
|
||||||
|
fops := make([]simtypes.FutureOperation, 1)
|
||||||
|
whenCall := ctx.BlockHeader().Time.Add(time.Duration(r.Intn(maxWaitSeconds)+1) * time.Second)
|
||||||
|
contractAddr := crypto.CreateAddress(from, nonce)
|
||||||
|
var tokenReceipient simtypes.Account
|
||||||
|
if r.Intn(2) == 1 {
|
||||||
|
tokenReceipient, _ = simtypes.RandomAcc(r, accs)
|
||||||
|
} else {
|
||||||
|
tokenReceipient = simtypes.RandomAccounts(r, 1)[0]
|
||||||
|
}
|
||||||
|
receipientAddr := common.BytesToAddress(tokenReceipient.Address)
|
||||||
|
fops[0] = simtypes.FutureOperation{
|
||||||
|
BlockTime: whenCall,
|
||||||
|
Op: operationSimulateEthCallContract(k, &contractAddr, &receipientAddr, nil),
|
||||||
|
}
|
||||||
|
return SimulateEthTx(simulateContext, &from, nil, nil, (*hexutil.Bytes)(&data), simAccount.PrivKey, fops)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// operationSimulateEthCallContract simulate calling an contract.
|
||||||
|
// It is always calling an ERC20 contract.
|
||||||
|
func operationSimulateEthCallContract(k *keeper.Keeper, contractAddr, to *common.Address, amount *big.Int) simtypes.Operation {
|
||||||
|
return func(
|
||||||
|
r *rand.Rand, bapp *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string,
|
||||||
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
||||||
|
simAccount, _ := simtypes.RandomAcc(r, accs)
|
||||||
|
|
||||||
|
from := common.BytesToAddress(simAccount.Address)
|
||||||
|
|
||||||
|
ctorArgs, err := types.ERC20Contract.ABI.Pack("transfer", to, amount)
|
||||||
|
if err != nil {
|
||||||
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "can not pack method and args"), nil, err
|
||||||
|
}
|
||||||
|
data := types.ERC20Contract.Bin
|
||||||
|
data = append(data, ctorArgs...)
|
||||||
|
|
||||||
|
simulateContext := &simulateContext{ctx, bapp, r, k}
|
||||||
|
|
||||||
|
return SimulateEthTx(simulateContext, &from, contractAddr, nil, (*hexutil.Bytes)(&data), simAccount.PrivKey, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SimulateEthTx creates valid ethereum tx and pack it as cosmos tx, and deliver it.
|
||||||
|
func SimulateEthTx(
|
||||||
|
ctx *simulateContext, from, to *common.Address, amount *big.Int, data *hexutil.Bytes, prv cryptotypes.PrivKey, fops []simtypes.FutureOperation,
|
||||||
|
) (simtypes.OperationMsg, []simtypes.FutureOperation, error) {
|
||||||
|
ethTx, err := CreateRandomValidEthTx(ctx, from, nil, nil, data)
|
||||||
|
if err == ErrNoEnoughBalance {
|
||||||
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "no enough balance"), nil, nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "can not create valid eth tx"), nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
txConfig := encoding.MakeConfig(module.NewBasicManager()).TxConfig
|
||||||
|
txBuilder := txConfig.NewTxBuilder()
|
||||||
|
signedTx, err := GetSignedTx(ctx, txBuilder, ethTx, prv)
|
||||||
|
if err != nil {
|
||||||
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "can not sign ethereum tx"), nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = ctx.bapp.SimDeliver(txConfig.TxEncoder(), signedTx)
|
||||||
|
if err != nil {
|
||||||
|
return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgEthereumTx, "failed to deliver tx"), nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return simtypes.OperationMsg{}, fops, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRandomValidEthTx create the ethereum tx with valid random values
|
||||||
|
func CreateRandomValidEthTx(ctx *simulateContext, from, to *common.Address, amount *big.Int, data *hexutil.Bytes) (ethTx *types.MsgEthereumTx, err error) {
|
||||||
|
estimateGas, err := EstimateGas(ctx, from, to, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
gasLimit := estimateGas + uint64(ctx.rand.Intn(int(sdktx.MaxGasWanted-estimateGas)))
|
||||||
|
ethChainID := ctx.keeper.ChainID()
|
||||||
|
chainConfig := ctx.keeper.GetParams(ctx.context).ChainConfig.EthereumConfig(ethChainID)
|
||||||
|
gasPrice := ctx.keeper.BaseFee(ctx.context, chainConfig)
|
||||||
|
gasFeeCap := new(big.Int).Add(gasPrice, big.NewInt(int64(ctx.rand.Int())))
|
||||||
|
gasTipCap := big.NewInt(int64(ctx.rand.Int()))
|
||||||
|
nonce := ctx.keeper.GetNonce(ctx.context, *from)
|
||||||
|
|
||||||
|
if amount == nil {
|
||||||
|
amount, err = RandomTransferableAmount(ctx, *from, gasLimit, gasFeeCap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ethTx = types.NewTx(ethChainID, nonce, to, amount, gasLimit, gasPrice, gasFeeCap, gasTipCap, *data, nil)
|
||||||
|
ethTx.From = from.String()
|
||||||
|
return ethTx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSignedTx sign the ethereum tx and packs it as a signing.Tx .
|
||||||
|
func GetSignedTx(ctx *simulateContext, txBuilder client.TxBuilder, msg *types.MsgEthereumTx, prv cryptotypes.PrivKey) (signedTx signing.Tx, err error) {
|
||||||
|
builder, ok := txBuilder.(tx.ExtensionOptionsTxBuilder)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("can not initiate ExtensionOptionsTxBuilder")
|
||||||
|
}
|
||||||
|
option, err := codectypes.NewAnyWithValue(&types.ExtensionOptionsEthereumTx{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
builder.SetExtensionOptions(option)
|
||||||
|
|
||||||
|
if err := msg.Sign(ethtypes.LatestSignerForChainID(ctx.keeper.ChainID()), tests.NewSigner(prv)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = builder.SetMsgs(msg); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
txData, err := types.UnpackTxData(msg.Data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fees := sdk.NewCoins(sdk.NewCoin(ctx.keeper.GetParams(ctx.context).EvmDenom, sdk.NewIntFromBigInt(txData.Fee())))
|
||||||
|
builder.SetFeeAmount(fees)
|
||||||
|
builder.SetGasLimit(msg.GetGas())
|
||||||
|
|
||||||
|
signedTx = builder.GetTx()
|
||||||
|
return signedTx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomTransferableAmount generates a random valid transferable amount.
|
||||||
|
// Transferable amount is between the range [0, spendable), spendable = balance - gasFeeCap * GasLimit.
|
||||||
|
func RandomTransferableAmount(ctx *simulateContext, address common.Address, gasLimit uint64, gasFeeCap *big.Int) (amount *big.Int, err error) {
|
||||||
|
balance := ctx.keeper.GetBalance(ctx.context, address)
|
||||||
|
feeLimit := new(big.Int).Mul(gasFeeCap, big.NewInt(int64(gasLimit)))
|
||||||
|
if (feeLimit.Cmp(balance)) > 0 {
|
||||||
|
return nil, ErrNoEnoughBalance
|
||||||
|
}
|
||||||
|
spendable := new(big.Int).Sub(balance, feeLimit)
|
||||||
|
if spendable.Cmp(big.NewInt(0)) == 0 {
|
||||||
|
amount = new(big.Int).Set(spendable)
|
||||||
|
return amount, nil
|
||||||
|
}
|
||||||
|
simAmount, err := simtypes.RandPositiveInt(ctx.rand, sdk.NewIntFromBigInt(spendable))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
amount = simAmount.BigInt()
|
||||||
|
return amount, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EstimateGas estimates the gas used by quering the keeper.
|
||||||
|
func EstimateGas(ctx *simulateContext, from, to *common.Address, data *hexutil.Bytes) (gas uint64, err error) {
|
||||||
|
args, err := json.Marshal(&types.TransactionArgs{To: to, From: from, Data: data})
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := ctx.keeper.EstimateGas(sdk.WrapSDKContext(ctx.context), &types.EthCallRequest{
|
||||||
|
Args: args,
|
||||||
|
GasCap: config.DefaultGasCap,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return res.Gas, nil
|
||||||
|
}
|
28
x/evm/simulation/params.go
Normal file
28
x/evm/simulation/params.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package simulation
|
||||||
|
|
||||||
|
// DONTCOVER
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/simulation"
|
||||||
|
"github.com/tharsis/ethermint/x/evm/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
keyExtraEIPs = "ExtraEIPs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParamChanges defines the parameters that can be modified by param change proposals
|
||||||
|
// on the simulation.
|
||||||
|
func ParamChanges(r *rand.Rand) []simtypes.ParamChange {
|
||||||
|
return []simtypes.ParamChange{
|
||||||
|
simulation.NewSimParamChange(types.ModuleName, keyExtraEIPs,
|
||||||
|
func(r *rand.Rand) string {
|
||||||
|
return fmt.Sprintf("\"%d\"", genExtraEIPs(r))
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,16 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
|
||||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
proto "github.com/gogo/protobuf/proto"
|
proto "github.com/gogo/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
|
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
TxResponse interface{}
|
||||||
ExtensionOptionsEthereumTxI interface{}
|
ExtensionOptionsEthereumTxI interface{}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,9 +20,8 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
|||||||
(*sdk.Msg)(nil),
|
(*sdk.Msg)(nil),
|
||||||
&MsgEthereumTx{},
|
&MsgEthereumTx{},
|
||||||
)
|
)
|
||||||
registry.RegisterInterface(
|
registry.RegisterImplementations(
|
||||||
"ethermint.evm.v1.ExtensionOptionsEthereumTx",
|
(*tx.TxExtensionOptionI)(nil),
|
||||||
(*ExtensionOptionsEthereumTxI)(nil),
|
|
||||||
&ExtensionOptionsEthereumTx{},
|
&ExtensionOptionsEthereumTx{},
|
||||||
)
|
)
|
||||||
registry.RegisterInterface(
|
registry.RegisterInterface(
|
||||||
@ -33,6 +31,16 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
|||||||
&AccessListTx{},
|
&AccessListTx{},
|
||||||
&LegacyTx{},
|
&LegacyTx{},
|
||||||
)
|
)
|
||||||
|
registry.RegisterInterface(
|
||||||
|
"ethermint.evm.v1.MsgEthereumTxResponse",
|
||||||
|
(*TxResponse)(nil),
|
||||||
|
&MsgEthereumTxResponse{},
|
||||||
|
)
|
||||||
|
registry.RegisterInterface(
|
||||||
|
"ethermint.evm.v1.ExtensionOptionsEthereumTx",
|
||||||
|
(*ExtensionOptionsEthereumTxI)(nil),
|
||||||
|
&ExtensionOptionsEthereumTx{},
|
||||||
|
)
|
||||||
|
|
||||||
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
|
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ type BankKeeper interface {
|
|||||||
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
|
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
|
||||||
MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
|
MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
|
||||||
BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
|
BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
|
||||||
|
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amount sdk.Coins) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// StakingKeeper returns the historical headers kept in store.
|
// StakingKeeper returns the historical headers kept in store.
|
||||||
|
@ -10,7 +10,8 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/ante"
|
|
||||||
|
authmiddleware "github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
|
|
||||||
@ -22,9 +23,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ sdk.Msg = &MsgEthereumTx{}
|
_ sdk.Msg = &MsgEthereumTx{}
|
||||||
_ sdk.Tx = &MsgEthereumTx{}
|
_ sdk.Tx = &MsgEthereumTx{}
|
||||||
_ ante.GasTx = &MsgEthereumTx{}
|
_ authmiddleware.GasTx = &MsgEthereumTx{}
|
||||||
|
|
||||||
_ codectypes.UnpackInterfacesMessage = MsgEthereumTx{}
|
_ codectypes.UnpackInterfacesMessage = MsgEthereumTx{}
|
||||||
)
|
)
|
||||||
|
@ -6,8 +6,8 @@ import (
|
|||||||
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
@ -18,25 +18,27 @@ const maxBitLen = 256
|
|||||||
var EmptyCodeHash = crypto.Keccak256(nil)
|
var EmptyCodeHash = crypto.Keccak256(nil)
|
||||||
|
|
||||||
// DecodeTxResponse decodes an protobuf-encoded byte slice into TxResponse
|
// DecodeTxResponse decodes an protobuf-encoded byte slice into TxResponse
|
||||||
func DecodeTxResponse(in []byte) (*MsgEthereumTxResponse, error) {
|
func DecodeTxResponse(in []byte, cdc codec.Codec) (*MsgEthereumTxResponse, error) {
|
||||||
var txMsgData sdk.TxMsgData
|
var txMsgData sdk.TxMsgData
|
||||||
if err := proto.Unmarshal(in, &txMsgData); err != nil {
|
if err := txMsgData.Unmarshal(in); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := txMsgData.GetData()
|
responses := txMsgData.GetMsgResponses()
|
||||||
if len(data) == 0 {
|
if len(responses) == 0 {
|
||||||
return &MsgEthereumTxResponse{}, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var res MsgEthereumTxResponse
|
if err := cdc.UnpackAny(responses[0], new(TxResponse)); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal tx response message: %w", err)
|
||||||
err := proto.Unmarshal(data[0].GetData(), &res)
|
|
||||||
if err != nil {
|
|
||||||
return nil, sdkerrors.Wrap(err, "failed to unmarshal tx response message data")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &res, nil
|
msgval := responses[0].GetCachedValue()
|
||||||
|
res, ok := msgval.(*MsgEthereumTxResponse)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("tx response message has invalid type: %T", msgval)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeTransactionLogs encodes TransactionLogs slice into a protobuf-encoded byte slice.
|
// EncodeTransactionLogs encodes TransactionLogs slice into a protobuf-encoded byte slice.
|
||||||
@ -44,16 +46,6 @@ func EncodeTransactionLogs(res *TransactionLogs) ([]byte, error) {
|
|||||||
return proto.Marshal(res)
|
return proto.Marshal(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeTxResponse decodes an protobuf-encoded byte slice into TransactionLogs
|
|
||||||
func DecodeTransactionLogs(data []byte) (TransactionLogs, error) {
|
|
||||||
var logs TransactionLogs
|
|
||||||
err := proto.Unmarshal(data, &logs)
|
|
||||||
if err != nil {
|
|
||||||
return TransactionLogs{}, err
|
|
||||||
}
|
|
||||||
return logs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnwrapEthereumMsg extract MsgEthereumTx from wrapping sdk.Tx
|
// UnwrapEthereumMsg extract MsgEthereumTx from wrapping sdk.Tx
|
||||||
func UnwrapEthereumMsg(tx *sdk.Tx, ethHash common.Hash) (*MsgEthereumTx, error) {
|
func UnwrapEthereumMsg(tx *sdk.Tx, ethHash common.Hash) (*MsgEthereumTx, error) {
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
|
@ -5,23 +5,33 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"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"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
proto "github.com/gogo/protobuf/proto"
|
|
||||||
"github.com/tharsis/ethermint/app"
|
"github.com/tharsis/ethermint/app"
|
||||||
"github.com/tharsis/ethermint/encoding"
|
"github.com/tharsis/ethermint/encoding"
|
||||||
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
evmtypes "github.com/tharsis/ethermint/x/evm/types"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var testCodec codec.Codec
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registry := codectypes.NewInterfaceRegistry()
|
||||||
|
evmtypes.RegisterInterfaces(registry)
|
||||||
|
testCodec = codec.NewProtoCodec(registry)
|
||||||
|
}
|
||||||
|
|
||||||
func TestEvmDataEncoding(t *testing.T) {
|
func TestEvmDataEncoding(t *testing.T) {
|
||||||
ret := []byte{0x5, 0x8}
|
ret := []byte{0x5, 0x8}
|
||||||
|
|
||||||
data := &evmtypes.MsgEthereumTxResponse{
|
resp := &evmtypes.MsgEthereumTxResponse{
|
||||||
Hash: common.BytesToHash([]byte("hash")).String(),
|
Hash: common.BytesToHash([]byte("hash")).String(),
|
||||||
Logs: []*evmtypes.Log{{
|
Logs: []*evmtypes.Log{{
|
||||||
Data: []byte{1, 2, 3, 4},
|
Data: []byte{1, 2, 3, 4},
|
||||||
@ -30,21 +40,20 @@ func TestEvmDataEncoding(t *testing.T) {
|
|||||||
Ret: ret,
|
Ret: ret,
|
||||||
}
|
}
|
||||||
|
|
||||||
enc, err := proto.Marshal(data)
|
any, err := codectypes.NewAnyWithValue(resp)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
txData := &sdk.TxMsgData{
|
txData := &sdk.TxMsgData{
|
||||||
Data: []*sdk.MsgData{{MsgType: evmtypes.TypeMsgEthereumTx, Data: enc}},
|
MsgResponses: []*codectypes.Any{any},
|
||||||
}
|
}
|
||||||
|
|
||||||
txDataBz, err := proto.Marshal(txData)
|
txDataBz, err := txData.Marshal()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
res, err := evmtypes.DecodeTxResponse(txDataBz)
|
decoded, err := evmtypes.DecodeTxResponse(txDataBz, testCodec)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, res)
|
require.NotNil(t, decoded)
|
||||||
require.Equal(t, data.Logs, res.Logs)
|
require.Equal(t, resp.Logs, decoded.Logs)
|
||||||
require.Equal(t, ret, res.Ret)
|
require.Equal(t, ret, decoded.Ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnwrapEthererumMsg(t *testing.T) {
|
func TestUnwrapEthererumMsg(t *testing.T) {
|
||||||
|
@ -2,8 +2,9 @@ package keeper_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
prototypes "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestCalculateBaseFee() {
|
func (suite *KeeperTestSuite) TestCalculateBaseFee() {
|
||||||
@ -38,11 +39,11 @@ func (suite *KeeperTestSuite) TestCalculateBaseFee() {
|
|||||||
suite.app.FeeMarketKeeper.SetBlockGasUsed(suite.ctx, 100)
|
suite.app.FeeMarketKeeper.SetBlockGasUsed(suite.ctx, 100)
|
||||||
|
|
||||||
// Set target/gasLimit through Consensus Param MaxGas
|
// Set target/gasLimit through Consensus Param MaxGas
|
||||||
blockParams := abci.BlockParams{
|
blockParams := prototypes.BlockParams{
|
||||||
MaxGas: 100,
|
MaxGas: 100,
|
||||||
MaxBytes: 10,
|
MaxBytes: 10,
|
||||||
}
|
}
|
||||||
consParams := abci.ConsensusParams{Block: &blockParams}
|
consParams := prototypes.ConsensusParams{Block: &blockParams}
|
||||||
suite.ctx = suite.ctx.WithConsensusParams(&consParams)
|
suite.ctx = suite.ctx.WithConsensusParams(&consParams)
|
||||||
|
|
||||||
// set ElasticityMultiplier
|
// set ElasticityMultiplier
|
||||||
@ -60,11 +61,11 @@ func (suite *KeeperTestSuite) TestCalculateBaseFee() {
|
|||||||
|
|
||||||
suite.app.FeeMarketKeeper.SetBlockGasUsed(suite.ctx, 200)
|
suite.app.FeeMarketKeeper.SetBlockGasUsed(suite.ctx, 200)
|
||||||
|
|
||||||
blockParams := abci.BlockParams{
|
blockParams := prototypes.BlockParams{
|
||||||
MaxGas: 100,
|
MaxGas: 100,
|
||||||
MaxBytes: 10,
|
MaxBytes: 10,
|
||||||
}
|
}
|
||||||
consParams := abci.ConsensusParams{Block: &blockParams}
|
consParams := prototypes.ConsensusParams{Block: &blockParams}
|
||||||
suite.ctx = suite.ctx.WithConsensusParams(&consParams)
|
suite.ctx = suite.ctx.WithConsensusParams(&consParams)
|
||||||
|
|
||||||
params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
|
params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
|
||||||
@ -81,11 +82,11 @@ func (suite *KeeperTestSuite) TestCalculateBaseFee() {
|
|||||||
|
|
||||||
suite.app.FeeMarketKeeper.SetBlockGasUsed(suite.ctx, 50)
|
suite.app.FeeMarketKeeper.SetBlockGasUsed(suite.ctx, 50)
|
||||||
|
|
||||||
blockParams := abci.BlockParams{
|
blockParams := prototypes.BlockParams{
|
||||||
MaxGas: 100,
|
MaxGas: 100,
|
||||||
MaxBytes: 10,
|
MaxBytes: 10,
|
||||||
}
|
}
|
||||||
consParams := abci.ConsensusParams{Block: &blockParams}
|
consParams := prototypes.ConsensusParams{Block: &blockParams}
|
||||||
suite.ctx = suite.ctx.WithConsensusParams(&consParams)
|
suite.ctx = suite.ctx.WithConsensusParams(&consParams)
|
||||||
|
|
||||||
params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
|
params := suite.app.FeeMarketKeeper.GetParams(suite.ctx)
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
|
|
||||||
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||||
"github.com/tharsis/ethermint/x/feemarket/types"
|
"github.com/tharsis/ethermint/x/feemarket/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -14,14 +15,14 @@ type Keeper struct {
|
|||||||
// Protobuf codec
|
// Protobuf codec
|
||||||
cdc codec.BinaryCodec
|
cdc codec.BinaryCodec
|
||||||
// Store key required for the Fee Market Prefix KVStore.
|
// Store key required for the Fee Market Prefix KVStore.
|
||||||
storeKey sdk.StoreKey
|
storeKey storetypes.StoreKey
|
||||||
// module specific parameter space that can be configured through governance
|
// module specific parameter space that can be configured through governance
|
||||||
paramSpace paramtypes.Subspace
|
paramSpace paramtypes.Subspace
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKeeper generates new fee market module keeper
|
// NewKeeper generates new fee market module keeper
|
||||||
func NewKeeper(
|
func NewKeeper(
|
||||||
cdc codec.BinaryCodec, storeKey sdk.StoreKey, paramSpace paramtypes.Subspace,
|
cdc codec.BinaryCodec, storeKey storetypes.StoreKey, paramSpace paramtypes.Subspace,
|
||||||
) Keeper {
|
) Keeper {
|
||||||
// set KeyTable if it has not already been set
|
// set KeyTable if it has not already been set
|
||||||
if !paramSpace.HasKeyTable() {
|
if !paramSpace.HasKeyTable() {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user