b1cd16e5bf
* Problem: feemarket's query cli has redundant height parameter Soluton: - remove the positional height parameter, since there's a flag already. Update CHANGELOG.md * Apply feemarket to native cosmos tx - add tx extension option for user to input tip price - apply feemarket's base fee to native tx comments and cleanup fallback to default sdk logic when london hardfork not enabled integration test cleanup feemarket query cli commands Update CHANGELOG.md update unit tests disable feemarket in simulation tests for now fix lint Update app/simulation_test.go fix python lint fix lint Update x/evm/types/extension_option.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> address review suggestions * fix unit tests * fix integration test * improve unit test coverage * fix go lint * refactor * fix integration test * fix simulation tests * fix go linter Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
810 lines
30 KiB
Go
810 lines
30 KiB
Go
package app
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/gorilla/mux"
|
|
"github.com/rakyll/statik/fs"
|
|
"github.com/spf13/cast"
|
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
tmos "github.com/tendermint/tendermint/libs/os"
|
|
dbm "github.com/tendermint/tm-db"
|
|
|
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
|
"github.com/cosmos/cosmos-sdk/client"
|
|
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
|
"github.com/cosmos/cosmos-sdk/server/api"
|
|
"github.com/cosmos/cosmos-sdk/server/config"
|
|
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
|
"github.com/cosmos/cosmos-sdk/simapp"
|
|
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/cosmos/cosmos-sdk/types/module"
|
|
"github.com/cosmos/cosmos-sdk/version"
|
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
|
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
|
"github.com/cosmos/cosmos-sdk/x/auth/posthandler"
|
|
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
|
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
|
|
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
|
|
"github.com/cosmos/cosmos-sdk/x/authz"
|
|
authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
|
|
authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module"
|
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
|
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
|
"github.com/cosmos/cosmos-sdk/x/capability"
|
|
capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
|
|
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
|
|
"github.com/cosmos/cosmos-sdk/x/crisis"
|
|
crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper"
|
|
crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
|
|
distr "github.com/cosmos/cosmos-sdk/x/distribution"
|
|
distrclient "github.com/cosmos/cosmos-sdk/x/distribution/client"
|
|
distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
|
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
|
"github.com/cosmos/cosmos-sdk/x/evidence"
|
|
evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper"
|
|
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
|
|
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
|
feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
|
|
feegrantmodule "github.com/cosmos/cosmos-sdk/x/feegrant/module"
|
|
"github.com/cosmos/cosmos-sdk/x/genutil"
|
|
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
|
"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"
|
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
|
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
|
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
|
"github.com/cosmos/cosmos-sdk/x/mint"
|
|
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
|
|
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
|
"github.com/cosmos/cosmos-sdk/x/params"
|
|
paramsclient "github.com/cosmos/cosmos-sdk/x/params/client"
|
|
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
|
|
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
|
paramproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal"
|
|
"github.com/cosmos/cosmos-sdk/x/slashing"
|
|
slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
|
|
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
|
"github.com/cosmos/cosmos-sdk/x/staking"
|
|
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
|
"github.com/cosmos/cosmos-sdk/x/upgrade"
|
|
upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
|
|
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
|
|
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
|
|
|
"github.com/cosmos/ibc-go/v5/modules/apps/transfer"
|
|
ibctransferkeeper "github.com/cosmos/ibc-go/v5/modules/apps/transfer/keeper"
|
|
ibctransfertypes "github.com/cosmos/ibc-go/v5/modules/apps/transfer/types"
|
|
ibc "github.com/cosmos/ibc-go/v5/modules/core"
|
|
ibcclient "github.com/cosmos/ibc-go/v5/modules/core/02-client"
|
|
ibcclientclient "github.com/cosmos/ibc-go/v5/modules/core/02-client/client"
|
|
porttypes "github.com/cosmos/ibc-go/v5/modules/core/05-port/types"
|
|
ibchost "github.com/cosmos/ibc-go/v5/modules/core/24-host"
|
|
ibckeeper "github.com/cosmos/ibc-go/v5/modules/core/keeper"
|
|
|
|
// unnamed import of statik for swagger UI support
|
|
_ "github.com/evmos/ethermint/client/docs/statik"
|
|
|
|
"github.com/evmos/ethermint/app/ante"
|
|
srvflags "github.com/evmos/ethermint/server/flags"
|
|
ethermint "github.com/evmos/ethermint/types"
|
|
"github.com/evmos/ethermint/x/evm"
|
|
evmkeeper "github.com/evmos/ethermint/x/evm/keeper"
|
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
|
"github.com/evmos/ethermint/x/feemarket"
|
|
feemarketkeeper "github.com/evmos/ethermint/x/feemarket/keeper"
|
|
feemarkettypes "github.com/evmos/ethermint/x/feemarket/types"
|
|
|
|
// Force-load the tracer engines to trigger registration due to Go-Ethereum v1.10.15 changes
|
|
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
|
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
|
|
)
|
|
|
|
func init() {
|
|
userHomeDir, err := os.UserHomeDir()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
DefaultNodeHome = filepath.Join(userHomeDir, ".ethermintd")
|
|
}
|
|
|
|
const appName = "ethermintd"
|
|
|
|
var (
|
|
// DefaultNodeHome default home directories for the application daemon
|
|
DefaultNodeHome string
|
|
|
|
// ModuleBasics defines the module BasicManager is in charge of setting up basic,
|
|
// non-dependant module elements, such as codec registration
|
|
// and genesis verification.
|
|
ModuleBasics = module.NewBasicManager(
|
|
auth.AppModuleBasic{},
|
|
genutil.AppModuleBasic{},
|
|
bank.AppModuleBasic{},
|
|
capability.AppModuleBasic{},
|
|
staking.AppModuleBasic{},
|
|
mint.AppModuleBasic{},
|
|
distr.AppModuleBasic{},
|
|
gov.NewAppModuleBasic([]govclient.ProposalHandler{
|
|
paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.LegacyProposalHandler, upgradeclient.LegacyCancelProposalHandler,
|
|
ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler,
|
|
}),
|
|
params.AppModuleBasic{},
|
|
crisis.AppModuleBasic{},
|
|
slashing.AppModuleBasic{},
|
|
ibc.AppModuleBasic{},
|
|
authzmodule.AppModuleBasic{},
|
|
feegrantmodule.AppModuleBasic{},
|
|
upgrade.AppModuleBasic{},
|
|
evidence.AppModuleBasic{},
|
|
transfer.AppModuleBasic{},
|
|
vesting.AppModuleBasic{},
|
|
// Ethermint modules
|
|
evm.AppModuleBasic{},
|
|
feemarket.AppModuleBasic{},
|
|
)
|
|
|
|
// module account permissions
|
|
maccPerms = map[string][]string{
|
|
authtypes.FeeCollectorName: nil,
|
|
distrtypes.ModuleName: nil,
|
|
minttypes.ModuleName: {authtypes.Minter},
|
|
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
|
|
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
|
|
govtypes.ModuleName: {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
|
|
}
|
|
|
|
// module accounts that are allowed to receive tokens
|
|
allowedReceivingModAcc = map[string]bool{
|
|
distrtypes.ModuleName: true,
|
|
}
|
|
)
|
|
|
|
var _ simapp.App = (*EthermintApp)(nil)
|
|
|
|
// var _ server.Application (*EthermintApp)(nil)
|
|
|
|
// EthermintApp implements an extended ABCI application. It is an application
|
|
// that may process transactions through Ethereum's EVM running atop of
|
|
// Tendermint consensus.
|
|
type EthermintApp struct {
|
|
*baseapp.BaseApp
|
|
|
|
// encoding
|
|
cdc *codec.LegacyAmino
|
|
appCodec codec.Codec
|
|
interfaceRegistry types.InterfaceRegistry
|
|
|
|
invCheckPeriod uint
|
|
|
|
// keys to access the substores
|
|
keys map[string]*storetypes.KVStoreKey
|
|
tkeys map[string]*storetypes.TransientStoreKey
|
|
memKeys map[string]*storetypes.MemoryStoreKey
|
|
|
|
// keepers
|
|
AccountKeeper authkeeper.AccountKeeper
|
|
BankKeeper bankkeeper.Keeper
|
|
CapabilityKeeper *capabilitykeeper.Keeper
|
|
StakingKeeper stakingkeeper.Keeper
|
|
SlashingKeeper slashingkeeper.Keeper
|
|
MintKeeper mintkeeper.Keeper
|
|
DistrKeeper distrkeeper.Keeper
|
|
GovKeeper govkeeper.Keeper
|
|
CrisisKeeper crisiskeeper.Keeper
|
|
UpgradeKeeper upgradekeeper.Keeper
|
|
ParamsKeeper paramskeeper.Keeper
|
|
FeeGrantKeeper feegrantkeeper.Keeper
|
|
AuthzKeeper authzkeeper.Keeper
|
|
IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly
|
|
EvidenceKeeper evidencekeeper.Keeper
|
|
TransferKeeper ibctransferkeeper.Keeper
|
|
|
|
// make scoped keepers public for test purposes
|
|
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
|
|
ScopedTransferKeeper capabilitykeeper.ScopedKeeper
|
|
|
|
// Ethermint keepers
|
|
EvmKeeper *evmkeeper.Keeper
|
|
FeeMarketKeeper feemarketkeeper.Keeper
|
|
|
|
// the module manager
|
|
mm *module.Manager
|
|
|
|
// simulation manager
|
|
sm *module.SimulationManager
|
|
|
|
// the configurator
|
|
configurator module.Configurator
|
|
}
|
|
|
|
// NewEthermintApp returns a reference to a new initialized Ethermint application.
|
|
func NewEthermintApp(
|
|
logger log.Logger,
|
|
db dbm.DB,
|
|
traceStore io.Writer,
|
|
loadLatest bool,
|
|
skipUpgradeHeights map[int64]bool,
|
|
homePath string,
|
|
invCheckPeriod uint,
|
|
encodingConfig simappparams.EncodingConfig,
|
|
appOpts servertypes.AppOptions,
|
|
baseAppOptions ...func(*baseapp.BaseApp),
|
|
) *EthermintApp {
|
|
appCodec := encodingConfig.Codec
|
|
cdc := encodingConfig.Amino
|
|
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(
|
|
// SDK keys
|
|
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
|
|
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
|
|
govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey,
|
|
evidencetypes.StoreKey, capabilitytypes.StoreKey,
|
|
feegrant.StoreKey, authzkeeper.StoreKey,
|
|
// ibc keys
|
|
ibchost.StoreKey, ibctransfertypes.StoreKey,
|
|
// ethermint keys
|
|
evmtypes.StoreKey, feemarkettypes.StoreKey,
|
|
)
|
|
|
|
// Add the EVM transient store key
|
|
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
|
|
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
|
|
|
app := &EthermintApp{
|
|
BaseApp: bApp,
|
|
cdc: cdc,
|
|
appCodec: appCodec,
|
|
interfaceRegistry: interfaceRegistry,
|
|
invCheckPeriod: invCheckPeriod,
|
|
keys: keys,
|
|
tkeys: tkeys,
|
|
memKeys: memKeys,
|
|
}
|
|
|
|
// init params keeper and subspaces
|
|
app.ParamsKeeper = initParamsKeeper(appCodec, cdc, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
|
|
// set the BaseApp's parameter store
|
|
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramstypes.ConsensusParamsKeyTable()))
|
|
|
|
// add capability keeper and ScopeToModule for ibc module
|
|
app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
|
|
|
|
scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName)
|
|
scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName)
|
|
|
|
// Applications that wish to enforce statically created ScopedKeepers should call `Seal` after creating
|
|
// their scoped modules in `NewApp` with `ScopeToModule`
|
|
app.CapabilityKeeper.Seal()
|
|
|
|
// use custom Ethermint account for contracts
|
|
app.AccountKeeper = authkeeper.NewAccountKeeper(
|
|
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), ethermint.ProtoAccount, maccPerms, sdk.GetConfig().GetBech32AccountAddrPrefix(),
|
|
)
|
|
app.BankKeeper = bankkeeper.NewBaseKeeper(
|
|
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs(),
|
|
)
|
|
stakingKeeper := stakingkeeper.NewKeeper(
|
|
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName),
|
|
)
|
|
app.MintKeeper = mintkeeper.NewKeeper(
|
|
appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper,
|
|
app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName,
|
|
)
|
|
app.DistrKeeper = distrkeeper.NewKeeper(
|
|
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
|
&stakingKeeper, authtypes.FeeCollectorName,
|
|
)
|
|
app.SlashingKeeper = slashingkeeper.NewKeeper(
|
|
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
|
|
)
|
|
app.CrisisKeeper = crisiskeeper.NewKeeper(
|
|
app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName,
|
|
)
|
|
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
|
|
|
|
// set the governance module account as the authority for conducting upgrades
|
|
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String())
|
|
|
|
// register the staking hooks
|
|
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
|
|
app.StakingKeeper = *stakingKeeper.SetHooks(
|
|
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
|
|
)
|
|
|
|
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper)
|
|
|
|
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
|
|
|
|
// Create Ethermint keepers
|
|
app.FeeMarketKeeper = feemarketkeeper.NewKeeper(
|
|
appCodec, app.GetSubspace(feemarkettypes.ModuleName), keys[feemarkettypes.StoreKey], tkeys[feemarkettypes.TransientKey],
|
|
)
|
|
|
|
app.EvmKeeper = evmkeeper.NewKeeper(
|
|
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], app.GetSubspace(evmtypes.ModuleName),
|
|
app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.FeeMarketKeeper,
|
|
tracer,
|
|
)
|
|
|
|
// Create IBC Keeper
|
|
app.IBCKeeper = ibckeeper.NewKeeper(
|
|
appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
|
|
)
|
|
|
|
// register the proposal types
|
|
govRouter := govv1beta1.NewRouter()
|
|
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
|
|
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
|
|
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
|
|
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)).
|
|
AddRoute(ibchost.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))
|
|
govConfig := govtypes.DefaultConfig()
|
|
/*
|
|
Example of setting gov params:
|
|
govConfig.MaxMetadataLen = 10000
|
|
*/
|
|
govKeeper := govkeeper.NewKeeper(
|
|
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
|
&stakingKeeper, govRouter, app.MsgServiceRouter(), govConfig,
|
|
)
|
|
|
|
app.GovKeeper = *govKeeper.SetHooks(
|
|
govtypes.NewMultiGovHooks(
|
|
// register the governance hooks
|
|
),
|
|
)
|
|
|
|
// Create Transfer Keepers
|
|
app.TransferKeeper = ibctransferkeeper.NewKeeper(
|
|
appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName),
|
|
app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper,
|
|
app.AccountKeeper, app.BankKeeper, scopedTransferKeeper,
|
|
)
|
|
transferModule := transfer.NewAppModule(app.TransferKeeper)
|
|
transferIBCModule := transfer.NewIBCModule(app.TransferKeeper)
|
|
|
|
// Create static IBC router, add transfer route, then set and seal it
|
|
ibcRouter := porttypes.NewRouter()
|
|
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferIBCModule)
|
|
app.IBCKeeper.SetRouter(ibcRouter)
|
|
|
|
// create evidence keeper with router
|
|
evidenceKeeper := evidencekeeper.NewKeeper(
|
|
appCodec, keys[evidencetypes.StoreKey], &app.StakingKeeper, app.SlashingKeeper,
|
|
)
|
|
// If evidence needs to be handled for the app, set routes in router here and seal
|
|
app.EvidenceKeeper = *evidenceKeeper
|
|
|
|
/**** Module Options ****/
|
|
|
|
// NOTE: we may consider parsing `appOpts` inside module constructors. For the moment
|
|
// we prefer to be more strict in what arguments the modules expect.
|
|
skipGenesisInvariants := cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants))
|
|
|
|
// NOTE: Any module instantiated in the module manager that is later modified
|
|
// must be passed by reference here.
|
|
app.mm = module.NewManager(
|
|
// SDK app modules
|
|
genutil.NewAppModule(
|
|
app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
|
|
encodingConfig.TxConfig,
|
|
),
|
|
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
|
|
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
|
|
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
|
|
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
|
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
|
|
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
|
|
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
|
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
|
|
slashing.NewAppModule(appCodec, app.SlashingKeeper, 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),
|
|
upgrade.NewAppModule(app.UpgradeKeeper),
|
|
evidence.NewAppModule(app.EvidenceKeeper),
|
|
params.NewAppModule(app.ParamsKeeper),
|
|
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
|
|
|
|
// ibc modules
|
|
ibc.NewAppModule(app.IBCKeeper),
|
|
transferModule,
|
|
// Ethermint app modules
|
|
evm.NewAppModule(app.EvmKeeper, app.AccountKeeper),
|
|
feemarket.NewAppModule(app.FeeMarketKeeper),
|
|
)
|
|
|
|
// During begin block slashing happens after distr.BeginBlocker so that
|
|
// there is nothing left over in the validator fee pool, so as to keep the
|
|
// CanWithdrawInvariant invariant.
|
|
// NOTE: upgrade module must go first to handle software upgrades.
|
|
// NOTE: staking module is required if HistoricalEntries param > 0
|
|
// NOTE: capability module's beginblocker must come before any modules using capabilities (e.g. IBC)
|
|
app.mm.SetOrderBeginBlockers(
|
|
upgradetypes.ModuleName,
|
|
capabilitytypes.ModuleName,
|
|
feemarkettypes.ModuleName,
|
|
evmtypes.ModuleName,
|
|
minttypes.ModuleName,
|
|
distrtypes.ModuleName,
|
|
slashingtypes.ModuleName,
|
|
evidencetypes.ModuleName,
|
|
stakingtypes.ModuleName,
|
|
ibchost.ModuleName,
|
|
// no-op modules
|
|
ibctransfertypes.ModuleName,
|
|
authtypes.ModuleName,
|
|
banktypes.ModuleName,
|
|
govtypes.ModuleName,
|
|
crisistypes.ModuleName,
|
|
genutiltypes.ModuleName,
|
|
authz.ModuleName,
|
|
feegrant.ModuleName,
|
|
paramstypes.ModuleName,
|
|
vestingtypes.ModuleName,
|
|
)
|
|
|
|
// NOTE: fee market module must go last in order to retrieve the block gas used.
|
|
app.mm.SetOrderEndBlockers(
|
|
crisistypes.ModuleName,
|
|
govtypes.ModuleName,
|
|
stakingtypes.ModuleName,
|
|
evmtypes.ModuleName,
|
|
feemarkettypes.ModuleName,
|
|
// no-op modules
|
|
ibchost.ModuleName,
|
|
ibctransfertypes.ModuleName,
|
|
capabilitytypes.ModuleName,
|
|
authtypes.ModuleName,
|
|
banktypes.ModuleName,
|
|
distrtypes.ModuleName,
|
|
slashingtypes.ModuleName,
|
|
minttypes.ModuleName,
|
|
genutiltypes.ModuleName,
|
|
evidencetypes.ModuleName,
|
|
authz.ModuleName,
|
|
feegrant.ModuleName,
|
|
paramstypes.ModuleName,
|
|
upgradetypes.ModuleName,
|
|
vestingtypes.ModuleName,
|
|
)
|
|
|
|
// NOTE: The genutils module must occur after staking so that pools are
|
|
// properly initialized with tokens from genesis accounts.
|
|
// NOTE: The genutils module must also occur after auth so that it can access the params from auth.
|
|
// NOTE: Capability module must occur first so that it can initialize any capabilities
|
|
// so that other modules that want to create or claim capabilities afterwards in InitChain
|
|
// can do so safely.
|
|
app.mm.SetOrderInitGenesis(
|
|
// SDK modules
|
|
capabilitytypes.ModuleName,
|
|
authtypes.ModuleName,
|
|
banktypes.ModuleName,
|
|
distrtypes.ModuleName,
|
|
stakingtypes.ModuleName,
|
|
slashingtypes.ModuleName,
|
|
govtypes.ModuleName,
|
|
minttypes.ModuleName,
|
|
ibchost.ModuleName,
|
|
// evm module denomination is used by the feemarket module, in AnteHandle
|
|
evmtypes.ModuleName,
|
|
// NOTE: feemarket need to be initialized before genutil module:
|
|
// gentx transactions use MinGasPriceDecorator.AnteHandle
|
|
feemarkettypes.ModuleName,
|
|
genutiltypes.ModuleName,
|
|
evidencetypes.ModuleName,
|
|
ibctransfertypes.ModuleName,
|
|
authz.ModuleName,
|
|
feegrant.ModuleName,
|
|
paramstypes.ModuleName,
|
|
upgradetypes.ModuleName,
|
|
vestingtypes.ModuleName,
|
|
// NOTE: crisis module must go at the end to check for invariants on each module
|
|
crisistypes.ModuleName,
|
|
)
|
|
|
|
// Uncomment if you want to set a custom migration order here.
|
|
// app.mm.SetOrderMigrations(custom order)
|
|
|
|
app.mm.RegisterInvariants(&app.CrisisKeeper)
|
|
app.mm.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino)
|
|
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
|
|
app.mm.RegisterServices(app.configurator)
|
|
|
|
// RegisterUpgradeHandlers is used for registering any on-chain upgrades.
|
|
// Make sure it's called after `app.mm` and `app.configurator` are set.
|
|
// app.RegisterUpgradeHandlers()
|
|
|
|
// add test gRPC service for testing gRPC queries in isolation
|
|
// testdata.RegisterTestServiceServer(app.GRPCQueryRouter(), testdata.TestServiceImpl{})
|
|
|
|
// create the simulation manager and define the order of the modules for deterministic simulations
|
|
//
|
|
// NOTE: this is not required apps that don't use the simulator for fuzz testing
|
|
// transactions
|
|
overrideModules := map[string]module.AppModuleSimulation{
|
|
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
|
|
}
|
|
app.sm = module.NewSimulationManagerFromAppModules(app.mm.Modules, overrideModules)
|
|
|
|
app.sm.RegisterStoreDecoders()
|
|
|
|
// initialize stores
|
|
app.MountKVStores(keys)
|
|
app.MountTransientStores(tkeys)
|
|
app.MountMemoryStores(memKeys)
|
|
|
|
// initialize BaseApp
|
|
app.SetInitChainer(app.InitChainer)
|
|
app.SetBeginBlocker(app.BeginBlocker)
|
|
app.SetEndBlocker(app.EndBlocker)
|
|
app.setAnteHandler(encodingConfig.TxConfig, cast.ToUint64(appOpts.Get(srvflags.EVMMaxTxGasWanted)))
|
|
// In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
|
|
// antehandlers, but are run _after_ the `runMsgs` execution. They are also
|
|
// defined as a chain, and have the same signature as antehandlers.
|
|
//
|
|
// In baseapp, postHandlers are run in the same store branch as `runMsgs`,
|
|
// meaning that both `runMsgs` and `postHandler` state will be committed if
|
|
// both are successful, and both will be reverted if any of the two fails.
|
|
//
|
|
// The SDK exposes a default empty postHandlers chain.
|
|
//
|
|
// Please note that changing any of the anteHandler or postHandler chain is
|
|
// likely to be a state-machine breaking change, which needs a coordinated
|
|
// upgrade.
|
|
app.setPostHandler()
|
|
|
|
if loadLatest {
|
|
if err := app.LoadLatestVersion(); err != nil {
|
|
tmos.Exit(err.Error())
|
|
}
|
|
}
|
|
|
|
app.ScopedIBCKeeper = scopedIBCKeeper
|
|
app.ScopedTransferKeeper = scopedTransferKeeper
|
|
|
|
return app
|
|
}
|
|
|
|
// use Ethermint's custom AnteHandler
|
|
func (app *EthermintApp) setAnteHandler(txConfig client.TxConfig, maxGasWanted uint64) {
|
|
anteHandler, err := ante.NewAnteHandler(ante.HandlerOptions{
|
|
AccountKeeper: app.AccountKeeper,
|
|
BankKeeper: app.BankKeeper,
|
|
SignModeHandler: txConfig.SignModeHandler(),
|
|
FeegrantKeeper: app.FeeGrantKeeper,
|
|
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
|
|
IBCKeeper: app.IBCKeeper,
|
|
EvmKeeper: app.EvmKeeper,
|
|
FeeMarketKeeper: app.FeeMarketKeeper,
|
|
MaxTxGasWanted: maxGasWanted,
|
|
ExtensionOptionChecker: ethermint.HasDynamicFeeExtensionOption,
|
|
TxFeeChecker: ante.NewDynamicFeeChecker(app.EvmKeeper),
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
app.SetAnteHandler(anteHandler)
|
|
}
|
|
|
|
func (app *EthermintApp) setPostHandler() {
|
|
postHandler, err := posthandler.NewPostHandler(
|
|
posthandler.HandlerOptions{},
|
|
)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
app.SetPostHandler(postHandler)
|
|
}
|
|
|
|
// Name returns the name of the App
|
|
func (app *EthermintApp) Name() string { return app.BaseApp.Name() }
|
|
|
|
// BeginBlocker updates every begin block
|
|
func (app *EthermintApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
|
return app.mm.BeginBlock(ctx, req)
|
|
}
|
|
|
|
// EndBlocker updates every end block
|
|
func (app *EthermintApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
|
return app.mm.EndBlock(ctx, req)
|
|
}
|
|
|
|
// InitChainer updates at chain initialization
|
|
func (app *EthermintApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
|
var genesisState simapp.GenesisState
|
|
if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
|
|
panic(err)
|
|
}
|
|
app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap())
|
|
return app.mm.InitGenesis(ctx, app.appCodec, genesisState)
|
|
}
|
|
|
|
// LoadHeight loads state at a particular height
|
|
func (app *EthermintApp) LoadHeight(height int64) error {
|
|
return app.LoadVersion(height)
|
|
}
|
|
|
|
// ModuleAccountAddrs returns all the app's module account addresses.
|
|
func (app *EthermintApp) ModuleAccountAddrs() map[string]bool {
|
|
modAccAddrs := make(map[string]bool)
|
|
for acc := range maccPerms {
|
|
modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
|
|
}
|
|
|
|
return modAccAddrs
|
|
}
|
|
|
|
// BlockedAddrs returns all the app's module account addresses that are not
|
|
// allowed to receive external tokens.
|
|
func (app *EthermintApp) BlockedAddrs() map[string]bool {
|
|
blockedAddrs := make(map[string]bool)
|
|
for acc := range maccPerms {
|
|
blockedAddrs[authtypes.NewModuleAddress(acc).String()] = !allowedReceivingModAcc[acc]
|
|
}
|
|
|
|
return blockedAddrs
|
|
}
|
|
|
|
// LegacyAmino returns EthermintApp's amino codec.
|
|
//
|
|
// NOTE: This is solely to be used for testing purposes as it may be desirable
|
|
// for modules to register their own custom testing types.
|
|
func (app *EthermintApp) LegacyAmino() *codec.LegacyAmino {
|
|
return app.cdc
|
|
}
|
|
|
|
// AppCodec returns EthermintApp's app codec.
|
|
//
|
|
// NOTE: This is solely to be used for testing purposes as it may be desirable
|
|
// for modules to register their own custom testing types.
|
|
func (app *EthermintApp) AppCodec() codec.Codec {
|
|
return app.appCodec
|
|
}
|
|
|
|
// InterfaceRegistry returns EthermintApp's InterfaceRegistry
|
|
func (app *EthermintApp) InterfaceRegistry() types.InterfaceRegistry {
|
|
return app.interfaceRegistry
|
|
}
|
|
|
|
// GetKey returns the KVStoreKey for the provided store key.
|
|
//
|
|
// NOTE: This is solely to be used for testing purposes.
|
|
func (app *EthermintApp) GetKey(storeKey string) *storetypes.KVStoreKey {
|
|
return app.keys[storeKey]
|
|
}
|
|
|
|
// GetTKey returns the TransientStoreKey for the provided store key.
|
|
//
|
|
// NOTE: This is solely to be used for testing purposes.
|
|
func (app *EthermintApp) GetTKey(storeKey string) *storetypes.TransientStoreKey {
|
|
return app.tkeys[storeKey]
|
|
}
|
|
|
|
// GetMemKey returns the MemStoreKey for the provided mem key.
|
|
//
|
|
// NOTE: This is solely used for testing purposes.
|
|
func (app *EthermintApp) GetMemKey(storeKey string) *storetypes.MemoryStoreKey {
|
|
return app.memKeys[storeKey]
|
|
}
|
|
|
|
// GetSubspace returns a param subspace for a given module name.
|
|
//
|
|
// NOTE: This is solely to be used for testing purposes.
|
|
func (app *EthermintApp) GetSubspace(moduleName string) paramstypes.Subspace {
|
|
subspace, _ := app.ParamsKeeper.GetSubspace(moduleName)
|
|
return subspace
|
|
}
|
|
|
|
// SimulationManager implements the SimulationApp interface
|
|
func (app *EthermintApp) SimulationManager() *module.SimulationManager {
|
|
return app.sm
|
|
}
|
|
|
|
// RegisterAPIRoutes registers all application module routes with the provided
|
|
// API server.
|
|
func (app *EthermintApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
|
clientCtx := apiSvr.ClientCtx
|
|
// Register new tx routes from grpc-gateway.
|
|
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
|
// Register new tendermint queries routes from grpc-gateway.
|
|
tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
|
|
|
// Register grpc-gateway routes for all modules.
|
|
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
|
|
|
// register swagger API from root so that other applications can override easily
|
|
if apiConfig.Swagger {
|
|
RegisterSwaggerAPI(clientCtx, apiSvr.Router)
|
|
}
|
|
}
|
|
|
|
// RegisterTxService implements the Application.RegisterTxService method.
|
|
func (app *EthermintApp) RegisterTxService(clientCtx client.Context) {
|
|
authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
|
|
}
|
|
|
|
// RegisterTendermintService implements the Application.RegisterTendermintService method.
|
|
func (app *EthermintApp) RegisterTendermintService(clientCtx client.Context) {
|
|
tmservice.RegisterTendermintService(
|
|
clientCtx,
|
|
app.BaseApp.GRPCQueryRouter(),
|
|
app.interfaceRegistry,
|
|
app.Query,
|
|
)
|
|
}
|
|
|
|
// RegisterSwaggerAPI registers swagger route with API Server
|
|
func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) {
|
|
statikFS, err := fs.New()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
staticServer := http.FileServer(statikFS)
|
|
rtr.PathPrefix("/swagger/").Handler(http.StripPrefix("/swagger/", staticServer))
|
|
}
|
|
|
|
// GetMaccPerms returns a copy of the module account permissions
|
|
func GetMaccPerms() map[string][]string {
|
|
dupMaccPerms := make(map[string][]string)
|
|
for k, v := range maccPerms {
|
|
dupMaccPerms[k] = v
|
|
}
|
|
return dupMaccPerms
|
|
}
|
|
|
|
// initParamsKeeper init params keeper and its subspaces
|
|
func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey storetypes.StoreKey) paramskeeper.Keeper {
|
|
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
|
|
|
|
// SDK subspaces
|
|
paramsKeeper.Subspace(authtypes.ModuleName)
|
|
paramsKeeper.Subspace(banktypes.ModuleName)
|
|
paramsKeeper.Subspace(stakingtypes.ModuleName)
|
|
paramsKeeper.Subspace(minttypes.ModuleName)
|
|
paramsKeeper.Subspace(distrtypes.ModuleName)
|
|
paramsKeeper.Subspace(slashingtypes.ModuleName)
|
|
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govv1.ParamKeyTable())
|
|
paramsKeeper.Subspace(crisistypes.ModuleName)
|
|
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
|
|
paramsKeeper.Subspace(ibchost.ModuleName)
|
|
// ethermint subspaces
|
|
paramsKeeper.Subspace(evmtypes.ModuleName)
|
|
paramsKeeper.Subspace(feemarkettypes.ModuleName)
|
|
return paramsKeeper
|
|
}
|