diff --git a/app/app.go b/app/app.go index 38ec7fb9c..6dcd7b145 100644 --- a/app/app.go +++ b/app/app.go @@ -209,54 +209,54 @@ func NewAxelarApp( baseAppOptions ...func(*bam.BaseApp), ) *AxelarApp { - keys := createStoreKeys() + keys := CreateStoreKeys() tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) - keepers := newKeeperCache() - setKeeper(keepers, initParamsKeeper(encodingConfig, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])) + keepers := NewKeeperCache() + SetKeeper(keepers, InitParamsKeeper(encodingConfig, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])) // BaseApp handles interactions with Tendermint through the ABCI protocol bApp := initBaseApp(db, traceStore, encodingConfig, keepers, baseAppOptions, logger) appCodec := encodingConfig.Codec - moduleAccountPermissions := initModuleAccountPermissions() + moduleAccountPermissions := InitModuleAccountPermissions() // set up predefined keepers - setKeeper(keepers, initAccountKeeper(appCodec, keys, keepers, moduleAccountPermissions)) - setKeeper(keepers, initBankKeeper(appCodec, keys, keepers, moduleAccountPermissions)) - setKeeper(keepers, initStakingKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initMintKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initDistributionKeeper(appCodec, keys, keepers, moduleAccountPermissions)) - setKeeper(keepers, initSlashingKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initCrisisKeeper(keepers, invCheckPeriod)) - setKeeper(keepers, initUpgradeKeeper(appCodec, keys, skipUpgradeHeights, homePath, bApp)) - setKeeper(keepers, initEvidenceKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initFeegrantKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initCapabilityKeeper(appCodec, keys, memKeys)) - setKeeper(keepers, initIBCKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, InitAccountKeeper(appCodec, keys, keepers, moduleAccountPermissions)) + SetKeeper(keepers, InitBankKeeper(appCodec, keys, keepers, moduleAccountPermissions)) + SetKeeper(keepers, InitStakingKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initMintKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initDistributionKeeper(appCodec, keys, keepers, moduleAccountPermissions)) + SetKeeper(keepers, initSlashingKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initCrisisKeeper(keepers, invCheckPeriod)) + SetKeeper(keepers, InitUpgradeKeeper(appCodec, keys, skipUpgradeHeights, homePath, bApp)) + SetKeeper(keepers, initEvidenceKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, InitFeegrantKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, InitCapabilityKeeper(appCodec, keys, memKeys)) + SetKeeper(keepers, InitIBCKeeper(appCodec, keys, keepers)) // set up custom axelar keepers - setKeeper(keepers, initAxelarnetKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initEvmKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initNexusKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initRewardKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initMultisigKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initTssKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initSnapshotKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initVoteKeeper(appCodec, keys, keepers)) - setKeeper(keepers, initPermissionKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, InitAxelarnetKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initEvmKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, InitNexusKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initRewardKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initMultisigKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initTssKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initSnapshotKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initVoteKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initPermissionKeeper(appCodec, keys, keepers)) // set up ibc/wasm keepers - wasmHooks := initWasmHooks(keys) - ics4Wrapper := initICS4Wrapper(keepers, wasmHooks) - setKeeper(keepers, initIBCTransferKeeper(appCodec, keys, keepers, ics4Wrapper)) + wasmHooks := InitWasmHooks(keys) + ics4Wrapper := InitICS4Wrapper(keepers, wasmHooks) + SetKeeper(keepers, initIBCTransferKeeper(appCodec, keys, keepers, ics4Wrapper)) - setKeeper(keepers, initAxelarIBCKeeper(keepers)) + SetKeeper(keepers, initAxelarIBCKeeper(keepers)) if IsWasmEnabled() { - setKeeper(keepers, initWasmKeeper(encodingConfig, keys, keepers, bApp, appOpts, wasmOpts, homePath)) - setKeeper(keepers, initWasmContractKeeper(keepers)) + SetKeeper(keepers, initWasmKeeper(encodingConfig, keys, keepers, bApp, appOpts, wasmOpts, homePath)) + SetKeeper(keepers, initWasmContractKeeper(keepers)) // set the contract keeper for the Ics20WasmHooks if wasmHooks != nil { @@ -265,7 +265,7 @@ func NewAxelarApp( } // set up governance keeper last when it has access to all other keepers to set up governance routes - setKeeper(keepers, initGovernanceKeeper(appCodec, keys, keepers)) + SetKeeper(keepers, initGovernanceKeeper(appCodec, keys, keepers)) // seal capability keeper after all keepers are set to be certain that all capabilities have been registered getKeeper[capabilitykeeper.Keeper](keepers).Seal() @@ -362,7 +362,7 @@ func NewAxelarApp( return app } -func initICS4Wrapper(keepers *keeperCache, wasmHooks *ibchooks.WasmHooks) ibchooks.ICS4Middleware { +func InitICS4Wrapper(keepers *KeeperCache, wasmHooks *ibchooks.WasmHooks) ibchooks.ICS4Middleware { // ICS4Wrapper deals with sending IBC packets. These need to get rate limited when appropriate, // so we wrap the channel keeper (which implements the ICS4Wrapper interface) with a rate limiter. ics4Wrapper := axelarnet.NewRateLimitedICS4Wrapper( @@ -371,10 +371,16 @@ func initICS4Wrapper(keepers *keeperCache, wasmHooks *ibchooks.WasmHooks) ibchoo getKeeper[axelarnetKeeper.Keeper](keepers), ) // create a middleware to integrate wasm hooks into the ibc pipeline - return ibchooks.NewICS4Middleware(ics4Wrapper, wasmHooks) + if wasmHooks != nil { + return ibchooks.NewICS4Middleware(ics4Wrapper, wasmHooks) + } else { + // we need to erase the type of the wasm hooks when it is nil so the middleware's type casts do not succeed. + // Otherwise, it will try to call an interface function on wasmHooks and create a nil pointer panic + return ibchooks.NewICS4Middleware(ics4Wrapper, nil) + } } -func initIBCMiddleware(keepers *keeperCache, ics4Middleware ibchooks.ICS4Middleware) ibchooks.IBCMiddleware { +func initIBCMiddleware(keepers *KeeperCache, ics4Middleware ibchooks.ICS4Middleware) ibchooks.IBCMiddleware { // IBCModule deals with received IBC packets. These need to get rate limited when appropriate, // so we wrap the transfer module's IBCModule with a rate limiter. ibcModule := axelarnet.NewAxelarnetIBCModule( @@ -389,7 +395,7 @@ func initIBCMiddleware(keepers *keeperCache, ics4Middleware ibchooks.ICS4Middlew return ibchooks.NewIBCMiddleware(ibcModule, &ics4Middleware) } -func initWasmHooks(keys map[string]*sdk.KVStoreKey) *ibchooks.WasmHooks { +func InitWasmHooks(keys map[string]*sdk.KVStoreKey) *ibchooks.WasmHooks { if !(IsWasmEnabled() && IsIBCWasmHooksEnabled()) { return nil } @@ -402,7 +408,7 @@ func initWasmHooks(keys map[string]*sdk.KVStoreKey) *ibchooks.WasmHooks { return &wasmHooks } -func initIBCRouter(keepers *keeperCache, axelarnetModule porttypes.IBCModule) *porttypes.Router { +func initIBCRouter(keepers *KeeperCache, axelarnetModule porttypes.IBCModule) *porttypes.Router { // Finalize the IBC router // Create static IBC router, add axelarnet module as the IBC transfer route, and seal it ibcRouter := porttypes.NewRouter() @@ -419,7 +425,7 @@ func initIBCRouter(keepers *keeperCache, axelarnetModule porttypes.IBCModule) *p return ibcRouter } -func initMessageRouter(keepers *keeperCache) nexusTypes.MessageRouter { +func initMessageRouter(keepers *KeeperCache) nexusTypes.MessageRouter { messageRouter := nexusTypes.NewMessageRouter(). AddRoute(evmTypes.ModuleName, evmKeeper.NewMessageRoute()). AddRoute(axelarnetTypes.ModuleName, axelarnetKeeper.NewMessageRoute( @@ -469,7 +475,7 @@ func (app *AxelarApp) setUpgradeBehaviour(configurator module.Configurator) { } } -func initBaseApp(db dbm.DB, traceStore io.Writer, encodingConfig axelarParams.EncodingConfig, keepers *keeperCache, baseAppOptions []func(*bam.BaseApp), logger log.Logger) *bam.BaseApp { +func initBaseApp(db dbm.DB, traceStore io.Writer, encodingConfig axelarParams.EncodingConfig, keepers *KeeperCache, baseAppOptions []func(*bam.BaseApp), logger log.Logger) *bam.BaseApp { bApp := bam.NewBaseApp(Name, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...) bApp.SetCommitMultiStoreTracer(traceStore) bApp.SetVersion(version.Version) @@ -478,7 +484,7 @@ func initBaseApp(db dbm.DB, traceStore io.Writer, encodingConfig axelarParams.En return bApp } -func initAppModules(keepers *keeperCache, bApp *bam.BaseApp, encodingConfig axelarParams.EncodingConfig, appOpts servertypes.AppOptions, axelarnetModule axelarnet.AppModule) []module.AppModule { +func initAppModules(keepers *KeeperCache, bApp *bam.BaseApp, encodingConfig axelarParams.EncodingConfig, appOpts servertypes.AppOptions, axelarnetModule axelarnet.AppModule) []module.AppModule { // NOTE: we may consider parsing `appOpts` inside module constructors. For the moment // we prefer to be more strict in what arguments the modules expect. var skipGenesisInvariants = cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants)) @@ -593,7 +599,7 @@ func mustReadWasmConfig(appOpts servertypes.AppOptions) wasmtypes.WasmConfig { return wasmConfig } -func initAnteHandlers(encodingConfig axelarParams.EncodingConfig, keys map[string]*sdk.KVStoreKey, keepers *keeperCache, appOpts servertypes.AppOptions) sdk.AnteHandler { +func initAnteHandlers(encodingConfig axelarParams.EncodingConfig, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache, appOpts servertypes.AppOptions) sdk.AnteHandler { // The baseAnteHandler handles signature verification and transaction pre-processing baseAnteHandler, err := authAnte.NewAnteHandler( authAnte.HandlerOptions{ @@ -639,7 +645,7 @@ func initAnteHandlers(encodingConfig axelarParams.EncodingConfig, keys map[strin return sdk.ChainAnteDecorators(anteDecorators...) } -func initMessageAnteDecorators(encodingConfig axelarParams.EncodingConfig, keepers *keeperCache) ante.MessageAnteHandler { +func initMessageAnteDecorators(encodingConfig axelarParams.EncodingConfig, keepers *KeeperCache) ante.MessageAnteHandler { return ante.ChainMessageAnteDecorators( ante.NewLogMsgDecorator(encodingConfig.Codec), ante.NewCheckCommissionRate(getKeeper[stakingkeeper.Keeper](keepers)), @@ -654,7 +660,7 @@ func initMessageAnteDecorators(encodingConfig axelarParams.EncodingConfig, keepe ) } -func initModuleAccountPermissions() map[string][]string { +func InitModuleAccountPermissions() map[string][]string { return map[string][]string{ authtypes.FeeCollectorName: nil, distrtypes.ModuleName: nil, @@ -860,7 +866,7 @@ func orderModulesForGenesis() []string { return genesisOrder } -func createStoreKeys() map[string]*sdk.KVStoreKey { +func CreateStoreKeys() map[string]*sdk.KVStoreKey { keys := []string{authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, diff --git a/app/app_test.go b/app/app_test.go index e066a212e..558f4689a 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -21,20 +21,34 @@ import ( func TestNewAxelarApp(t *testing.T) { version.Version = "0.27.0" - assert.NotPanics(t, func() { - app.NewAxelarApp( - log.TestingLogger(), - dbm.NewMemDB(), - nil, - true, - nil, - "", - 0, - app.MakeEncodingConfig(), - simapp.EmptyAppOptions{}, - []wasm.Option{}, - ) - }) + testCases := []struct { + wasm string + hooks string + }{ + {"false", "false"}, + {"true", "false"}, + {"true", "true"}} + + for _, testCase := range testCases { + app.WasmEnabled, app.IBCWasmHooksEnabled = testCase.wasm, testCase.hooks + + t.Run("wasm_enabled:"+testCase.wasm+"-hooks_enabled:"+testCase.hooks, func(t *testing.T) { + assert.NotPanics(t, func() { + app.NewAxelarApp( + log.TestingLogger(), + dbm.NewMemDB(), + nil, + true, + nil, + "", + 0, + app.MakeEncodingConfig(), + simapp.EmptyAppOptions{}, + []wasm.Option{}, + ) + }) + }) + } } // check that encoding is set so gogoproto extensions are supported diff --git a/app/keepers.go b/app/keepers.go index 86592cc26..94cf736de 100644 --- a/app/keepers.go +++ b/app/keepers.go @@ -74,17 +74,17 @@ import ( "github.com/axelarnetwork/utils/maps" ) -type keeperCache struct { +type KeeperCache struct { repository map[string]any } -func newKeeperCache() *keeperCache { - return &keeperCache{ +func NewKeeperCache() *KeeperCache { + return &KeeperCache{ repository: make(map[string]any), } } -func (k *keeperCache) getSubspace(moduleName string) paramstypes.Subspace { +func (k *KeeperCache) getSubspace(moduleName string) paramstypes.Subspace { paramsK := getKeeper[paramskeeper.Keeper](k) subspace, ok := paramsK.GetSubspace(moduleName) if !ok { @@ -93,7 +93,7 @@ func (k *keeperCache) getSubspace(moduleName string) paramstypes.Subspace { return subspace } -func getKeeper[T any](k *keeperCache) *T { +func getKeeper[T any](k *KeeperCache) *T { if reflect.TypeOf(*new(T)).Kind() == reflect.Ptr { panic(fmt.Sprintf("the generic parameter for %s cannot be a reference type", fullTypeName[T]())) } @@ -105,7 +105,7 @@ func getKeeper[T any](k *keeperCache) *T { return keeper } -func setKeeper[T any](k *keeperCache, keeper T) { +func SetKeeper[T any](k *KeeperCache, keeper T) { if reflect.TypeOf(keeper).Kind() != reflect.Ptr { panic(fmt.Sprintf("keeper %s must be a reference type", fullTypeName[T]())) } @@ -123,7 +123,7 @@ func fullTypeName[T any]() string { return keeperType.PkgPath() + "." + keeperType.Name() } -func initParamsKeeper(encodingConfig axelarParams.EncodingConfig, key, tkey sdk.StoreKey) *paramskeeper.Keeper { +func InitParamsKeeper(encodingConfig axelarParams.EncodingConfig, key, tkey sdk.StoreKey) *paramskeeper.Keeper { paramsKeeper := paramskeeper.NewKeeper(encodingConfig.Codec, encodingConfig.Amino, key, tkey) paramsKeeper.Subspace(bam.Paramspace).WithKeyTable(paramskeeper.ConsensusParamsKeyTable()) @@ -151,7 +151,7 @@ func initParamsKeeper(encodingConfig axelarParams.EncodingConfig, key, tkey sdk. return ¶msKeeper } -func initStakingKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *stakingkeeper.Keeper { +func InitStakingKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *stakingkeeper.Keeper { stakingK := stakingkeeper.NewKeeper( appCodec, keys[stakingtypes.StoreKey], @@ -162,7 +162,7 @@ func initStakingKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, ke return &stakingK } -func initWasmKeeper(encodingConfig axelarParams.EncodingConfig, keys map[string]*sdk.KVStoreKey, keepers *keeperCache, bApp *bam.BaseApp, appOpts types.AppOptions, wasmOpts []wasm.Option, homePath string) *wasm.Keeper { +func initWasmKeeper(encodingConfig axelarParams.EncodingConfig, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache, bApp *bam.BaseApp, appOpts types.AppOptions, wasmOpts []wasm.Option, homePath string) *wasm.Keeper { wasmDir := filepath.Join(homePath, "wasm") wasmConfig := mustReadWasmConfig(appOpts) @@ -206,7 +206,7 @@ func initWasmKeeper(encodingConfig axelarParams.EncodingConfig, keys map[string] return &wasmK } -func initGovernanceKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *govkeeper.Keeper { +func initGovernanceKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *govkeeper.Keeper { // Add governance proposal hooks govRouter := govtypes.NewRouter() govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). @@ -230,12 +230,12 @@ func initGovernanceKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, return &govK } -func initPermissionKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *permissionKeeper.Keeper { +func initPermissionKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *permissionKeeper.Keeper { permissionK := permissionKeeper.NewKeeper(appCodec, keys[permissionTypes.StoreKey], keepers.getSubspace(permissionTypes.ModuleName)) return &permissionK } -func initVoteKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *voteKeeper.Keeper { +func initVoteKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *voteKeeper.Keeper { voteRouter := voteTypes.NewRouter() voteRouter.AddHandler( evmTypes.ModuleName, @@ -259,7 +259,7 @@ func initVoteKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepe return &voteK } -func initSnapshotKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *snapKeeper.Keeper { +func initSnapshotKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *snapKeeper.Keeper { snapK := snapKeeper.NewKeeper( appCodec, keys[snapTypes.StoreKey], @@ -271,12 +271,12 @@ func initSnapshotKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, k return &snapK } -func initTssKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *tssKeeper.Keeper { +func initTssKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *tssKeeper.Keeper { tssK := tssKeeper.NewKeeper(appCodec, keys[tssTypes.StoreKey], keepers.getSubspace(tssTypes.ModuleName)) return &tssK } -func initMultisigKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *multisigKeeper.Keeper { +func initMultisigKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *multisigKeeper.Keeper { multisigRouter := multisigTypes.NewSigRouter() multisigRouter.AddHandler(evmTypes.ModuleName, evmKeeper.NewSigHandler(appCodec, getKeeper[evmKeeper.BaseKeeper](keepers))) @@ -285,7 +285,7 @@ func initMultisigKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, k return &multisigK } -func initRewardKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *rewardKeeper.Keeper { +func initRewardKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *rewardKeeper.Keeper { rewardK := rewardKeeper.NewKeeper( appCodec, keys[rewardTypes.StoreKey], @@ -297,7 +297,7 @@ func initRewardKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, kee return &rewardK } -func initIBCKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *ibckeeper.Keeper { +func InitIBCKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *ibckeeper.Keeper { scopedIBCK := getKeeper[capabilitykeeper.Keeper](keepers).ScopeToModule(ibchost.ModuleName) return ibckeeper.NewKeeper( appCodec, @@ -309,7 +309,7 @@ func initIBCKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keeper ) } -func initIBCTransferKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache, ics4Wrapper ibctransfertypes.ICS4Wrapper) *ibctransferkeeper.Keeper { +func initIBCTransferKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache, ics4Wrapper ibctransfertypes.ICS4Wrapper) *ibctransferkeeper.Keeper { scopedTransferK := getKeeper[capabilitykeeper.Keeper](keepers).ScopeToModule(ibctransfertypes.ModuleName) transferK := ibctransferkeeper.NewKeeper( appCodec, keys[ibctransfertypes.StoreKey], keepers.getSubspace(ibctransfertypes.ModuleName), @@ -321,16 +321,16 @@ func initIBCTransferKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey return &transferK } -func initWasmContractKeeper(keepers *keeperCache) *wasmkeeper.PermissionedKeeper { +func initWasmContractKeeper(keepers *KeeperCache) *wasmkeeper.PermissionedKeeper { return wasmkeeper.NewDefaultPermissionKeeper(getKeeper[wasm.Keeper](keepers)) } -func initAxelarIBCKeeper(keepers *keeperCache) *axelarnetKeeper.IBCKeeper { +func initAxelarIBCKeeper(keepers *KeeperCache) *axelarnetKeeper.IBCKeeper { ibcK := axelarnetKeeper.NewIBCKeeper(*getKeeper[axelarnetKeeper.Keeper](keepers), getKeeper[ibctransferkeeper.Keeper](keepers)) return &ibcK } -func initAxelarnetKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *axelarnetKeeper.Keeper { +func InitAxelarnetKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *axelarnetKeeper.Keeper { axelarnetK := axelarnetKeeper.NewKeeper( appCodec, keys[axelarnetTypes.StoreKey], @@ -341,11 +341,11 @@ func initAxelarnetKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, return &axelarnetK } -func initEvmKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *evmKeeper.BaseKeeper { +func initEvmKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *evmKeeper.BaseKeeper { return evmKeeper.NewKeeper(appCodec, keys[evmTypes.StoreKey], getKeeper[paramskeeper.Keeper](keepers)) } -func initNexusKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *nexusKeeper.Keeper { +func InitNexusKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *nexusKeeper.Keeper { // setting validator will finalize all by sealing it // no more validators can be added addressValidators := nexusTypes.NewAddressValidators(). @@ -359,20 +359,20 @@ func initNexusKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keep return &nexusK } -func initCapabilityKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, memKeys map[string]*sdk.MemoryStoreKey) *capabilitykeeper.Keeper { +func InitCapabilityKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, memKeys map[string]*sdk.MemoryStoreKey) *capabilitykeeper.Keeper { return capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey]) } -func initFeegrantKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *feegrantkeeper.Keeper { +func InitFeegrantKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *feegrantkeeper.Keeper { feegrantK := feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], getKeeper[authkeeper.AccountKeeper](keepers)) return &feegrantK } -func initEvidenceKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *evidencekeeper.Keeper { +func initEvidenceKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *evidencekeeper.Keeper { return evidencekeeper.NewKeeper(appCodec, keys[evidencetypes.StoreKey], getKeeper[stakingkeeper.Keeper](keepers), getKeeper[slashingkeeper.Keeper](keepers)) } -func initUpgradeKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, skipUpgradeHeights map[int64]bool, homePath string, bApp *bam.BaseApp) *upgradekeeper.Keeper { +func InitUpgradeKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, skipUpgradeHeights map[int64]bool, homePath string, bApp *bam.BaseApp) *upgradekeeper.Keeper { upgradeK := upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, bApp) return &upgradeK } @@ -388,7 +388,7 @@ func upgradeName(version string) string { return name } -func initCrisisKeeper(keepers *keeperCache, invCheckPeriod uint) *crisiskeeper.Keeper { +func initCrisisKeeper(keepers *KeeperCache, invCheckPeriod uint) *crisiskeeper.Keeper { crisisK := crisiskeeper.NewKeeper( keepers.getSubspace(crisistypes.ModuleName), invCheckPeriod, @@ -398,12 +398,12 @@ func initCrisisKeeper(keepers *keeperCache, invCheckPeriod uint) *crisiskeeper.K return &crisisK } -func initSlashingKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *slashingkeeper.Keeper { +func initSlashingKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *slashingkeeper.Keeper { slashK := slashingkeeper.NewKeeper(appCodec, keys[slashingtypes.StoreKey], getKeeper[stakingkeeper.Keeper](keepers), keepers.getSubspace(slashingtypes.ModuleName)) return &slashK } -func initDistributionKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache, moduleAccPerms map[string][]string) *distrkeeper.Keeper { +func initDistributionKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache, moduleAccPerms map[string][]string) *distrkeeper.Keeper { distrK := distrkeeper.NewKeeper( appCodec, keys[distrtypes.StoreKey], @@ -417,7 +417,7 @@ func initDistributionKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKe return &distrK } -func initMintKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache) *mintkeeper.Keeper { +func initMintKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache) *mintkeeper.Keeper { mintK := mintkeeper.NewKeeper( appCodec, keys[minttypes.StoreKey], @@ -430,7 +430,7 @@ func initMintKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepe return &mintK } -func initBankKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache, moduleAccPerms map[string][]string) *bankkeeper.BaseKeeper { +func InitBankKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache, moduleAccPerms map[string][]string) *bankkeeper.BaseKeeper { bankK := bankkeeper.NewBaseKeeper( appCodec, keys[banktypes.StoreKey], @@ -447,7 +447,7 @@ func initBankKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepe return &bankK } -func initAccountKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *keeperCache, moduleAccPerms map[string][]string) *authkeeper.AccountKeeper { +func InitAccountKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepers *KeeperCache, moduleAccPerms map[string][]string) *authkeeper.AccountKeeper { authK := authkeeper.NewAccountKeeper( appCodec, keys[authtypes.StoreKey], diff --git a/app/mock/ibchooks.go b/app/mock/ibchooks.go new file mode 100644 index 000000000..cbbe70fcf --- /dev/null +++ b/app/mock/ibchooks.go @@ -0,0 +1,365 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package mock + +import ( + "github.com/axelarnetwork/axelar-core/app" + ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" + "sync" +) + +// Ensure, that PacketIMock does implement app.PacketI. +// If this is not the case, regenerate this file with moq. +var _ app.PacketI = &PacketIMock{} + +// PacketIMock is a mock implementation of app.PacketI. +// +// func TestSomethingThatUsesPacketI(t *testing.T) { +// +// // make and configure a mocked app.PacketI +// mockedPacketI := &PacketIMock{ +// GetDataFunc: func() []byte { +// panic("mock out the GetData method") +// }, +// GetDestChannelFunc: func() string { +// panic("mock out the GetDestChannel method") +// }, +// GetDestPortFunc: func() string { +// panic("mock out the GetDestPort method") +// }, +// GetSequenceFunc: func() uint64 { +// panic("mock out the GetSequence method") +// }, +// GetSourceChannelFunc: func() string { +// panic("mock out the GetSourceChannel method") +// }, +// GetSourcePortFunc: func() string { +// panic("mock out the GetSourcePort method") +// }, +// GetTimeoutHeightFunc: func() ibcexported.Height { +// panic("mock out the GetTimeoutHeight method") +// }, +// GetTimeoutTimestampFunc: func() uint64 { +// panic("mock out the GetTimeoutTimestamp method") +// }, +// ValidateBasicFunc: func() error { +// panic("mock out the ValidateBasic method") +// }, +// } +// +// // use mockedPacketI in code that requires app.PacketI +// // and then make assertions. +// +// } +type PacketIMock struct { + // GetDataFunc mocks the GetData method. + GetDataFunc func() []byte + + // GetDestChannelFunc mocks the GetDestChannel method. + GetDestChannelFunc func() string + + // GetDestPortFunc mocks the GetDestPort method. + GetDestPortFunc func() string + + // GetSequenceFunc mocks the GetSequence method. + GetSequenceFunc func() uint64 + + // GetSourceChannelFunc mocks the GetSourceChannel method. + GetSourceChannelFunc func() string + + // GetSourcePortFunc mocks the GetSourcePort method. + GetSourcePortFunc func() string + + // GetTimeoutHeightFunc mocks the GetTimeoutHeight method. + GetTimeoutHeightFunc func() ibcexported.Height + + // GetTimeoutTimestampFunc mocks the GetTimeoutTimestamp method. + GetTimeoutTimestampFunc func() uint64 + + // ValidateBasicFunc mocks the ValidateBasic method. + ValidateBasicFunc func() error + + // calls tracks calls to the methods. + calls struct { + // GetData holds details about calls to the GetData method. + GetData []struct { + } + // GetDestChannel holds details about calls to the GetDestChannel method. + GetDestChannel []struct { + } + // GetDestPort holds details about calls to the GetDestPort method. + GetDestPort []struct { + } + // GetSequence holds details about calls to the GetSequence method. + GetSequence []struct { + } + // GetSourceChannel holds details about calls to the GetSourceChannel method. + GetSourceChannel []struct { + } + // GetSourcePort holds details about calls to the GetSourcePort method. + GetSourcePort []struct { + } + // GetTimeoutHeight holds details about calls to the GetTimeoutHeight method. + GetTimeoutHeight []struct { + } + // GetTimeoutTimestamp holds details about calls to the GetTimeoutTimestamp method. + GetTimeoutTimestamp []struct { + } + // ValidateBasic holds details about calls to the ValidateBasic method. + ValidateBasic []struct { + } + } + lockGetData sync.RWMutex + lockGetDestChannel sync.RWMutex + lockGetDestPort sync.RWMutex + lockGetSequence sync.RWMutex + lockGetSourceChannel sync.RWMutex + lockGetSourcePort sync.RWMutex + lockGetTimeoutHeight sync.RWMutex + lockGetTimeoutTimestamp sync.RWMutex + lockValidateBasic sync.RWMutex +} + +// GetData calls GetDataFunc. +func (mock *PacketIMock) GetData() []byte { + if mock.GetDataFunc == nil { + panic("PacketIMock.GetDataFunc: method is nil but PacketI.GetData was just called") + } + callInfo := struct { + }{} + mock.lockGetData.Lock() + mock.calls.GetData = append(mock.calls.GetData, callInfo) + mock.lockGetData.Unlock() + return mock.GetDataFunc() +} + +// GetDataCalls gets all the calls that were made to GetData. +// Check the length with: +// +// len(mockedPacketI.GetDataCalls()) +func (mock *PacketIMock) GetDataCalls() []struct { +} { + var calls []struct { + } + mock.lockGetData.RLock() + calls = mock.calls.GetData + mock.lockGetData.RUnlock() + return calls +} + +// GetDestChannel calls GetDestChannelFunc. +func (mock *PacketIMock) GetDestChannel() string { + if mock.GetDestChannelFunc == nil { + panic("PacketIMock.GetDestChannelFunc: method is nil but PacketI.GetDestChannel was just called") + } + callInfo := struct { + }{} + mock.lockGetDestChannel.Lock() + mock.calls.GetDestChannel = append(mock.calls.GetDestChannel, callInfo) + mock.lockGetDestChannel.Unlock() + return mock.GetDestChannelFunc() +} + +// GetDestChannelCalls gets all the calls that were made to GetDestChannel. +// Check the length with: +// +// len(mockedPacketI.GetDestChannelCalls()) +func (mock *PacketIMock) GetDestChannelCalls() []struct { +} { + var calls []struct { + } + mock.lockGetDestChannel.RLock() + calls = mock.calls.GetDestChannel + mock.lockGetDestChannel.RUnlock() + return calls +} + +// GetDestPort calls GetDestPortFunc. +func (mock *PacketIMock) GetDestPort() string { + if mock.GetDestPortFunc == nil { + panic("PacketIMock.GetDestPortFunc: method is nil but PacketI.GetDestPort was just called") + } + callInfo := struct { + }{} + mock.lockGetDestPort.Lock() + mock.calls.GetDestPort = append(mock.calls.GetDestPort, callInfo) + mock.lockGetDestPort.Unlock() + return mock.GetDestPortFunc() +} + +// GetDestPortCalls gets all the calls that were made to GetDestPort. +// Check the length with: +// +// len(mockedPacketI.GetDestPortCalls()) +func (mock *PacketIMock) GetDestPortCalls() []struct { +} { + var calls []struct { + } + mock.lockGetDestPort.RLock() + calls = mock.calls.GetDestPort + mock.lockGetDestPort.RUnlock() + return calls +} + +// GetSequence calls GetSequenceFunc. +func (mock *PacketIMock) GetSequence() uint64 { + if mock.GetSequenceFunc == nil { + panic("PacketIMock.GetSequenceFunc: method is nil but PacketI.GetSequence was just called") + } + callInfo := struct { + }{} + mock.lockGetSequence.Lock() + mock.calls.GetSequence = append(mock.calls.GetSequence, callInfo) + mock.lockGetSequence.Unlock() + return mock.GetSequenceFunc() +} + +// GetSequenceCalls gets all the calls that were made to GetSequence. +// Check the length with: +// +// len(mockedPacketI.GetSequenceCalls()) +func (mock *PacketIMock) GetSequenceCalls() []struct { +} { + var calls []struct { + } + mock.lockGetSequence.RLock() + calls = mock.calls.GetSequence + mock.lockGetSequence.RUnlock() + return calls +} + +// GetSourceChannel calls GetSourceChannelFunc. +func (mock *PacketIMock) GetSourceChannel() string { + if mock.GetSourceChannelFunc == nil { + panic("PacketIMock.GetSourceChannelFunc: method is nil but PacketI.GetSourceChannel was just called") + } + callInfo := struct { + }{} + mock.lockGetSourceChannel.Lock() + mock.calls.GetSourceChannel = append(mock.calls.GetSourceChannel, callInfo) + mock.lockGetSourceChannel.Unlock() + return mock.GetSourceChannelFunc() +} + +// GetSourceChannelCalls gets all the calls that were made to GetSourceChannel. +// Check the length with: +// +// len(mockedPacketI.GetSourceChannelCalls()) +func (mock *PacketIMock) GetSourceChannelCalls() []struct { +} { + var calls []struct { + } + mock.lockGetSourceChannel.RLock() + calls = mock.calls.GetSourceChannel + mock.lockGetSourceChannel.RUnlock() + return calls +} + +// GetSourcePort calls GetSourcePortFunc. +func (mock *PacketIMock) GetSourcePort() string { + if mock.GetSourcePortFunc == nil { + panic("PacketIMock.GetSourcePortFunc: method is nil but PacketI.GetSourcePort was just called") + } + callInfo := struct { + }{} + mock.lockGetSourcePort.Lock() + mock.calls.GetSourcePort = append(mock.calls.GetSourcePort, callInfo) + mock.lockGetSourcePort.Unlock() + return mock.GetSourcePortFunc() +} + +// GetSourcePortCalls gets all the calls that were made to GetSourcePort. +// Check the length with: +// +// len(mockedPacketI.GetSourcePortCalls()) +func (mock *PacketIMock) GetSourcePortCalls() []struct { +} { + var calls []struct { + } + mock.lockGetSourcePort.RLock() + calls = mock.calls.GetSourcePort + mock.lockGetSourcePort.RUnlock() + return calls +} + +// GetTimeoutHeight calls GetTimeoutHeightFunc. +func (mock *PacketIMock) GetTimeoutHeight() ibcexported.Height { + if mock.GetTimeoutHeightFunc == nil { + panic("PacketIMock.GetTimeoutHeightFunc: method is nil but PacketI.GetTimeoutHeight was just called") + } + callInfo := struct { + }{} + mock.lockGetTimeoutHeight.Lock() + mock.calls.GetTimeoutHeight = append(mock.calls.GetTimeoutHeight, callInfo) + mock.lockGetTimeoutHeight.Unlock() + return mock.GetTimeoutHeightFunc() +} + +// GetTimeoutHeightCalls gets all the calls that were made to GetTimeoutHeight. +// Check the length with: +// +// len(mockedPacketI.GetTimeoutHeightCalls()) +func (mock *PacketIMock) GetTimeoutHeightCalls() []struct { +} { + var calls []struct { + } + mock.lockGetTimeoutHeight.RLock() + calls = mock.calls.GetTimeoutHeight + mock.lockGetTimeoutHeight.RUnlock() + return calls +} + +// GetTimeoutTimestamp calls GetTimeoutTimestampFunc. +func (mock *PacketIMock) GetTimeoutTimestamp() uint64 { + if mock.GetTimeoutTimestampFunc == nil { + panic("PacketIMock.GetTimeoutTimestampFunc: method is nil but PacketI.GetTimeoutTimestamp was just called") + } + callInfo := struct { + }{} + mock.lockGetTimeoutTimestamp.Lock() + mock.calls.GetTimeoutTimestamp = append(mock.calls.GetTimeoutTimestamp, callInfo) + mock.lockGetTimeoutTimestamp.Unlock() + return mock.GetTimeoutTimestampFunc() +} + +// GetTimeoutTimestampCalls gets all the calls that were made to GetTimeoutTimestamp. +// Check the length with: +// +// len(mockedPacketI.GetTimeoutTimestampCalls()) +func (mock *PacketIMock) GetTimeoutTimestampCalls() []struct { +} { + var calls []struct { + } + mock.lockGetTimeoutTimestamp.RLock() + calls = mock.calls.GetTimeoutTimestamp + mock.lockGetTimeoutTimestamp.RUnlock() + return calls +} + +// ValidateBasic calls ValidateBasicFunc. +func (mock *PacketIMock) ValidateBasic() error { + if mock.ValidateBasicFunc == nil { + panic("PacketIMock.ValidateBasicFunc: method is nil but PacketI.ValidateBasic was just called") + } + callInfo := struct { + }{} + mock.lockValidateBasic.Lock() + mock.calls.ValidateBasic = append(mock.calls.ValidateBasic, callInfo) + mock.lockValidateBasic.Unlock() + return mock.ValidateBasicFunc() +} + +// ValidateBasicCalls gets all the calls that were made to ValidateBasic. +// Check the length with: +// +// len(mockedPacketI.ValidateBasicCalls()) +func (mock *PacketIMock) ValidateBasicCalls() []struct { +} { + var calls []struct { + } + mock.lockValidateBasic.RLock() + calls = mock.calls.ValidateBasic + mock.lockValidateBasic.RUnlock() + return calls +} diff --git a/app/wasm.go b/app/wasm.go index 1b10bd8d7..4ba22a2f7 100644 --- a/app/wasm.go +++ b/app/wasm.go @@ -10,11 +10,16 @@ import ( wasmvmtypes "github.com/CosmWasm/wasmvm/types" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" "golang.org/x/exp/maps" "github.com/axelarnetwork/axelar-core/x/ante" ) +//go:generate moq -pkg mock -out ./mock/ibchooks.go . PacketI + +type PacketI ibcexported.PacketI + type AnteHandlerMessenger struct { anteHandle ante.MessageAnteHandler encoders wasm.MessageEncoders diff --git a/app/wasm_test.go b/app/wasm_test.go index 2c5f530e3..a8fbbac4b 100644 --- a/app/wasm_test.go +++ b/app/wasm_test.go @@ -10,9 +10,15 @@ import ( wasmvmtypes "github.com/CosmWasm/wasmvm/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/stretchr/testify/assert" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/axelarnetwork/axelar-core/app" + "github.com/axelarnetwork/axelar-core/app/mock" + "github.com/axelarnetwork/axelar-core/testutils/fake" . "github.com/axelarnetwork/utils/test" ) @@ -250,3 +256,58 @@ func TestNewWasmAppModuleBasicOverride(t *testing.T) { assert.True(t, state.Params.CodeUploadAccess.Allowed(uploader)) assert.Len(t, state.Params.CodeUploadAccess.AllAuthorizedAddresses(), 1) } + +func TestICSMiddleWare(t *testing.T) { + encodingConfig := app.MakeEncodingConfig() + appCodec := encodingConfig.Codec + + keys := app.CreateStoreKeys() + tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) + memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) + moduleAccountPermissions := app.InitModuleAccountPermissions() + + testCases := []struct { + wasm string + hooks string + }{ + {"false", "false"}, + {"true", "false"}, + {"true", "true"}} + + for _, testCase := range testCases { + t.Run("wasm_enabled:"+testCase.wasm+"-hooks_enabled:"+testCase.hooks, func(t *testing.T) { + app.WasmEnabled, app.IBCWasmHooksEnabled = testCase.wasm, testCase.hooks + + keepers := app.NewKeeperCache() + app.SetKeeper(keepers, app.InitParamsKeeper(encodingConfig, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])) + app.SetKeeper(keepers, app.InitAccountKeeper(appCodec, keys, keepers, moduleAccountPermissions)) + app.SetKeeper(keepers, app.InitBankKeeper(appCodec, keys, keepers, moduleAccountPermissions)) + app.SetKeeper(keepers, app.InitStakingKeeper(appCodec, keys, keepers)) + app.SetKeeper(keepers, app.InitCapabilityKeeper(appCodec, keys, memKeys)) + app.SetKeeper(keepers, app.InitUpgradeKeeper(appCodec, keys, nil, "home", nil)) + app.SetKeeper(keepers, app.InitIBCKeeper(appCodec, keys, keepers)) + app.SetKeeper(keepers, app.InitFeegrantKeeper(appCodec, keys, keepers)) + app.SetKeeper(keepers, app.InitAxelarnetKeeper(appCodec, keys, keepers)) + app.SetKeeper(keepers, app.InitNexusKeeper(appCodec, keys, keepers)) + + // this is the focus of the test, we need to ensure that the hooks and wrapper are correctly set up for each valid wasm/hooks flag combination + wasmHooks := app.InitWasmHooks(keys) + ics4Wrapper := app.InitICS4Wrapper(keepers, wasmHooks) + + ctx := sdk.NewContext(fake.NewMultiStore(), tmproto.Header{}, false, log.TestingLogger()) + packet := &mock.PacketIMock{ + ValidateBasicFunc: func() error { return nil }, + GetSourcePortFunc: func() string { return "source port" }, + GetSourceChannelFunc: func() string { return "source channel" }, + GetDestPortFunc: func() string { return "destination port" }, + GetDestChannelFunc: func() string { return "destination channel" }, + } + + // these must not panic and return an error unrelated to the wasm hook + assert.ErrorContains(t, ics4Wrapper.SendPacket(ctx, nil, packet), "channel: channel not found") + assert.ErrorContains(t, ics4Wrapper.WriteAcknowledgement(ctx, nil, packet, nil), "channel: channel not found") + _, ok := ics4Wrapper.GetAppVersion(ctx, "port", "channel") + assert.False(t, ok) + }) + } +}