// 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"), } }