gcx/blockchain/genex-chain/app.go

980 lines
36 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package genexchain — Genex Chain Application
//
// Genex Chain 是基于 Cosmos SDK + cosmos/evm + CometBFT 构建的券金融专用应用链。
// 基于 cosmos/evm v0.5.1 的 evmd 示例链定制。
//
// 特性:
// - 完全 EVM 兼容 (Solidity, Hardhat, MetaMask)
// - CometBFT 即时终结性共识 (≤1s 出块)
// - 链级合规 (OFAC, Travel Rule, KYC)
// - 平台 Gas 全额补贴 (用户零 Gas)
// - IBC 跨链 + ERC-20 代币桥接
package genexchain
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
"github.com/spf13/cast"
// Force-load the tracer engines to trigger registration
"github.com/ethereum/go-ethereum/common"
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
abci "github.com/cometbft/cometbft/abci/types"
dbm "github.com/cosmos/cosmos-db"
evmante "github.com/cosmos/evm/ante"
antetypes "github.com/cosmos/evm/ante/types"
evmconfig "github.com/cosmos/evm/config"
evmencoding "github.com/cosmos/evm/encoding"
evmaddress "github.com/cosmos/evm/encoding/address"
evmmempool "github.com/cosmos/evm/mempool"
precompiletypes "github.com/cosmos/evm/precompiles/types"
srvflags "github.com/cosmos/evm/server/flags"
"github.com/cosmos/evm/utils"
"github.com/cosmos/evm/x/erc20"
erc20keeper "github.com/cosmos/evm/x/erc20/keeper"
erc20types "github.com/cosmos/evm/x/erc20/types"
erc20v2 "github.com/cosmos/evm/x/erc20/v2"
"github.com/cosmos/evm/x/feemarket"
feemarketkeeper "github.com/cosmos/evm/x/feemarket/keeper"
feemarkettypes "github.com/cosmos/evm/x/feemarket/types"
ibccallbackskeeper "github.com/cosmos/evm/x/ibc/callbacks/keeper"
"github.com/cosmos/evm/x/ibc/transfer"
transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper"
transferv2 "github.com/cosmos/evm/x/ibc/transfer/v2"
"github.com/cosmos/evm/x/precisebank"
precisebankkeeper "github.com/cosmos/evm/x/precisebank/keeper"
precisebanktypes "github.com/cosmos/evm/x/precisebank/types"
"github.com/cosmos/evm/x/vm"
evmkeeper "github.com/cosmos/evm/x/vm/keeper"
evmtypes "github.com/cosmos/evm/x/vm/types"
"github.com/cosmos/gogoproto/proto"
ibccallbacks "github.com/cosmos/ibc-go/v10/modules/apps/callbacks"
ibctransfer "github.com/cosmos/ibc-go/v10/modules/apps/transfer"
ibctransfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types"
ibc "github.com/cosmos/ibc-go/v10/modules/core"
porttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types"
ibcapi "github.com/cosmos/ibc-go/v10/modules/core/api"
ibcexported "github.com/cosmos/ibc-go/v10/modules/core/exported"
ibckeeper "github.com/cosmos/ibc-go/v10/modules/core/keeper"
ibctm "github.com/cosmos/ibc-go/v10/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v10/testing"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
"cosmossdk.io/client/v2/autocli"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/log"
storetypes "cosmossdk.io/store/types"
"cosmossdk.io/x/evidence"
evidencekeeper "cosmossdk.io/x/evidence/keeper"
evidencetypes "cosmossdk.io/x/evidence/types"
"cosmossdk.io/x/feegrant"
feegrantkeeper "cosmossdk.io/x/feegrant/keeper"
feegrantmodule "cosmossdk.io/x/feegrant/module"
"cosmossdk.io/x/upgrade"
upgradekeeper "cosmossdk.io/x/upgrade/keeper"
upgradetypes "cosmossdk.io/x/upgrade/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
"github.com/cosmos/cosmos-sdk/client/grpc/node"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/runtime"
runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
sdkserver "github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/api"
"github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
testdata_pulsar "github.com/cosmos/cosmos-sdk/testutil/testdata/testpb"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/types/msgservice"
signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
"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"
txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
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/consensus"
consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types"
distr "github.com/cosmos/cosmos-sdk/x/distribution"
distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/cosmos/cosmos-sdk/x/gov"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"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/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"
cosmosevmserver "github.com/cosmos/evm/server"
genexante "github.com/genex/genex-chain/x/evm/ante"
)
const (
AppName = "GenexChain"
// Genex Chain 参数
GenexBech32Prefix = "genex"
GenexBondDenom = "agnx" // atto GNX, 18 decimals for EVM compatibility
GenexDisplayDenom = "GNX"
GenexEVMChainID = uint64(8888)
)
var defaultNodeHome string
func init() {
// Use atto power reduction (18 decimals) for EVM compatibility
sdk.DefaultPowerReduction = utils.AttoPowerReduction
defaultNodeHome = GenexDefaultNodeHome()
}
// GenexDefaultNodeHome returns the default node home directory (~/.genexd)
func GenexDefaultNodeHome() string {
homeDir, _ := os.UserHomeDir()
return homeDir + "/.genexd"
}
// SetGenexBech32Prefixes sets the bech32 prefixes for Genex Chain
func SetGenexBech32Prefixes(config *sdk.Config) {
config.SetBech32PrefixForAccount(GenexBech32Prefix, GenexBech32Prefix+"pub")
config.SetBech32PrefixForValidator(GenexBech32Prefix+"valoper", GenexBech32Prefix+"valoperpub")
config.SetBech32PrefixForConsensusNode(GenexBech32Prefix+"valcons", GenexBech32Prefix+"valconspub")
}
var (
_ runtime.AppI = (*GenexApp)(nil)
_ cosmosevmserver.Application = (*GenexApp)(nil)
_ ibctesting.TestingApp = (*GenexApp)(nil)
)
// GenexApp 是 Genex Chain 的核心 Application
// 继承 Cosmos SDK BaseApp集成 cosmos/evm EVM 模块
type GenexApp struct {
*baseapp.BaseApp
legacyAmino *codec.LegacyAmino
appCodec codec.Codec
interfaceRegistry types.InterfaceRegistry
txConfig client.TxConfig
clientCtx client.Context
pendingTxListeners []evmante.PendingTxListener
// keys to access the substores
keys map[string]*storetypes.KVStoreKey
tkeys map[string]*storetypes.TransientStoreKey
memKeys map[string]*storetypes.MemoryStoreKey
// Cosmos SDK keepers
AccountKeeper authkeeper.AccountKeeper
BankKeeper bankkeeper.Keeper
StakingKeeper *stakingkeeper.Keeper
SlashingKeeper slashingkeeper.Keeper
MintKeeper mintkeeper.Keeper
DistrKeeper distrkeeper.Keeper
GovKeeper govkeeper.Keeper
UpgradeKeeper *upgradekeeper.Keeper
AuthzKeeper authzkeeper.Keeper
EvidenceKeeper evidencekeeper.Keeper
FeeGrantKeeper feegrantkeeper.Keeper
ConsensusParamsKeeper consensusparamkeeper.Keeper
// IBC keepers
IBCKeeper *ibckeeper.Keeper
TransferKeeper transferkeeper.Keeper
CallbackKeeper ibccallbackskeeper.ContractKeeper
// Cosmos EVM keepers
FeeMarketKeeper feemarketkeeper.Keeper
EVMKeeper *evmkeeper.Keeper
Erc20Keeper erc20keeper.Keeper
PreciseBankKeeper precisebankkeeper.Keeper
EVMMempool *evmmempool.ExperimentalEVMMempool
// Genex compliance handler — 验证节点级合规拦截 (OFAC, Travel Rule, Structuring)
// 链下合规服务通过此 handler 同步 OFAC 名单和 Travel Rule 记录
ComplianceHandler *genexante.ComplianceAnteHandler
// Module manager
ModuleManager *module.Manager
BasicModuleManager module.BasicManager
// Simulation manager
sm *module.SimulationManager
// Module configurator
configurator module.Configurator
}
// NewGenexApp 创建 GenexApp 实例
func NewGenexApp(
logger log.Logger,
db dbm.DB,
traceStore io.Writer,
loadLatest bool,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
) *GenexApp {
evmChainID := cast.ToUint64(appOpts.Get(srvflags.EVMChainID))
// Note: don't default to GenexEVMChainID here.
// The real app gets 8888 from app.toml (set by evmconfig.InitAppConfig in root.go).
// tempApp (EmptyAppOptions) uses 0 → DefaultEVMChainID (262144), allowing
// the real app to later override the chain config via SetChainConfig.
encodingConfig := evmencoding.MakeConfig(evmChainID)
appCodec := encodingConfig.Codec
legacyAmino := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
txConfig := encodingConfig.TxConfig
bApp := baseapp.NewBaseApp(
AppName, logger, db,
encodingConfig.TxConfig.TxDecoder(),
baseAppOptions...,
)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
bApp.SetTxEncoder(txConfig.TxEncoder())
keys := storetypes.NewKVStoreKeys(
// Cosmos SDK
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, consensusparamtypes.StoreKey,
upgradetypes.StoreKey, feegrant.StoreKey, evidencetypes.StoreKey, authzkeeper.StoreKey,
// IBC
ibcexported.StoreKey, ibctransfertypes.StoreKey,
// Cosmos EVM
evmtypes.StoreKey, feemarkettypes.StoreKey, erc20types.StoreKey, precisebanktypes.StoreKey,
)
tkeys := storetypes.NewTransientStoreKeys(evmtypes.TransientKey, feemarkettypes.TransientKey)
if err := bApp.RegisterStreamingServices(appOpts, keys); err != nil {
fmt.Printf("failed to load state streaming: %s", err)
os.Exit(1)
}
app := &GenexApp{
BaseApp: bApp,
legacyAmino: legacyAmino,
appCodec: appCodec,
txConfig: txConfig,
interfaceRegistry: interfaceRegistry,
keys: keys,
tkeys: tkeys,
}
// Authority address (governance module)
authAddr := authtypes.NewModuleAddress(govtypes.ModuleName).String()
// Consensus params keeper
app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]),
authAddr,
runtime.EventService{},
)
bApp.SetParamStore(app.ConsensusParamsKeeper.ParamsStore)
// Account keeper
app.AccountKeeper = authkeeper.NewAccountKeeper(
appCodec, runtime.NewKVStoreService(keys[authtypes.StoreKey]),
authtypes.ProtoBaseAccount, evmconfig.GetMaccPerms(),
evmaddress.NewEvmCodec(GenexBech32Prefix),
GenexBech32Prefix,
authAddr,
)
// Bank keeper
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec,
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
app.AccountKeeper,
evmconfig.BlockedAddresses(),
authAddr,
logger,
)
// Enable SIGN_MODE_TEXTUAL
enabledSignModes := append(authtx.DefaultSignModes, signingtypes.SignMode_SIGN_MODE_TEXTUAL)
txConfigOpts := authtx.ConfigOptions{
EnabledSignModes: enabledSignModes,
TextualCoinMetadataQueryFn: txmodule.NewBankKeeperCoinMetadataQueryFn(app.BankKeeper),
}
txConfig, err := authtx.NewTxConfigWithOptions(appCodec, txConfigOpts)
if err != nil {
panic(err)
}
app.txConfig = txConfig
// Staking keeper
app.StakingKeeper = stakingkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[stakingtypes.StoreKey]),
app.AccountKeeper,
app.BankKeeper,
authAddr,
evmaddress.NewEvmCodec(GenexBech32Prefix+"valoper"),
evmaddress.NewEvmCodec(GenexBech32Prefix+"valcons"),
)
// Mint keeper
app.MintKeeper = mintkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[minttypes.StoreKey]),
app.StakingKeeper,
app.AccountKeeper,
app.BankKeeper,
authtypes.FeeCollectorName,
authAddr,
)
// Distribution keeper
app.DistrKeeper = distrkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[distrtypes.StoreKey]),
app.AccountKeeper,
app.BankKeeper,
app.StakingKeeper,
authtypes.FeeCollectorName,
authAddr,
)
// Slashing keeper
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec,
app.LegacyAmino(),
runtime.NewKVStoreService(keys[slashingtypes.StoreKey]),
app.StakingKeeper,
authAddr,
)
// FeeGrant keeper
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(
appCodec, runtime.NewKVStoreService(keys[feegrant.StoreKey]), app.AccountKeeper,
)
// Staking hooks
app.StakingKeeper.SetHooks(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)
// Authz keeper
app.AuthzKeeper = authzkeeper.NewKeeper(
runtime.NewKVStoreService(keys[authzkeeper.StoreKey]),
appCodec,
app.MsgServiceRouter(),
app.AccountKeeper,
)
// Upgrade keeper
skipUpgradeHeights := map[int64]bool{}
for _, h := range cast.ToIntSlice(appOpts.Get(sdkserver.FlagUnsafeSkipUpgrades)) {
skipUpgradeHeights[int64(h)] = true
}
homePath := cast.ToString(appOpts.Get(flags.FlagHome))
app.UpgradeKeeper = upgradekeeper.NewKeeper(
skipUpgradeHeights,
runtime.NewKVStoreService(keys[upgradetypes.StoreKey]),
appCodec,
homePath,
app.BaseApp,
authAddr,
)
// IBC keeper
app.IBCKeeper = ibckeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[ibcexported.StoreKey]),
nil,
app.UpgradeKeeper,
authAddr,
)
// Gov keeper
govConfig := govtypes.DefaultConfig()
govKeeper := govkeeper.NewKeeper(
appCodec, runtime.NewKVStoreService(keys[govtypes.StoreKey]),
app.AccountKeeper, app.BankKeeper,
app.StakingKeeper, app.DistrKeeper,
app.MsgServiceRouter(), govConfig, authAddr,
)
app.GovKeeper = *govKeeper.SetHooks(govtypes.NewMultiGovHooks())
// Evidence keeper
evidenceKeeper := evidencekeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[evidencetypes.StoreKey]),
app.StakingKeeper,
app.SlashingKeeper,
app.AccountKeeper.AddressCodec(),
runtime.ProvideCometInfoService(),
)
app.EvidenceKeeper = *evidenceKeeper
// ============================================================
// Cosmos EVM keepers
// ============================================================
// FeeMarket keeper
app.FeeMarketKeeper = feemarketkeeper.NewKeeper(
appCodec, authtypes.NewModuleAddress(govtypes.ModuleName),
keys[feemarkettypes.StoreKey],
tkeys[feemarkettypes.TransientKey],
)
// PreciseBank keeper (handles EVM 18-decimal conversion)
app.PreciseBankKeeper = precisebankkeeper.NewKeeper(
appCodec,
keys[precisebanktypes.StoreKey],
app.BankKeeper,
app.AccountKeeper,
)
// EVM keeper
tracer := cast.ToString(appOpts.Get(srvflags.EVMTracer))
app.EVMKeeper = evmkeeper.NewKeeper(
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], keys,
authtypes.NewModuleAddress(govtypes.ModuleName),
app.AccountKeeper,
app.PreciseBankKeeper,
app.StakingKeeper,
app.FeeMarketKeeper,
&app.ConsensusParamsKeeper,
&app.Erc20Keeper,
evmChainID,
tracer,
).WithStaticPrecompiles(
precompiletypes.DefaultStaticPrecompiles(
*app.StakingKeeper,
app.DistrKeeper,
app.PreciseBankKeeper,
&app.Erc20Keeper,
&app.TransferKeeper,
app.IBCKeeper.ChannelKeeper,
app.GovKeeper,
app.SlashingKeeper,
appCodec,
),
)
// ERC-20 keeper
app.Erc20Keeper = erc20keeper.NewKeeper(
keys[erc20types.StoreKey],
appCodec,
authtypes.NewModuleAddress(govtypes.ModuleName),
app.AccountKeeper,
app.PreciseBankKeeper,
app.EVMKeeper,
app.StakingKeeper,
&app.TransferKeeper,
)
// IBC Transfer keeper (after ERC-20 keeper)
app.TransferKeeper = transferkeeper.NewKeeper(
appCodec,
runtime.NewKVStoreService(keys[ibctransfertypes.StoreKey]),
app.IBCKeeper.ChannelKeeper,
app.IBCKeeper.ChannelKeeper,
app.MsgServiceRouter(),
app.AccountKeeper,
app.BankKeeper,
app.Erc20Keeper,
authAddr,
)
app.TransferKeeper.SetAddressCodec(evmaddress.NewEvmCodec(GenexBech32Prefix))
// ============================================================
// IBC Transfer Stack (bottom to top):
// IBC Transfer → ERC-20 Middleware → IBC Callbacks
// ============================================================
var transferStack porttypes.IBCModule
transferStack = transfer.NewIBCModule(app.TransferKeeper)
maxCallbackGas := uint64(1_000_000)
transferStack = erc20.NewIBCMiddleware(app.Erc20Keeper, transferStack)
app.CallbackKeeper = ibccallbackskeeper.NewKeeper(
app.AccountKeeper, app.EVMKeeper, app.Erc20Keeper,
)
transferStack = ibccallbacks.NewIBCMiddleware(
transferStack, app.IBCKeeper.ChannelKeeper, app.CallbackKeeper, maxCallbackGas,
)
var transferStackV2 ibcapi.IBCModule
transferStackV2 = transferv2.NewIBCModule(app.TransferKeeper)
transferStackV2 = erc20v2.NewIBCMiddleware(transferStackV2, app.Erc20Keeper)
// IBC Router
ibcRouter := porttypes.NewRouter()
ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack)
ibcRouterV2 := ibcapi.NewRouter()
ibcRouterV2.AddRoute(ibctransfertypes.ModuleName, transferStackV2)
app.IBCKeeper.SetRouter(ibcRouter)
app.IBCKeeper.SetRouterV2(ibcRouterV2)
// Light client
clientKeeper := app.IBCKeeper.ClientKeeper
storeProvider := app.IBCKeeper.ClientKeeper.GetStoreProvider()
tmLightClientModule := ibctm.NewLightClientModule(appCodec, storeProvider)
clientKeeper.AddRoute(ibctm.ModuleName, &tmLightClientModule)
transferModule := transfer.NewAppModule(app.TransferKeeper)
// ============================================================
// Module Manager
// ============================================================
app.ModuleManager = module.NewManager(
// Cosmos SDK modules
genutil.NewAppModule(app.AccountKeeper, app.StakingKeeper, app, app.txConfig),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, nil),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, nil),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, nil),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil, app.interfaceRegistry),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, nil),
upgrade.NewAppModule(app.UpgradeKeeper, app.AccountKeeper.AddressCodec()),
evidence.NewAppModule(app.EvidenceKeeper),
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
// IBC modules
ibc.NewAppModule(app.IBCKeeper),
ibctm.NewAppModule(tmLightClientModule),
transferModule,
// Cosmos EVM modules
vm.NewAppModule(app.EVMKeeper, app.AccountKeeper, app.BankKeeper, app.AccountKeeper.AddressCodec()),
feemarket.NewAppModule(app.FeeMarketKeeper),
erc20.NewAppModule(app.Erc20Keeper, app.AccountKeeper),
precisebank.NewAppModule(app.PreciseBankKeeper, app.BankKeeper, app.AccountKeeper),
)
// Basic module manager
app.BasicModuleManager = module.NewBasicManagerFromManager(
app.ModuleManager,
map[string]module.AppModuleBasic{
genutiltypes.ModuleName: genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
stakingtypes.ModuleName: staking.AppModuleBasic{},
govtypes.ModuleName: gov.NewAppModuleBasic(nil),
ibctransfertypes.ModuleName: transfer.AppModuleBasic{AppModuleBasic: &ibctransfer.AppModuleBasic{}},
},
)
app.BasicModuleManager.RegisterLegacyAminoCodec(legacyAmino)
app.BasicModuleManager.RegisterInterfaces(interfaceRegistry)
// Module ordering
app.ModuleManager.SetOrderPreBlockers(
upgradetypes.ModuleName,
authtypes.ModuleName,
evmtypes.ModuleName,
)
app.ModuleManager.SetOrderBeginBlockers(
minttypes.ModuleName,
ibcexported.ModuleName, ibctransfertypes.ModuleName,
erc20types.ModuleName, feemarkettypes.ModuleName,
evmtypes.ModuleName,
distrtypes.ModuleName, slashingtypes.ModuleName,
evidencetypes.ModuleName, stakingtypes.ModuleName,
authtypes.ModuleName, banktypes.ModuleName, govtypes.ModuleName, genutiltypes.ModuleName,
authz.ModuleName, feegrant.ModuleName,
consensusparamtypes.ModuleName,
precisebanktypes.ModuleName,
vestingtypes.ModuleName,
)
app.ModuleManager.SetOrderEndBlockers(
govtypes.ModuleName, stakingtypes.ModuleName,
authtypes.ModuleName, banktypes.ModuleName,
evmtypes.ModuleName, erc20types.ModuleName, feemarkettypes.ModuleName,
ibcexported.ModuleName, ibctransfertypes.ModuleName,
distrtypes.ModuleName,
slashingtypes.ModuleName, minttypes.ModuleName,
genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName,
feegrant.ModuleName, upgradetypes.ModuleName, consensusparamtypes.ModuleName,
precisebanktypes.ModuleName,
vestingtypes.ModuleName,
)
genesisModuleOrder := []string{
authtypes.ModuleName, banktypes.ModuleName,
distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName,
minttypes.ModuleName,
ibcexported.ModuleName,
evmtypes.ModuleName,
feemarkettypes.ModuleName,
erc20types.ModuleName,
precisebanktypes.ModuleName,
ibctransfertypes.ModuleName,
genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName,
feegrant.ModuleName, upgradetypes.ModuleName, vestingtypes.ModuleName,
}
app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)
app.ModuleManager.SetOrderExportGenesis(genesisModuleOrder...)
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
if err = app.ModuleManager.RegisterServices(app.configurator); err != nil {
panic(fmt.Sprintf("failed to register services: %s", err.Error()))
}
app.RegisterUpgradeHandlers()
autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules))
reflectionSvc, err := runtimeservices.NewReflectionService()
if err != nil {
panic(err)
}
reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc)
testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.QueryImpl{})
// Simulation manager
overrideModules := map[string]module.AppModuleSimulation{
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil),
}
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)
app.sm.RegisterStoreDecoders()
// Mount stores
app.MountKVStores(keys)
app.MountTransientStores(tkeys)
maxGasWanted := cast.ToUint64(appOpts.Get(srvflags.EVMMaxTxGasWanted))
// Set lifecycle handlers
app.SetInitChainer(app.InitChainer)
app.SetPreBlocker(app.PreBlocker)
app.SetBeginBlocker(app.BeginBlocker)
app.SetEndBlocker(app.EndBlocker)
app.setAnteHandler(app.txConfig, maxGasWanted)
// EVM mempool
if err := app.configureEVMMempool(appOpts, logger); err != nil {
panic(fmt.Sprintf("failed to configure EVM mempool: %s", err.Error()))
}
app.setPostHandler()
// Validate proto annotations
protoFiles, err := proto.MergedRegistry()
if err != nil {
panic(err)
}
err = msgservice.ValidateProtoAnnotations(protoFiles)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
}
if loadLatest {
if err := app.LoadLatestVersion(); err != nil {
logger.Error("error on loading last version", "err", err)
os.Exit(1)
}
}
return app
}
// setAnteHandler configures the ante handler chain including Genex compliance checks.
//
// Ante handler 链结构:
//
// TX → Genex ComplianceAnteWrapper (OFAC/TravelRule/Structuring 拦截)
// → cosmos/evm AnteHandler (签名验证/Gas计算/Nonce检查/EVM路由)
// → Mempool
//
// ComplianceAnteWrapper 在标准 ante handler 之前运行合规检查:
// - OFAC 制裁名单地址拒绝
// - Travel Rule ≥$3,000 身份数据预检查
// - Structuring 拆分交易模式检测
//
// 参考: 06-区块链开发指南.md §6 (链级合规能力) 和 §16 (验证节点级交易拦截)
func (app *GenexApp) setAnteHandler(txConfig client.TxConfig, maxGasWanted uint64) {
options := evmante.HandlerOptions{
Cdc: app.appCodec,
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
ExtensionOptionChecker: antetypes.HasDynamicFeeExtensionOption,
EvmKeeper: app.EVMKeeper,
FeegrantKeeper: app.FeeGrantKeeper,
IBCKeeper: app.IBCKeeper,
FeeMarketKeeper: app.FeeMarketKeeper,
SignModeHandler: txConfig.SignModeHandler(),
SigGasConsumer: evmante.SigVerificationGasConsumer,
MaxTxGasWanted: maxGasWanted,
DynamicFeeChecker: true,
PendingTxListener: app.onPendingTx,
}
if err := options.Validate(); err != nil {
panic(err)
}
// 标准 cosmos/evm ante handler签名/Gas/Nonce/EVM 路由)
standardHandler := evmante.NewAnteHandler(options)
// 初始化 Genex 合规检查处理器
app.ComplianceHandler = genexante.NewComplianceAnteHandler()
// 将合规检查包装在标准 handler 之前
// OFAC 名单和 Travel Rule 记录由链下 compliance-service 通过
// app.ComplianceHandler.UpdateOFACList() / RecordTravelRule() 同步
wrappedHandler := NewComplianceAnteWrapper(standardHandler, app.ComplianceHandler)
app.SetAnteHandler(wrappedHandler)
}
func (app *GenexApp) onPendingTx(hash common.Hash) {
for _, listener := range app.pendingTxListeners {
listener(hash)
}
}
// RegisterPendingTxListener registers a pending tx listener for JSON-RPC
func (app *GenexApp) RegisterPendingTxListener(listener func(common.Hash)) {
app.pendingTxListeners = append(app.pendingTxListeners, listener)
}
func (app *GenexApp) setPostHandler() {
postHandler, err := posthandler.NewPostHandler(
posthandler.HandlerOptions{},
)
if err != nil {
panic(err)
}
app.SetPostHandler(postHandler)
}
// Name returns the name of the App
func (app *GenexApp) Name() string { return app.BaseApp.Name() }
// BeginBlocker application updates every begin block
func (app *GenexApp) BeginBlocker(ctx sdk.Context) (sdk.BeginBlock, error) {
return app.ModuleManager.BeginBlock(ctx)
}
// EndBlocker application updates every end block
func (app *GenexApp) EndBlocker(ctx sdk.Context) (sdk.EndBlock, error) {
return app.ModuleManager.EndBlock(ctx)
}
// FinalizeBlock processes a block
func (app *GenexApp) FinalizeBlock(req *abci.RequestFinalizeBlock) (res *abci.ResponseFinalizeBlock, err error) {
return app.BaseApp.FinalizeBlock(req)
}
// Configurator returns the app configurator
func (app *GenexApp) Configurator() module.Configurator {
return app.configurator
}
// InitChainer application update at chain initialization
func (app *GenexApp) InitChainer(ctx sdk.Context, req *abci.RequestInitChain) (*abci.ResponseInitChain, error) {
var genesisState GenesisState
if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
panic(err)
}
if err := app.UpgradeKeeper.SetModuleVersionMap(ctx, app.ModuleManager.GetVersionMap()); err != nil {
panic(err)
}
return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState)
}
// PreBlocker runs before each block
func (app *GenexApp) PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
return app.ModuleManager.PreBlock(ctx)
}
// LoadHeight loads a particular height
func (app *GenexApp) LoadHeight(height int64) error {
return app.LoadVersion(height)
}
// LegacyAmino returns GenexApp's amino codec
func (app *GenexApp) LegacyAmino() *codec.LegacyAmino {
return app.legacyAmino
}
// AppCodec returns GenexApp's app codec
func (app *GenexApp) AppCodec() codec.Codec {
return app.appCodec
}
// InterfaceRegistry returns GenexApp's InterfaceRegistry
func (app *GenexApp) InterfaceRegistry() types.InterfaceRegistry {
return app.interfaceRegistry
}
// TxConfig returns GenexApp's TxConfig
func (app *GenexApp) TxConfig() client.TxConfig {
return app.txConfig
}
// DefaultGenesis returns default genesis with Genex customizations
func (app *GenexApp) DefaultGenesis() map[string]json.RawMessage {
genesis := app.BasicModuleManager.DefaultGenesis(app.appCodec)
// Genex: customize mint denom
mintGenState := NewMintGenesisState()
genesis[minttypes.ModuleName] = app.appCodec.MustMarshalJSON(mintGenState)
// Genex: EVM genesis with precompiles
evmGenState := NewEVMGenesisState()
genesis[evmtypes.ModuleName] = app.appCodec.MustMarshalJSON(evmGenState)
// Genex: FeeMarket genesis (NoBaseFee = true for gas subsidy)
feeMarketGenState := NewFeeMarketGenesisState()
genesis[feemarkettypes.ModuleName] = app.appCodec.MustMarshalJSON(feeMarketGenState)
return genesis
}
// GetKey returns the KVStoreKey for the provided store key
func (app *GenexApp) GetKey(storeKey string) *storetypes.KVStoreKey {
return app.keys[storeKey]
}
// GetTKey returns the TransientStoreKey for the provided store key
func (app *GenexApp) GetTKey(storeKey string) *storetypes.TransientStoreKey {
return app.tkeys[storeKey]
}
// GetMemKey returns the MemStoreKey for the provided mem key
func (app *GenexApp) GetMemKey(storeKey string) *storetypes.MemoryStoreKey {
return app.memKeys[storeKey]
}
// SimulationManager implements the SimulationApp interface
func (app *GenexApp) SimulationManager() *module.SimulationManager {
return app.sm
}
// RegisterAPIRoutes registers all application module routes
func (app *GenexApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
clientCtx := apiSvr.ClientCtx
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
cmtservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
node.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
app.BasicModuleManager.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
if err := sdkserver.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
panic(err)
}
}
// RegisterTxService implements the Application.RegisterTxService method
func (app *GenexApp) RegisterTxService(clientCtx client.Context) {
authtx.RegisterTxService(app.GRPCQueryRouter(), clientCtx, app.Simulate, app.interfaceRegistry)
}
// RegisterTendermintService implements the Application.RegisterTendermintService method
func (app *GenexApp) RegisterTendermintService(clientCtx client.Context) {
cmtservice.RegisterTendermintService(clientCtx, app.GRPCQueryRouter(), app.interfaceRegistry, app.Query)
}
// RegisterNodeService registers the node gRPC service
func (app *GenexApp) RegisterNodeService(clientCtx client.Context, cfg config.Config) {
node.RegisterNodeService(clientCtx, app.GRPCQueryRouter(), cfg)
}
// ============================================================
// IBC Testing App interface implementations
// ============================================================
func (app *GenexApp) GetBaseApp() *baseapp.BaseApp { return app.BaseApp }
func (app *GenexApp) GetStakingKeeperSDK() stakingkeeper.Keeper { return *app.StakingKeeper }
func (app *GenexApp) GetIBCKeeper() *ibckeeper.Keeper { return app.IBCKeeper }
func (app *GenexApp) GetEVMKeeper() *evmkeeper.Keeper { return app.EVMKeeper }
func (app *GenexApp) GetErc20Keeper() *erc20keeper.Keeper { return &app.Erc20Keeper }
func (app *GenexApp) SetErc20Keeper(k erc20keeper.Keeper) { app.Erc20Keeper = k }
func (app *GenexApp) GetGovKeeper() govkeeper.Keeper { return app.GovKeeper }
func (app *GenexApp) GetEvidenceKeeper() *evidencekeeper.Keeper { return &app.EvidenceKeeper }
func (app *GenexApp) GetSlashingKeeper() slashingkeeper.Keeper { return app.SlashingKeeper }
func (app *GenexApp) GetBankKeeper() bankkeeper.Keeper { return app.BankKeeper }
func (app *GenexApp) GetFeeMarketKeeper() *feemarketkeeper.Keeper { return &app.FeeMarketKeeper }
func (app *GenexApp) GetFeeGrantKeeper() feegrantkeeper.Keeper { return app.FeeGrantKeeper }
func (app *GenexApp) GetConsensusParamsKeeper() consensusparamkeeper.Keeper { return app.ConsensusParamsKeeper }
func (app *GenexApp) GetAccountKeeper() authkeeper.AccountKeeper { return app.AccountKeeper }
func (app *GenexApp) GetAuthzKeeper() authzkeeper.Keeper { return app.AuthzKeeper }
func (app *GenexApp) GetDistrKeeper() distrkeeper.Keeper { return app.DistrKeeper }
func (app *GenexApp) GetStakingKeeper() *stakingkeeper.Keeper { return app.StakingKeeper }
func (app *GenexApp) GetMintKeeper() mintkeeper.Keeper { return app.MintKeeper }
func (app *GenexApp) GetPreciseBankKeeper() *precisebankkeeper.Keeper { return &app.PreciseBankKeeper }
func (app *GenexApp) GetCallbackKeeper() ibccallbackskeeper.ContractKeeper { return app.CallbackKeeper }
func (app *GenexApp) GetTransferKeeper() transferkeeper.Keeper { return app.TransferKeeper }
func (app *GenexApp) SetTransferKeeper(k transferkeeper.Keeper) { app.TransferKeeper = k }
func (app *GenexApp) GetMempool() sdkmempool.ExtMempool { return app.EVMMempool }
func (app *GenexApp) GetAnteHandler() sdk.AnteHandler { return app.BaseApp.AnteHandler() }
func (app *GenexApp) GetTxConfig() client.TxConfig { return app.txConfig }
func (app *GenexApp) SetClientCtx(clientCtx client.Context) { app.clientCtx = clientCtx }
// Close gracefully shuts down the application
func (app *GenexApp) Close() error {
var err error
if m, ok := app.GetMempool().(*evmmempool.ExperimentalEVMMempool); ok {
app.Logger().Info("Shutting down mempool")
err = m.Close()
}
msg := "Genex Chain gracefully shutdown"
err = errors.Join(err, app.BaseApp.Close())
if err == nil {
app.Logger().Info(msg)
} else {
app.Logger().Error(msg, "error", err)
}
return err
}
// AutoCliOpts returns the autocli options for the app
func (app *GenexApp) AutoCliOpts() autocli.AppOptions {
modules := make(map[string]appmodule.AppModule, 0)
for _, m := range app.ModuleManager.Modules {
if moduleWithName, ok := m.(module.HasName); ok {
moduleName := moduleWithName.Name()
if appModule, ok := moduleWithName.(appmodule.AppModule); ok {
modules[moduleName] = appModule
}
}
}
return autocli.AppOptions{
Modules: modules,
ModuleOptions: runtimeservices.ExtractAutoCLIOptions(app.ModuleManager.Modules),
AddressCodec: evmaddress.NewEvmCodec(GenexBech32Prefix),
ValidatorAddressCodec: evmaddress.NewEvmCodec(GenexBech32Prefix + "valoper"),
ConsensusAddressCodec: evmaddress.NewEvmCodec(GenexBech32Prefix + "valcons"),
}
}