From fe9cc81e165ca8740238f6d25a8ca883aa4b20d7 Mon Sep 17 00:00:00 2001 From: Andrey Kobrin Date: Mon, 26 Jan 2026 12:13:28 -0500 Subject: [PATCH 1/5] v1.10.0: upgrade Cosmos SDK to v0.53.5 with IBC v10.5.0 + Wasm 0.61.6 --- .github/actions/install-wasmvm/action.yml | 2 +- .github/workflows/release.yml | 2 +- Makefile | 2 +- app/app.go | 21 +- app/app_config.go | 13 +- app/export.go | 3 +- app/ibc.go | 14 +- app/options.go | 7 +- app/sim_bench_test.go | 21 +- app/test_helpers.go | 22 +- app/upgrades/params/params.go | 8 +- app/upgrades/upgrades.go | 32 +- app/upgrades/upgrades_test.go | 12 +- app/upgrades/v1_10_0/store.go | 11 + app/upgrades/v1_10_0/upgrade.go | 52 + app/wasm.go | 8 +- config/config.go | 3 + devnet/go.mod | 46 +- devnet/go.sum | 138 +- docs/lumeraid/ibc.md | 259 +--- docs/upgrade.md | 84 ++ go.mod | 102 +- go.sum | 225 +-- tests/ibctesting/events.go | 39 - tests/ibctesting/events_test.go | 182 ++- tests/ibctesting/mock/ibcmodule.go | 24 +- tests/ibctesting/mock/mock_callbacks.go | 20 +- tests/ibctesting/mock/v2/ibc_app.go | 14 + tests/ibctesting/mock/v2/ibc_module.go | 72 + tests/ibctesting/mock/v2/mock.go | 37 + tests/ibctesting/wasm.go | 14 +- tests/integration/staking/unbonding_test.go | 2 +- .../update_params_integration_test.go | 5 +- tests/integration/wasm/common_test.go | 9 +- tests/integration/wasm/genesis_test.go | 103 ++ .../integration/wasm/ibc_integration_test.go | 4 +- .../wasm/migrations_integration_test.go | 128 ++ tests/integration/wasm/module_test.go | 670 +++++++++ .../wasm/msg_server_integration_test.go | 1224 +++++++++++++++++ .../wasm/query_plugin_integration_test.go | 28 +- .../wasm/snapshotter_integration_test.go | 141 ++ tests/systemtests/go.mod | 79 +- tests/systemtests/go.sum | 154 ++- tests/testdata/escrow_0.7.wasm | Bin 0 -> 91577 bytes tests/testdata/ibc2.wasm | Bin 267602 -> 383624 bytes tests/testdata/ibc_callbacks.wasm | Bin 231737 -> 311144 bytes x/lumeraid/module/depinject.go | 73 + x/lumeraid/module/module.go | 62 - 48 files changed, 3337 insertions(+), 834 deletions(-) create mode 100644 app/upgrades/v1_10_0/store.go create mode 100644 app/upgrades/v1_10_0/upgrade.go create mode 100644 docs/upgrade.md create mode 100644 tests/ibctesting/mock/v2/ibc_app.go create mode 100644 tests/ibctesting/mock/v2/ibc_module.go create mode 100644 tests/ibctesting/mock/v2/mock.go create mode 100644 tests/integration/wasm/genesis_test.go create mode 100644 tests/integration/wasm/migrations_integration_test.go create mode 100644 tests/integration/wasm/module_test.go create mode 100644 tests/integration/wasm/msg_server_integration_test.go create mode 100644 tests/integration/wasm/snapshotter_integration_test.go create mode 100644 tests/testdata/escrow_0.7.wasm create mode 100644 x/lumeraid/module/depinject.go diff --git a/.github/actions/install-wasmvm/action.yml b/.github/actions/install-wasmvm/action.yml index 7e2f8076..acfd9489 100644 --- a/.github/actions/install-wasmvm/action.yml +++ b/.github/actions/install-wasmvm/action.yml @@ -5,7 +5,7 @@ inputs: description: Path to the Makefile containing WASMVM_VERSION default: Makefile version: - description: Override wasmvm version (e.g. v3.0.0-ibc2.0) + description: Override wasmvm version (e.g. v3.0.2) required: false outputs: version: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cbd79c92..abd4cc86 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6.0.1 with: fetch-depth: 0 diff --git a/Makefile b/Makefile index 481897a2..821b125a 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ IGNITE_INSTALL_SCRIPT ?= https://get.ignite.com/cli! GOFLAGS = "-trimpath" -WASMVM_VERSION := v3@v3.0.0-ibc2.0 +WASMVM_VERSION := v3@v3.0.2 RELEASE_CGO_LDFLAGS ?= -Wl,-rpath,/usr/lib -Wl,--disable-new-dtags COSMOS_PROTO_VERSION := $(call module_version,github.com/cosmos/cosmos-proto) GOGOPROTO_VERSION := $(call module_version,github.com/cosmos/gogoproto) diff --git a/app/app.go b/app/app.go index 2abad273..ce049728 100644 --- a/app/app.go +++ b/app/app.go @@ -35,6 +35,7 @@ import ( servertypes "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/auth" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" @@ -47,8 +48,6 @@ import ( bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" _ "github.com/cosmos/cosmos-sdk/x/consensus" // import for side-effects consensuskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" - _ "github.com/cosmos/cosmos-sdk/x/crisis" // import for side-effects - crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper" _ "github.com/cosmos/cosmos-sdk/x/distribution" // import for side-effects distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" "github.com/cosmos/cosmos-sdk/x/genutil" @@ -129,7 +128,6 @@ type App struct { AuthzKeeper authzkeeper.Keeper ConsensusParamsKeeper consensuskeeper.Keeper CircuitBreakerKeeper circuitkeeper.Keeper - CrisisKeeper *crisiskeeper.Keeper ParamsKeeper paramskeeper.Keeper EvidenceKeeper evidencekeeper.Keeper FeeGrantKeeper feegrantkeeper.Keeper @@ -240,7 +238,6 @@ func New( &app.MintKeeper, &app.DistrKeeper, &app.GovKeeper, - &app.CrisisKeeper, &app.UpgradeKeeper, &app.ParamsKeeper, &app.AuthzKeeper, @@ -264,6 +261,7 @@ func New( // build app app.App = appBuilder.Build(db, traceStore, baseAppOptions...) + app.SetVersion(version.Version) // register legacy modules if err := app.registerIBCModules(appOpts, wasmOpts...); err != nil { @@ -280,7 +278,6 @@ func New( app.setupUpgrades() /**** Module Options ****/ - app.ModuleManager.RegisterInvariants(app.CrisisKeeper) // create the simulation manager and define the order of the modules for deterministic simulations overrideModules := map[string]module.AppModuleSimulation{ @@ -324,12 +321,14 @@ func (app *App) GetSubspace(moduleName string) paramstypes.Subspace { // This needs to be called BEFORE app.Load() func (app *App) setupUpgrades() { params := appParams.AppUpgradeParams{ - ChainID: app.ChainID(), - Logger: app.Logger(), - ModuleManager: app.ModuleManager, - Configurator: app.Configurator(), - ActionKeeper: &app.ActionKeeper, - SupernodeKeeper: app.SupernodeKeeper, + ChainID: app.ChainID(), + Logger: app.Logger(), + ModuleManager: app.ModuleManager, + Configurator: app.Configurator(), + ActionKeeper: &app.ActionKeeper, + SupernodeKeeper: app.SupernodeKeeper, + ParamsKeeper: &app.ParamsKeeper, + ConsensusParamsKeeper: &app.ConsensusParamsKeeper, } allUpgrades := upgrades.AllUpgrades(params) diff --git a/app/app_config.go b/app/app_config.go index ac883ea9..f05f509e 100644 --- a/app/app_config.go +++ b/app/app_config.go @@ -14,7 +14,6 @@ import ( bankmodulev1 "cosmossdk.io/api/cosmos/bank/module/v1" circuitmodulev1 "cosmossdk.io/api/cosmos/circuit/module/v1" consensusmodulev1 "cosmossdk.io/api/cosmos/consensus/module/v1" - crisismodulev1 "cosmossdk.io/api/cosmos/crisis/module/v1" distrmodulev1 "cosmossdk.io/api/cosmos/distribution/module/v1" evidencemodulev1 "cosmossdk.io/api/cosmos/evidence/module/v1" feegrantmodulev1 "cosmossdk.io/api/cosmos/feegrant/module/v1" @@ -54,8 +53,6 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" _ "github.com/cosmos/cosmos-sdk/x/consensus" // import for side-effects consensustypes "github.com/cosmos/cosmos-sdk/x/consensus/types" - _ "github.com/cosmos/cosmos-sdk/x/crisis" // import for side-effects - crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" _ "github.com/cosmos/cosmos-sdk/x/distribution" // import for side-effects distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" @@ -99,7 +96,6 @@ var ( slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, - crisistypes.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, @@ -155,7 +151,6 @@ var ( endBlockers = []string{ // cosmos sdk modules - crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName, feegrant.ModuleName, @@ -178,6 +173,7 @@ var ( // NOTE: upgrade module is required to be prioritized preBlockers = []string{ upgradetypes.ModuleName, + authtypes.ModuleName, // this line is used by starport scaffolding # stargate/app/preBlockers } @@ -239,6 +235,9 @@ var ( Config: appconfig.WrapAny(&authmodulev1.Module{ Bech32Prefix: lcfg.AccountAddressPrefix, ModuleAccountPermissions: moduleAccPerms, + // Cosmos SDK 0.53.x new feature - unordered transactions + // "Fire-and-forget" submission model with timeout_timestamp as TTL/replay protection + EnableUnorderedTransactions: false, // By default modules authority is the governance module. This is configurable with the following: // Authority: "group", // A custom module authority can be set using a module name // Authority: "cosmos1cwwv22j5ca08ggdv9c2uky355k908694z577tv", // or a specific address @@ -314,10 +313,6 @@ var ( Name: govtypes.ModuleName, Config: appconfig.WrapAny(&govmodulev1.Module{}), }, - { - Name: crisistypes.ModuleName, - Config: appconfig.WrapAny(&crisismodulev1.Module{}), - }, { Name: consensustypes.ModuleName, Config: appconfig.WrapAny(&consensusmodulev1.Module{}), diff --git a/app/export.go b/app/export.go index e6934aa3..28a217a7 100644 --- a/app/export.go +++ b/app/export.go @@ -69,8 +69,7 @@ func (app *App) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []str allowedAddrsMap[addr] = true } - /* Just to be safe, assert the invariants on current state. */ - app.CrisisKeeper.AssertInvariants(ctx) + // NOTE: x/crisis is removed, so invariants are not asserted here. /* Handle fee distribution state. */ diff --git a/app/ibc.go b/app/ibc.go index 0f89f3d9..11be8939 100644 --- a/app/ibc.go +++ b/app/ibc.go @@ -140,7 +140,7 @@ func (app *App) registerIBCModules( ibcRouterV2 := ibcapi.NewRouter() // Wasm module - wasmStackIBCHandler, err := app.registerWasmModules(appOpts, ibcRouterV2, wasmOpts...) + wasmStackIBCHandler, err := app.registerWasmModules(appOpts, wasmOpts...) if err != nil { return err } @@ -224,7 +224,17 @@ func (app *App) registerIBCModules( app.ibcRouter = ibcRouter ibcRouterV2 = ibcRouterV2. - AddRoute(ibctransfertypes.PortID, ibcv2transferStack) + AddRoute(ibctransfertypes.PortID, ibcv2transferStack). + AddPrefixRoute(wasmkeeper.PortIDPrefixV2, wasmkeeper.NewIBC2Handler(app.WasmKeeper)) + + // Additional IBC v2 modules can be registered here. + if v := appOpts.Get(IBCModuleRegisterFnOptionV2); v != nil { + if registerFn, ok := v.(func(router *ibcapi.Router)); ok { + registerFn(ibcRouterV2) + } else { + return errors.New("invalid IBC v2 module register function option") + } + } app.IBCKeeper.SetRouterV2(ibcRouterV2) clientKeeper := app.IBCKeeper.ClientKeeper diff --git a/app/options.go b/app/options.go index 143ac324..6345c911 100644 --- a/app/options.go +++ b/app/options.go @@ -2,12 +2,15 @@ package app import ( ibcporttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" + ibcapi "github.com/cosmos/ibc-go/v10/modules/core/api" ) const ( - IBCModuleRegisterFnOption = "ibc_module_register_fn" + IBCModuleRegisterFnOption = "ibc_module_register_fn" + IBCModuleRegisterFnOptionV2 = "ibc_module_register_fn_v2" - FlagWasmHomeDir = "wasm-homedir" + FlagWasmHomeDir = "wasm-homedir" ) type IBCModuleRegisterFn func(router *ibcporttypes.Router) +type IBCModuleRegisterFnV2 func(router *ibcapi.Router) diff --git a/app/sim_bench_test.go b/app/sim_bench_test.go index f2e4ff92..d517626d 100644 --- a/app/sim_bench_test.go +++ b/app/sim_bench_test.go @@ -1,11 +1,9 @@ package app_test import ( - "fmt" "os" "testing" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/server" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" @@ -128,21 +126,6 @@ func BenchmarkInvariants(b *testing.B) { simtestutil.PrintStats(db) } - ctx := bApp.NewContextLegacy(true, cmtproto.Header{Height: bApp.LastBlockHeight() + 1}) - - // 3. Benchmark each invariant separately - // - // NOTE: We use the crisis keeper as it has all the invariants registered with - // their respective metadata which makes it useful for testing/benchmarking. - for _, cr := range bApp.CrisisKeeper.Routes() { - cr := cr - b.Run(fmt.Sprintf("%s/%s", cr.ModuleName, cr.Route), func(b *testing.B) { - if res, stop := cr.Invar(ctx); stop { - b.Fatalf( - "broken invariant at block %d of %d\n%s", - ctx.BlockHeight()-1, config.NumBlocks, res, - ) - } - }) - } + // NOTE: x/crisis is removed, so invariant benchmarks are not available. + b.Skip("x/crisis disabled; invariants benchmark not available") } diff --git a/app/test_helpers.go b/app/test_helpers.go index a7de7062..05f4cdb8 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -15,6 +15,8 @@ import ( "cosmossdk.io/log" sdkmath "cosmossdk.io/math" pruningtypes "cosmossdk.io/store/pruning/types" + "cosmossdk.io/store/snapshots" + snapshottypes "cosmossdk.io/store/snapshots/types" abci "github.com/cometbft/cometbft/abci/types" cmttypes "github.com/cometbft/cometbft/types" @@ -47,9 +49,11 @@ import ( wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" ibcporttypes "github.com/cosmos/ibc-go/v10/modules/core/05-port/types" + ibcapi "github.com/cosmos/ibc-go/v10/modules/core/api" lcfg "github.com/LumeraProtocol/lumera/config" ibcmock "github.com/LumeraProtocol/lumera/tests/ibctesting/mock" + mockv2 "github.com/LumeraProtocol/lumera/tests/ibctesting/mock/v2" claimtypes "github.com/LumeraProtocol/lumera/x/claim/types" ) @@ -93,7 +97,6 @@ func NewTestApp( &app.SlashingKeeper, &app.MintKeeper, &app.GovKeeper, - &app.CrisisKeeper, &app.UpgradeKeeper, &app.ParamsKeeper, &app.AuthzKeeper, @@ -197,6 +200,8 @@ func setup(t testing.TB, chainID string, withGenesis bool, invCheckPeriod uint, require.NoError(t, err) t.Cleanup(func() { snapshotDB.Close() }) require.NoError(t, err) + snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir) + require.NoError(t, err) appOptions := make(simtestutil.AppOptionsMap, 0) appOptions[flags.FlagHome] = nodeHome // ensure unique folder @@ -206,8 +211,21 @@ func setup(t testing.TB, chainID string, withGenesis bool, invCheckPeriod uint, // Register the mock IBC module for testing ibcRouter.AddRoute(MockPort, ibcmock.NewMockIBCModule(nil, MockPort)) } + appOptions[IBCModuleRegisterFnOptionV2] = func(ibcRouter *ibcapi.Router) { + ibcRouter.AddRoute(mockv2.PortIDA, mockv2.NewIBCModule()) + ibcRouter.AddRoute(mockv2.PortIDB, mockv2.NewIBCModule()) + } - app := New(log.NewNopLogger(), db, nil, true, appOptions, wasmOpts, bam.SetChainID(chainID)) + app := New( + log.NewNopLogger(), + db, + nil, + true, + appOptions, + wasmOpts, + bam.SetChainID(chainID), + bam.SetSnapshot(snapshotStore, snapshottypes.SnapshotOptions{KeepRecent: 2}), + ) if withGenesis { return app, app.DefaultGenesis() } diff --git a/app/upgrades/params/params.go b/app/upgrades/params/params.go index 4b22ca68..5c48e408 100644 --- a/app/upgrades/params/params.go +++ b/app/upgrades/params/params.go @@ -3,6 +3,8 @@ package params import ( "cosmossdk.io/log" "github.com/cosmos/cosmos-sdk/types/module" + consensuskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" + paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" actionmodulekeeper "github.com/LumeraProtocol/lumera/x/action/v1/keeper" sntypes "github.com/LumeraProtocol/lumera/x/supernode/v1/types" @@ -18,6 +20,8 @@ type AppUpgradeParams struct { // Keepers required by custom upgrade handlers. These are populated by the app // at startup (before state load) so upgrade handlers can safely perform // bespoke store migrations beyond RunMigrations. - ActionKeeper *actionmodulekeeper.Keeper - SupernodeKeeper sntypes.SupernodeKeeper + ActionKeeper *actionmodulekeeper.Keeper + SupernodeKeeper sntypes.SupernodeKeeper + ParamsKeeper *paramskeeper.Keeper + ConsensusParamsKeeper *consensuskeeper.Keeper } diff --git a/app/upgrades/upgrades.go b/app/upgrades/upgrades.go index 363ba60a..d114b6c8 100644 --- a/app/upgrades/upgrades.go +++ b/app/upgrades/upgrades.go @@ -15,21 +15,23 @@ import ( upgrade_v1_8_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_0" upgrade_v1_8_4 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_4" upgrade_v1_9_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_9_0" + upgrade_v1_10_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_10_0" ) -// ====================================================================================================================== +// ================================================================================================================================= // Upgrade overview: -// ====================================================================================================================== -// | Name | Handler | Store changes | Notes -// | v1.6.1 | custom | none | Adds action module consensus version after migrations -// | v1.7.0 | standard | none | Migrations only -// | v1.7.2 | standard | none | Migrations only -// | v1.8.0 | standard | testnet/devnet: add PFM, drop NFT | Store upgrade gated to non-mainnet; handler is migrations only -// | v1.8.4 | standard | mainnet: add PFM, drop NFT | Store upgrade gated to mainnet; handler is migrations only -// | v1.8.5 | standard | none | Migrations only -// | v1.9.0 | custom | none | Backfills action/supernode secondary indices -// | v1.9.1 | standard | none | Migrations only -// ====================================================================================================================== +// ================================================================================================================================= +// | Name | Handler | Store changes | Notes +// | v1.6.1 | custom | none | Adds action module consensus version after migrations +// | v1.7.0 | standard | none | Migrations only +// | v1.7.2 | standard | none | Migrations only +// | v1.8.0 | standard | testnet/devnet: add PFM, drop NFT | Store upgrade gated to non-mainnet; handler is migrations only +// | v1.8.4 | standard | mainnet: add PFM, drop NFT | Store upgrade gated to mainnet; handler is migrations only +// | v1.8.5 | standard | none | Migrations only +// | v1.9.0 | custom | none | Backfills action/supernode secondary indices +// | v1.9.1 | standard | none | Migrations only +// | v1.10.0 | custom | drop crisis | Migrate consensus params from x/params to x/consensus; remove x/crisis +// ================================================================================================================================= type UpgradeConfig struct { StoreUpgrade *storetypes.StoreUpgrades @@ -53,6 +55,7 @@ var upgradeNames = []string{ upgradeNameV185, upgrade_v1_9_0.UpgradeName, upgradeNameV191, + upgrade_v1_10_0.UpgradeName, } var NoUpgradeConfig = UpgradeConfig{ @@ -107,6 +110,11 @@ func SetupUpgrades(upgradeName string, params appParams.AppUpgradeParams) (Upgra return UpgradeConfig{ Handler: standardUpgradeHandler(upgradeNameV191, params), }, true + case upgrade_v1_10_0.UpgradeName: + return UpgradeConfig{ + StoreUpgrade: &upgrade_v1_10_0.StoreUpgrades, + Handler: upgrade_v1_10_0.CreateUpgradeHandler(params), + }, true // add future upgrades here default: diff --git a/app/upgrades/upgrades_test.go b/app/upgrades/upgrades_test.go index 9231d7aa..5cba46e0 100644 --- a/app/upgrades/upgrades_test.go +++ b/app/upgrades/upgrades_test.go @@ -15,7 +15,9 @@ import ( upgrade_v1_8_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_0" upgrade_v1_8_4 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_4" upgrade_v1_9_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_9_0" + upgrade_v1_10_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_10_0" actiontypes "github.com/LumeraProtocol/lumera/x/action/v1/types" + crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" ) func TestUpgradeNamesOrder(t *testing.T) { @@ -28,6 +30,7 @@ func TestUpgradeNamesOrder(t *testing.T) { upgradeNameV185, upgrade_v1_9_0.UpgradeName, upgradeNameV191, + upgrade_v1_10_0.UpgradeName, } require.Equal(t, expected, upgradeNames, "upgradeNames should stay in ascending order") } @@ -63,13 +66,17 @@ func TestSetupUpgradesAndHandlers(t *testing.T) { "store upgrade presence mismatch for %s on %s", upgradeName, tt.chainID, ) + if upgradeName == upgrade_v1_10_0.UpgradeName && config.StoreUpgrade != nil { + require.Contains(t, config.StoreUpgrade.Deleted, crisistypes.StoreKey, "v1.10.0 should delete crisis store key") + } + if config.Handler == nil { continue } // v1.9.0 requires full keeper wiring; exercising it here would require // a full app harness. This test only verifies registration and gating. - if upgradeName == upgrade_v1_9_0.UpgradeName { + if upgradeName == upgrade_v1_9_0.UpgradeName || upgradeName == upgrade_v1_10_0.UpgradeName { continue } @@ -82,6 +89,7 @@ func TestSetupUpgradesAndHandlers(t *testing.T) { _, ok := vm[actiontypes.ModuleName] require.True(t, ok, "v1.6.1 should set action module version") } + } }) } @@ -111,6 +119,8 @@ func expectStoreUpgrade(upgradeName, chainID string) bool { return IsTestnet(chainID) || IsDevnet(chainID) case upgrade_v1_8_4.UpgradeName: return IsMainnet(chainID) + case upgrade_v1_10_0.UpgradeName: + return true default: return false } diff --git a/app/upgrades/v1_10_0/store.go b/app/upgrades/v1_10_0/store.go new file mode 100644 index 00000000..b26804f9 --- /dev/null +++ b/app/upgrades/v1_10_0/store.go @@ -0,0 +1,11 @@ +package v1_10_0 + +import ( + storetypes "cosmossdk.io/store/types" + crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" +) + +// StoreUpgrades defines store changes for v1.10.0. +var StoreUpgrades = storetypes.StoreUpgrades{ + Deleted: []string{crisistypes.StoreKey}, +} diff --git a/app/upgrades/v1_10_0/upgrade.go b/app/upgrades/v1_10_0/upgrade.go new file mode 100644 index 00000000..f8b36533 --- /dev/null +++ b/app/upgrades/v1_10_0/upgrade.go @@ -0,0 +1,52 @@ +package v1_10_0 + +import ( + "context" + "fmt" + + upgradetypes "cosmossdk.io/x/upgrade/types" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + + appParams "github.com/LumeraProtocol/lumera/app/upgrades/params" +) + +// UpgradeName is the on-chain name used for this upgrade. +const UpgradeName = "v1.10.0" + +// CreateUpgradeHandler migrates consensus params from x/params to x/consensus +// and then runs module migrations. +func CreateUpgradeHandler(p appParams.AppUpgradeParams) upgradetypes.UpgradeHandler { + return func(goCtx context.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + p.Logger.Info(fmt.Sprintf("Starting upgrade %s...", UpgradeName)) + + ctx := sdk.UnwrapSDKContext(goCtx) + + if p.ParamsKeeper == nil || p.ConsensusParamsKeeper == nil { + return nil, fmt.Errorf("%s upgrade requires ParamsKeeper and ConsensusParamsKeeper", UpgradeName) + } + + // Use the legacy baseapp paramspace to read existing consensus params from x/params. + // This is required for in-place upgrades where consensus params were historically stored in x/params. + legacySubspace := p.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramstypes.ConsensusParamsKeyTable()) + // Migrate consensus params into x/consensus (ConsensusParamsKeeper), which is collections-backed in v0.53+. + if err := baseapp.MigrateParams(ctx, legacySubspace, p.ConsensusParamsKeeper.ParamsStore); err != nil { + return nil, fmt.Errorf("failed to migrate consensus params: %w", err) + } + + // Run all module migrations after consensus params have been moved. + p.Logger.Info("Running module migrations...") + newVM, err := p.ModuleManager.RunMigrations(ctx, p.Configurator, fromVM) + if err != nil { + p.Logger.Error("Failed to run migrations", "error", err) + return nil, fmt.Errorf("failed to run migrations: %w", err) + } + p.Logger.Info("Module migrations completed.") + + p.Logger.Info(fmt.Sprintf("Successfully completed upgrade %s", UpgradeName)) + return newVM, nil + } +} diff --git a/app/wasm.go b/app/wasm.go index 7c41fb47..1f661aab 100644 --- a/app/wasm.go +++ b/app/wasm.go @@ -18,7 +18,6 @@ import ( distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/cosmos/gogoproto/proto" - ibcapi "github.com/cosmos/ibc-go/v10/modules/core/api" ) func uint32Ptr(v uint32) *uint32 { @@ -28,7 +27,6 @@ func uint32Ptr(v uint32) *uint32 { // registerWasmModules register CosmWasm keepers and non dependency inject modules. func (app *App) registerWasmModules( appOpts servertypes.AppOptions, - ibcRouterV2 *ibcapi.Router, wasmOpts ...wasmkeeper.Option, ) (*wasm.IBCHandler, error) { // set up non depinject support modules store keys @@ -74,6 +72,7 @@ func (app *App) registerWasmModules( distrkeeper.NewQuerier(app.DistrKeeper), app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, + app.IBCKeeper.ChannelKeeperV2, app.TransferKeeper, app.MsgServiceRouter(), app.GRPCQueryRouter(), @@ -82,7 +81,6 @@ func (app *App) registerWasmModules( vmConfig, capabilities, authority, - ibcRouterV2, wasmOpts..., ) app.WasmKeeper = &wasmKeeper @@ -133,7 +131,9 @@ func (app *App) registerWasmModules( wasmStackIBCHandler := wasm.NewIBCHandler( app.WasmKeeper, app.IBCKeeper.ChannelKeeper, - app.IBCKeeper.ChannelKeeper) + app.TransferKeeper, + app.IBCKeeper.ChannelKeeper, + ) return &wasmStackIBCHandler, nil } diff --git a/config/config.go b/config/config.go index 3c458a3f..83c7d3f4 100644 --- a/config/config.go +++ b/config/config.go @@ -43,6 +43,9 @@ func SetupConfig() { // Set and seal config config := sdk.GetConfig() + // Keep SDK fallback in sync with chain denom. + sdk.DefaultBondDenom = ChainDenom + // Set the chain coin type config.SetCoinType(ChainCoinType) diff --git a/devnet/go.mod b/devnet/go.mod index 46cdb225..447afd22 100644 --- a/devnet/go.mod +++ b/devnet/go.mod @@ -7,7 +7,6 @@ replace ( // Comment lines with github.com/LumeraProtocol/ before releasing // github.com/LumeraProtocol/lumera => .. //github.com/LumeraProtocol/sdk-go => ../../sdk-go - github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.50.14 github.com/envoyproxy/protoc-gen-validate => github.com/bufbuild/protoc-gen-validate v1.3.0 github.com/lyft/protoc-gen-validate => github.com/envoyproxy/protoc-gen-validate v1.3.0 github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 @@ -19,19 +18,19 @@ require ( cosmossdk.io/math v1.5.3 github.com/LumeraProtocol/lumera v1.9.1 github.com/LumeraProtocol/sdk-go v1.0.6 - github.com/cosmos/cosmos-sdk v0.53.0 - github.com/cosmos/ibc-go/v10 v10.3.0 + github.com/cosmos/cosmos-sdk v0.53.5 + github.com/cosmos/ibc-go/v10 v10.5.0 github.com/stretchr/testify v1.11.1 go.uber.org/zap v1.27.0 gopkg.in/yaml.v2 v2.4.0 ) require ( - cosmossdk.io/collections v1.3.0 // indirect + cosmossdk.io/collections v1.3.1 // indirect cosmossdk.io/core v0.11.3 // indirect - cosmossdk.io/depinject v1.2.0 // indirect + cosmossdk.io/depinject v1.2.1 // indirect cosmossdk.io/errors v1.0.2 // indirect - cosmossdk.io/log v1.6.0 // indirect + cosmossdk.io/log v1.6.1 // indirect cosmossdk.io/schema v1.1.0 // indirect cosmossdk.io/store v1.1.2 // indirect cosmossdk.io/x/tx v0.14.0 // indirect @@ -48,8 +47,8 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.2.0 // indirect github.com/bytedance/gopkg v0.1.3 // indirect - github.com/bytedance/sonic v1.14.1 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/bytedance/sonic v1.14.2 // indirect + github.com/bytedance/sonic/loader v0.4.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect @@ -59,23 +58,23 @@ require ( github.com/cockroachdb/pebble v1.1.5 // indirect github.com/cockroachdb/redact v1.1.6 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft v0.38.18 // indirect + github.com/cometbft/cometbft v0.38.20 // indirect github.com/cometbft/cometbft-db v0.14.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.2 // indirect + github.com/cosmos/cosmos-db v1.1.3 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect - github.com/cosmos/gogoproto v1.7.0 // indirect + github.com/cosmos/gogoproto v1.7.2 // indirect github.com/cosmos/iavl v1.2.4 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect - github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.16.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/desertbit/timer v1.0.1 // indirect github.com/dgraph-io/badger/v4 v4.2.0 // indirect - github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgraph-io/ristretto v0.2.0 // indirect github.com/dgraph-io/ristretto/v2 v2.2.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect @@ -84,7 +83,7 @@ require ( github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/getsentry/sentry-go v0.32.0 // indirect + github.com/getsentry/sentry-go v0.35.0 // indirect github.com/go-errors/errors v1.5.1 // indirect github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -93,8 +92,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.5 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect github.com/google/btree v1.1.3 // indirect @@ -140,10 +138,10 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect + github.com/prometheus/client_golang v1.23.0 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.63.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/prometheus/common v0.65.0 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/cors v1.11.1 // indirect @@ -161,14 +159,16 @@ require ( github.com/tendermint/go-amino v0.16.0 // indirect github.com/tidwall/btree v1.7.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/zondax/golem v0.27.0 // indirect github.com/zondax/hid v0.9.2 // indirect - github.com/zondax/ledger-go v0.14.3 // indirect + github.com/zondax/ledger-go v1.0.1 // indirect go.etcd.io/bbolt v1.4.0-alpha.1 // indirect go.opencensus.io v0.24.0 // indirect go.uber.org/mock v0.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/arch v0.15.0 // indirect + golang.org/x/arch v0.17.0 // indirect golang.org/x/crypto v0.43.0 // indirect golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 // indirect @@ -176,7 +176,7 @@ require ( golang.org/x/sys v0.37.0 // indirect golang.org/x/term v0.36.0 // indirect golang.org/x/text v0.30.0 // indirect - google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect + google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect google.golang.org/grpc v1.77.0 // indirect @@ -186,5 +186,5 @@ require ( lukechampine.com/blake3 v1.4.1 // indirect nhooyr.io/websocket v1.8.17 // indirect pgregory.net/rapid v1.2.0 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/devnet/go.sum b/devnet/go.sum index 3634f9d3..ded2db5a 100644 --- a/devnet/go.sum +++ b/devnet/go.sum @@ -21,8 +21,8 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA= cloud.google.com/go v0.120.0/go.mod h1:/beW32s8/pGRuj4IILWQNd4uuebeT4dkOhKmkfit64Q= -cloud.google.com/go/auth v0.16.0 h1:Pd8P1s9WkcrBE2n/PhAwKsdrR35V3Sg2II9B+ndM3CU= -cloud.google.com/go/auth v0.16.0/go.mod h1:1howDHJ5IETh/LwYs3ZxvlkXF48aSqqJUM+5o02dNOI= +cloud.google.com/go/auth v0.16.4 h1:fXOAIQmkApVvcIn7Pc2+5J8QTMVbUGLscnSVNl11su8= +cloud.google.com/go/auth v0.16.4/go.mod h1:j10ncYwjX/g3cdX7GpEzsdM+d+ZNsXAbb6qXA7p1Y5M= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= @@ -31,7 +31,7 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.37.0 h1:XxtZlXYkZXub3LNaLu90TTemcFqIU1yZ4E4q9VlR39A= +cloud.google.com/go/compute v1.38.0 h1:MilCLYQW2m7Dku8hRIIKo4r0oKastlD74sSu16riYKs= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -56,16 +56,16 @@ cosmossdk.io/api v0.9.2 h1:9i9ptOBdmoIEVEVWLtYYHjxZonlF/aOVODLFaxpmNtg= cosmossdk.io/api v0.9.2/go.mod h1:CWt31nVohvoPMTlPv+mMNCtC0a7BqRdESjCsstHcTkU= cosmossdk.io/client/v2 v2.0.0-beta.8.0.20250402172810-41e3e9d004a1 h1:nlMUeKu6CGrO7Gxt5S31qT3g27CHmBJHsZPjqHApVTI= cosmossdk.io/client/v2 v2.0.0-beta.8.0.20250402172810-41e3e9d004a1/go.mod h1:xgv0ejeOk5yeDraPW5tv+PfBkCDt4yYa/+u45MyP+bM= -cosmossdk.io/collections v1.3.0 h1:RUY23xXBy/bu5oSHZ5y+mkJRyA4ZboKDO4Yvx4+g2uc= -cosmossdk.io/collections v1.3.0/go.mod h1:cqVpBMDGEYhuNmNSXIOmqpnQ7Eav43hpJIetzLuEkns= +cosmossdk.io/collections v1.3.1 h1:09e+DUId2brWsNOQ4nrk+bprVmMUaDH9xvtZkeqIjVw= +cosmossdk.io/collections v1.3.1/go.mod h1:ynvkP0r5ruAjbmedE+vQ07MT6OtJ0ZIDKrtJHK7Q/4c= cosmossdk.io/core v0.11.3 h1:mei+MVDJOwIjIniaKelE3jPDqShCc/F4LkNNHh+4yfo= cosmossdk.io/core v0.11.3/go.mod h1:9rL4RE1uDt5AJ4Tg55sYyHWXA16VmpHgbe0PbJc6N2Y= -cosmossdk.io/depinject v1.2.0 h1:6NW/FSK1IkWTrX7XxUpBmX1QMBozpEI9SsWkKTBc5zw= -cosmossdk.io/depinject v1.2.0/go.mod h1:pvitjtUxZZZTQESKNS9KhGjWVslJZxtO9VooRJYyPjk= +cosmossdk.io/depinject v1.2.1 h1:eD6FxkIjlVaNZT+dXTQuwQTKZrFZ4UrfCq1RKgzyhMw= +cosmossdk.io/depinject v1.2.1/go.mod h1:lqQEycz0H2JXqvOgVwTsjEdMI0plswI7p6KX+MVqFOM= cosmossdk.io/errors v1.0.2 h1:wcYiJz08HThbWxd/L4jObeLaLySopyyuUFB5w4AGpCo= cosmossdk.io/errors v1.0.2/go.mod h1:0rjgiHkftRYPj//3DrD6y8hcm40HcPv/dR4R/4efr0k= -cosmossdk.io/log v1.6.0 h1:SJIOmJ059wi1piyRgNRXKXhlDXGqnB5eQwhcZKv2tOk= -cosmossdk.io/log v1.6.0/go.mod h1:5cXXBvfBkR2/BcXmosdCSLXllvgSjphrrDVdfVRmBGM= +cosmossdk.io/log v1.6.1 h1:YXNwAgbDwMEKwDlCdH8vPcoggma48MgZrTQXCfmMBeI= +cosmossdk.io/log v1.6.1/go.mod h1:gMwsWyyDBjpdG9u2avCFdysXqxq28WJapJvu+vF1y+E= cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= cosmossdk.io/schema v1.1.0 h1:mmpuz3dzouCoyjjcMcA/xHBEmMChN+EHh8EHxHRHhzE= @@ -158,10 +158,10 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4= -github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= -github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/bits-and-blooms/bitset v1.24.3 h1:Bte86SlO3lwPQqww+7BE9ZuUCKIjfqnG5jtEyqA9y9Y= +github.com/bits-and-blooms/bitset v1.24.3/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd/btcec/v2 v2.3.5 h1:dpAlnAwmT1yIBm3exhT1/8iUSD98RDJM5vqJVQDQLiU= +github.com/btcsuite/btcd/btcec/v2 v2.3.5/go.mod h1:m22FrOAiuxl/tht9wIqAoGHcbnCCaPWyauO8y2LGGtQ= github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= @@ -172,10 +172,10 @@ github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/ github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= -github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w= -github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc= -github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= -github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE= +github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980= +github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o= +github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -227,8 +227,8 @@ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1: github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coder/websocket v1.8.7 h1:jiep6gmlfP/yq2w1gBoubJEXL9gf8x3bp6lzzX8nJxE= github.com/coder/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -github.com/cometbft/cometbft v0.38.18 h1:1ZHYMdu0S75YxFM13LlPXnOwiIpUW5z9TKMQtTIALpw= -github.com/cometbft/cometbft v0.38.18/go.mod h1:PlOQgf3jQorep+g6oVnJgtP65TJvBJoLiXjGaMdNxBE= +github.com/cometbft/cometbft v0.38.20 h1:i9v9rvh3Z4CZvGSWrByAOpiqNq5WLkat3r/tE/B49RU= +github.com/cometbft/cometbft v0.38.20/go.mod h1:UCu8dlHqvkAsmAFmWDRWNZJPlu6ya2fTWZlDrWsivwo= github.com/cometbft/cometbft-db v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -239,29 +239,29 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.2 h1:KZm4xLlPp6rLkyIOmPOhh+XDK9oH1++pNH/csLdX0Dk= -github.com/cosmos/cosmos-db v1.1.2/go.mod h1:dMg2gav979Ig2N076POEw4CEKbCsieaOfDWSfFZxs8M= +github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOPY= +github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.50.14 h1:G8CtGHFWbExa+ZpVOVAb4kFmko/R30igsYOwyzRMtgY= -github.com/cosmos/cosmos-sdk v0.50.14/go.mod h1:hrWEFMU1eoXqLJeE6VVESpJDQH67FS1nnMrQIjO2daw= +github.com/cosmos/cosmos-sdk v0.53.5 h1:JPue+SFn2gyDzTV9TYb8mGpuIH3kGt7WbGadulkpTcU= +github.com/cosmos/cosmos-sdk v0.53.5/go.mod h1:AQJx0jpon70WAD4oOs/y+SlST4u7VIwEPR6F8S7JMdo= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= -github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= -github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= +github.com/cosmos/gogoproto v1.7.2 h1:5G25McIraOC0mRFv9TVO139Uh3OklV2hczr13KKVHCA= +github.com/cosmos/gogoproto v1.7.2/go.mod h1:8S7w53P1Y1cHwND64o0BnArT6RmdgIvsBuco6uTllsk= github.com/cosmos/iavl v1.2.4 h1:IHUrG8dkyueKEY72y92jajrizbkZKPZbMmG14QzsEkw= github.com/cosmos/iavl v1.2.4/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v10 v10.1.0 h1:epKcbFAeWRRw1i1jZnYzLIEm9sgUPaL1RftuRjjUKGw= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v10 v10.1.0/go.mod h1:S4ZQwf5/LhpOi8JXSAese/6QQDk87nTdicJPlZ5q9UQ= -github.com/cosmos/ibc-go/v10 v10.3.0 h1:w5DkHih8qn15deAeFoTk778WJU+xC1krJ5kDnicfUBc= -github.com/cosmos/ibc-go/v10 v10.3.0/go.mod h1:CthaR7n4d23PJJ7wZHegmNgbVcLXCQql7EwHrAXnMtw= +github.com/cosmos/ibc-go/v10 v10.5.0 h1:NI+cX04fXdu9JfP0V0GYeRi1ENa7PPdq0BYtVYo8Zrs= +github.com/cosmos/ibc-go/v10 v10.5.0/go.mod h1:a74pAPUSJ7NewvmvELU74hUClJhwnmm5MGbEaiTw/kE= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= -github.com/cosmos/ledger-cosmos-go v0.14.0 h1:WfCHricT3rPbkPSVKRH+L4fQGKYHuGOK9Edpel8TYpE= -github.com/cosmos/ledger-cosmos-go v0.14.0/go.mod h1:E07xCWSBl3mTGofZ2QnL4cIUzMbbGVyik84QYKbX3RA= +github.com/cosmos/ledger-cosmos-go v0.16.0 h1:YKlWPG9NnGZIEUb2bEfZ6zhON1CHlNTg0QKRRGcNEd0= +github.com/cosmos/ledger-cosmos-go v0.16.0/go.mod h1:WrM2xEa8koYoH2DgeIuZXNarF7FGuZl3mrIOnp3Dp0o= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -281,12 +281,11 @@ github.com/desertbit/timer v1.0.1 h1:yRpYNn5Vaaj6QXecdLMPMJsW81JLiI1eokUft5nBmeo github.com/desertbit/timer v1.0.1/go.mod h1:htRrYeY5V/t4iu1xCJ5XsQvp4xve8QulXXctAzxqcwE= github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE= +github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU= github.com/dgraph-io/ristretto/v2 v2.2.0 h1:bkY3XzJcXoMuELV8F+vS8kzNgicwQFAaGINAEJdWGOM= github.com/dgraph-io/ristretto/v2 v2.2.0/go.mod h1:RZrm63UmcBAaYWC1DotLYBmTvgkrs0+XhBd7Npn7/zI= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= @@ -296,7 +295,6 @@ github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vma github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= @@ -337,8 +335,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/getsentry/sentry-go v0.32.0 h1:YKs+//QmwE3DcYtfKRH8/KyOOF/I6Qnx7qYGNHCGmCY= -github.com/getsentry/sentry-go v0.32.0/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= +github.com/getsentry/sentry-go v0.35.0 h1:+FJNlnjJsZMG3g0/rmmP7GiKjQoUF5EXfEtBwtPtkzY= +github.com/getsentry/sentry-go v0.35.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -400,14 +398,12 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= -github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -458,7 +454,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= @@ -492,8 +487,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= -github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo= +github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -587,8 +582,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= -github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= +github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= +github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= @@ -641,8 +636,8 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U github.com/linxGnu/grocksdb v1.9.8 h1:vOIKv9/+HKiqJAElJIEYv3ZLcihRxyP7Suu/Mu8Dxjs= github.com/linxGnu/grocksdb v1.9.8/go.mod h1:C3CNe9UYc9hlEM2pC82AqiGS3LRW537u9LFV4wIZuHk= github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -699,8 +694,8 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= @@ -771,8 +766,8 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc= +github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -788,8 +783,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= -github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= +github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= +github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -797,8 +792,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -875,6 +870,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -903,10 +900,12 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zondax/golem v0.27.0 h1:IbBjGIXF3SoGOZHsILJvIM/F/ylwJzMcHAcggiqniPw= +github.com/zondax/golem v0.27.0/go.mod h1:AmorCgJPt00L8xN1VrMBe13PSifoZksnQ1Ge906bu4A= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= -github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +github.com/zondax/ledger-go v1.0.1 h1:Ks/2tz/dOF+dbRynfZ0dEhcdL1lqw43Sa0zMXHpQ3aQ= +github.com/zondax/ledger-go v1.0.1/go.mod h1:j7IgMY39f30apthJYMd1YsHZRqdyu4KbVmUp0nU78X0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= @@ -925,8 +924,8 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/detectors/gcp v1.38.0 h1:ZoYbqX7OaA/TAikspPl3ozPI6iY6LiIY9I8cUfm+pJs= go.opentelemetry.io/contrib/detectors/gcp v1.38.0/go.mod h1:SU+iU7nu5ud4oCb3LQOhIZ3nRLj6FNVrKgtflbaf2ts= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= @@ -960,10 +959,12 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= -golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= +golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU= +golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -1179,7 +1180,6 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1222,8 +1222,8 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1311,8 +1311,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.229.0 h1:p98ymMtqeJ5i3lIBMj5MpR9kzIIgzpHHh8vQ+vgAzx8= -google.golang.org/api v0.229.0/go.mod h1:wyDfmq5g1wYJWn29O22FDWN48P7Xcz0xz+LBpptYvB0= +google.golang.org/api v0.247.0 h1:tSd/e0QrUlLsrwMKmkbQhYVa109qIintOls2Wh6bngc= +google.golang.org/api v0.247.0/go.mod h1:r1qZOPmxXffXg6xS5uhx16Fa/UFY8QU/K4bfKrnvovM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1363,8 +1363,8 @@ google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78= -google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s= google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4= google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk= @@ -1463,6 +1463,6 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/docs/lumeraid/ibc.md b/docs/lumeraid/ibc.md index 058b7315..5b577875 100644 --- a/docs/lumeraid/ibc.md +++ b/docs/lumeraid/ibc.md @@ -1,251 +1,16 @@ -# Proposal: Upgrading Lumera IBC to v2 (ibc-go v10) and Cross-Chain Service Integration +# Benefits of Upgrading IBC for Lumera -## Background and Rationale +## Benefits of upgrading to IBC v2 (IBC-Go v10) -Lumera’s blockchain currently uses the Cosmos **IBC-Go v8** implementation (IBC spec v1) for inter-chain communication. We propose upgrading to **IBC-Go v10** which introduces **IBC v2** support, while retaining backward compatibility with IBC v1 (classic). IBC v2 (launching with Cosmos SDK 0.50) significantly simplifies the IBC protocol without sacrificing functionality. By upgrading, Lumera can leverage improved cross-chain composability, more flexible packet handling, and better performance for interchain interactions. This upgrade will position Lumera to connect more easily with diverse blockchains (Cosmos chains and beyond) and to expose its unique services (Cascade, Sense, Inference, NFT metadata) to the broader interchain ecosystem. +- **Backward compatibility**: Keep IBC v1 channels while enabling IBC v2, so Lumera can upgrade without forcing counterparties to move immediately. +- **Simplified handshakes**: Reduce connection and channel setup time, lowering relayer overhead and speeding new integrations. +- **Unified routing**: Support multiple Lumera services (Cascade, Sense, Inference, NFT metadata) over a single connection, improving composability and reducing channel sprawl. +- **Payload flexibility**: Allow app-specific encodings and multi-action workflows (e.g., payment + service request in one flow) with less protocol friction. +- **Faster feature adoption**: Enable ICA, queries, and cross-chain calls without reworking the IBC stack as new apps are added. +- **Lower maintenance risk**: Trim the IBC module stack, reducing upgrade risk during the Cosmos SDK 0.53.5 transition while improving long-term scalability. -Key motivations for the upgrade include: +## Benefits of upgrading to IBC-Go v10.5.0 -- **Enhanced Cross-Chain Compatibility**: IBC v2 reduces handshake complexity, making it easier to connect with non-Cosmos ecosystems (e.g. Ethereum, Solana). This broadens Lumera’s potential integration partners. -- **Future-Proofing**: Aligning with the latest interchain standards ensures Lumera remains compatible with upcoming Cosmos SDK improvements and IBC features (like cross-chain smart contract calls). -- **Facilitating New Services**: IBC v2’s design is more accommodating to custom application protocols, which is critical for Lumera to offer storage, AI, and NFT services over IBC channels. - -In summary, upgrading to IBC-Go v10 (IBC v2) will modernize Lumera’s interop layer, simplify cross-chain interactions, and enable Lumera to act as a provider of advanced interchain services. - -## Technical Upgrade Plan (IBC-Go v8 to v10) - -Upgrading the IBC module requires careful changes to Lumera’s codebase and configuration. Below we detail the specific technical steps and modifications needed for moving from ibc-go v8 (IBC v1) to ibc-go v10 (IBC v2): - -### Dependency and Module Updates - -- **Bump IBC-Go Version**: Update Lumera’s Go modules to use ibc-go/v10 (replacing any v8 references). -- **Remove Capability Module**: IBC v2 no longer uses the Cosmos SDK Capability keeper for channel scoping. We will remove the capabilitykeeper from the app, including any scoped keepers for IBC ports. This cleans up app.go by dropping the CapabilityKeeper and all Scoped*Keeper instances related to IBC. -- **Remove Legacy Client Proposal Handler**: Eliminate the registration of the legacy 02-Client proposal handler in governance. In app.go, the upgrade client proposal route (used for updating IBC clients in IBC v1) should be removed, as IBC v2 handles client updates differently. -- **Integrate New Light Clients**: Register the updated light client modules with the IBC client keeper. For example, instantiate the Tendermint light client module via ibctm.NewLightClientModule and add it to the client router. Do the same for any other client types in use (e.g., 08-wasm if Lumera supports Wasm-based clients). This ensures Lumera’s IBC can support the new client abstractions (and any future clients like Ethereum light clients). -- **IBC Module Interface Changes**: Update any IBC keeper constructor calls to match new function signatures in v10. For instance, the IBC keeper and routing setup might now require fewer parameters (since capability and fee middleware are removed) and use a unified router abstraction for channels. - -### IBC Application Stack Adjustments - -- **IBC Transfer Module (ICS-20) v2**: Wire up the new transfer v2 stack for token transfers. The ibc-transfer module in v10 has a revised implementation (transferv2) to work with IBC v2. In Lumera’s app.go, instead of the old transfer.NewIBCModule, use transferv2.NewIBCModule(app.TransferKeeper) and register it on the IBC router. This ensures that fungible token transfers use the IBC v2 packet format and routing. -- **Remove Fee Middleware (ICS-29)**: In IBC-Go v10, the fee middleware (ICS-29) is no longer wired in the same way. The migration guidelines explicitly instruct chains to remove the ibc-fee module from the stack. Accordingly, delete any IBCFeeKeeper initialization and omit wrapping IBC modules with ibcfee.NewIBCMiddleware. (Relayer incentivization can be revisited later if needed via updated middleware patterns, but for now v2 simplifies the stack.) -- **Callbacks Middleware**: The IBC Callbacks middleware module has moved into the core ibc-go module and its initialization signature has changed. We will import ibccallbacks/v10 and wrap it appropriately around the transfer module if those hooks are needed (ensuring it uses the new ChannelKeeperV2 where required). -- **Interchain Accounts (ICS-27) Modules**: Lumera’s Interchain Accounts host/controller modules should be updated to the v10 API. In practice, this means using the latest icahost and icacontroller implementations and removing any dummy modules or fee wrapping. For example, previously a “no-authz” dummy module and fee middleware wrapped the ICA controller – these should be simplified to just icacontroller.NewIBCMiddleware(app.ICAControllerKeeper). Likewise, instantiate the ICA host with icahost.NewIBCModule alone (no fee wrapper). This aligns ICA with IBC v2’s streamlined channel management. - -### Configuration and State Considerations - -- **Genesis / AppState**: No explicit genesis field changes are expected solely for IBC v2, since the upgrade is mainly code-level. However, because we remove the Capability module, we should ensure that the on-chain capability store (if present) can be left inert or safely migrated. The upgrade handler can simply drop capability references since IBC channel locking will be handled via the new router logic. -- **Version Negotiation**: IBC-Go v10 introduces an application version negotiation interface for handshake (the NegotiateAppVersion method). Ensure Lumera’s custom IBC app modules (if any) implement this if needed, to agree on versions during channel setup. The standard modules (transfer, ICA, etc.) already handle this. -- **Backward Compatibility Mode**: Out of the box, ibc-go v10 supports both IBC v1 (classic) and v2 protocols for interoperability. We will configure the IBC keeper to support connections with IBC v1 chains. This means Lumera can still open **IBC Classic channels** to chains that have not yet upgraded, ensuring continuity of existing connections. No special config is required beyond not disabling the legacy channel handshake logic present in ibc-go v10 (it remains enabled by default to maintain compatibility [ccvalidators.com] (https://ccvalidators.com/blog/ibc-eureka-the-endgame-of-blockchain-interoperability/)). -- **Testing the Upgrade Path**: Write an upgrade handler (if using Cosmos SDK in-place upgrade) to perform any needed state migrations. This includes removing the now-unused fee module account permission (if defined) and possibly clearing capability indices. We will simulate an upgrade in a dev environment to ensure that after restarting with the new binary, all IBC connections and channels are functional. - -### Validation and Testing - -After implementing the above changes, thorough testing is essential: - -- **Unit Tests**: Run the IBC module’s test suite and add new tests for the modified handshake. Test that opening a channel to a known IBC v1 counterparty works (the handshake should gracefully fall back to v1). -- **Integration Tests**: Set up a local testnet with two Lumera nodes using the new code and attempt to establish IBC connectivity with another chain (or a loopback connection). Validate that ICS-20 token transfers still succeed end-to-end. -- **Relayer Compatibility**: Test with the common IBC relayer (e.g. Hermes or Go Relayer) to ensure it can relay packets to/from Lumera after the upgrade. Relayers may need minor config updates (like recognizing the new channel version string for v2 channels), so we’ll verify this in advance. -- **Performance Benchmarking**: Compare the handshake time and packet throughput before vs. after. We expect improved performance (faster channel setup due to fewer steps). Any issues will be addressed before mainnet deployment. - -By completing these technical steps, Lumera’s codebase will be ready to run IBC v2, unlocking the new capabilities while remaining compatible with existing IBC networks. - -## Benefits of Upgrading to IBC v2 - -Upgrading to IBC v2 (ibc-go v10) offers several **concrete benefits** for Lumera, improving both the developer experience and cross-chain functionality: - -- **Simplified Handshake & Improved Performance**: IBC v2 reduces the connection handshake from a 10-step process (4 steps each for connection and channel, plus client setup) to just 3 steps. This streamlined startup means faster time-to-connect and less overhead for relayers. It also condenses channels and connections into a single abstraction (the new Router), eliminating the lengthy channel open/confirm dance. The result is quicker integration with other chains and lower latency for starting cross-chain operations. -- **Greater Composability and Upgradability**: In IBC v2, all applications run over a single connection, with dynamic routing by port ID. This means Lumera and a counterparty chain can use one connection to support multiple services or module interactions simultaneously, without needing separate channels for each service. New IBC applications (or new versions) can be added without coordinating a new channel handshake, greatly improving extensibility. For example, Lumera could add a new interchain service post-upgrade and immediately route packets over the existing connection. This unified routing model also avoids the fragmentation of multiple channels and the reliance on off-chain “canonical channel” conventions. -- **Custom Packet Flexibility (Payloads)**: IBC v2 introduces a Payload abstraction in packets. Instead of a single opaque bytes field tied to a specific port/channel, a packet can carry a list of payloads, each with its own destination port, app version, and encoding type. This unlocks flexibility for custom packet designs. Lumera can define custom packet types for its services (if needed) with domain-specific encoding (e.g., using efficient binary codecs or Ethereum ABI encoding for certain interactions). The payload structure even allows combining multiple operations in one packet (e.g., a token transfer plus a callback invocation in one go), enabling atomic cross-chain composability in future releases. In short, Lumera gains more control over how data is packaged and interpreted across chains. -- **Advanced IBC Features Availability**: By moving to the latest IBC implementation, Lumera can easily adopt new IBC features such as Interchain Accounts, Interchain Queries, and upcoming cross-chain contract calls. These existed in IBC v1 but are further refined or easier to use in v2. For instance, Interchain Accounts (ICS-27) allow a chain to control an account on another chain via IBC, which Lumera can use to let other chains invoke its services (or vice versa). Cross-Chain Queries (ICS-31/32) enable direct reading of state from another chain over IBC, useful for fetching NFT metadata or verification results from Lumera. Upgrading ensures Lumera is fully compatible with these modules, which improves cross-chain composability (chains can seamlessly incorporate Lumera’s functionality into their own workflows). -- **Performance and Scalability**: Beyond handshake improvements, IBC v2 is designed with broader ecosystem scalability in mind. The lighter protocol is more amenable to varied environments (even non-Tendermint chains), meaning Lumera can potentially handle more connections in parallel with less overhead. The elimination of redundant fields (like port IDs in the packet, and using only timestamps for timeouts) trims packet size and verification work, which could slightly improve throughput and reduce gas costs per packet on Lumera. -- **Cross-Chain Service Enablement**: Perhaps most importantly, IBC v2 better enables cross-chain services – a core goal for Lumera. With the new capabilities, Lumera can serve as an interchain utility chain providing storage and AI services. For example, improved routing means a single IBC connection to another chain can carry both token transfers and service requests back-and-forth, making it easier to compose multi-step cross-chain transactions (e.g., sending payment and a service request together). This composability was more clunky in IBC v1, where separate channels or sequential transactions were needed. - -In summary, upgrading to IBC v2 brings Lumera speed, flexibility, and access to richer interchain functionality. It lays a strong foundation for Lumera to not just participate in the interchain, but to become a **key service provider** within it, thanks to these improvements in protocol design and capabilities. - -## Exposing Lumera Features as IBC Services - -One of the strategic advantages of upgrading is the ability to expose Lumera’s unique features – **Cascade** (distributed storage), **Sense** (near-duplicate NFT detection), **Inference** (AI/ML agents), and **NFT Metadata** services – as **IBC-compatible services**. This means other blockchains can seamlessly invoke Lumera’s capabilities through standard IBC channels and packets. Below we propose how each feature can be integrated into the IBC framework: - -### Cascade: Distributed Storage Service - -Cascade is Lumera’s distributed, permanent storage protocol for NFT data, built on RaptorQ fountain codes and a Kademlia DHT. It breaks files into redundant chunks and stores them across the network, ensuring durable NFT storage. To offer Cascade as an interchain service, we can leverage IBC in the following ways: - -- **IBC Application Module for Storage**: Implement a custom IBC application (port) on Lumera named, for example, "cascade" or "storage". External chains can open an IBC channel to this port. Through this channel, they send storage requests as IBC packets (containing the data or references to data that needs storage). Lumera’s module on receiving a request will process it by encoding the asset into chunks and storing it via Cascade’s logic. Upon success, Lumera can return an acknowledgement packet with a **storage receipt** – e.g., a content ID or storage tx hash. -- **Data Transfer Considerations**: NFT images or files can be large, so the design must handle chunking. IBC v2’s packet payload improvements allow flexible encoding; we could define a chunked transfer protocol (sending multiple ordered packets carrying file chunks) under the Cascade channel. Alternatively, the requesting chain might first upload the asset to a known location (or send via ICS-20 if it’s tokenized), and then just send a reference (like a hash or URL) to Lumera for retrieval. Lumera’s Cascade module could have the capability to fetch external data given a reference (if security permits) or rely on the relayer to carry the actual payload. -- **Interchain Accounts Alternative**: Another approach is to utilize ICS-27 (Interchain Accounts). A chain could create an account on Lumera and invoke a MsgStoreFile transaction on Lumera through that account. The Cascade logic would execute as if the user directly submitted it on Lumera. The result (e.g., a stored file ID) would be committed to Lumera’s state. The requesting chain can then query this via an interchain query or wait for the transaction result in the acknowledgement. Using ICS-27 ensures we reuse Lumera’s existing transaction flow, though it requires the counterparty chain to support the controller side of interchain accounts. -- **Benefits**: By exposing Cascade over IBC, any NFT-centric chain in the Cosmos ecosystem (and beyond) can utilize permanent, decentralized storage for their NFT media. This mitigates the common problem of NFT assets disappearing from centralized hosts. Lumera could charge fees in PSTL (Pastel token) or another token for storage, possibly handled via an ICS-20 transfer accompanying the request (e.g., attach payment and the store request in one flow). IBC v2’s multi-payload packets might even allow combining payment and request in one packet in the future. - -### Sense: Near-Duplicate NFT Detection - -Sense is Lumera’s AI-driven protocol for near-duplicate NFT detection and rareness scoring. It generates a fingerprint vector for an image and compares it against a database to produce a Relative Rareness Score (0% = identical, 100% = completely unique). To provide Sense as an IBC service: - -- **IBC Request/Response Workflow**: Similar to Cascade, define an IBC application port (e.g., "sense"). Other chains (especially NFT marketplaces or minting platforms) can send a SenseRequest packet containing either the NFT data (image) or a fingerprint of the image. Lumera’s Sense module, upon receiving the request, computes the rareness score by comparing the NFT’s fingerprint against its extensive dataset (which includes NFTs from Pastel/Lumera and possibly other sources). It then returns the result in the packet acknowledgement – e.g., the score and perhaps a list of any detected duplicates or their IDs. -- **Data Input Options**: If sending full image data over IBC is too heavy, an alternative is to require the requesting chain to store the image via Cascade first, then send a Sense request referencing the stored image’s content ID. Since Lumera would then have the image data internally, the Sense module can access it directly for analysis. This two-step approach (store, then analyze) can be orchestrated via IBC: first an ICS-27 call or Cascade packet to store, then an ack or subsequent message triggers Sense. We can also consider allowing a perceptual hash or fingerprint vector to be sent instead of the raw image (if the external chain can compute the same fingerprint algorithm). However, given Sense’s sophisticated deep learning model (10,000+ dimensional fingerprint), it may be preferable to let Lumera compute it for consistency. -- **Interchain Account / Query Integration**: A chain could use an interchain account to call a MsgCheckImage on Lumera (passing an image hash or ID), which triggers Sense. The result could be written to Lumera’s state (e.g., as an event or a temporary record). The requesting chain could then use ICS-31 (cross-chain query) to read the result back if not present in the ack. Alternatively, the transaction’s success ack could carry the primary result. -- **Benefits**: Exposing Sense via IBC means any NFT minting operation on any chain can vet the uniqueness of the NFT before finalizing a mint. For example, an NFT marketplace chain could, upon mint, automatically query Lumera’s Sense service to ensure the content isn’t a copy of an existing NFT. This enhances trust and provenance across the interchain NFT ecosystem. Lumera’s service would effectively act as a decentralized plagiarism checker for digital art, accessible through a trust-minimized channel. This also drives usage of Lumera’s AI capabilities, potentially with fee payment attached per request (which could be handled via a token transfer or deduction of credits – see below). - -### Inference: AI Agents - -**Inference** is Lumera’s AI/LLM layer that brings advanced machine learning functionalities (like language models and AI-driven analysis) into the network. It integrates with providers such as OpenAI, Anthropic, and others to enable intelligent data processing and content generation in dApps. To make Inference available to other chains via IBC: - -- **Unified Service Interface**: Provide an IBC port (e.g., "inference"). Other chains can send AI task requests to this port. A request might specify the type of model or service (e.g., “run text through GPT-4 for summarization” or “classify image for NSFW content”), along with the input data or reference. Lumera’s Inference module would receive the task, route it to an appropriate supernode or external API as configured (Lumera leverages specialized nodes and possibly off-chain APIs for AI), then return the result. -- **Request Payload Format**: Because inference tasks can vary widely, we’d design a flexible message schema – including fields like model_type (or model ID), parameters, and payload. IBC v2’s ability to handle different encoding types is useful here: for instance, we might use JSON or MsgPack encoding for AI requests for readability, or a binary format if needed. The response might be textual (for chatbot replies, etc.) or binary data (for images or other media generated). Splitting large responses over multiple packets may be needed for very large outputs. -- **Stateful vs Stateless Agents**: If Lumera supports stateful AI agents (e.g., an agent that maintains context over multiple calls), we could implement a session identifier in the requests. This would allow a chain to initiate an AI agent session and continue feeding it inputs via subsequent IBC messages. However, managing long-lived sessions over IBC can be complex (timeouts, ordering, etc.), so initially we may focus on stateless query-style requests (each request yields an independent result). -- **Payment and Access Control**: The Inference protocol on Lumera uses a credit system for users (buying inference credits with PSTL). For cross-chain use, Lumera could require that the calling account (or chain) has sufficient credits or attaches payment. One approach is to use ICS-20 token transfers alongside the request: for example, a chain could escrow some PSTL on Lumera or include a fee in the request packet (if we extend the packet format to carry a fee, or simply do two IBC operations back-to-back: one token transfer, one inference request). Another approach is ICS-27: an interchain account from the requester could hold PSTL and spend the credits when making the call on Lumera’s chain. -- **Benefits**: By offering AI as a service, Lumera can become the AI co-processor for the interchain. Chains that lack the resources or desire to integrate large AI models can offload tasks to Lumera. For example, a social media chain might use Lumera to perform content moderation (by sending images/text for analysis), or a DeFi chain might use it for AI-based risk assessments. All of this can happen trustlessly via IBC. Lumera’s inference service thus expands the realm of what cross-chain applications can do, bringing Web2 AI power into Web3 ecosystems without centralized intermediaries. - -### NFT Metadata: Interchain Metadata Hub - -Lumera can also position itself as a metadata repository and verification layer for NFTs across chains. NFT metadata includes attributes, provenance info, and ownership records that might benefit from being standardized or permanently stored. - -- **Metadata Storage and Retrieval**: Lumera could maintain a registry of NFT metadata that is submitted to it via IBC. For example, when an NFT is minted on Chain A, it could send the metadata (properties, description, etc.) to Lumera for permanent storage (possibly alongside the asset itself via Cascade). Lumera would index this under a composite key (like /). Other chains could later query this metadata to verify an NFT’s details or to display them consistently. -- **Authenticity and Provenance Service**: Because Lumera can aggregate NFT information from multiple chains, it could serve as an authentication oracle. Via IBC, a chain could ask Lumera questions like “Does NFT X on chain A have a valid registration and what’s its metadata hash?” and Lumera can respond with the canonical data. This can prevent malicious actors from forging NFT details on another chain – since Lumera’s records (if widely accepted) become a source of truth. Essentially, Lumera acts as a trustless NFT metadata catalogue for the interchain. -- **Using IBC Features**: Implementing this may use a mix of ICS-27 and ICS-31. To register metadata, an interchain account on Lumera could submit a transaction (MsgRegisterMetadata) carrying the NFT’s info (or a hash of it plus a link to full content stored via Cascade). The transaction would commit the data on Lumera. Then, to retrieve metadata, ICS-31 cross-chain queries could allow any chain to fetch that data by key. If ICS-31 is not yet widely available, we could alternatively allow a direct query request packet (similar to how Sense returns a score) where a chain sends a MetadataQuery packet and Lumera replies with the data in the ack. -- **Integration with Cascade and Sense**: These services complement each other. For instance, upon storing an image via Cascade, Lumera can automatically generate a fingerprint and update the Sense index. Similarly, when metadata is registered, Lumera can ensure the corresponding asset is stored and link them. Other chains might simply call a higher-level “Register NFT” IBC method that triggers storing the asset (Cascade), storing metadata, and running Sense detection – all coordinated on Lumera’s side. Thanks to IBC v2’s design, such a complex flow could be done over one robust connection and even in one combined packet in the future (leveraging multiple payloads for different apps in one atomic submission). -- **Benefits**: Chains get immutable storage and verification of their NFT metadata, enhancing security (no more lost metadata if source chain data is pruned or altered). It fosters an interoperable NFT ecosystem: NFTs on different chains can be verified against a common reference point (Lumera), enabling cross-chain NFT marketplaces or bridges to trust the metadata consistency. Lumera in turn becomes a critical infrastructure node for NFTs, increasing usage of its network and token. - -In all of the above, the overarching idea is to transform Lumera into a suite of interchain services accessible via standard IBC channels. Each service (storage, duplicate detection, AI compute, metadata registry) would be exposed in a modular way, either through distinct IBC application ports or via general frameworks like interchain accounts. The upgrade to IBC v2 greatly aids this by making it simpler to manage multiple services over IBC and by providing the necessary flexibility in packet handling. - -## Staged Deployment Plan and Backward Compatibility - -Upgrading a live blockchain and rolling out new cross-chain services is a complex process. We propose a **phased deployment plan** to ensure a smooth transition: - -1. **Development and Internal Testing**: -In this initial phase, the dev team will implement the ibc-go v10 changes on a development branch. Extensive testing (unit tests, simulation, local networks) is conducted as described earlier. The team will also write migration scripts or an upgrade handler to automate state changes (e.g., removing module accounts for fee, capability cleanup). We will verify that a node can upgrade from the old binary to the new one without issues, and that core functionality (transactions, existing modules) remains unaffected. This phase is strictly internal and uses no external connections – focusing on code stability. -2. **Testnet Deployment (IBC v2 readiness)**: -Once confident, we will deploy the new version to a Lumera testnet. If an official public testnet exists, coordinate a specific upgrade height via governance or simply relaunch the testnet if ephemeral. On this testnet, we will: - - **Connect with Counterparty Chains**: Establish IBC connections with other testnets (e.g., Cosmos Hub’s testnet, Osmosis testnet) to ensure interoperability. This tests backward compatibility: Lumera (v2) should successfully open channels with v1 counterparties, proving that relayers and handshake downgrading work. - - **Try New Features**: If feasible, spin up a small dummy chain (or use an existing one) to act as a client of Lumera’s services. For example, demonstrate an NFT stored on Chain A being sent to Lumera for Cascade storage and Sense analysis, all on testnet. This will likely involve deploying and testing ICS-27 and ICS-31 functionality in a controlled setting. - - **Bug Fixes**: Use the findings from testnet to fix any issues. For instance, if relayers encountered errors with the new handshake, adjust parameters or inform relayer developers. Monitor the network for any instability introduced by the new code. -3. **Audit and Review (Optional)**: -Given the scope of changes (IBC being critical infrastructure), it may be prudent to have an **external audit** of the upgrade implementation, especially the custom logic for new service modules. Auditors would review the IBC upgrade diff as well as the new IBC application modules for Cascade, Sense, etc. This can run in parallel with extended testnet runs. Community testing and bug bounty programs on the testnet could further harden the code. -4. **Mainnet Upgrade Preparation**: -Prior to scheduling the upgrade on mainnet, coordinate with all stakeholders: - - **Validator Coordination**: Communicate the planned upgrade (block height or governance proposal) well in advance. Provide upgrade instructions and binaries to validators. Emphasize that this upgrade is significant (new IBC version) and encourage them to test their nodes on the testnet or a dry-run. - - **Relayer Coordination**: Reach out to major relayer operators in the Cosmos ecosystem (who facilitate Lumera’s IBC transactions) and inform them of the upgrade timeline. Since ibc-go v10 still supports IBC classic, relayers can continue operating normally for existing channels. However, to use the new IBC v2 features (like connecting to Ethereum via ZK light clients, etc.), they might need to update their relayer software to versions that know about IBC v2. We ensure that at least one well-maintained relayer (like Hermes) has a release supporting ibc-go v10. - - **Governance Proposal**: If Lumera uses on-chain governance for upgrades, draft a proposal describing the upgrade (including benefits like those outlined above). Highlight that from an operations perspective, nothing drastic will change initially – e.g., “IBC will continue to function as before for users” to alleviate concerns. Garner support by outlining new possibilities post-upgrade. -5. **Mainnet Upgrade Execution**: -At the scheduled time (or height), the Lumera mainnet will undergo the upgrade. Validators will switch to the new binary containing ibc-go v10. Post-upgrade: - - **Stability Checks**: Confirm that the chain produces blocks and that all modules (bank, staking, etc.) are running fine. Then specifically check the IBC module: all existing IBC channels and clients should be listed and active. Because we removed the capability module, we will verify that existing channel state is accessible (ibc-go v10 should internally manage channel references now). If any existing channel is non-functional, we might coordinate with the connected chain to reopen a connection using the new protocol, but this is unlikely since backward support is in place. - - **Backward Compatibility**: Ensure that **IBC Classic channels continue seamlessly**. According to IBC developers, Cosmos chains upgrading to v2 see no interruption in normal IBC operations – light clients still verify proofs, relayers still relay packets in the same way. We will test a token transfer over an old channel as soon as the chain is up to confirm this. In the unlikely event of an issue (say, the channel capability was lost), our fallback plan would involve using governance or admin authority to recreate channel bindings or ask users to migrate to a new channel. However, given the design of ibc-go v10, such disruption is not expected. - - **Monitoring**: Closely monitor the mempool and blockchain for any IBC errors, and watch relayer logs. It’s critical to catch any unexpected bugs early. We’ll also keep communication open with relayers for quick troubleshooting. -6. **Phased Rollout of New Services**: -With the core upgrade live, we can begin enabling the new IBC services of Lumera in phases: - - **Enable ICS-27 Interchain Accounts**: Activate the ICA host module on Lumera via a parameter change or simply by usage (if compiled in, it may be live by default). Announce that other chains can now open interchain accounts on Lumera. Initially, whitelist some partner chains to try out controlling Lumera accounts to use Cascade or Sense. This careful approach ensures the feature is used in a controlled manner before broad exposure. - - **Offer Cascade and Sense on Testnet/Mainnet**: Possibly launch a beta program where select projects integrate with Cascade or Sense via IBC. For example, an NFT marketplace could try storing their new mints on Lumera and retrieving the Sense score. Their feedback will help refine the modules. On-chain, this might involve opening dedicated IBC channels for those services (if not using ICA). We will monitor these channels for correct behavior (packet flow, acknowledgements). Over time, as confidence grows, make these services publicly available to any chain that connects. - - **Documentation and SDKs**: To encourage adoption, produce documentation and possibly SDK support for Lumera’s IBC endpoints (e.g., a developer guide on how another chain can send a Cascade storage request, including code examples). This will likely be done as we enable the services. - - **Inference Service Rollout**: The AI inference service might be introduced a bit later given its complexity. We may run a pilot where Lumera connects with a specific chain (or an application) that wants to leverage AI. During this stage, we’ll fine-tune pricing, performance, and security (since calling external AI APIs has different considerations). Once stable, open it up as an interchain service similar to Cascade and Sense. - - **NFT Metadata and Query Services**: Establish Lumera as an interchain NFT metadata hub by onboarding a few chains to push their metadata to Lumera. Ensure that our cross-chain query implementation (if using ICS-31) is working so those chains can fetch the info. Over time, advertise this as a general service. -7. **Post-Upgrade Evaluation and Maintenance**: -After full deployment, conduct an evaluation of the upgrade’s impact: - - **Performance Metrics**: Review if block processing times for IBC transactions improved and if the throughput of IBC packets increased. Check if relayer fees or latencies dropped due to the more efficient protocol. - - **Reliability**: Gather data on any IBC packet failures or unexpected behavior. If the new multi-app single-connection approach caused any hiccups, patch as needed. For instance, ensure that if one service’s logic fails, it doesn’t block the whole connection’s packets (the router should isolate apps by port). - - **Backward Compatibility Period**: Plan to support IBC classic channels for as long as needed. Cosmos chains will gradually all upgrade to v2, but in the interim, Lumera may operate with some classic channels. We’ll maintain code paths for IBC v1 as provided by ibc-go v10 until we are sure they are no longer used. Thereafter, we might deprecate those for cleanliness (perhaps in a future release). - - **Security Monitoring**: New features mean new surface area. Keep a close watch on cross-chain transactions invoking Lumera’s services to detect any abuse or vulnerabilities (e.g., denial-of-service via spammy requests, or attempts to exploit the AI services). Rate limiting or fee requirements may be adjusted based on real usage patterns. - -Throughout this process, **communication is key**. We will keep the Lumera community and partners informed at each stage, with clear documentation of changes. By proceeding methodically through testnet trials, mainnet upgrade, and gradual feature rollout, we aim to minimize disruptions and ensure that the transition to IBC v2 and the launch of cross-chain services are successful. Lumera will emerge from this process not only up-to-date with the latest interchain protocol, but positioned as a **leader in cross-chain utility**, providing valuable services across the interchain ecosystem. - -## Setting Up IBC Communication with Other Chains - -After Lumera is upgraded to use IBC-Go v10 (IBC v2), establishing connections with other chains requires configuring ports, using relayers, and setting up IBC clients, connections, and channels. Here's a step-by-step guide: - -### ✅ Prerequisites (for Lumera and the remote chain) - -- Both chains must: - - Be running Cosmos SDK with IBC-Go (v1 or v2). - - Enable required IBC modules in `app.go`. - - Be publicly accessible via RPC, GRPC, and P2P ports. - - Have relayer access (Hermes or Go Relayer). - -### 🔧 Step 1: Configure IBC Ports and Applications in `app.go` - -```go -ibcRouter.AddRoute("transfer", transferIBCModule) -ibcRouter.AddRoute("cascade", cascadeIBCModule) -ibcRouter.AddRoute("sense", senseIBCModule) -ibcRouter.AddRoute("inference", inferenceIBCModule) -ibcRouter.AddRoute(icacontrollertypes.ModuleName, icacontrollerIBCModule) -ibcRouter.AddRoute(icahosttypes.ModuleName, icahostIBCModule) -``` - -### 🔁 Step 2: Relayer Configuration (Hermes example) - -#### Create Hermes config - -The official website for the Hermes IBC Relayer is [hermes.informal.systems](https://hermes.informal.systems). -```toml -[[chains]] -id = "lumera" -rpc_addr = "http://:26657" -grpc_addr = "http://:9090" -websocket_addr = "ws://:26657/websocket" -account_prefix = "lum" # or "tP" for testnet -... - -[[chains]] -id = "osmosis-1" -rpc_addr = "https://rpc-osmosis.blockapsis.com:443" -grpc_addr = "https://grpc-osmosis.blockapsis.com:443" -websocket_addr = "wss://rpc-osmosis.blockapsis.com/websocket" -account_prefix = "osmo" -... -``` - -#### Add keys - -```bash -hermes keys add --chain lumera --mnemonic-file lumera.mnemonic -hermes keys add --chain osmosis-1 --mnemonic-file osmosis.mnemonic -``` - -### 🔌 Step 3: Create IBC Client, Connection, Channel with Osmosis - -```bash -# Create client -hermes create client --host-chain lumera --counterparty-chain osmosis-1 - -# Create connection -hermes create connection --a-chain lumera --b-chain osmosis-1 - -# Create channel for ICS-20 -hermes create channel --a-chain lumera --a-port transfer --b-chain osmosis-1 --b-port transfer --order unordered --channel-version transfer - -# Or for a custom service (e.g., cascade) -hermes create channel --a-chain lumera --a-port cascade --b-chain osmosis-1 --b-port cascade --order ordered --channel-version 1 -``` - -### 🧪 Step 4: Test Packet Relay - -- Send a transaction (ICS-20, Cascade request, etc.) -- Observe relayer processing packet and acknowledgment - -### 📦 Step 5: Optional — Set Up Interchain Accounts (ICS-27) - -An **Interchain Account** allows Chain A (*the controller chain*) to: - -- Create and control an account on Chain B (*the host chain*) -- Submit arbitrary Cosmos SDK messages (like MsgSend, MsgDelegate, or even custom messages) -- Do this over IBC, securely and permissionlessly - -So instead of Chain A asking users to send tokens or interact with Chain B manually, Chain A can act on their behalf directly on Chain B. -For example, some other chain could create an ICA on Lumera, then invoke MsgStoreFile (Cascade), MsgAnalyzeImage (Sense) or MsgRunInference (Inference). - -1. **Create ICA channel**: - - ```bash - hermes create channel --a-port icacontroller --b-port icahost --order ordered --channel-version icacontroller-1 - ``` - -2. Send `MsgSendTx` from controller chain to Lumera via ICA -3. Lumera processes and emits event or result - -### ✅ Summary -| Task | Who | Command / Config | -|------|-----|------------------| -| Enable IBC apps | Lumera devs | `app.go`, add routes | -| Run relayer | Operator | Hermes / Go Relayer setup | -| Add keys | Operator | `hermes keys add` | -| Open connection/channel | Operator | Hermes CLI | -| Test services | Any | Send IBC tx, confirm ack | - -These steps ensure a smooth and secure IBC setup for cross-chain communication between Lumera and partner chains like Osmosis. \ No newline at end of file +- **Upstream fixes**: Pick up v10-series fixes and maintenance improvements, reducing the risk of carrying known IBC bugs. +- **Developer ergonomics**: Use newer helper APIs (including v1/v2 event parsing) to reduce custom code in Lumera. +- **Ecosystem alignment**: Stay on the latest v10 patch level for relayer compatibility and support. diff --git a/docs/upgrade.md b/docs/upgrade.md new file mode 100644 index 00000000..cd1920ce --- /dev/null +++ b/docs/upgrade.md @@ -0,0 +1,84 @@ +# Benefits of upgrading Lumera from Cosmos SDK 0.50.x to 0.53.5 + +## Cosmos SDK upgrade benefits + +### App wiring modernization + +- **Declarative app wiring (depinject + core/appconfig)**: Replaces much of historical app.go wiring with declarative config (Go/YAML/JSON), improving modularity and reducing initialization boilerplate. +- **runtime/v2 AppBuilder support**: Enables hybrid setups (part declarative, part classic app.go), making it easier to evolve app composition over time. + +### Interchain readiness + +- **IBC v2 readiness**: Aligns with the IBC-Go v10 stack and its v2 features while keeping IBC v1 compatibility for existing channels. +- **Interchain feature enablement**: Paves the way for modern interchain features (ICA, IBC v2 routes, improved packet workflows) without heavy custom shims. + +### Core modules and optional features + +- **Module parity and compatibility**: Brings core modules (gov, staking, auth, bank, feegrant, evidence, circuit, etc.) to current versions, improving ecosystem alignment and upstream support. + +#### New optional modules and features + +- **x/epochs**: Standardized on-chain timers ("run logic every N period") that other modules can hook into. +- **x/protocolpool**: Separates community-pool accounting from distribution into a dedicated module account, making pool assets easier to track and manage. +- **Unordered transactions (opt-in)**: "Fire-and-forget" submission model with `timeout_timestamp` as TTL/replay protection, useful for throughput-focused clients where strict ordering is not required. + +### Parameter and consensus-params cleanup + +- **x/params deprecation**: `x/params` is deprecated as of SDK v0.53 (planned removal next release), so upgrading aligns Lumera with current ecosystem cleanup. +- **Consensus params migration**: The SDK calls out moving CometBFT consensus params from `x/params` to `x/consensus`; upgrade handlers should ensure `ConsensusParamsKeeper.Set()` is invoked appropriately. + +### Deprecations that reduce bloat + +- **x/crisis deprecation/removal**: `x/crisis` is deprecated as of SDK v0.53 (planned removal next release). Lumera removes it in the v1.10.0 upgrade, deletes its store key, and disables crisis invariants by default. + +### Testing, stability, and operations + +- **Testing and tooling maturity**: Updated test helpers, BaseApp options, and CLI utilities reduce local workarounds and make test scaffolding more consistent. +- **Performance and stability**: Accumulates patch-level fixes across the 0.5x series, improving reliability for production workloads and upgrade safety. +- **Operational consistency**: Keeps Lumera closer to current Cosmos SDK practices, making it easier to adopt upstream fixes and collaborate with the ecosystem. +- **Upgrade process enhancements (ADR-047)**: Upgrade module and cosmovisor flow support richer upgrade-plan information, enabling more structured and automatable upgrade operations. + +### Client and indexer impact + +- **Legacy tx logs removed**: SDK v0.53 no longer constructs "legacy logs" for tx query/broadcast responses, which can affect indexers or clients parsing legacy log shapes. + +## IBC upgrade benefits + +### Benefits of upgrading to IBC v2 (IBC-Go v10) + +- **Backward compatibility**: Keep IBC v1 channels while enabling IBC v2, so Lumera can upgrade without forcing counterparties to move immediately. +- **Simplified handshakes**: Reduce connection and channel setup time, lowering relayer overhead and speeding new integrations. +- **Unified routing**: Support multiple Lumera services (Cascade, Sense, Inference, NFT metadata) over a single connection, improving composability and reducing channel sprawl. +- **Payload flexibility**: Allow app-specific encodings and multi-action workflows (e.g., payment + service request in one flow) with less protocol friction. +- **Faster feature adoption**: Enable ICA, queries, and cross-chain calls without reworking the IBC stack as new apps are added. +- **Lower maintenance risk**: Trim the IBC module stack, reducing upgrade risk during the Cosmos SDK 0.53.5 transition while improving long-term scalability. + +### Benefits of upgrading to IBC-Go v10.5.0 + +- **Upstream fixes**: Pick up v10-series fixes and maintenance improvements, reducing the risk of carrying known IBC bugs. +- **Developer ergonomics**: Use newer helper APIs (including v1/v2 event parsing) to reduce custom code in Lumera. +- **Ecosystem alignment**: Stay on the latest v10 patch level for relayer compatibility and support. +- **ICA integrity hardening**: Adds extra validations for ProtoJSON-encoded ICA packets; release notes flag this as state-breaking and best rolled out via a coordinated chain upgrade. + +## Wasm upgrade benefits + +### Benefits of upgrading wasmd from 0.55 to 0.61.6 + +- **Ecosystem alignment**: Match current CosmWasm/wasmd releases commonly used alongside Cosmos SDK 0.53.5. +- **Consensus-sensitive VM upgrade**: wasmvm minor version bumps are generally consensus-breaking per wasmd compatibility notes, so this is a deliberate chain-level upgrade rather than a routine dependency bump. +- **Contract compatibility**: The contract-host interface has been stable since CosmWasm 1.0; CosmWasm 2.0 contracts remain compatible at the Wasm interface level (capabilities gated via feature flags). +- **Operational tuning hooks**: wasmd exposes knobs like `memory_cache_size` (module caching for faster instantiation) and `query_gas_limit` for performance and safety tradeoffs. +- **Security posture**: Includes fixes for consensus-critical issues (for example, non-deterministic crashes during wasm execution simulation patched in wasmvm/wasmd), strengthening chain safety. + +### Benefits of upgrading wasmvm to 3.0.2 + +- **Runtime stability**: Pick up wasmvm bug fixes and runtime hardening from the 3.x line. +- **Compatibility**: Keep contract execution compatible with modern wasm tooling and wasmd expectations. +- **Operational reliability**: Reduce risk of edge-case failures in contract execution and state sync workflows. + +## Notable changes in Lumera + +- **IBC-Go v10.5.0 alignment**: Updated IBC dependencies and test utilities to the v10 line, including v2 packet/event handling and mocks. +- **Wasm stack refresh**: Bumped wasmd/wasmvm to the current compatible versions, keeping CosmWasm integration aligned with the SDK upgrade. +- **Test harness updates**: Ported and adjusted wasm and IBC testing helpers to match newer SDK/IBC behaviors, reducing drift from upstream. +- **Crisis module removal**: The v1.10.0 upgrade drops `x/crisis`, deletes its store key, and removes invariant checks via the crisis module. diff --git a/go.mod b/go.mod index 7e8f800d..33564546 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/LumeraProtocol/lumera go 1.25.5 replace ( - github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.50.14 github.com/envoyproxy/protoc-gen-validate => github.com/bufbuild/protoc-gen-validate v1.3.0 github.com/lyft/protoc-gen-validate => github.com/envoyproxy/protoc-gen-validate v1.3.0 // replace broken goleveldb @@ -13,35 +12,34 @@ replace ( require ( cosmossdk.io/api v0.9.2 - cosmossdk.io/client/v2 v2.0.0-beta.8.0.20250402172810-41e3e9d004a1 - cosmossdk.io/collections v1.3.0 + cosmossdk.io/client/v2 v2.0.0-beta.11 + cosmossdk.io/collections v1.3.1 cosmossdk.io/core v0.11.3 - cosmossdk.io/depinject v1.2.0 + cosmossdk.io/depinject v1.2.1 cosmossdk.io/errors v1.0.2 - cosmossdk.io/log v1.6.0 + cosmossdk.io/log v1.6.1 cosmossdk.io/math v1.5.3 cosmossdk.io/store v1.1.2 cosmossdk.io/tools/confix v0.1.2 - cosmossdk.io/x/circuit v0.1.1 - cosmossdk.io/x/evidence v0.1.1 - cosmossdk.io/x/feegrant v0.1.1 + cosmossdk.io/x/circuit v0.2.0 + cosmossdk.io/x/evidence v0.2.0 + cosmossdk.io/x/feegrant v0.2.0 cosmossdk.io/x/tx v0.14.0 cosmossdk.io/x/upgrade v0.2.0 - github.com/CosmWasm/wasmd v0.55.0-ibc2.0 - github.com/CosmWasm/wasmvm/v3 v3.0.0-ibc2.0 + github.com/CosmWasm/wasmd v0.61.6 + github.com/CosmWasm/wasmvm/v3 v3.0.2 github.com/DataDog/zstd v1.5.7 github.com/Masterminds/semver/v3 v3.3.1 github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce - github.com/cometbft/cometbft v0.38.18 + github.com/cometbft/cometbft v0.38.20 github.com/cosmos/btcutil v1.0.5 - github.com/cosmos/cosmos-db v1.1.2 + github.com/cosmos/cosmos-db v1.1.3 github.com/cosmos/cosmos-proto v1.0.0-beta.5 - github.com/cosmos/cosmos-sdk v0.53.0 + github.com/cosmos/cosmos-sdk v0.53.5 github.com/cosmos/go-bip39 v1.0.0 - github.com/cosmos/gogoproto v1.7.0 + github.com/cosmos/gogoproto v1.7.2 github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v10 v10.1.0 - github.com/cosmos/ibc-go/v10 v10.3.0 - github.com/golang/mock v1.6.0 + github.com/cosmos/ibc-go/v10 v10.5.0 github.com/golang/protobuf v1.5.4 github.com/gorilla/mux v1.8.1 github.com/grpc-ecosystem/grpc-gateway v1.16.0 @@ -51,11 +49,11 @@ require ( github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 go.uber.org/mock v0.6.0 - golang.org/x/crypto v0.43.0 - golang.org/x/sync v0.17.0 + golang.org/x/crypto v0.47.0 + golang.org/x/sync v0.19.0 google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 google.golang.org/grpc v1.77.0 - google.golang.org/protobuf v1.36.10 + google.golang.org/protobuf v1.36.11 gotest.tools/v3 v3.5.2 lukechampine.com/blake3 v1.4.1 lukechampine.com/uint128 v1.3.0 @@ -79,7 +77,7 @@ require ( buf.build/go/standard v0.1.0 // indirect cel.dev/expr v0.24.0 // indirect cloud.google.com/go v0.120.0 // indirect - cloud.google.com/go/auth v0.16.0 // indirect + cloud.google.com/go/auth v0.16.4 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.5.2 // indirect @@ -119,7 +117,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.2.0 // indirect - github.com/bits-and-blooms/bitset v1.22.0 // indirect + github.com/bits-and-blooms/bitset v1.24.3 // indirect github.com/bkielbasa/cyclop v1.2.3 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect github.com/bombsimon/wsl/v4 v4.5.0 // indirect @@ -131,8 +129,8 @@ require ( github.com/butuzov/ireturn v0.3.1 // indirect github.com/butuzov/mirror v1.3.0 // indirect github.com/bytedance/gopkg v0.1.3 // indirect - github.com/bytedance/sonic v1.14.1 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/bytedance/sonic v1.14.2 // indirect + github.com/bytedance/sonic/loader v0.4.0 // indirect github.com/catenacyber/perfsprint v0.8.2 // indirect github.com/ccojocar/zxcvbn-go v1.0.2 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect @@ -155,9 +153,9 @@ require ( github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.17.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect - github.com/cosmos/iavl v1.2.4 // indirect + github.com/cosmos/iavl v1.2.6 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect - github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.16.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/creachadair/atomicfile v0.3.1 // indirect github.com/creachadair/tomledit v0.0.24 // indirect @@ -169,7 +167,7 @@ require ( github.com/denis-tingaikin/go-header v0.5.0 // indirect github.com/desertbit/timer v1.0.1 // indirect github.com/dgraph-io/badger/v4 v4.2.0 // indirect - github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgraph-io/ristretto v0.2.0 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/cli v28.4.0+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect @@ -190,7 +188,7 @@ require ( github.com/firefart/nonamedreturns v1.0.5 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/getsentry/sentry-go v0.32.0 // indirect + github.com/getsentry/sentry-go v0.35.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/ghostiam/protogetter v0.3.9 // indirect github.com/go-chi/chi/v5 v5.2.3 // indirect @@ -212,13 +210,12 @@ require ( github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/gobwas/ws v1.2.1 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.12.1 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.2.5 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect github.com/golangci/go-printf-func-name v0.1.0 // indirect @@ -239,7 +236,7 @@ require ( github.com/google/s2a-go v0.1.9 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect - github.com/googleapis/gax-go/v2 v2.14.1 // indirect + github.com/googleapis/gax-go/v2 v2.15.0 // indirect github.com/gordonklaus/ineffassign v0.1.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/websocket v1.5.3 // indirect @@ -251,7 +248,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-getter v1.7.8 // indirect + github.com/hashicorp/go-getter v1.7.9 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect @@ -304,10 +301,10 @@ require ( github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mdp/qrterminal/v3 v3.2.1 // indirect github.com/mgechev/revive v1.7.0 // indirect github.com/minio/highwayhash v1.0.3 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/term v0.5.2 // indirect github.com/moricho/tparallel v0.3.2 // indirect @@ -331,10 +328,10 @@ require ( github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polyfloyd/go-errorlint v1.7.1 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.63.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect @@ -360,7 +357,7 @@ require ( github.com/securego/gosec/v2 v2.22.2 // indirect github.com/segmentio/asm v1.2.0 // indirect github.com/segmentio/encoding v0.5.3 // indirect - github.com/shamaton/msgpack/v2 v2.2.0 // indirect + github.com/shamaton/msgpack/v2 v2.2.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect github.com/sivchari/tenv v1.12.1 // indirect @@ -386,7 +383,7 @@ require ( github.com/tomarrell/wrapcheck/v2 v2.10.0 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ulikunitz/xz v0.5.11 // indirect + github.com/ulikunitz/xz v0.5.14 // indirect github.com/ultraware/funlen v0.2.0 // indirect github.com/ultraware/whitespace v0.2.0 // indirect github.com/uudashr/gocognit v1.2.0 // indirect @@ -396,8 +393,9 @@ require ( github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect + github.com/zondax/golem v0.27.0 // indirect github.com/zondax/hid v0.9.2 // indirect - github.com/zondax/ledger-go v0.14.3 // indirect + github.com/zondax/ledger-go v1.0.1 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect go-simpler.org/musttag v0.13.0 // indirect go-simpler.org/sloglint v0.9.0 // indirect @@ -409,7 +407,7 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.38.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect go.opentelemetry.io/otel/metric v1.38.0 // indirect @@ -419,21 +417,22 @@ require ( go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/arch v0.15.0 // indirect + golang.org/x/arch v0.17.0 // indirect golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/mod v0.28.0 // indirect - golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 // indirect + golang.org/x/mod v0.31.0 // indirect + golang.org/x/net v0.48.0 // indirect golang.org/x/oauth2 v0.32.0 // indirect - golang.org/x/sys v0.37.0 // indirect - golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect - golang.org/x/term v0.36.0 // indirect - golang.org/x/text v0.30.0 // indirect - golang.org/x/time v0.11.0 // indirect - golang.org/x/tools v0.37.0 // indirect - google.golang.org/api v0.229.0 // indirect - google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc // indirect + golang.org/x/term v0.39.0 // indirect + golang.org/x/text v0.33.0 // indirect + golang.org/x/time v0.12.0 // indirect + golang.org/x/tools v0.40.0 // indirect + google.golang.org/api v0.247.0 // indirect + google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -443,7 +442,8 @@ require ( mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect nhooyr.io/websocket v1.8.17 // indirect pluginrpc.com/pluginrpc v0.5.0 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + rsc.io/qr v0.2.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) tool ( diff --git a/go.sum b/go.sum index 0f845f7a..d7483dad 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,8 @@ cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVo cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= -cloud.google.com/go/auth v0.16.0 h1:Pd8P1s9WkcrBE2n/PhAwKsdrR35V3Sg2II9B+ndM3CU= -cloud.google.com/go/auth v0.16.0/go.mod h1:1howDHJ5IETh/LwYs3ZxvlkXF48aSqqJUM+5o02dNOI= +cloud.google.com/go/auth v0.16.4 h1:fXOAIQmkApVvcIn7Pc2+5J8QTMVbUGLscnSVNl11su8= +cloud.google.com/go/auth v0.16.4/go.mod h1:j10ncYwjX/g3cdX7GpEzsdM+d+ZNsXAbb6qXA7p1Y5M= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= @@ -648,18 +648,18 @@ connectrpc.com/otelconnect v0.8.0 h1:a4qrN4H8aEE2jAoCxheZYYfEjXMgVPyL9OzPQLBEFXU connectrpc.com/otelconnect v0.8.0/go.mod h1:AEkVLjCPXra+ObGFCOClcJkNjS7zPaQSqvO0lCyjfZc= cosmossdk.io/api v0.9.2 h1:9i9ptOBdmoIEVEVWLtYYHjxZonlF/aOVODLFaxpmNtg= cosmossdk.io/api v0.9.2/go.mod h1:CWt31nVohvoPMTlPv+mMNCtC0a7BqRdESjCsstHcTkU= -cosmossdk.io/client/v2 v2.0.0-beta.8.0.20250402172810-41e3e9d004a1 h1:nlMUeKu6CGrO7Gxt5S31qT3g27CHmBJHsZPjqHApVTI= -cosmossdk.io/client/v2 v2.0.0-beta.8.0.20250402172810-41e3e9d004a1/go.mod h1:xgv0ejeOk5yeDraPW5tv+PfBkCDt4yYa/+u45MyP+bM= -cosmossdk.io/collections v1.3.0 h1:RUY23xXBy/bu5oSHZ5y+mkJRyA4ZboKDO4Yvx4+g2uc= -cosmossdk.io/collections v1.3.0/go.mod h1:cqVpBMDGEYhuNmNSXIOmqpnQ7Eav43hpJIetzLuEkns= +cosmossdk.io/client/v2 v2.0.0-beta.11 h1:iHbjDw/NuNz2OVaPmx0iE9eu2HrbX+WAv2u9guRcd6o= +cosmossdk.io/client/v2 v2.0.0-beta.11/go.mod h1:ZmmxMUpALO2r1aG6fNOonE7f8I1g/WsafJgVAeQ0ffs= +cosmossdk.io/collections v1.3.1 h1:09e+DUId2brWsNOQ4nrk+bprVmMUaDH9xvtZkeqIjVw= +cosmossdk.io/collections v1.3.1/go.mod h1:ynvkP0r5ruAjbmedE+vQ07MT6OtJ0ZIDKrtJHK7Q/4c= cosmossdk.io/core v0.11.3 h1:mei+MVDJOwIjIniaKelE3jPDqShCc/F4LkNNHh+4yfo= cosmossdk.io/core v0.11.3/go.mod h1:9rL4RE1uDt5AJ4Tg55sYyHWXA16VmpHgbe0PbJc6N2Y= -cosmossdk.io/depinject v1.2.0 h1:6NW/FSK1IkWTrX7XxUpBmX1QMBozpEI9SsWkKTBc5zw= -cosmossdk.io/depinject v1.2.0/go.mod h1:pvitjtUxZZZTQESKNS9KhGjWVslJZxtO9VooRJYyPjk= +cosmossdk.io/depinject v1.2.1 h1:eD6FxkIjlVaNZT+dXTQuwQTKZrFZ4UrfCq1RKgzyhMw= +cosmossdk.io/depinject v1.2.1/go.mod h1:lqQEycz0H2JXqvOgVwTsjEdMI0plswI7p6KX+MVqFOM= cosmossdk.io/errors v1.0.2 h1:wcYiJz08HThbWxd/L4jObeLaLySopyyuUFB5w4AGpCo= cosmossdk.io/errors v1.0.2/go.mod h1:0rjgiHkftRYPj//3DrD6y8hcm40HcPv/dR4R/4efr0k= -cosmossdk.io/log v1.6.0 h1:SJIOmJ059wi1piyRgNRXKXhlDXGqnB5eQwhcZKv2tOk= -cosmossdk.io/log v1.6.0/go.mod h1:5cXXBvfBkR2/BcXmosdCSLXllvgSjphrrDVdfVRmBGM= +cosmossdk.io/log v1.6.1 h1:YXNwAgbDwMEKwDlCdH8vPcoggma48MgZrTQXCfmMBeI= +cosmossdk.io/log v1.6.1/go.mod h1:gMwsWyyDBjpdG9u2avCFdysXqxq28WJapJvu+vF1y+E= cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= cosmossdk.io/schema v1.1.0 h1:mmpuz3dzouCoyjjcMcA/xHBEmMChN+EHh8EHxHRHhzE= @@ -668,12 +668,12 @@ cosmossdk.io/store v1.1.2 h1:3HOZG8+CuThREKv6cn3WSohAc6yccxO3hLzwK6rBC7o= cosmossdk.io/store v1.1.2/go.mod h1:60rAGzTHevGm592kFhiUVkNC9w7gooSEn5iUBPzHQ6A= cosmossdk.io/tools/confix v0.1.2 h1:2hoM1oFCNisd0ltSAAZw2i4ponARPmlhuNu3yy0VwI4= cosmossdk.io/tools/confix v0.1.2/go.mod h1:7XfcbK9sC/KNgVGxgLM0BrFbVcR/+6Dg7MFfpx7duYo= -cosmossdk.io/x/circuit v0.1.1 h1:KPJCnLChWrxD4jLwUiuQaf5mFD/1m7Omyo7oooefBVQ= -cosmossdk.io/x/circuit v0.1.1/go.mod h1:B6f/urRuQH8gjt4eLIXfZJucrbreuYrKh5CSjaOxr+Q= -cosmossdk.io/x/evidence v0.1.1 h1:Ks+BLTa3uftFpElLTDp9L76t2b58htjVbSZ86aoK/E4= -cosmossdk.io/x/evidence v0.1.1/go.mod h1:OoDsWlbtuyqS70LY51aX8FBTvguQqvFrt78qL7UzeNc= -cosmossdk.io/x/feegrant v0.1.1 h1:EKFWOeo/pup0yF0svDisWWKAA9Zags6Zd0P3nRvVvw8= -cosmossdk.io/x/feegrant v0.1.1/go.mod h1:2GjVVxX6G2fta8LWj7pC/ytHjryA6MHAJroBWHFNiEQ= +cosmossdk.io/x/circuit v0.2.0 h1:RJPMBQWCQU77EcM9HDTBnqRhq21fcUxgWZl7BZylJZo= +cosmossdk.io/x/circuit v0.2.0/go.mod h1:CjiGXDeZs64nMv0fG+QmvGVTcn7n3Sv4cDszMRR2JqU= +cosmossdk.io/x/evidence v0.2.0 h1:o72zbmgCM7U0v7z7b0XnMB+NqX0tFamqb1HHkQbhrZ0= +cosmossdk.io/x/evidence v0.2.0/go.mod h1:zx/Xqy+hnGVzkqVuVuvmP9KsO6YCl4SfbAetYi+k+sE= +cosmossdk.io/x/feegrant v0.2.0 h1:oq3WVpoJdxko/XgWmpib63V1mYy9ZQN/1qxDajwGzJ8= +cosmossdk.io/x/feegrant v0.2.0/go.mod h1:9CutZbmhulk/Yo6tQSVD5LG8Lk40ZAQ1OX4d1CODWAE= cosmossdk.io/x/tx v0.14.0 h1:hB3O25kIcyDW/7kMTLMaO8Ripj3yqs5imceVd6c/heA= cosmossdk.io/x/tx v0.14.0/go.mod h1:Tn30rSRA1PRfdGB3Yz55W4Sn6EIutr9xtMKSHij+9PM= cosmossdk.io/x/upgrade v0.2.0 h1:ZHy0xny3wBCSLomyhE06+UmQHWO8cYlVYjfFAJxjz5g= @@ -703,10 +703,10 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CosmWasm/wasmd v0.55.0-ibc2.0 h1:9bH+QDnSGxmZhjSykLYGtW4sltzGFFVm10Awk683q2Y= -github.com/CosmWasm/wasmd v0.55.0-ibc2.0/go.mod h1:c9l+eycjUB2zNVLIGjAXd7QrFEbxVTEa1Fh1Mx74VwQ= -github.com/CosmWasm/wasmvm/v3 v3.0.0-ibc2.0 h1:QoagSm5iYuRSPYDxgRxsa6hVfDppUp4+bOwY7bDuMO0= -github.com/CosmWasm/wasmvm/v3 v3.0.0-ibc2.0/go.mod h1:oknpb1bFERvvKcY7vHRp1F/Y/z66xVrsl7n9uWkOAlM= +github.com/CosmWasm/wasmd v0.61.6 h1:wa1rY/mZi8OYnf0f6a02N7o3vBockOfL3P37hSH0XtY= +github.com/CosmWasm/wasmd v0.61.6/go.mod h1:Wg2gfY2qrjjFY8UvpkTCRdy8t67qebOQn7UvRiGRzDw= +github.com/CosmWasm/wasmvm/v3 v3.0.2 h1:+MLkOX+IdklITLqfG26PCFv5OXdZvNb8z5Wq5JFXTRM= +github.com/CosmWasm/wasmvm/v3 v3.0.2/go.mod h1:oknpb1bFERvvKcY7vHRp1F/Y/z66xVrsl7n9uWkOAlM= github.com/Crocmagnon/fatcontext v0.7.1 h1:SC/VIbRRZQeQWj/TcQBS6JmrXcfA+BU4OGSVUt54PjM= github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= @@ -802,8 +802,8 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4= -github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.24.3 h1:Bte86SlO3lwPQqww+7BE9ZuUCKIjfqnG5jtEyqA9y9Y= +github.com/bits-and-blooms/bitset v1.24.3/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w= github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= @@ -818,8 +818,8 @@ github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAd github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= -github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcec/v2 v2.3.5 h1:dpAlnAwmT1yIBm3exhT1/8iUSD98RDJM5vqJVQDQLiU= +github.com/btcsuite/btcd/btcec/v2 v2.3.5/go.mod h1:m22FrOAiuxl/tht9wIqAoGHcbnCCaPWyauO8y2LGGtQ= github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= @@ -845,10 +845,10 @@ github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= -github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w= -github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc= -github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= -github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE= +github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980= +github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o= +github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/catenacyber/perfsprint v0.8.2 h1:+o9zVmCSVa7M4MvabsWvESEhpsMkhfE7k0sHNGL95yw= github.com/catenacyber/perfsprint v0.8.2/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= @@ -924,8 +924,8 @@ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1: github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coder/websocket v1.8.7 h1:jiep6gmlfP/yq2w1gBoubJEXL9gf8x3bp6lzzX8nJxE= github.com/coder/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -github.com/cometbft/cometbft v0.38.18 h1:1ZHYMdu0S75YxFM13LlPXnOwiIpUW5z9TKMQtTIALpw= -github.com/cometbft/cometbft v0.38.18/go.mod h1:PlOQgf3jQorep+g6oVnJgtP65TJvBJoLiXjGaMdNxBE= +github.com/cometbft/cometbft v0.38.20 h1:i9v9rvh3Z4CZvGSWrByAOpiqNq5WLkat3r/tE/B49RU= +github.com/cometbft/cometbft v0.38.20/go.mod h1:UCu8dlHqvkAsmAFmWDRWNZJPlu6ya2fTWZlDrWsivwo= github.com/cometbft/cometbft-db v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -944,29 +944,29 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.2 h1:KZm4xLlPp6rLkyIOmPOhh+XDK9oH1++pNH/csLdX0Dk= -github.com/cosmos/cosmos-db v1.1.2/go.mod h1:dMg2gav979Ig2N076POEw4CEKbCsieaOfDWSfFZxs8M= +github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOPY= +github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.50.14 h1:G8CtGHFWbExa+ZpVOVAb4kFmko/R30igsYOwyzRMtgY= -github.com/cosmos/cosmos-sdk v0.50.14/go.mod h1:hrWEFMU1eoXqLJeE6VVESpJDQH67FS1nnMrQIjO2daw= +github.com/cosmos/cosmos-sdk v0.53.5 h1:JPue+SFn2gyDzTV9TYb8mGpuIH3kGt7WbGadulkpTcU= +github.com/cosmos/cosmos-sdk v0.53.5/go.mod h1:AQJx0jpon70WAD4oOs/y+SlST4u7VIwEPR6F8S7JMdo= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= -github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= -github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= -github.com/cosmos/iavl v1.2.4 h1:IHUrG8dkyueKEY72y92jajrizbkZKPZbMmG14QzsEkw= -github.com/cosmos/iavl v1.2.4/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= +github.com/cosmos/gogoproto v1.7.2 h1:5G25McIraOC0mRFv9TVO139Uh3OklV2hczr13KKVHCA= +github.com/cosmos/gogoproto v1.7.2/go.mod h1:8S7w53P1Y1cHwND64o0BnArT6RmdgIvsBuco6uTllsk= +github.com/cosmos/iavl v1.2.6 h1:Hs3LndJbkIB+rEvToKJFXZvKo6Vy0Ex1SJ54hhtioIs= +github.com/cosmos/iavl v1.2.6/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v10 v10.1.0 h1:epKcbFAeWRRw1i1jZnYzLIEm9sgUPaL1RftuRjjUKGw= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v10 v10.1.0/go.mod h1:S4ZQwf5/LhpOi8JXSAese/6QQDk87nTdicJPlZ5q9UQ= -github.com/cosmos/ibc-go/v10 v10.3.0 h1:w5DkHih8qn15deAeFoTk778WJU+xC1krJ5kDnicfUBc= -github.com/cosmos/ibc-go/v10 v10.3.0/go.mod h1:CthaR7n4d23PJJ7wZHegmNgbVcLXCQql7EwHrAXnMtw= +github.com/cosmos/ibc-go/v10 v10.5.0 h1:NI+cX04fXdu9JfP0V0GYeRi1ENa7PPdq0BYtVYo8Zrs= +github.com/cosmos/ibc-go/v10 v10.5.0/go.mod h1:a74pAPUSJ7NewvmvELU74hUClJhwnmm5MGbEaiTw/kE= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= -github.com/cosmos/ledger-cosmos-go v0.14.0 h1:WfCHricT3rPbkPSVKRH+L4fQGKYHuGOK9Edpel8TYpE= -github.com/cosmos/ledger-cosmos-go v0.14.0/go.mod h1:E07xCWSBl3mTGofZ2QnL4cIUzMbbGVyik84QYKbX3RA= +github.com/cosmos/ledger-cosmos-go v0.16.0 h1:YKlWPG9NnGZIEUb2bEfZ6zhON1CHlNTg0QKRRGcNEd0= +github.com/cosmos/ledger-cosmos-go v0.16.0/go.mod h1:WrM2xEa8koYoH2DgeIuZXNarF7FGuZl3mrIOnp3Dp0o= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= @@ -1001,10 +1001,9 @@ github.com/desertbit/timer v1.0.1 h1:yRpYNn5Vaaj6QXecdLMPMJsW81JLiI1eokUft5nBmeo github.com/desertbit/timer v1.0.1/go.mod h1:htRrYeY5V/t4iu1xCJ5XsQvp4xve8QulXXctAzxqcwE= github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= +github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE= +github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= @@ -1083,8 +1082,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/getsentry/sentry-go v0.32.0 h1:YKs+//QmwE3DcYtfKRH8/KyOOF/I6Qnx7qYGNHCGmCY= -github.com/getsentry/sentry-go v0.32.0/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= +github.com/getsentry/sentry-go v0.35.0 h1:+FJNlnjJsZMG3g0/rmmP7GiKjQoUF5EXfEtBwtPtkzY= +github.com/getsentry/sentry-go v0.35.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ= @@ -1169,15 +1168,12 @@ github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUW github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= -github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= @@ -1204,8 +1200,9 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -1344,8 +1341,8 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= -github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo= +github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -1396,8 +1393,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-getter v1.7.8 h1:mshVHx1Fto0/MydBekWan5zUipGq7jO0novchgMmSiY= -github.com/hashicorp/go-getter v1.7.8/go.mod h1:2c6CboOEb9jG6YvmC9xdD+tyAFsrUaJPedwXDGr0TM4= +github.com/hashicorp/go-getter v1.7.9 h1:G9gcjrDixz7glqJ+ll5IWvggSBR+R0B54DSRt4qfdC4= +github.com/hashicorp/go-getter v1.7.9/go.mod h1:dyFCmT1AQkDfOIt9NH8pw9XBDqNrIKJT5ylbpi7zPNE= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -1468,8 +1465,8 @@ github.com/jdx/go-netrc v1.0.0/go.mod h1:Gh9eFQJnoTNIRHXl2j5bJXA1u84hQWJWgGh569z github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= -github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= -github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= +github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= +github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/jhump/protoreflect/v2 v2.0.0-beta.2 h1:qZU+rEZUOYTz1Bnhi3xbwn+VxdXkLVeEpAeZzVXLY88= github.com/jhump/protoreflect/v2 v2.0.0-beta.2/go.mod h1:4tnOYkB/mq7QTyS3YKtVtNrJv4Psqout8HA1U+hZtgM= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= @@ -1571,8 +1568,8 @@ github.com/linxGnu/grocksdb v1.9.8/go.mod h1:C3CNe9UYc9hlEM2pC82AqiGS3LRW537u9LF github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= @@ -1604,6 +1601,8 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFet4= +github.com/mdp/qrterminal/v3 v3.2.1/go.mod h1:jOTmXvnBsMy5xqLniO0R++Jmjs2sTm9dFSuQ5kpz/SU= github.com/mgechev/revive v1.7.0 h1:JyeQ4yO5K8aZhIKf5rec56u0376h8AlKNQEmjfkjKlY= github.com/mgechev/revive v1.7.0/go.mod h1:qZnwcNhoguE58dfi96IJeSTPeZQejNeoMQLUZGi4SW4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -1616,8 +1615,6 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -1666,8 +1663,8 @@ github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3L github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4= github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= @@ -1759,8 +1756,8 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1777,8 +1774,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= -github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1786,8 +1783,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= @@ -1854,8 +1851,8 @@ github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/segmentio/encoding v0.5.3 h1:OjMgICtcSFuNvQCdwqMCv9Tg7lEOXGwm1J5RPQccx6w= github.com/segmentio/encoding v0.5.3/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0= -github.com/shamaton/msgpack/v2 v2.2.0 h1:IP1m01pHwCrMa6ZccP9B3bqxEMKMSmMVAVKk54g3L/Y= -github.com/shamaton/msgpack/v2 v2.2.0/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI= +github.com/shamaton/msgpack/v2 v2.2.3 h1:uDOHmxQySlvlUYfQwdjxyybAOzjlQsD1Vjy+4jmO9NM= +github.com/shamaton/msgpack/v2 v2.2.3/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -1925,6 +1922,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -1962,8 +1960,8 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= -github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.14 h1:uv/0Bq533iFdnMHZdRBTOlaNMdb1+ZxXIlHDZHIHcvg= +github.com/ulikunitz/xz v0.5.14/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= github.com/ultraware/funlen v0.2.0/go.mod h1:ZE0q4TsJ8T1SQcjmkhN/w+MceuatI6pBFSxxyteHIJA= github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSWoFa+g= @@ -1994,10 +1992,12 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +github.com/zondax/golem v0.27.0 h1:IbBjGIXF3SoGOZHsILJvIM/F/ylwJzMcHAcggiqniPw= +github.com/zondax/golem v0.27.0/go.mod h1:AmorCgJPt00L8xN1VrMBe13PSifoZksnQ1Ge906bu4A= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= -github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +github.com/zondax/ledger-go v1.0.1 h1:Ks/2tz/dOF+dbRynfZ0dEhcdL1lqw43Sa0zMXHpQ3aQ= +github.com/zondax/ledger-go v1.0.1/go.mod h1:j7IgMY39f30apthJYMd1YsHZRqdyu4KbVmUp0nU78X0= gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= @@ -2033,8 +2033,8 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/detectors/gcp v1.38.0 h1:ZoYbqX7OaA/TAikspPl3ozPI6iY6LiIY9I8cUfm+pJs= go.opentelemetry.io/contrib/detectors/gcp v1.38.0/go.mod h1:SU+iU7nu5ud4oCb3LQOhIZ3nRLj6FNVrKgtflbaf2ts= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= @@ -2080,10 +2080,12 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= -golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= +golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU= +golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -2105,8 +2107,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2175,8 +2177,8 @@ golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= -golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= +golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= +golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2253,8 +2255,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= -golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 h1:6/3JGEh1C88g7m+qzzTbl3A0FtsLguXieqofVLU/JAo= -golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -2308,8 +2310,8 @@ golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2409,7 +2411,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2425,11 +2426,11 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= -golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8= -golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE= +golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc h1:bH6xUXay0AIFMElXG2rQ4uiE+7ncwtiOdPfYK1NK2XA= +golang.org/x/telemetry v0.0.0-20251203150158-8fff8a5912fc/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -2445,8 +2446,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2468,8 +2469,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2477,8 +2478,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2561,8 +2562,8 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= +golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= @@ -2643,8 +2644,8 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.229.0 h1:p98ymMtqeJ5i3lIBMj5MpR9kzIIgzpHHh8vQ+vgAzx8= -google.golang.org/api v0.229.0/go.mod h1:wyDfmq5g1wYJWn29O22FDWN48P7Xcz0xz+LBpptYvB0= +google.golang.org/api v0.247.0 h1:tSd/e0QrUlLsrwMKmkbQhYVa109qIintOls2Wh6bngc= +google.golang.org/api v0.247.0/go.mod h1:r1qZOPmxXffXg6xS5uhx16Fa/UFY8QU/K4bfKrnvovM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2790,8 +2791,8 @@ google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOl google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78= -google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s= google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4= google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk= @@ -2866,8 +2867,8 @@ google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2959,9 +2960,11 @@ pluginrpc.com/pluginrpc v0.5.0 h1:tOQj2D35hOmvHyPu8e7ohW2/QvAnEtKscy2IJYWQ2yo= pluginrpc.com/pluginrpc v0.5.0/go.mod h1:UNWZ941hcVAoOZUn8YZsMmOZBzbUjQa3XMns8RQLp9o= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY= +rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/tests/ibctesting/events.go b/tests/ibctesting/events.go index 5457c020..db4d30c4 100644 --- a/tests/ibctesting/events.go +++ b/tests/ibctesting/events.go @@ -6,49 +6,10 @@ import ( abci "github.com/cometbft/cometbft/abci/types" - gogoproto "github.com/cosmos/gogoproto/proto" - channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" ) -// TODO: Remove this once it's implemented in the `ibc-go`. -// https://github.com/cosmos/ibc-go/issues/8284 -// -// ParsePacketsFromEventsV2 parses events emitted from a MsgRecvPacket and returns -// all the packets found. -// Returns an error if no packet is found. -func ParsePacketsFromEventsV2(eventType string, events []abci.Event) ([]channeltypesv2.Packet, error) { - ferr := func(err error) ([]channeltypesv2.Packet, error) { - return nil, fmt.Errorf("ParsePacketsFromEventsV2: %w", err) - } - var packets []channeltypesv2.Packet - for _, ev := range events { - if ev.Type == eventType { - for _, attr := range ev.Attributes { - switch attr.Key { - case channeltypesv2.AttributeKeyEncodedPacketHex: - data, err := hex.DecodeString(attr.Value) - if err != nil { - return ferr(err) - } - var packet channeltypesv2.Packet - err = gogoproto.Unmarshal(data, &packet) - if err != nil { - return ferr(err) - } - packets = append(packets, packet) - - default: - continue - } - } - } - } - return packets, nil -} - - // ParseAckFromEventsV2 parses events emitted from a MsgRecvPacket and returns the // acknowledgement. func ParseAckFromEventsV2(events []abci.Event) ([]byte, error) { diff --git a/tests/ibctesting/events_test.go b/tests/ibctesting/events_test.go index 728ba84c..b026174c 100644 --- a/tests/ibctesting/events_test.go +++ b/tests/ibctesting/events_test.go @@ -4,16 +4,22 @@ import ( "encoding/hex" "testing" + "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/require" abci "github.com/cometbft/cometbft/abci/types" - "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" + transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" + channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" ibctst "github.com/cosmos/ibc-go/v10/testing" + + mockv1 "github.com/LumeraProtocol/lumera/tests/ibctesting/mock" + mockv2 "github.com/LumeraProtocol/lumera/tests/ibctesting/mock/v2" ) -func TestParsePacketsFromEvents(t *testing.T) { +func TestParseV1PacketsFromEvents(t *testing.T) { testCases := []struct { name string events []abci.Event @@ -112,7 +118,7 @@ func TestParsePacketsFromEvents(t *testing.T) { DestinationPort: "dstPort", DestinationChannel: "dstChannel", Data: []byte("data1"), - TimeoutHeight: types.Height{ + TimeoutHeight: clienttypes.Height{ RevisionNumber: 1, RevisionHeight: 2, }, @@ -125,7 +131,7 @@ func TestParsePacketsFromEvents(t *testing.T) { DestinationPort: "dstPort", DestinationChannel: "dstChannel", Data: []byte("data2"), - TimeoutHeight: types.Height{ + TimeoutHeight: clienttypes.Height{ RevisionNumber: 1, RevisionHeight: 3, }, @@ -199,7 +205,7 @@ func TestParsePacketsFromEvents(t *testing.T) { } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - allPackets, err := ibctst.ParsePacketsFromEvents(channeltypes.EventTypeSendPacket, tc.events) + allPackets, err := ibctst.ParseIBCV1Packets(channeltypes.EventTypeSendPacket, tc.events) if tc.expectedError == "" { require.NoError(t, err) @@ -208,7 +214,7 @@ func TestParsePacketsFromEvents(t *testing.T) { require.ErrorContains(t, err, tc.expectedError) } - firstPacket, err := ibctst.ParsePacketFromEvents(tc.events) + firstPacket, err := ibctst.ParseV1PacketFromEvents(tc.events) if tc.expectedError == "" { require.NoError(t, err) @@ -219,3 +225,167 @@ func TestParsePacketsFromEvents(t *testing.T) { }) } } + +func TestParseV2PacketsFromEvents(t *testing.T) { + testCases := []struct { + name string + eventType string + events []abci.Event + expectedPackets []channeltypesv2.Packet + expectedError string + }{ + { + name: "success: One v2 packet without payload + One v2 packet with payload", + eventType: channeltypesv2.EventTypeRecvPacket, + events: []abci.Event{ + { + Type: "xxx", + }, + { + Type: channeltypesv2.EventTypeRecvPacket, + Attributes: []abci.EventAttribute{ + { + Key: channeltypesv2.AttributeKeySequence, + Value: "42", + }, + { + Key: channeltypesv2.AttributeKeySrcClient, + Value: "srcClient", + }, + { + Key: channeltypesv2.AttributeKeyDstClient, + Value: "destClient", + }, + { + Key: channeltypesv2.AttributeKeyTimeoutTimestamp, + Value: "1283798137", + }, + }, + }, + { + Type: "yyy", + }, + { + Type: channeltypesv2.EventTypeRecvPacket, + // If AttributeKeyEncodedPacketHex is present, other attributes are ignored. + Attributes: []abci.EventAttribute{ + { + Key: channeltypesv2.AttributeKeySequence, + Value: "43", + }, + { + Key: channeltypesv2.AttributeKeySrcClient, + Value: "srcClient-2", + }, + { + Key: channeltypesv2.AttributeKeyDstClient, + Value: "destClient-2", + }, + { + Key: channeltypesv2.AttributeKeyTimeoutTimestamp, + Value: "12837997475", + }, + { + Key: channeltypesv2.AttributeKeyEncodedPacketHex, + Value: func() string { + payload := mockv2.NewMockPayload(mockv2.ModuleNameA, mockv2.ModuleNameB) + packet := channeltypesv2.NewPacket(44, "srcClient", "destClient", 19474197444, payload) + encodedPacket, err := proto.Marshal(&packet) + if err != nil { + panic(err) + } + return hex.EncodeToString(encodedPacket) + }(), + }, + }, + }, + }, + expectedPackets: []channeltypesv2.Packet{ + { + Sequence: 42, + SourceClient: "srcClient", + DestinationClient: "destClient", + TimeoutTimestamp: 1283798137, + }, + { + Sequence: 44, + SourceClient: "srcClient", + DestinationClient: "destClient", + TimeoutTimestamp: 19474197444, + Payloads: []channeltypesv2.Payload{ + { + SourcePort: mockv2.ModuleNameA, + DestinationPort: mockv2.ModuleNameB, + Version: mockv1.Version, + Encoding: transfertypes.EncodingProtobuf, + Value: mockv1.MockPacketData, + }, + }, + }, + }, + }, + + { + name: "fail: no events", + eventType: channeltypesv2.EventTypeSendPacket, + events: []abci.Event{}, + expectedError: "no IBC v2 packets found in events", + }, + { + name: "fail: events without packet", + eventType: channeltypesv2.EventTypeSendPacket, + events: []abci.Event{ + { + Type: "xxx", + }, + { + Type: "yyy", + }, + }, + expectedError: "no IBC v2 packets found in events", + }, + { + name: "fail: event packet with invalid AttributeKeySequence", + eventType: channeltypesv2.EventTypeSendPacket, + events: []abci.Event{ + { + Type: channeltypesv2.EventTypeSendPacket, + Attributes: []abci.EventAttribute{ + { + Key: channeltypesv2.AttributeKeySequence, + Value: "x", + }, + }, + }, + }, + expectedError: "strconv.ParseUint: parsing \"x\": invalid syntax", + }, + { + name: "fail: event packet with invalid AttributeKeyTimeoutHeight", + eventType: channeltypesv2.EventTypeSendPacket, + events: []abci.Event{ + { + Type: channeltypesv2.EventTypeSendPacket, + Attributes: []abci.EventAttribute{ + { + Key: channeltypesv2.AttributeKeyTimeoutTimestamp, + Value: "x", + }, + }, + }, + }, + expectedError: "strconv.ParseUint: parsing \"x\": invalid syntax", + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + packets, err := ibctst.ParseIBCV2Packets(tc.eventType, tc.events) + if tc.expectedError != "" { + require.ErrorContains(t, err, tc.expectedError) + return + } + require.NoError(t, err) + require.Equal(t, tc.expectedPackets, packets) + }) + } +} diff --git a/tests/ibctesting/mock/ibcmodule.go b/tests/ibctesting/mock/ibcmodule.go index 3ca4845a..32b8e060 100644 --- a/tests/ibctesting/mock/ibcmodule.go +++ b/tests/ibctesting/mock/ibcmodule.go @@ -31,6 +31,7 @@ var ( MockApplicationCallbackError error = &applicationCallbackError{} _ porttypes.IBCModule = &MockIBCModule{} + _ porttypes.PacketDataUnmarshaler = &MockIBCModule{} _ ibcexported.Path = KeyPath{} _ ibcexported.Height = Height{} ) @@ -63,7 +64,7 @@ func (m *MockIBCModule) OnChanOpenInit(ctx sdk.Context, order channeltypes.Order version = Version } - if m.IBCApp != nil && m.IBCApp.OnChanOpenInit != nil { + if m.IBCApp != nil { return m.IBCApp.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, counterparty, version) } return version, nil @@ -72,7 +73,7 @@ func (m *MockIBCModule) OnChanOpenInit(ctx sdk.Context, order channeltypes.Order func (m *MockIBCModule) OnChanOpenTry(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID, channelID string, counterparty channeltypes.Counterparty, counterpartyVersion string) (string, error) { - if m.IBCApp != nil && m.IBCApp.OnChanOpenTry != nil { + if m.IBCApp != nil { return m.IBCApp.OnChanOpenTry(ctx, order, connectionHops, portID, channelID, counterparty, counterpartyVersion) } @@ -80,7 +81,7 @@ func (m *MockIBCModule) OnChanOpenTry(ctx sdk.Context, order channeltypes.Order, } func (m *MockIBCModule) OnChanOpenAck(ctx sdk.Context, portID, channelID, counterpartyChannelID, counterpartyVersion string) error { - if m.IBCApp != nil && m.IBCApp.OnChanOpenAck != nil { + if m.IBCApp != nil { return m.IBCApp.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) } @@ -88,7 +89,7 @@ func (m *MockIBCModule) OnChanOpenAck(ctx sdk.Context, portID, channelID, counte } func (m *MockIBCModule) OnChanOpenConfirm(ctx sdk.Context, portID, channelID string) error { - if m.IBCApp != nil && m.IBCApp.OnChanOpenConfirm != nil { + if m.IBCApp != nil { return m.IBCApp.OnChanOpenConfirm(ctx, portID, channelID) } @@ -96,11 +97,15 @@ func (m *MockIBCModule) OnChanOpenConfirm(ctx sdk.Context, portID, channelID str } func (m *MockIBCModule) OnChanCloseInit(ctx sdk.Context, portID, channelID string) error { - return m.IBCApp.OnChanCloseInit(ctx, portID, channelID) + if m.IBCApp != nil { + return m.IBCApp.OnChanCloseInit(ctx, portID, channelID) + } + + return nil } func (m *MockIBCModule) OnChanCloseConfirm(ctx sdk.Context, portID, channelID string) error { - if m.IBCApp != nil && m.IBCApp.OnChanCloseConfirm != nil { + if m.IBCApp != nil { return m.IBCApp.OnChanCloseConfirm(ctx, portID, channelID) } @@ -108,7 +113,7 @@ func (m *MockIBCModule) OnChanCloseConfirm(ctx sdk.Context, portID, channelID st } func (m *MockIBCModule) OnRecvPacket(ctx sdk.Context, channelVersion string, packet channeltypes.Packet, relayer sdk.AccAddress) ibcexported.Acknowledgement { - if m.IBCApp != nil && m.IBCApp.OnRecvPacket != nil { + if m.IBCApp != nil { return m.IBCApp.OnRecvPacket(ctx, channelVersion, packet, relayer) } @@ -124,7 +129,7 @@ func (m *MockIBCModule) OnRecvPacket(ctx sdk.Context, channelVersion string, pac } func (m *MockIBCModule) OnAcknowledgementPacket(ctx sdk.Context, channelVersion string, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error { - if m.IBCApp != nil && m.IBCApp.OnAcknowledgementPacket != nil { + if m.IBCApp != nil { return m.IBCApp.OnAcknowledgementPacket(ctx, channelVersion, packet, acknowledgement, relayer) } @@ -133,7 +138,7 @@ func (m *MockIBCModule) OnAcknowledgementPacket(ctx sdk.Context, channelVersion } func (m *MockIBCModule) OnTimeoutPacket(ctx sdk.Context, channelVersion string, packet channeltypes.Packet, relayer sdk.AccAddress) error { - if m.IBCApp != nil && m.IBCApp.OnTimeoutPacket != nil { + if m.IBCApp != nil { return m.IBCApp.OnTimeoutPacket(ctx, channelVersion, packet, relayer) } @@ -167,4 +172,3 @@ func (KeyPath) Empty() bool { type Height struct { ibcexported.Height } - diff --git a/tests/ibctesting/mock/mock_callbacks.go b/tests/ibctesting/mock/mock_callbacks.go index 4a9302a4..4afdd4c8 100644 --- a/tests/ibctesting/mock/mock_callbacks.go +++ b/tests/ibctesting/mock/mock_callbacks.go @@ -40,8 +40,10 @@ type MockWasmEngine struct { IBCPacketTimeoutFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResult, uint64, error) IBCSourceCallbackFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCSourceCallbackMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResult, uint64, error) IBCDestinationCallbackFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCDestinationCallbackMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResult, uint64, error) + IBC2PacketAckFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBC2AcknowledgeMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResult, uint64, error) IBC2PacketReceiveFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBC2PacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResult, uint64, error) IBC2PacketTimeoutFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBC2PacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResult, uint64, error) + IBC2PacketSendFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBC2PacketSendMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResult, uint64, error) PinFn func(checksum wasmvm.Checksum) error UnpinFn func(checksum wasmvm.Checksum) error GetMetricsFn func() (*wasmvmtypes.Metrics, error) @@ -153,12 +155,19 @@ func (m MockWasmEngine) IBCDestinationCallback(codeID wasmvm.Checksum, env wasmv } func (m *MockWasmEngine) IBC2PacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBC2PacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResult, uint64, error) { - if m.IBCPacketReceiveFn == nil { + if m.IBC2PacketReceiveFn == nil { panic("not supposed to be called!") } return m.IBC2PacketReceiveFn(codeID, env, msg, store, goapi, querier, gasMeter, gasLimit, deserCost) } +func (m *MockWasmEngine) IBC2PacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBC2AcknowledgeMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResult, uint64, error) { + if m.IBC2PacketAckFn == nil { + panic("not supposed to be called!") + } + return m.IBC2PacketAckFn(codeID, env, msg, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + func (m *MockWasmEngine) IBC2PacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBC2PacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResult, uint64, error) { if m.IBC2PacketTimeoutFn == nil { panic("not supposed to be called!") @@ -166,6 +175,13 @@ func (m *MockWasmEngine) IBC2PacketTimeout(codeID wasmvm.Checksum, env wasmvmtyp return m.IBC2PacketTimeoutFn(codeID, env, msg, store, goapi, querier, gasMeter, gasLimit, deserCost) } +func (m *MockWasmEngine) IBC2PacketSend(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBC2PacketSendMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResult, uint64, error) { + if m.IBC2PacketSendFn == nil { + panic("not supposed to be called!") + } + return m.IBC2PacketSendFn(codeID, env, msg, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + func (m *MockWasmEngine) StoreCode(codeID wasmvm.WasmCode, gasLimit uint64) (wasmvm.Checksum, uint64, error) { if m.StoreCodeFn == nil { panic("not supposed to be called!") @@ -223,7 +239,7 @@ func (m *MockWasmEngine) Migrate(codeID wasmvm.Checksum, env wasmvmtypes.Env, mi } func (m *MockWasmEngine) MigrateWithInfo(codeID wasmvm.Checksum, env wasmvmtypes.Env, migrateMsg []byte, migrateInfo wasmvmtypes.MigrateInfo, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.ContractResult, uint64, error) { - if m.MigrateFn == nil { + if m.MigrateWithInfoFn == nil { panic("not supposed to be called!") } return m.MigrateWithInfoFn(codeID, env, migrateMsg, migrateInfo, store, goapi, querier, gasMeter, gasLimit, deserCost) diff --git a/tests/ibctesting/mock/v2/ibc_app.go b/tests/ibctesting/mock/v2/ibc_app.go new file mode 100644 index 00000000..9999e3bd --- /dev/null +++ b/tests/ibctesting/mock/v2/ibc_app.go @@ -0,0 +1,14 @@ +package mock + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" +) + +type IBCApp struct { + OnSendPacket func(ctx sdk.Context, sourceChannel string, destinationChannel string, sequence uint64, payload channeltypesv2.Payload, signer sdk.AccAddress) error + OnRecvPacket func(ctx sdk.Context, sourceChannel string, destinationChannel string, sequence uint64, payload channeltypesv2.Payload, relayer sdk.AccAddress) channeltypesv2.RecvPacketResult + OnTimeoutPacket func(ctx sdk.Context, sourceChannel string, destinationChannel string, sequence uint64, payload channeltypesv2.Payload, relayer sdk.AccAddress) error + OnAcknowledgementPacket func(ctx sdk.Context, sourceChannel string, destinationChannel string, sequence uint64, payload channeltypesv2.Payload, acknowledgement []byte, relayer sdk.AccAddress) error +} diff --git a/tests/ibctesting/mock/v2/ibc_module.go b/tests/ibctesting/mock/v2/ibc_module.go new file mode 100644 index 00000000..5d5ffcbc --- /dev/null +++ b/tests/ibctesting/mock/v2/ibc_module.go @@ -0,0 +1,72 @@ +package mock + +import ( + "bytes" + + sdk "github.com/cosmos/cosmos-sdk/types" + + channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" + "github.com/cosmos/ibc-go/v10/modules/core/api" + + mockv1 "github.com/LumeraProtocol/lumera/tests/ibctesting/mock" +) + +var _ api.IBCModule = (*IBCModule)(nil) + +const ( + ModuleNameA = ModuleName + "A" + ModuleNameB = ModuleName + "B" + PortIDA = ModuleNameA + PortIDB = ModuleNameB +) + +// IBCModule is a mock implementation of the IBCModule interface +// which delegates calls to the underlying IBCApp. +type IBCModule struct { + IBCApp *IBCApp +} + +// NewIBCModule creates a new IBCModule with an underlying mock IBC application. +func NewIBCModule() IBCModule { + return IBCModule{ + IBCApp: &IBCApp{}, + } +} + +func (im IBCModule) OnSendPacket(ctx sdk.Context, sourceChannel string, destinationChannel string, sequence uint64, data channeltypesv2.Payload, signer sdk.AccAddress) error { + if im.IBCApp.OnSendPacket != nil { + return im.IBCApp.OnSendPacket(ctx, sourceChannel, destinationChannel, sequence, data, signer) + } + return nil +} + +func (im IBCModule) OnRecvPacket(ctx sdk.Context, sourceChannel string, destinationChannel string, sequence uint64, payload channeltypesv2.Payload, relayer sdk.AccAddress) channeltypesv2.RecvPacketResult { + if im.IBCApp.OnRecvPacket != nil { + return im.IBCApp.OnRecvPacket(ctx, sourceChannel, destinationChannel, sequence, payload, relayer) + } + if bytes.Equal(payload.Value, mockv1.MockPacketData) { + return MockRecvPacketResult + } + return channeltypesv2.RecvPacketResult{Status: channeltypesv2.PacketStatus_Failure} +} + +func (im IBCModule) OnAcknowledgementPacket(ctx sdk.Context, sourceChannel string, destinationChannel string, sequence uint64, acknowledgement []byte, payload channeltypesv2.Payload, relayer sdk.AccAddress) error { + if im.IBCApp.OnAcknowledgementPacket != nil { + return im.IBCApp.OnAcknowledgementPacket(ctx, sourceChannel, destinationChannel, sequence, payload, acknowledgement, relayer) + } + return nil +} + +func (im IBCModule) OnTimeoutPacket(ctx sdk.Context, sourceChannel string, destinationChannel string, sequence uint64, payload channeltypesv2.Payload, relayer sdk.AccAddress) error { + if im.IBCApp.OnTimeoutPacket != nil { + return im.IBCApp.OnTimeoutPacket(ctx, sourceChannel, destinationChannel, sequence, payload, relayer) + } + return nil +} + +func (IBCModule) UnmarshalPacketData(payload channeltypesv2.Payload) (any, error) { + if bytes.Equal(payload.Value, mockv1.MockPacketData) { + return mockv1.MockPacketData, nil + } + return nil, mockv1.MockApplicationCallbackError +} diff --git a/tests/ibctesting/mock/v2/mock.go b/tests/ibctesting/mock/v2/mock.go new file mode 100644 index 00000000..6721c419 --- /dev/null +++ b/tests/ibctesting/mock/v2/mock.go @@ -0,0 +1,37 @@ +package mock + +import ( + transfertypes "github.com/cosmos/ibc-go/v10/modules/apps/transfer/types" + channeltypesv2 "github.com/cosmos/ibc-go/v10/modules/core/04-channel/v2/types" + + mockv1 "github.com/LumeraProtocol/lumera/tests/ibctesting/mock" +) + +const ( + ModuleName = "mockv2" +) + +var MockRecvPacketResult = channeltypesv2.RecvPacketResult{ + Status: channeltypesv2.PacketStatus_Success, + Acknowledgement: mockv1.MockAcknowledgement.Acknowledgement(), +} + +func NewMockPayload(sourcePort, destPort string) channeltypesv2.Payload { + return channeltypesv2.Payload{ + SourcePort: sourcePort, + DestinationPort: destPort, + Encoding: transfertypes.EncodingProtobuf, + Value: mockv1.MockPacketData, + Version: mockv1.Version, + } +} + +func NewErrorMockPayload(sourcePort, destPort string) channeltypesv2.Payload { + return channeltypesv2.Payload{ + SourcePort: sourcePort, + DestinationPort: destPort, + Encoding: transfertypes.EncodingProtobuf, + Value: mockv1.MockFailPacketData, + Version: mockv1.Version, + } +} diff --git a/tests/ibctesting/wasm.go b/tests/ibctesting/wasm.go index fdd8b804..061ea98f 100644 --- a/tests/ibctesting/wasm.go +++ b/tests/ibctesting/wasm.go @@ -40,10 +40,10 @@ type PendingAckPacketV2 struct { } func (chain *TestChain) CaptureIBCEvents(result *abci.ExecTxResult) { - toSend, _ := ibctst.ParsePacketsFromEvents(channeltypes.EventTypeSendPacket, result.Events) + toSend, _ := ibctst.ParseIBCV1Packets(channeltypes.EventTypeSendPacket, result.Events) // IBCv1 and IBCv2 `EventTypeSendPacket` are the same - // and the [`ParsePacketsFromEvents`] parses both of them as they were IBCv1 + // and ParseIBCV1Packets parses both of them as they were IBCv1 // so we have to filter them here. // // While parsing IBC2 events in IBC1 context the only overlapping event is the @@ -64,8 +64,13 @@ func (chain *TestChain) CaptureIBCEvents(result *abci.ExecTxResult) { } func (chain *TestChain) CaptureIBCEventsV2(result *abci.ExecTxResult) { - toSend, err := ParsePacketsFromEventsV2(channeltypesv2.EventTypeSendPacket, result.Events) - require.NoError(chain, err) + toSend, err := ibctst.ParseIBCV2Packets(channeltypesv2.EventTypeSendPacket, result.Events) + if err != nil { + if err.Error() == "no IBC v2 packets found in events" { + return + } + require.NoError(chain, err) + } if len(toSend) > 0 { // Keep a queue on the chain that we can relay in tests *chain.PendingSendPacketsV2 = append(*chain.PendingSendPacketsV2, toSend...) @@ -324,4 +329,3 @@ func CloseChannel(coord *Coordinator, path *Path) { _, err = dst.Chain.SendMsgs(msg) require.NoError(coord, err) } - diff --git a/tests/integration/staking/unbonding_test.go b/tests/integration/staking/unbonding_test.go index 4bd80dc5..b8e466c9 100644 --- a/tests/integration/staking/unbonding_test.go +++ b/tests/integration/staking/unbonding_test.go @@ -8,7 +8,7 @@ import ( "cosmossdk.io/math" - "github.com/golang/mock/gomock" + "go.uber.org/mock/gomock" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/tests/integration/update_params_integration_test.go b/tests/integration/update_params_integration_test.go index 038eeed5..2e6a1004 100644 --- a/tests/integration/update_params_integration_test.go +++ b/tests/integration/update_params_integration_test.go @@ -17,6 +17,7 @@ import ( "github.com/LumeraProtocol/lumera/app" claimtypes "github.com/LumeraProtocol/lumera/x/claim/types" + lcfg "github.com/LumeraProtocol/lumera/config" ) type IntegrationTestSuite struct { @@ -44,8 +45,8 @@ func (s *IntegrationTestSuite) SetupTest() { s.app.AuthKeeper.SetAccount(s.ctx, s.app.AuthKeeper.NewAccountWithAddress(s.ctx, s.proposer)) s.app.AuthKeeper.SetAccount(s.ctx, s.app.AuthKeeper.NewAccountWithAddress(s.ctx, s.voter)) - proposerCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 1_000_000_000)) - voterCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 1_000_000_000)) + proposerCoins := sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, 1_000_000_000)) + voterCoins := sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, 1_000_000_000)) err := s.app.BankKeeper.MintCoins(s.ctx, minttypes.ModuleName, proposerCoins.Add(voterCoins...)) s.Require().NoError(err, "Failed to mint coins") diff --git a/tests/integration/wasm/common_test.go b/tests/integration/wasm/common_test.go index 7fd3603c..4a23782a 100644 --- a/tests/integration/wasm/common_test.go +++ b/tests/integration/wasm/common_test.go @@ -46,8 +46,6 @@ import ( "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/crisis" - crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" "github.com/cosmos/cosmos-sdk/x/distribution" distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" @@ -251,7 +249,6 @@ var moduleBasics = module.NewBasicManager( paramsclient.ProposalHandler, }), params.AppModuleBasic{}, - crisis.AppModuleBasic{}, slashing.AppModuleBasic{}, ibc.AppModuleBasic{}, upgrade.AppModuleBasic{}, @@ -268,7 +265,6 @@ func MakeEncodingConfig(t testing.TB) moduletestutil.TestEncodingConfig { mint.AppModule{}, slashing.AppModule{}, gov.AppModule{}, - crisis.AppModule{}, ibc.AppModule{}, ibctransfer.AppModule{}, vesting.AppModule{}, @@ -365,7 +361,6 @@ func createTestInput( minttypes.ModuleName, distributiontypes.ModuleName, slashingtypes.ModuleName, - crisistypes.ModuleName, ibctransfertypes.ModuleName, ibcexported.ModuleName, govtypes.ModuleName, @@ -481,6 +476,7 @@ func createTestInput( distributionkeeper.NewQuerier(distKeeper), ibcKeeper.ChannelKeeper, // ICS4Wrapper ibcKeeper.ChannelKeeper, + ibcKeeper.ChannelKeeperV2, ibcmock.MockIBCTransferKeeper{}, msgRouter, querier, @@ -489,7 +485,6 @@ func createTestInput( vmConfig, availableCapabilities, authtypes.NewModuleAddress(govtypes.ModuleName).String(), - nil, opts..., ) require.NoError(t, keeper.SetParams(ctx, wasmtypes.DefaultParams())) @@ -799,4 +794,4 @@ func keyPubAddr() (crypto.PrivKey, sdk.AccAddress) { pub := key.PubKey() addr := sdk.AccAddress(pub.Address()) return key, addr -} \ No newline at end of file +} diff --git a/tests/integration/wasm/genesis_test.go b/tests/integration/wasm/genesis_test.go new file mode 100644 index 00000000..d094f0bd --- /dev/null +++ b/tests/integration/wasm/genesis_test.go @@ -0,0 +1,103 @@ +package wasm_test + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + "github.com/CosmWasm/wasmd/x/wasm/types" +) + +func TestInitGenesis(t *testing.T) { + data := setupTest(t) + + deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000)) + topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000)) + creator := data.faucet.NewFundedRandomAccount(data.ctx, deposit.Add(deposit...)...) + fred := data.faucet.NewFundedRandomAccount(data.ctx, topUp...) + + msg := types.MsgStoreCode{ + Sender: creator.String(), + WASMByteCode: testContract, + } + h := data.msgServiceRouter.Handler(&msg) + q := data.grpcQueryRouter + + err := msg.ValidateBasic() + require.NoError(t, err) + + res, err := h(data.ctx, &msg) + require.NoError(t, err) + assertStoreCodeResponse(t, res.Data, 1) + + _, bob := keyPubAddr() + initMsg := initMsg{ + Verifier: fred, + Beneficiary: bob, + } + initMsgBz, err := json.Marshal(initMsg) + require.NoError(t, err) + + instMsg := types.MsgInstantiateContract{ + Sender: creator.String(), + CodeID: firstCodeID, + Msg: initMsgBz, + Funds: deposit, + Label: "testing", + } + h = data.msgServiceRouter.Handler(&instMsg) + res, err = h(data.ctx, &instMsg) + require.NoError(t, err) + contractBech32Addr := parseInitResponse(t, res.Data) + + execMsg := types.MsgExecuteContract{ + Sender: fred.String(), + Contract: contractBech32Addr, + Msg: []byte(`{"release":{}}`), + Funds: topUp, + } + h = data.msgServiceRouter.Handler(&execMsg) + res, err = h(data.ctx, &execMsg) + require.NoError(t, err) + // from https://github.com/CosmWasm/cosmwasm/blob/master/contracts/hackatom/src/contract.rs#L167 + assertExecuteResponse(t, res.Data, []byte{0xf0, 0x0b, 0xaa}) + + // ensure all contract state is as after init + assertCodeList(t, q, data.ctx, 1, data.encConf.Codec) + assertCodeBytes(t, q, data.ctx, 1, testContract, data.encConf.Codec) + + assertContractList(t, q, data.ctx, 1, []string{contractBech32Addr}, data.encConf.Codec) + assertContractInfo(t, q, data.ctx, contractBech32Addr, 1, creator, data.encConf.Codec) + assertContractState(t, q, data.ctx, contractBech32Addr, state{ + Verifier: fred.String(), + Beneficiary: bob.String(), + Funder: creator.String(), + }, data.encConf.Codec) + + // export into genstate + genState := wasmkeeper.ExportGenesis(data.ctx, &data.keeper) + + // create new app to import genstate into + newData := setupTest(t) + q2 := newData.grpcQueryRouter + + // initialize new app with genstate + _, err = wasmkeeper.InitGenesis(newData.ctx, &newData.keeper, *genState) + require.NoError(t, err) + + // run same checks again on newdata, to make sure it was reinitialized correctly + assertCodeList(t, q2, newData.ctx, 1, data.encConf.Codec) + assertCodeBytes(t, q2, newData.ctx, 1, testContract, data.encConf.Codec) + + assertContractList(t, q2, newData.ctx, 1, []string{contractBech32Addr}, data.encConf.Codec) + assertContractInfo(t, q2, newData.ctx, contractBech32Addr, 1, creator, data.encConf.Codec) + assertContractState(t, q2, newData.ctx, contractBech32Addr, state{ + Verifier: fred.String(), + Beneficiary: bob.String(), + Funder: creator.String(), + }, data.encConf.Codec) +} diff --git a/tests/integration/wasm/ibc_integration_test.go b/tests/integration/wasm/ibc_integration_test.go index fea36aec..c3a13480 100644 --- a/tests/integration/wasm/ibc_integration_test.go +++ b/tests/integration/wasm/ibc_integration_test.go @@ -397,10 +397,10 @@ func TestIBCAsyncAck(t *testing.T) { path = ibctesting.NewPath(chainA, chainB) ) path.EndpointA.ChannelConfig = &ibctesting.ChannelConfig{ - PortID: sourcePortID, Version: "ibc-reflect-v1", Order: channeltypes.UNORDERED, + PortID: sourcePortID, Version: "ibc-reflect-v1", Order: channeltypes.ORDERED, } path.EndpointB.ChannelConfig = &ibctesting.ChannelConfig{ - PortID: counterpartPortID, Version: "ibc-reflect-v1", Order: channeltypes.UNORDERED, + PortID: counterpartPortID, Version: "ibc-reflect-v1", Order: channeltypes.ORDERED, } path.SetupConnections() diff --git a/tests/integration/wasm/migrations_integration_test.go b/tests/integration/wasm/migrations_integration_test.go new file mode 100644 index 00000000..9810a9f1 --- /dev/null +++ b/tests/integration/wasm/migrations_integration_test.go @@ -0,0 +1,128 @@ +package wasm_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + upgradetypes "cosmossdk.io/x/upgrade/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/CosmWasm/wasmd/x/wasm/types" + + "github.com/LumeraProtocol/lumera/app" +) + +func TestModuleMigrations(t *testing.T) { + wasmApp := app.Setup(t) + + upgradeHandler := func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + return wasmApp.ModuleManager.RunMigrations(ctx, wasmApp.Configurator(), fromVM) + } + + specs := map[string]struct { + setup func(ctx sdk.Context) + startVersion uint64 + exp types.Params + }{ + "fresh from genesis": { + startVersion: wasmApp.ModuleManager.GetVersionMap()[types.ModuleName], // latest + setup: func(ctx sdk.Context) {}, + exp: types.DefaultParams(), + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + ctx, _ := wasmApp.BaseApp.NewContext(false).CacheContext() + spec.setup(ctx) + + fromVM, err := wasmApp.UpgradeKeeper.GetModuleVersionMap(ctx) + require.NoError(t, err) + fromVM[types.ModuleName] = spec.startVersion + _, err = upgradeHandler(ctx, upgradetypes.Plan{Name: "testing"}, fromVM) + require.NoError(t, err) + + // when + gotVM, err := wasmApp.ModuleManager.RunMigrations(ctx, wasmApp.Configurator(), fromVM) + + // then + require.NoError(t, err) + var expModuleVersion uint64 = 4 + assert.Equal(t, expModuleVersion, gotVM[types.ModuleName]) + gotParams := wasmApp.WasmKeeper.GetParams(ctx) + assert.Equal(t, spec.exp, gotParams) + }) + } +} + +func TestAccessConfigMigrations(t *testing.T) { + address := sdk.AccAddress(make([]byte, types.ContractAddrLen)) + + wasmApp := app.Setup(t) + + upgradeHandler := func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + return wasmApp.ModuleManager.RunMigrations(ctx, wasmApp.Configurator(), fromVM) + } + + ctx, _ := wasmApp.BaseApp.NewContext(false).CacheContext() + + // any address permission + code1, err := storeCode(ctx, wasmApp, types.AccessTypeAnyOfAddresses.With(address)) + require.NoError(t, err) + + // allow everybody permission + code2, err := storeCode(ctx, wasmApp, types.AllowEverybody) + require.NoError(t, err) + + // allow nobody permission + code3, err := storeCode(ctx, wasmApp, types.AllowNobody) + require.NoError(t, err) + + fromVM, err := wasmApp.UpgradeKeeper.GetModuleVersionMap(ctx) + require.NoError(t, err) + fromVM[types.ModuleName] = wasmApp.ModuleManager.GetVersionMap()[types.ModuleName] + _, err = upgradeHandler(ctx, upgradetypes.Plan{Name: "testing"}, fromVM) + require.NoError(t, err) + + // when + gotVM, err := wasmApp.ModuleManager.RunMigrations(ctx, wasmApp.Configurator(), fromVM) + + // then + require.NoError(t, err) + var expModuleVersion uint64 = 4 + assert.Equal(t, expModuleVersion, gotVM[types.ModuleName]) + + // any address was not migrated + assert.Equal(t, types.AccessTypeAnyOfAddresses.With(address), wasmApp.WasmKeeper.GetCodeInfo(ctx, code1).InstantiateConfig) + + // allow everybody was not migrated + assert.Equal(t, types.AllowEverybody, wasmApp.WasmKeeper.GetCodeInfo(ctx, code2).InstantiateConfig) + + // allow nobody was not migrated + assert.Equal(t, types.AllowNobody, wasmApp.WasmKeeper.GetCodeInfo(ctx, code3).InstantiateConfig) +} + +func storeCode(ctx sdk.Context, wasmApp *app.App, instantiatePermission types.AccessConfig) (codeID uint64, err error) { + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = testContract + m.InstantiatePermission = &instantiatePermission + _, sender := keyPubAddr() + m.Sender = sender.String() + }) + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + if err != nil { + return + } + + var result types.MsgStoreCodeResponse + err = wasmApp.AppCodec().Unmarshal(rsp.Data, &result) + if err != nil { + return + } + + codeID = result.CodeID + return +} diff --git a/tests/integration/wasm/module_test.go b/tests/integration/wasm/module_test.go new file mode 100644 index 00000000..67c0e223 --- /dev/null +++ b/tests/integration/wasm/module_test.go @@ -0,0 +1,670 @@ +package wasm_test + +import ( + "bytes" + "encoding/json" + "os" + "strings" + "testing" + + abci "github.com/cometbft/cometbft/abci/types" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" + "github.com/cosmos/cosmos-sdk/types/module" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + + "github.com/CosmWasm/wasmd/x/wasm" + "github.com/CosmWasm/wasmd/x/wasm/exported" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + "github.com/CosmWasm/wasmd/x/wasm/keeper/testdata" + v2 "github.com/CosmWasm/wasmd/x/wasm/migrations/v2" + "github.com/CosmWasm/wasmd/x/wasm/types" +) + +const firstCodeID = 1 + +type mockSubspace struct { + ps v2.Params +} + +func newMockSubspace(ps v2.Params) mockSubspace { + return mockSubspace{ps: ps} +} + +func (ms mockSubspace) GetParamSet(ctx sdk.Context, ps exported.ParamSet) { + *ps.(*v2.Params) = ms.ps +} + +type testData struct { + module wasm.AppModule + ctx sdk.Context + acctKeeper authkeeper.AccountKeeper + keeper wasmkeeper.Keeper + bankKeeper bankkeeper.Keeper + stakingKeeper *stakingkeeper.Keeper + faucet *wasmkeeper.TestFaucet + grpcQueryRouter *baseapp.GRPCQueryRouter + msgServiceRouter *baseapp.MsgServiceRouter + encConf moduletestutil.TestEncodingConfig +} + +func setupTest(t *testing.T) testData { + t.Helper() + DefaultParams := v2.Params{ + CodeUploadAccess: v2.AccessConfig{Permission: v2.AccessTypeEverybody}, + InstantiateDefaultPermission: v2.AccessTypeEverybody, + } + + ctx, keepers := CreateTestInput(t, false, []string{ + "iterator", "staking", "stargate", "cosmwasm_1_1", "cosmwasm_1_2", "cosmwasm_1_3", + "cosmwasm_1_4", "cosmwasm_2_0", "cosmwasm_2_1", "cosmwasm_2_2", "ibc2", + }) + encConf := MakeEncodingConfig(t) + queryRouter := baseapp.NewGRPCQueryRouter() + serviceRouter := baseapp.NewMsgServiceRouter() + queryRouter.SetInterfaceRegistry(encConf.InterfaceRegistry) + serviceRouter.SetInterfaceRegistry(encConf.InterfaceRegistry) + data := testData{ + module: wasm.NewAppModule(encConf.Codec, keepers.WasmKeeper, keepers.StakingKeeper, keepers.AccountKeeper, keepers.BankKeeper, nil, newMockSubspace(DefaultParams)), + ctx: ctx, + acctKeeper: keepers.AccountKeeper, + keeper: *keepers.WasmKeeper, + bankKeeper: keepers.BankKeeper, + stakingKeeper: keepers.StakingKeeper, + faucet: keepers.Faucet, + grpcQueryRouter: queryRouter, + msgServiceRouter: serviceRouter, + encConf: encConf, + } + data.module.RegisterServices(module.NewConfigurator(encConf.Codec, serviceRouter, queryRouter)) + return data +} + +func mustLoad(path string) []byte { + bz, err := os.ReadFile(path) + if err != nil { + panic(err) + } + return bz +} + +var ( + addrAcc1 = func() sdk.AccAddress { + _, addr := keyPubAddr() + return addr + }() + addr1 = addrAcc1.String() + testContract = mustLoad(GetTestDataFilePath("hackatom.wasm")) + maskContract = testdata.ReflectContractWasm() + oldContract = mustLoad(GetTestDataFilePath("escrow_0.7.wasm")) +) + +func TestStoreCodeSimulation(t *testing.T) { + data := setupTest(t) + data.ctx = data.ctx.WithExecMode(sdk.ExecModeSimulate) + + msg := &types.MsgStoreCode{ + Sender: addr1, + WASMByteCode: testContract, + } + + h := data.msgServiceRouter.Handler(msg) + + _, err := h(data.ctx, msg) + require.NoError(t, err) +} + +func TestHandleCreate(t *testing.T) { + cases := map[string]struct { + msg sdk.Msg + isValid bool + }{ + "empty": { + msg: &types.MsgStoreCode{}, + isValid: false, + }, + "invalid wasm": { + msg: &types.MsgStoreCode{ + Sender: addr1, + WASMByteCode: []byte("foobar"), + }, + isValid: false, + }, + "valid wasm": { + msg: &types.MsgStoreCode{ + Sender: addr1, + WASMByteCode: testContract, + }, + isValid: true, + }, + "other valid wasm": { + msg: &types.MsgStoreCode{ + Sender: addr1, + WASMByteCode: maskContract, + }, + isValid: true, + }, + "old wasm (0.7)": { + msg: &types.MsgStoreCode{ + Sender: addr1, + WASMByteCode: oldContract, + }, + isValid: false, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + data := setupTest(t) + + h := data.msgServiceRouter.Handler(tc.msg) + // q := data.grpcQueryRouter.Route(sdk.MsgTypeURL(tc.msg)) + q := data.grpcQueryRouter + + res, err := h(data.ctx, tc.msg) + if !tc.isValid { + require.Error(t, err, "%#v", res) + assertCodeList(t, q, data.ctx, 0, data.encConf.Codec) + assertCodeBytes(t, q, data.ctx, 1, nil, data.encConf.Codec) + return + } + require.NoError(t, err) + assertCodeList(t, q, data.ctx, 1, data.encConf.Codec) + }) + } +} + +type initMsg struct { + Verifier sdk.AccAddress `json:"verifier"` + Beneficiary sdk.AccAddress `json:"beneficiary"` +} + +type state struct { + Verifier string `json:"verifier"` + Beneficiary string `json:"beneficiary"` + Funder string `json:"funder"` +} + +func TestHandleInstantiate(t *testing.T) { + data := setupTest(t) + creator := data.faucet.NewFundedRandomAccount(data.ctx, sdk.NewInt64Coin("denom", 100000)) + + msg := &types.MsgStoreCode{ + Sender: creator.String(), + WASMByteCode: testContract, + } + + h := data.msgServiceRouter.Handler(msg) + q := data.grpcQueryRouter + + res, err := h(data.ctx, msg) + require.NoError(t, err) + assertStoreCodeResponse(t, res.Data, 1) + + _, bob := keyPubAddr() + _, fred := keyPubAddr() + + initPayload := initMsg{ + Verifier: fred, + Beneficiary: bob, + } + initMsgBz, err := json.Marshal(initPayload) + require.NoError(t, err) + + // create with no balance is also legal + initMsg := &types.MsgInstantiateContract{ + Sender: creator.String(), + CodeID: firstCodeID, + Msg: initMsgBz, + Funds: nil, + Label: "testing", + } + h = data.msgServiceRouter.Handler(initMsg) + res, err = h(data.ctx, initMsg) + require.NoError(t, err) + contractBech32Addr := parseInitResponse(t, res.Data) + + // this should be standard x/wasm init event, nothing from contract + require.Equal(t, 2, len(res.Events), prettyEvents(res.Events)) + require.Equal(t, "instantiate", res.Events[0].Type) + require.Equal(t, "wasm", res.Events[1].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[1].Attributes[0]) + + assertCodeList(t, q, data.ctx, 1, data.encConf.Codec) + assertCodeBytes(t, q, data.ctx, 1, testContract, data.encConf.Codec) + + assertContractList(t, q, data.ctx, 1, []string{contractBech32Addr}, data.encConf.Codec) + assertContractInfo(t, q, data.ctx, contractBech32Addr, 1, creator, data.encConf.Codec) + assertContractState(t, q, data.ctx, contractBech32Addr, state{ + Verifier: fred.String(), + Beneficiary: bob.String(), + Funder: creator.String(), + }, data.encConf.Codec) +} + +func TestHandleExecute(t *testing.T) { + data := setupTest(t) + + deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000)) + topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000)) + + creator := data.faucet.NewFundedRandomAccount(data.ctx, deposit.Add(deposit...)...) + fred := data.faucet.NewFundedRandomAccount(data.ctx, topUp...) + + msg := &types.MsgStoreCode{ + Sender: creator.String(), + WASMByteCode: testContract, + } + h := data.msgServiceRouter.Handler(msg) + q := data.grpcQueryRouter + res, err := h(data.ctx, msg) + require.NoError(t, err) + assertStoreCodeResponse(t, res.Data, 1) + + _, bob := keyPubAddr() + initMsg := initMsg{ + Verifier: fred, + Beneficiary: bob, + } + initMsgBz, err := json.Marshal(initMsg) + require.NoError(t, err) + + initCmd := &types.MsgInstantiateContract{ + Sender: creator.String(), + CodeID: firstCodeID, + Msg: initMsgBz, + Funds: deposit, + Label: "testing", + } + h = data.msgServiceRouter.Handler(initCmd) + res, err = h(data.ctx, initCmd) + require.NoError(t, err) + contractBech32Addr := parseInitResponse(t, res.Data) + + // this should be standard x/wasm message event, init event, plus a bank send event (2), with no custom contract events + require.Equal(t, 5, len(res.Events), prettyEvents(res.Events)) + require.Equal(t, "coin_spent", res.Events[0].Type) + require.Equal(t, "coin_received", res.Events[1].Type) + require.Equal(t, "transfer", res.Events[2].Type) + require.Equal(t, "instantiate", res.Events[3].Type) + require.Equal(t, "wasm", res.Events[4].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[4].Attributes[0]) + + // ensure bob doesn't exist + bobAcct := data.acctKeeper.GetAccount(data.ctx, bob) + require.Nil(t, bobAcct) + + // ensure funder has reduced balance + creatorAcct := data.acctKeeper.GetAccount(data.ctx, creator) + require.NotNil(t, creatorAcct) + // we started at 2*deposit, should have spent one above + assert.Equal(t, deposit, data.bankKeeper.GetAllBalances(data.ctx, creatorAcct.GetAddress())) + + // ensure contract has updated balance + contractAddr, _ := sdk.AccAddressFromBech32(contractBech32Addr) + contractAcct := data.acctKeeper.GetAccount(data.ctx, contractAddr) + require.NotNil(t, contractAcct) + assert.Equal(t, deposit, data.bankKeeper.GetAllBalances(data.ctx, contractAcct.GetAddress())) + + execCmd := &types.MsgExecuteContract{ + Sender: fred.String(), + Contract: contractBech32Addr, + Msg: []byte(`{"release":{}}`), + Funds: topUp, + } + h = data.msgServiceRouter.Handler(execCmd) + res, err = h(data.ctx, execCmd) + require.NoError(t, err) + // from https://github.com/CosmWasm/cosmwasm/blob/master/contracts/hackatom/src/contract.rs#L167 + assertExecuteResponse(t, res.Data, []byte{0xf0, 0x0b, 0xaa}) + + // this should be standard message event, plus x/wasm init event, plus 2 bank send event, plus a special event from the contract + require.Equal(t, 9, len(res.Events), prettyEvents(res.Events)) + + assert.Equal(t, "coin_spent", res.Events[0].Type) + assert.Equal(t, "coin_received", res.Events[1].Type) + + require.Equal(t, "transfer", res.Events[2].Type) + require.Len(t, res.Events[2].Attributes, 3) + assertAttribute(t, "recipient", contractBech32Addr, res.Events[2].Attributes[0]) + assertAttribute(t, "sender", fred.String(), res.Events[2].Attributes[1]) + assertAttribute(t, "amount", "5000denom", res.Events[2].Attributes[2]) + + assert.Equal(t, "execute", res.Events[3].Type) + + // custom contract event attribute + assert.Equal(t, "wasm", res.Events[4].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[4].Attributes[0]) + assertAttribute(t, "action", "release", res.Events[4].Attributes[1]) + // custom contract event + assert.Equal(t, "wasm-hackatom", res.Events[5].Type) + assertAttribute(t, "_contract_address", contractBech32Addr, res.Events[5].Attributes[0]) + assertAttribute(t, "action", "release", res.Events[5].Attributes[1]) + // second transfer (this without conflicting message) + assert.Equal(t, "coin_spent", res.Events[6].Type) + assert.Equal(t, "coin_received", res.Events[7].Type) + + assert.Equal(t, "transfer", res.Events[8].Type) + assertAttribute(t, "recipient", bob.String(), res.Events[8].Attributes[0]) + assertAttribute(t, "sender", contractBech32Addr, res.Events[8].Attributes[1]) + assertAttribute(t, "amount", "105000denom", res.Events[8].Attributes[2]) + // finally, standard x/wasm tag + + // ensure bob now exists and got both payments released + bobAcct = data.acctKeeper.GetAccount(data.ctx, bob) + require.NotNil(t, bobAcct) + balance := data.bankKeeper.GetAllBalances(data.ctx, bobAcct.GetAddress()) + assert.Equal(t, deposit.Add(topUp...), balance) + + // ensure contract has updated balance + + contractAcct = data.acctKeeper.GetAccount(data.ctx, contractAddr) + require.NotNil(t, contractAcct) + assert.Equal(t, sdk.Coins{}, data.bankKeeper.GetAllBalances(data.ctx, contractAcct.GetAddress())) + + // ensure all contract state is as after init + assertCodeList(t, q, data.ctx, 1, data.encConf.Codec) + assertCodeBytes(t, q, data.ctx, 1, testContract, data.encConf.Codec) + + assertContractList(t, q, data.ctx, 1, []string{contractBech32Addr}, data.encConf.Codec) + assertContractInfo(t, q, data.ctx, contractBech32Addr, 1, creator, data.encConf.Codec) + assertContractState(t, q, data.ctx, contractBech32Addr, state{ + Verifier: fred.String(), + Beneficiary: bob.String(), + Funder: creator.String(), + }, data.encConf.Codec) +} + +func TestHandleExecuteEscrow(t *testing.T) { + data := setupTest(t) + + deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000)) + topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000)) + creator := sdk.AccAddress(bytes.Repeat([]byte{1}, address.Len)) + data.faucet.Fund(data.ctx, creator, sdk.NewInt64Coin("denom", 100000)) + fred := data.faucet.NewFundedRandomAccount(data.ctx, topUp...) + + msg := &types.MsgStoreCode{ + Sender: creator.String(), + WASMByteCode: testContract, + } + + h := data.msgServiceRouter.Handler(msg) + _, err := h(data.ctx, msg) + require.NoError(t, err) + + _, bob := keyPubAddr() + initMsg := map[string]interface{}{ + "verifier": fred.String(), + "beneficiary": bob.String(), + } + initMsgBz, err := json.Marshal(initMsg) + require.NoError(t, err) + + initCmd := types.MsgInstantiateContract{ + Sender: creator.String(), + CodeID: firstCodeID, + Msg: initMsgBz, + Funds: deposit, + Label: "testing", + } + h = data.msgServiceRouter.Handler(&initCmd) + res, err := h(data.ctx, &initCmd) + require.NoError(t, err) + contractBech32Addr := parseInitResponse(t, res.Data) + handleMsg := map[string]interface{}{ + "release": map[string]interface{}{}, + } + handleMsgBz, err := json.Marshal(handleMsg) + require.NoError(t, err) + + execCmd := types.MsgExecuteContract{ + Sender: fred.String(), + Contract: contractBech32Addr, + Msg: handleMsgBz, + Funds: topUp, + } + h = data.msgServiceRouter.Handler(&execCmd) + res, err = h(data.ctx, &execCmd) + require.NoError(t, err) + // from https://github.com/CosmWasm/cosmwasm/blob/master/contracts/hackatom/src/contract.rs#L167 + assertExecuteResponse(t, res.Data, []byte{0xf0, 0x0b, 0xaa}) + + // ensure bob now exists and got both payments released + bobAcct := data.acctKeeper.GetAccount(data.ctx, bob) + require.NotNil(t, bobAcct) + balance := data.bankKeeper.GetAllBalances(data.ctx, bobAcct.GetAddress()) + assert.Equal(t, deposit.Add(topUp...), balance) + + // ensure contract has updated balance + contractAddr, _ := sdk.AccAddressFromBech32(contractBech32Addr) + contractAcct := data.acctKeeper.GetAccount(data.ctx, contractAddr) + require.NotNil(t, contractAcct) + assert.Equal(t, sdk.Coins{}, data.bankKeeper.GetAllBalances(data.ctx, contractAcct.GetAddress())) +} + +func TestReadNodeConfig(t *testing.T) { + withViper := func(s string) *viper.Viper { + v := viper.New() + v.SetConfigType("toml") + require.NoError(t, v.ReadConfig(strings.NewReader(s))) + return v + } + var one uint64 = 1 + defaults := types.DefaultNodeConfig() + + specs := map[string]struct { + src servertypes.AppOptions + exp types.NodeConfig + }{ + "set query gas limit via opts": { + src: AppOptionsMock{ + "wasm.query_gas_limit": 1, + }, + exp: types.NodeConfig{ + SmartQueryGasLimit: 1, + MemoryCacheSize: defaults.MemoryCacheSize, + }, + }, + "set cache via opts": { + src: AppOptionsMock{ + "wasm.memory_cache_size": 2, + }, + exp: types.NodeConfig{ + MemoryCacheSize: 2, + SmartQueryGasLimit: defaults.SmartQueryGasLimit, + }, + }, + "set debug via opts": { + src: AppOptionsMock{ + "trace": true, + }, + exp: types.NodeConfig{ + SmartQueryGasLimit: defaults.SmartQueryGasLimit, + MemoryCacheSize: defaults.MemoryCacheSize, + ContractDebugMode: true, + }, + }, + "all defaults when no options set": { + src: AppOptionsMock{}, + exp: defaults, + }, + "default config template values": { + src: withViper(types.DefaultConfigTemplate()), + exp: defaults, + }, + "custom config template values": { + src: withViper(types.ConfigTemplate(types.NodeConfig{ + SimulationGasLimit: &one, + SmartQueryGasLimit: 2, + MemoryCacheSize: 3, + })), + exp: types.NodeConfig{ + SimulationGasLimit: &one, + SmartQueryGasLimit: 2, + MemoryCacheSize: 3, + ContractDebugMode: false, + }, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + got, err := wasm.ReadNodeConfig(spec.src) + require.NoError(t, err) + assert.Equal(t, spec.exp, got) + }) + } +} + +type AppOptionsMock map[string]interface{} + +func (a AppOptionsMock) Get(s string) interface{} { + return a[s] +} + +type prettyEvent struct { + Type string + Attr []sdk.Attribute +} + +func prettyEvents(evts []abci.Event) string { + res := make([]prettyEvent, len(evts)) + for i, e := range evts { + res[i] = prettyEvent{ + Type: e.Type, + Attr: prettyAttrs(e.Attributes), + } + } + bz, err := json.MarshalIndent(res, "", " ") + if err != nil { + panic(err) + } + return string(bz) +} + +func prettyAttrs(attrs []abci.EventAttribute) []sdk.Attribute { + pretty := make([]sdk.Attribute, len(attrs)) + for i, a := range attrs { + pretty[i] = prettyAttr(a) + } + return pretty +} + +func prettyAttr(attr abci.EventAttribute) sdk.Attribute { + return sdk.NewAttribute(attr.Key, attr.Value) +} + +func assertAttribute(t *testing.T, key, value string, attr abci.EventAttribute) { + t.Helper() + assert.Equal(t, key, attr.Key, prettyAttr(attr)) + assert.Equal(t, value, attr.Value, prettyAttr(attr)) +} + +func assertCodeList(t *testing.T, q *baseapp.GRPCQueryRouter, ctx sdk.Context, expectedNum int, marshaler codec.Codec) { + t.Helper() + path := "/cosmwasm.wasm.v1.Query/Codes" + resp, sdkerr := q.Route(path)(ctx, &abci.RequestQuery{Path: path}) + require.NoError(t, sdkerr) + require.True(t, resp.IsOK()) + + bz := resp.Value + if len(bz) == 0 { + require.Equal(t, expectedNum, 0) + return + } + + var res types.QueryCodesResponse + require.NoError(t, marshaler.Unmarshal(bz, &res)) + assert.Equal(t, expectedNum, len(res.CodeInfos)) +} + +func assertCodeBytes(t *testing.T, q *baseapp.GRPCQueryRouter, ctx sdk.Context, codeID uint64, expectedBytes []byte, marshaler codec.Codec) { + t.Helper() + bz, err := marshaler.Marshal(&types.QueryCodeRequest{CodeId: codeID}) + require.NoError(t, err) + + path := "/cosmwasm.wasm.v1.Query/Code" + resp, err := q.Route(path)(ctx, &abci.RequestQuery{Path: path, Data: bz}) + if len(expectedBytes) == 0 { + require.Equal(t, types.ErrNoSuchCodeFn(codeID).Wrapf("code id %d", codeID).Error(), err.Error()) + return + } + require.NoError(t, err) + require.True(t, resp.IsOK()) + bz = resp.Value + + var rsp types.QueryCodeResponse + require.NoError(t, marshaler.Unmarshal(bz, &rsp)) + assert.Equal(t, expectedBytes, rsp.Data) +} + +func assertContractList(t *testing.T, q *baseapp.GRPCQueryRouter, ctx sdk.Context, codeID uint64, expContractAddrs []string, marshaler codec.Codec) { + t.Helper() + bz, err := marshaler.Marshal(&types.QueryContractsByCodeRequest{CodeId: codeID}) + require.NoError(t, err) + + path := "/cosmwasm.wasm.v1.Query/ContractsByCode" + resp, sdkerr := q.Route(path)(ctx, &abci.RequestQuery{Path: path, Data: bz}) + if len(expContractAddrs) == 0 { + assert.ErrorIs(t, err, types.ErrNotFound) + return + } + require.NoError(t, sdkerr) + require.True(t, resp.IsOK()) + bz = resp.Value + + var rsp types.QueryContractsByCodeResponse + require.NoError(t, marshaler.Unmarshal(bz, &rsp)) + + hasAddrs := make([]string, len(rsp.Contracts)) + for i, r := range rsp.Contracts { //nolint:gosimple + hasAddrs[i] = r + } + assert.Equal(t, expContractAddrs, hasAddrs) +} + +func assertContractState(t *testing.T, q *baseapp.GRPCQueryRouter, ctx sdk.Context, contractBech32Addr string, expected state, marshaler codec.Codec) { + t.Helper() + bz, err := marshaler.Marshal(&types.QueryRawContractStateRequest{Address: contractBech32Addr, QueryData: []byte("config")}) + require.NoError(t, err) + + path := "/cosmwasm.wasm.v1.Query/RawContractState" + resp, sdkerr := q.Route(path)(ctx, &abci.RequestQuery{Path: path, Data: bz}) + require.NoError(t, sdkerr) + require.True(t, resp.IsOK()) + bz = resp.Value + + var rsp types.QueryRawContractStateResponse + require.NoError(t, marshaler.Unmarshal(bz, &rsp)) + expectedBz, err := json.Marshal(expected) + require.NoError(t, err) + assert.Equal(t, expectedBz, rsp.Data) +} + +func assertContractInfo(t *testing.T, q *baseapp.GRPCQueryRouter, ctx sdk.Context, contractBech32Addr string, codeID uint64, creator sdk.AccAddress, marshaler codec.Codec) { + t.Helper() + bz, err := marshaler.Marshal(&types.QueryContractInfoRequest{Address: contractBech32Addr}) + require.NoError(t, err) + + path := "/cosmwasm.wasm.v1.Query/ContractInfo" + resp, sdkerr := q.Route(path)(ctx, &abci.RequestQuery{Path: path, Data: bz}) + require.NoError(t, sdkerr) + require.True(t, resp.IsOK()) + bz = resp.Value + + var rsp types.QueryContractInfoResponse + require.NoError(t, marshaler.Unmarshal(bz, &rsp)) + + assert.Equal(t, codeID, rsp.CodeID) + assert.Equal(t, creator.String(), rsp.Creator) +} diff --git a/tests/integration/wasm/msg_server_integration_test.go b/tests/integration/wasm/msg_server_integration_test.go new file mode 100644 index 00000000..a004d968 --- /dev/null +++ b/tests/integration/wasm/msg_server_integration_test.go @@ -0,0 +1,1224 @@ +package wasm_test + +import ( + "encoding/json" + "testing" + "time" + + wasmvm "github.com/CosmWasm/wasmvm/v3" + wasmvmtypes "github.com/CosmWasm/wasmvm/v3/types" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/CosmWasm/wasmd/x/wasm/keeper" + "github.com/CosmWasm/wasmd/x/wasm/types" + + "github.com/LumeraProtocol/lumera/app" +) + +var reflectContract = mustLoad(GetTestDataFilePath("reflect_1_5.wasm")) + +func TestStoreCode(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContext(false) + _, sender := keyPubAddr() + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = reflectContract + m.Sender = sender.String() + }) + + // when + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + + // then + require.NoError(t, err) + var result types.MsgStoreCodeResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) + assert.Equal(t, uint64(1), result.CodeID) + + expHash, err := wasmvm.CreateChecksum(reflectContract) + require.NoError(t, err) + assert.Equal(t, expHash[:], wasmvmtypes.Checksum(result.Checksum)) + // and + info := wasmApp.WasmKeeper.GetCodeInfo(ctx, 1) + assert.NotNil(t, info) + assert.Equal(t, expHash[:], wasmvmtypes.Checksum(info.CodeHash)) + assert.Equal(t, sender.String(), info.Creator) + assert.Equal(t, types.DefaultParams().InstantiateDefaultPermission.With(sender), info.InstantiateConfig) +} + +func TestUpdateParams(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContext(false) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + oneAddressAccessConfig = types.AccessTypeAnyOfAddresses.With(myAddress) + govAuthority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + src types.MsgUpdateParams + expUploadConfig types.AccessConfig + expInstantiateType types.AccessType + }{ + "update upload permission param": { + src: types.MsgUpdateParams{ + Authority: govAuthority, + Params: types.Params{ + CodeUploadAccess: types.AllowNobody, + InstantiateDefaultPermission: types.AccessTypeEverybody, + }, + }, + expUploadConfig: types.AllowNobody, + expInstantiateType: types.AccessTypeEverybody, + }, + "update upload permission with same as current value": { + src: types.MsgUpdateParams{ + Authority: govAuthority, + Params: types.Params{ + CodeUploadAccess: types.AllowEverybody, + InstantiateDefaultPermission: types.AccessTypeEverybody, + }, + }, + expUploadConfig: types.AllowEverybody, + expInstantiateType: types.AccessTypeEverybody, + }, + "update upload permission param with address": { + src: types.MsgUpdateParams{ + Authority: govAuthority, + Params: types.Params{ + CodeUploadAccess: oneAddressAccessConfig, + InstantiateDefaultPermission: types.AccessTypeEverybody, + }, + }, + expUploadConfig: oneAddressAccessConfig, + expInstantiateType: types.AccessTypeEverybody, + }, + "update instantiate param": { + src: types.MsgUpdateParams{ + Authority: govAuthority, + Params: types.Params{ + CodeUploadAccess: types.AllowEverybody, + InstantiateDefaultPermission: types.AccessTypeNobody, + }, + }, + expUploadConfig: types.AllowEverybody, + expInstantiateType: types.AccessTypeNobody, + }, + "update instantiate param as default": { + src: types.MsgUpdateParams{ + Authority: govAuthority, + Params: types.Params{ + CodeUploadAccess: types.AllowEverybody, + InstantiateDefaultPermission: types.AccessTypeEverybody, + }, + }, + expUploadConfig: types.AllowEverybody, + expInstantiateType: types.AccessTypeEverybody, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + err := wasmApp.WasmKeeper.SetParams(ctx, types.DefaultParams()) + require.NoError(t, err) + + // when + rsp, err := wasmApp.MsgServiceRouter().Handler(&spec.src)(ctx, &spec.src) //nolint:gosec + require.NoError(t, err) + var result types.MsgUpdateParamsResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) + + // then + assert.True(t, spec.expUploadConfig.Equals(wasmApp.WasmKeeper.GetParams(ctx).CodeUploadAccess), + "got %#v not %#v", wasmApp.WasmKeeper.GetParams(ctx).CodeUploadAccess, spec.expUploadConfig) + assert.Equal(t, spec.expInstantiateType, wasmApp.WasmKeeper.GetParams(ctx).InstantiateDefaultPermission) + }) + } +} + +func TestAddCodeUploadParamsAddresses(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContext(false) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + otherAddr = func() sdk.AccAddress { _, addr := keyPubAddr(); return addr }() + govAuthority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + src types.MsgAddCodeUploadParamsAddresses + uploadConfig types.AccessConfig + expUploadConfig types.AccessConfig + expErr bool + }{ + "authority can add addresses when permission is any of addresses": { + src: types.MsgAddCodeUploadParamsAddresses{ + Authority: govAuthority, + Addresses: []string{otherAddr.String()}, + }, + uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress), + expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr), + }, + "add existing address": { + src: types.MsgAddCodeUploadParamsAddresses{ + Authority: govAuthority, + Addresses: []string{myAddress.String()}, + }, + uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress), + expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress), + }, + "authority cannot add addresses when permission is allow everybody": { + src: types.MsgAddCodeUploadParamsAddresses{ + Authority: govAuthority, + Addresses: []string{otherAddr.String()}, + }, + uploadConfig: types.AllowEverybody, + expUploadConfig: types.AllowEverybody, + expErr: true, + }, + "authority cannot add addresses when permission is allow nobody": { + src: types.MsgAddCodeUploadParamsAddresses{ + Authority: govAuthority, + Addresses: []string{otherAddr.String()}, + }, + uploadConfig: types.AllowNobody, + expUploadConfig: types.AllowNobody, + expErr: true, + }, + "authority cannot add duplicate addresses when permission is any of addresses": { + src: types.MsgAddCodeUploadParamsAddresses{ + Authority: govAuthority, + Addresses: []string{otherAddr.String(), otherAddr.String()}, + }, + uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress), + expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress), + expErr: true, + }, + "other address cannot add addresses when permission is any of addresses": { + src: types.MsgAddCodeUploadParamsAddresses{ + Authority: otherAddr.String(), + Addresses: []string{otherAddr.String()}, + }, + uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress), + expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr), + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + err := wasmApp.WasmKeeper.SetParams(ctx, types.Params{ + CodeUploadAccess: spec.uploadConfig, + InstantiateDefaultPermission: types.AccessTypeEverybody, + }) + require.NoError(t, err) + + // when + rsp, err := wasmApp.MsgServiceRouter().Handler(&spec.src)(ctx, &spec.src) //nolint:gosec + if spec.expErr { + require.Error(t, err) + require.Nil(t, rsp) + return + } + require.NoError(t, err) + require.Len(t, rsp.MsgResponses, 1) + assert.IsType(t, rsp.MsgResponses[0].GetCachedValue(), &types.MsgAddCodeUploadParamsAddressesResponse{}) + + // then + gotUploadConfig := wasmApp.WasmKeeper.GetParams(ctx).CodeUploadAccess + assert.True(t, spec.expUploadConfig.Equals(gotUploadConfig), + "got %#v not %#v", gotUploadConfig, spec.expUploadConfig) + }) + } +} + +func TestRemoveCodeUploadParamsAddresses(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContext(false) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + otherAddr = func() sdk.AccAddress { _, addr := keyPubAddr(); return addr }() + govAuthority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + src types.MsgRemoveCodeUploadParamsAddresses + uploadConfig types.AccessConfig + expUploadConfig types.AccessConfig + expErr bool + }{ + "authority can remove addresses when permission is any of addresses": { + src: types.MsgRemoveCodeUploadParamsAddresses{ + Authority: govAuthority, + Addresses: []string{otherAddr.String()}, + }, + uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr), + expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress), + }, + "authority cannot remove not existing addresses when permission is any of addresses": { + src: types.MsgRemoveCodeUploadParamsAddresses{ + Authority: govAuthority, + Addresses: []string{otherAddr.String()}, + }, + uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress), + expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress), + }, + "authority cannot remove addresses when permission is allow everybody": { + src: types.MsgRemoveCodeUploadParamsAddresses{ + Authority: govAuthority, + Addresses: []string{otherAddr.String()}, + }, + uploadConfig: types.AllowEverybody, + expUploadConfig: types.AllowEverybody, + expErr: true, + }, + "authority cannot remove addresses when permission is allow nobody": { + src: types.MsgRemoveCodeUploadParamsAddresses{ + Authority: govAuthority, + Addresses: []string{otherAddr.String()}, + }, + uploadConfig: types.AllowNobody, + expUploadConfig: types.AllowNobody, + expErr: true, + }, + "authority cannot remove duplicate addresses when permission is any of addresses": { + src: types.MsgRemoveCodeUploadParamsAddresses{ + Authority: govAuthority, + Addresses: []string{otherAddr.String(), otherAddr.String()}, + }, + uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr), + expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr), + expErr: true, + }, + "other address cannot remove addresses when permission is any of addresses": { + src: types.MsgRemoveCodeUploadParamsAddresses{ + Authority: otherAddr.String(), + Addresses: []string{otherAddr.String()}, + }, + uploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr), + expUploadConfig: types.AccessTypeAnyOfAddresses.With(myAddress, otherAddr), + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + err := wasmApp.WasmKeeper.SetParams(ctx, types.Params{ + CodeUploadAccess: spec.uploadConfig, + InstantiateDefaultPermission: types.AccessTypeEverybody, + }) + require.NoError(t, err) + + // when + rsp, err := wasmApp.MsgServiceRouter().Handler(&spec.src)(ctx, &spec.src) //nolint:gosec + if spec.expErr { + require.Error(t, err) + require.Nil(t, rsp) + return + } + require.NoError(t, err) + require.Len(t, rsp.MsgResponses, 1) + assert.IsType(t, rsp.MsgResponses[0].GetCachedValue(), &types.MsgRemoveCodeUploadParamsAddressesResponse{}) + + // then + gotUploadConfig := wasmApp.WasmKeeper.GetParams(ctx).CodeUploadAccess + assert.True(t, spec.expUploadConfig.Equals(gotUploadConfig), + "got %#v not %#v", gotUploadConfig, spec.expUploadConfig) + }) + } +} + +func TestPinCodes(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContext(false) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + addr string + expErr bool + }{ + "authority can pin codes": { + addr: authority, + expErr: false, + }, + "other address cannot pin codes": { + addr: myAddress.String(), + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + _, sender := keyPubAddr() + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = reflectContract + m.Sender = sender.String() + }) + + // store code + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var result types.MsgStoreCodeResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) + require.False(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID)) + + // when + msgPinCodes := &types.MsgPinCodes{ + Authority: spec.addr, + CodeIDs: []uint64{result.CodeID}, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgPinCodes)(ctx, msgPinCodes) + + // then + if spec.expErr { + require.Error(t, err) + assert.False(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID)) + } else { + require.NoError(t, err) + assert.True(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID)) + } + }) + } +} + +func TestUnpinCodes(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContext(false) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + addr string + expErr bool + }{ + "authority can unpin codes": { + addr: authority, + expErr: false, + }, + "other address cannot unpin codes": { + addr: myAddress.String(), + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + _, sender := keyPubAddr() + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = reflectContract + m.Sender = sender.String() + }) + + // store code + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var result types.MsgStoreCodeResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) + + // pin code + msgPin := &types.MsgPinCodes{ + Authority: authority, + CodeIDs: []uint64{result.CodeID}, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgPin)(ctx, msgPin) + require.NoError(t, err) + assert.True(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID)) + + // when + msgUnpinCodes := &types.MsgUnpinCodes{ + Authority: spec.addr, + CodeIDs: []uint64{result.CodeID}, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgUnpinCodes)(ctx, msgUnpinCodes) + + // then + if spec.expErr { + require.Error(t, err) + assert.True(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID)) + } else { + require.NoError(t, err) + assert.False(t, wasmApp.WasmKeeper.IsPinnedCode(ctx, result.CodeID)) + } + }) + } +} + +func TestSudoContract(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + ) + + type StealMsg struct { + Recipient string `json:"recipient"` + Amount []sdk.Coin `json:"amount"` + } + + stealMsg := struct { + Steal StealMsg `json:"steal_funds"` + }{Steal: StealMsg{ + Recipient: myAddress.String(), + Amount: []sdk.Coin{}, + }} + + stealMsgBz, err := json.Marshal(stealMsg) + require.NoError(t, err) + + specs := map[string]struct { + addr string + expErr bool + }{ + "authority can call sudo on a contract": { + addr: authority, + expErr: false, + }, + "other address cannot call sudo on a contract": { + addr: myAddress.String(), + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + _, sender := keyPubAddr() + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = testContract + m.Sender = sender.String() + }) + + // store code + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var storeCodeResponse types.MsgStoreCodeResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeCodeResponse)) + + // instantiate contract + initMsg := keeper.HackatomExampleInitMsg{ + Verifier: sender, + Beneficiary: myAddress, + } + initMsgBz, err := json.Marshal(initMsg) + require.NoError(t, err) + + msgInstantiate := &types.MsgInstantiateContract{ + Sender: sender.String(), + Admin: sender.String(), + CodeID: storeCodeResponse.CodeID, + Label: "test", + Msg: initMsgBz, + Funds: sdk.Coins{}, + } + rsp, err = wasmApp.MsgServiceRouter().Handler(msgInstantiate)(ctx, msgInstantiate) + require.NoError(t, err) + var instantiateResponse types.MsgInstantiateContractResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &instantiateResponse)) + + // when + msgSudoContract := &types.MsgSudoContract{ + Authority: spec.addr, + Msg: stealMsgBz, + Contract: instantiateResponse.Address, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgSudoContract)(ctx, msgSudoContract) + + // then + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestStoreAndInstantiateContract(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + addr string + permission *types.AccessConfig + expErr bool + }{ + "authority can store and instantiate a contract when permission is nobody": { + addr: authority, + permission: &types.AllowNobody, + expErr: false, + }, + "other address cannot store and instantiate a contract when permission is nobody": { + addr: myAddress.String(), + permission: &types.AllowNobody, + expErr: true, + }, + "authority can store and instantiate a contract when permission is everybody": { + addr: authority, + permission: &types.AllowEverybody, + expErr: false, + }, + "other address can store and instantiate a contract when permission is everybody": { + addr: myAddress.String(), + permission: &types.AllowEverybody, + expErr: false, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // when + msg := &types.MsgStoreAndInstantiateContract{ + Authority: spec.addr, + WASMByteCode: reflectContract, + InstantiatePermission: spec.permission, + Admin: myAddress.String(), + UnpinCode: false, + Label: "test", + Msg: []byte(`{}`), + Funds: sdk.Coins{}, + } + _, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + + // then + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestUpdateAdmin(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + otherAddr = func() sdk.AccAddress { _, addr := keyPubAddr(); return addr }() + ) + + specs := map[string]struct { + addr string + expErr bool + }{ + "authority can update admin": { + addr: authority, + expErr: false, + }, + "admin can update admin": { + addr: myAddress.String(), + expErr: false, + }, + "other address cannot update admin": { + addr: otherAddr.String(), + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + _, newAdmin := keyPubAddr() + + // setup + msg := &types.MsgStoreAndInstantiateContract{ + Authority: spec.addr, + WASMByteCode: reflectContract, + InstantiatePermission: &types.AllowEverybody, + Admin: myAddress.String(), + UnpinCode: false, + Label: "test", + Msg: []byte(`{}`), + Funds: sdk.Coins{}, + } + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var storeAndInstantiateResponse types.MsgStoreAndInstantiateContractResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeAndInstantiateResponse)) + + // when + msgUpdateAdmin := &types.MsgUpdateAdmin{ + Sender: spec.addr, + NewAdmin: newAdmin.String(), + Contract: storeAndInstantiateResponse.Address, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgUpdateAdmin)(ctx, msgUpdateAdmin) + + // then + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestClearAdmin(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + otherAddr = func() sdk.AccAddress { _, addr := keyPubAddr(); return addr }() + ) + + specs := map[string]struct { + addr string + expErr bool + }{ + "authority can clear admin": { + addr: authority, + expErr: false, + }, + "admin can clear admin": { + addr: myAddress.String(), + expErr: false, + }, + "other address cannot clear admin": { + addr: otherAddr.String(), + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + msg := &types.MsgStoreAndInstantiateContract{ + Authority: spec.addr, + WASMByteCode: reflectContract, + InstantiatePermission: &types.AllowEverybody, + Admin: myAddress.String(), + UnpinCode: false, + Label: "test", + Msg: []byte(`{}`), + Funds: sdk.Coins{}, + } + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var storeAndInstantiateResponse types.MsgStoreAndInstantiateContractResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeAndInstantiateResponse)) + + // when + msgClearAdmin := &types.MsgClearAdmin{ + Sender: spec.addr, + Contract: storeAndInstantiateResponse.Address, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgClearAdmin)(ctx, msgClearAdmin) + + // then + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMigrateContract(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + otherAddr = func() sdk.AccAddress { _, addr := keyPubAddr(); return addr }() + ) + + specs := map[string]struct { + addr string + expErr bool + }{ + "authority can migrate a contract": { + addr: authority, + expErr: false, + }, + "admin can migrate a contract": { + addr: myAddress.String(), + expErr: false, + }, + "other address cannot migrate a contract": { + addr: otherAddr.String(), + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + _, sender := keyPubAddr() + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = testContract + m.Sender = sender.String() + }) + + // store code + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var storeCodeResponse types.MsgStoreCodeResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeCodeResponse)) + + // instantiate contract + initMsg := keeper.HackatomExampleInitMsg{ + Verifier: sender, + Beneficiary: myAddress, + } + initMsgBz, err := json.Marshal(initMsg) + require.NoError(t, err) + + msgInstantiate := &types.MsgInstantiateContract{ + Sender: sender.String(), + Admin: myAddress.String(), + CodeID: storeCodeResponse.CodeID, + Label: "test", + Msg: initMsgBz, + Funds: sdk.Coins{}, + } + rsp, err = wasmApp.MsgServiceRouter().Handler(msgInstantiate)(ctx, msgInstantiate) + require.NoError(t, err) + var instantiateResponse types.MsgInstantiateContractResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &instantiateResponse)) + + // when + migMsg := struct { + Verifier sdk.AccAddress `json:"verifier"` + }{Verifier: myAddress} + migMsgBz, err := json.Marshal(migMsg) + require.NoError(t, err) + msgMigrateContract := &types.MsgMigrateContract{ + Sender: spec.addr, + Msg: migMsgBz, + Contract: instantiateResponse.Address, + CodeID: storeCodeResponse.CodeID, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgMigrateContract)(ctx, msgMigrateContract) + + // then + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestInstantiateContract(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + addr string + permission *types.AccessConfig + expErr bool + }{ + "authority can instantiate a contract when permission is nobody": { + addr: authority, + permission: &types.AllowNobody, + expErr: false, + }, + "other address cannot instantiate a contract when permission is nobody": { + addr: myAddress.String(), + permission: &types.AllowNobody, + expErr: true, + }, + "authority can instantiate a contract when permission is everybody": { + addr: authority, + permission: &types.AllowEverybody, + expErr: false, + }, + "other address can instantiate a contract when permission is everybody": { + addr: myAddress.String(), + permission: &types.AllowEverybody, + expErr: false, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + _, sender := keyPubAddr() + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = reflectContract + m.Sender = sender.String() + m.InstantiatePermission = spec.permission + }) + + // store code + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var result types.MsgStoreCodeResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) + + // when + msgInstantiate := &types.MsgInstantiateContract{ + Sender: spec.addr, + Admin: myAddress.String(), + CodeID: result.CodeID, + Label: "test", + Msg: []byte(`{}`), + Funds: sdk.Coins{}, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgInstantiate)(ctx, msgInstantiate) + + // then + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestInstantiateContract2(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + addr string + salt string + permission *types.AccessConfig + expErr bool + }{ + "authority can instantiate a contract when permission is nobody": { + addr: authority, + permission: &types.AllowNobody, + salt: "salt1", + expErr: false, + }, + "other address cannot instantiate a contract when permission is nobody": { + addr: myAddress.String(), + permission: &types.AllowNobody, + salt: "salt2", + expErr: true, + }, + "authority can instantiate a contract when permission is everybody": { + addr: authority, + permission: &types.AllowEverybody, + salt: "salt3", + expErr: false, + }, + "other address can instantiate a contract when permission is everybody": { + addr: myAddress.String(), + permission: &types.AllowEverybody, + salt: "salt4", + expErr: false, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + _, sender := keyPubAddr() + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = reflectContract + m.Sender = sender.String() + m.InstantiatePermission = spec.permission + }) + + // store code + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var result types.MsgStoreCodeResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) + + // when + msgInstantiate := &types.MsgInstantiateContract2{ + Sender: spec.addr, + Admin: myAddress.String(), + CodeID: result.CodeID, + Label: "label", + Msg: []byte(`{}`), + Funds: sdk.Coins{}, + Salt: []byte(spec.salt), + FixMsg: true, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgInstantiate)(ctx, msgInstantiate) + + // then + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestUpdateInstantiateConfig(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) + + var ( + creator sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + addr string + permission *types.AccessConfig + expErr bool + }{ + "authority can update instantiate config when permission is subset": { + addr: authority, + permission: &types.AllowNobody, + expErr: false, + }, + "creator can update instantiate config when permission is subset": { + addr: creator.String(), + permission: &types.AllowNobody, + expErr: false, + }, + "authority can update instantiate config when permission is not subset": { + addr: authority, + permission: &types.AllowEverybody, + expErr: false, + }, + "creator cannot update instantiate config when permission is not subset": { + addr: creator.String(), + permission: &types.AllowEverybody, + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + err := wasmApp.WasmKeeper.SetParams(ctx, types.Params{ + CodeUploadAccess: types.AllowEverybody, + InstantiateDefaultPermission: types.AccessTypeNobody, + }) + require.NoError(t, err) + + msg := types.MsgStoreCodeFixture(func(m *types.MsgStoreCode) { + m.WASMByteCode = reflectContract + m.Sender = creator.String() + m.InstantiatePermission = &types.AllowNobody + }) + + // store code + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var result types.MsgStoreCodeResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) + + // when + msgUpdateInstantiateConfig := &types.MsgUpdateInstantiateConfig{ + Sender: spec.addr, + CodeID: result.CodeID, + NewInstantiatePermission: spec.permission, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgUpdateInstantiateConfig)(ctx, msgUpdateInstantiateConfig) + + // then + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestStoreAndMigrateContract(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) + + checksum, err := wasmvm.CreateChecksum(testContract) + require.NoError(t, err) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + ) + + specs := map[string]struct { + addr string + permission *types.AccessConfig + expChecksum []byte + expErr bool + }{ + "authority can store and migrate a contract when permission is nobody": { + addr: authority, + permission: &types.AllowNobody, + expChecksum: checksum, + }, + "authority can store and migrate a contract when permission is everybody": { + addr: authority, + permission: &types.AllowEverybody, + expChecksum: checksum, + }, + "other address can store and migrate a contract when permission is everybody": { + addr: myAddress.String(), + permission: &types.AllowEverybody, + expChecksum: checksum, + }, + "other address cannot store and migrate a contract when permission is nobody": { + addr: myAddress.String(), + permission: &types.AllowNobody, + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + initMsg := keeper.HackatomExampleInitMsg{ + Verifier: myAddress, + Beneficiary: myAddress, + } + initMsgBz, err := json.Marshal(initMsg) + require.NoError(t, err) + storeAndInstantiateMsg := &types.MsgStoreAndInstantiateContract{ + Authority: spec.addr, + WASMByteCode: testContract, + InstantiatePermission: &types.AllowEverybody, + Admin: myAddress.String(), + UnpinCode: false, + Label: "test", + Msg: initMsgBz, + Funds: sdk.Coins{}, + } + rsp, err := wasmApp.MsgServiceRouter().Handler(storeAndInstantiateMsg)(ctx, storeAndInstantiateMsg) + require.NoError(t, err) + var storeAndInstantiateResponse types.MsgStoreAndInstantiateContractResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeAndInstantiateResponse)) + + contractAddr := storeAndInstantiateResponse.Address + + // when + migMsg := struct { + Verifier sdk.AccAddress `json:"verifier"` + }{Verifier: myAddress} + migMsgBz, err := json.Marshal(migMsg) + require.NoError(t, err) + msg := &types.MsgStoreAndMigrateContract{ + Authority: spec.addr, + WASMByteCode: testContract, + InstantiatePermission: spec.permission, + Msg: migMsgBz, + Contract: contractAddr, + } + rsp, err = wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + + // then + if spec.expErr { + require.Error(t, err) + require.Nil(t, rsp) + return + } + + require.NoError(t, err) + var result types.MsgStoreAndMigrateContractResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &result)) + assert.Equal(t, spec.expChecksum, result.Checksum) + require.NotZero(t, result.CodeID) + }) + } +} + +func TestUpdateContractLabel(t *testing.T) { + wasmApp := app.Setup(t) + ctx := wasmApp.BaseApp.NewContextLegacy(false, tmproto.Header{Time: time.Now()}) + + var ( + myAddress sdk.AccAddress = make([]byte, types.ContractAddrLen) + authority = wasmApp.WasmKeeper.GetAuthority() + otherAddr = func() sdk.AccAddress { _, addr := keyPubAddr(); return addr }() + ) + + specs := map[string]struct { + addr string + newLabel string + expErr bool + }{ + "authority can update contract label": { + addr: authority, + newLabel: "new label", + expErr: false, + }, + "admin can update contract label": { + addr: myAddress.String(), + newLabel: "new label", + expErr: false, + }, + "other address cannot update contract label": { + addr: otherAddr.String(), + newLabel: "new label", + expErr: true, + }, + "empty new label": { + addr: authority, + expErr: true, + }, + "invalid new label": { + addr: authority, + newLabel: " start with space ", + expErr: true, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup + msg := &types.MsgStoreAndInstantiateContract{ + Authority: spec.addr, + WASMByteCode: reflectContract, + InstantiatePermission: &types.AllowEverybody, + Admin: myAddress.String(), + UnpinCode: false, + Label: "old label", + Msg: []byte(`{}`), + Funds: sdk.Coins{}, + } + rsp, err := wasmApp.MsgServiceRouter().Handler(msg)(ctx, msg) + require.NoError(t, err) + var storeAndInstantiateResponse types.MsgStoreAndInstantiateContractResponse + require.NoError(t, wasmApp.AppCodec().Unmarshal(rsp.Data, &storeAndInstantiateResponse)) + + contract := storeAndInstantiateResponse.Address + contractAddr, err := sdk.AccAddressFromBech32(contract) + require.NoError(t, err) + require.Equal(t, "old label", wasmApp.WasmKeeper.GetContractInfo(ctx, contractAddr).Label) + + // when + msgUpdateLabel := &types.MsgUpdateContractLabel{ + Sender: spec.addr, + NewLabel: spec.newLabel, + Contract: storeAndInstantiateResponse.Address, + } + _, err = wasmApp.MsgServiceRouter().Handler(msgUpdateLabel)(ctx, msgUpdateLabel) + + // then + if spec.expErr { + require.Error(t, err) + require.Equal(t, "old label", wasmApp.WasmKeeper.GetContractInfo(ctx, contractAddr).Label) + } else { + require.NoError(t, err) + require.Equal(t, spec.newLabel, wasmApp.WasmKeeper.GetContractInfo(ctx, contractAddr).Label) + } + }) + } +} diff --git a/tests/integration/wasm/query_plugin_integration_test.go b/tests/integration/wasm/query_plugin_integration_test.go index f3d51500..f33150d5 100644 --- a/tests/integration/wasm/query_plugin_integration_test.go +++ b/tests/integration/wasm/query_plugin_integration_test.go @@ -13,7 +13,7 @@ import ( wasmvmtypes "github.com/CosmWasm/wasmvm/v3/types" "github.com/cometbft/cometbft/crypto/secp256k1" cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - gogoproto "github.com/cosmos/gogoproto/proto" + proto "github.com/cosmos/gogoproto/proto" channeltypes "github.com/cosmos/ibc-go/v10/modules/core/04-channel/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -130,7 +130,7 @@ func TestReflectStargateQuery(t *testing.T) { func TestReflectGrpcQuery(t *testing.T) { queryPlugins := (*reflectPlugins()).Merge(&wasmKeeper.QueryPlugins{ - Grpc: func(ctx sdk.Context, request *wasmvmtypes.GrpcQuery) (gogoproto.Message, error) { + Grpc: func(ctx sdk.Context, request *wasmvmtypes.GrpcQuery) (proto.Message, error) { if request.Path == "cosmos.bank.v1beta1.Query/AllBalances" { return &banktypes.QueryAllBalancesResponse{ Balances: sdk.NewCoins(), @@ -157,7 +157,7 @@ func TestReflectGrpcQuery(t *testing.T) { // now grpc query for the bank balance cosmosBankQuery := banktypes.NewQueryAllBalancesRequest(creator, nil, false) - cosmosBankQueryBz, err := gogoproto.Marshal(cosmosBankQuery) + cosmosBankQueryBz, err := proto.Marshal(cosmosBankQuery) require.NoError(t, err) reflectQuery := wasmvmtypes.QueryRequest{ Grpc: &wasmvmtypes.GrpcQuery{ @@ -176,7 +176,7 @@ func TestReflectGrpcQuery(t *testing.T) { mustUnmarshal(t, reflectRespBz, &reflectResp) // now unmarshal the protobuf response var grpcBalance banktypes.QueryAllBalancesResponse - err = gogoproto.Unmarshal(reflectResp.Data, &grpcBalance) + err = proto.Unmarshal(reflectResp.Data, &grpcBalance) require.NoError(t, err) } @@ -254,7 +254,7 @@ func TestReflectInvalidStargateQuery(t *testing.T) { protoQuery := banktypes.QueryAllBalancesRequest{ Address: creator.String(), } - protoQueryBin, err := gogoproto.Marshal(&protoQuery) + protoQueryBin, err := proto.Marshal(&protoQuery) require.NoError(t, err) protoRequest := wasmvmtypes.QueryRequest{ @@ -953,16 +953,16 @@ func TestAcceptListStargateQuerier(t *testing.T) { addrs := app.AddTestAddrsIncremental(lumeraApp, ctx, 2, sdkmath.NewInt(1_000_000)) accepted := wasmKeeper.AcceptedQueries{ - "/cosmos.auth.v1beta1.Query/Account": func() gogoproto.Message { + "/cosmos.auth.v1beta1.Query/Account": func() proto.Message { return &authtypes.QueryAccountResponse{} }, - "/no/route/to/this": func() gogoproto.Message { + "/no/route/to/this": func() proto.Message { return &authtypes.QueryAccountResponse{} }, } - marshal := func(pb gogoproto.Message) []byte { - b, err := gogoproto.Marshal(pb) + marshal := func(pb proto.Message) []byte { + b, err := proto.Marshal(pb) require.NoError(t, err) return b } @@ -1048,8 +1048,8 @@ func TestDeterministicJsonMarshal(t *testing.T) { originalResponse string updatedResponse string queryPath string - responseProtoStruct gogoproto.Message - expectedProto func() gogoproto.Message + responseProtoStruct proto.Message + expectedProto func() proto.Message }{ /** * @@ -1077,7 +1077,7 @@ func TestDeterministicJsonMarshal(t *testing.T) { "0a530a202f636f736d6f732e617574682e763162657461312e426173654163636f756e74122f0a2d636f736d6f733166387578756c746e3873717a687a6e72737a3371373778776171756867727367366a79766679122d636f736d6f733166387578756c746e3873717a687a6e72737a3371373778776171756867727367366a79766679", "/cosmos.auth.v1beta1.Query/Account", &authtypes.QueryAccountResponse{}, - func() gogoproto.Message { + func() proto.Message { account := authtypes.BaseAccount{ Address: "cosmos1f8uxultn8sqzhznrsz3q77xwaquhgrsg6jyvfy", } @@ -1119,9 +1119,9 @@ func TestConvertProtoToJSONMarshal(t *testing.T) { testCases := []struct { name string queryPath string - protoResponseStruct gogoproto.Message + protoResponseStruct proto.Message originalResponse string - expectedProtoResponse gogoproto.Message + expectedProtoResponse proto.Message expectedError bool }{ { diff --git a/tests/integration/wasm/snapshotter_integration_test.go b/tests/integration/wasm/snapshotter_integration_test.go new file mode 100644 index 00000000..028503da --- /dev/null +++ b/tests/integration/wasm/snapshotter_integration_test.go @@ -0,0 +1,141 @@ +package wasm_test + +import ( + "os" + "testing" + "time" + + wasmvm "github.com/CosmWasm/wasmvm/v3" + wasmvmtypes "github.com/CosmWasm/wasmvm/v3/types" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + tmtypes "github.com/cometbft/cometbft/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + sdkmath "cosmossdk.io/math" + + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/CosmWasm/wasmd/x/wasm/keeper" + "github.com/CosmWasm/wasmd/x/wasm/types" + + "github.com/LumeraProtocol/lumera/app" + lcfg "github.com/LumeraProtocol/lumera/config" +) + +func TestSnapshotter(t *testing.T) { + specs := map[string]struct { + wasmFiles []string + }{ + "single contract": { + wasmFiles: []string{GetTestDataFilePath("reflect_1_5.wasm")}, + }, + "multiple contract": { + wasmFiles: []string{ + GetTestDataFilePath("reflect_1_5.wasm"), + GetTestDataFilePath("burner.wasm"), + GetTestDataFilePath("reflect_1_5.wasm"), + }, + }, + "duplicate contracts": { + wasmFiles: []string{GetTestDataFilePath("reflect_1_5.wasm"), GetTestDataFilePath("reflect_1_5.wasm")}, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + // setup source app + srcWasmApp, genesisAddr := newWasmExampleApp(t) + + // store wasm codes on chain + ctx := srcWasmApp.NewUncachedContext(false, tmproto.Header{ + ChainID: "foo", + Height: srcWasmApp.LastBlockHeight() + 1, + Time: time.Now(), + }) + wasmKeeper := srcWasmApp.WasmKeeper + contractKeeper := keeper.NewDefaultPermissionKeeper(wasmKeeper) + + srcCodeIDToChecksum := make(map[uint64][]byte, len(spec.wasmFiles)) + for i, v := range spec.wasmFiles { + wasmCode, err := os.ReadFile(v) + require.NoError(t, err) + codeID, checksum, err := contractKeeper.Create(ctx, genesisAddr, wasmCode, nil) + require.NoError(t, err) + require.Equal(t, uint64(i+1), codeID) + srcCodeIDToChecksum[codeID] = checksum + } + // create snapshot + _, err := srcWasmApp.Commit() + require.NoError(t, err) + + snapshotHeight := uint64(srcWasmApp.LastBlockHeight()) + snapshot, err := srcWasmApp.SnapshotManager().Create(snapshotHeight) + require.NoError(t, err) + assert.NotNil(t, snapshot) + + originalMaxWasmSize := types.MaxWasmSize + types.MaxWasmSize = 1 + t.Cleanup(func() { + types.MaxWasmSize = originalMaxWasmSize + }) + + // when snapshot imported into dest app instance + destWasmApp := app.SetupWithEmptyStore(t) + require.NoError(t, destWasmApp.SnapshotManager().Restore(*snapshot)) + for i := uint32(0); i < snapshot.Chunks; i++ { + chunkBz, err := srcWasmApp.SnapshotManager().LoadChunk(snapshot.Height, snapshot.Format, i) + require.NoError(t, err) + end, err := destWasmApp.SnapshotManager().RestoreChunk(chunkBz) + require.NoError(t, err) + if end { + break + } + } + + // then all wasm contracts are imported + wasmKeeper = destWasmApp.WasmKeeper + ctx = destWasmApp.NewUncachedContext(false, tmproto.Header{ + ChainID: "foo", + Height: destWasmApp.LastBlockHeight() + 1, + Time: time.Now(), + }) + + destCodeIDToChecksum := make(map[uint64][]byte, len(spec.wasmFiles)) + wasmKeeper.IterateCodeInfos(ctx, func(id uint64, info types.CodeInfo) bool { + bz, err := wasmKeeper.GetByteCode(ctx, id) + require.NoError(t, err) + + hash, err := wasmvm.CreateChecksum(bz) + require.NoError(t, err) + destCodeIDToChecksum[id] = hash[:] + assert.Equal(t, hash[:], wasmvmtypes.Checksum(info.CodeHash)) + return false + }) + assert.Equal(t, srcCodeIDToChecksum, destCodeIDToChecksum) + }) + } +} + +func newWasmExampleApp(t *testing.T) (*app.App, sdk.AccAddress) { + senderPrivKey, senderAddr := keyPubAddr() + pubKey := senderPrivKey.PubKey() + sdkPubKey, err := cryptocodec.FromCmtPubKeyInterface(pubKey) + require.NoError(t, err) + + acc := authtypes.NewBaseAccount(senderAddr, sdkPubKey, 0, 0) + amount, ok := sdkmath.NewIntFromString("10000000000000000000") + require.True(t, ok) + + balance := banktypes.Balance{ + Address: acc.GetAddress().String(), + Coins: sdk.NewCoins(sdk.NewCoin(lcfg.ChainDenom, amount)), + } + validator := tmtypes.NewValidator(pubKey, 1) + valSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) + wasmApp := app.SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, "testing", sdk.DefaultPowerReduction, []banktypes.Balance{balance}) + + return wasmApp, senderAddr +} diff --git a/tests/systemtests/go.mod b/tests/systemtests/go.mod index 392ead95..af8a812f 100644 --- a/tests/systemtests/go.mod +++ b/tests/systemtests/go.mod @@ -4,50 +4,48 @@ go 1.25.5 replace ( github.com/LumeraProtocol/lumera => ../../ - - github.com/cosmos/cosmos-sdk => github.com/cosmos/cosmos-sdk v0.50.14 github.com/envoyproxy/protoc-gen-validate => github.com/bufbuild/protoc-gen-validate v1.3.0 github.com/lyft/protoc-gen-validate => github.com/envoyproxy/protoc-gen-validate v1.3.0 nhooyr.io/websocket => github.com/coder/websocket v1.8.7 ) +require ( + cosmossdk.io/math v1.5.3 + github.com/LumeraProtocol/lumera v1.9.1 + github.com/cometbft/cometbft v0.38.20 + github.com/cosmos/cosmos-sdk v0.53.5 + github.com/tidwall/gjson v1.14.2 + github.com/tidwall/sjson v1.2.5 + golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b +) + require ( github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect - github.com/cosmos/gogoproto v1.7.0 // indirect - github.com/cosmos/iavl v1.2.4 // indirect + github.com/cosmos/gogoproto v1.7.2 // indirect + github.com/cosmos/iavl v1.2.6 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/spf13/cobra v1.10.1 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/stretchr/testify v1.11.1 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect - google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect + google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/grpc v1.77.0 // indirect ) -require ( - cosmossdk.io/math v1.5.3 - github.com/LumeraProtocol/lumera v1.8.5 - github.com/cometbft/cometbft v0.38.18 - github.com/cosmos/cosmos-sdk v0.53.0 - github.com/tidwall/gjson v1.14.2 - github.com/tidwall/sjson v1.2.5 - golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b -) - require ( cosmossdk.io/api v0.9.2 // indirect - cosmossdk.io/collections v1.3.0 // indirect + cosmossdk.io/collections v1.3.1 // indirect cosmossdk.io/core v0.11.3 // indirect - cosmossdk.io/depinject v1.2.0 // indirect + cosmossdk.io/depinject v1.2.1 // indirect cosmossdk.io/errors v1.0.2 // indirect - cosmossdk.io/log v1.6.0 // indirect + cosmossdk.io/log v1.6.1 // indirect cosmossdk.io/schema v1.1.0 // indirect cosmossdk.io/store v1.1.2 // indirect cosmossdk.io/x/tx v0.14.0 // indirect @@ -62,8 +60,8 @@ require ( github.com/bgentry/speakeasy v0.2.0 // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/bytedance/gopkg v0.1.3 // indirect - github.com/bytedance/sonic v1.14.1 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect + github.com/bytedance/sonic v1.14.2 // indirect + github.com/bytedance/sonic/loader v0.4.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect @@ -75,23 +73,23 @@ require ( github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cometbft/cometbft-db v0.14.1 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/cosmos-db v1.1.2 // indirect + github.com/cosmos/cosmos-db v1.1.3 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/ics23/go v0.11.0 // indirect - github.com/cosmos/ledger-cosmos-go v0.14.0 // indirect + github.com/cosmos/ledger-cosmos-go v0.16.0 // indirect github.com/danieljoos/wincred v1.2.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/desertbit/timer v1.0.1 // indirect github.com/dgraph-io/badger/v4 v4.2.0 // indirect - github.com/dgraph-io/ristretto v0.1.1 // indirect + github.com/dgraph-io/ristretto v0.2.0 // indirect github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emicklei/dot v1.6.2 // indirect github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/getsentry/sentry-go v0.32.0 // indirect + github.com/getsentry/sentry-go v0.35.0 // indirect github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect @@ -99,8 +97,7 @@ require ( github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.5 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect github.com/google/btree v1.1.3 // indirect github.com/google/flatbuffers v24.3.25+incompatible // indirect @@ -142,8 +139,8 @@ require ( github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.63.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/prometheus/common v0.66.1 // indirect + github.com/prometheus/procfs v0.16.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rs/cors v1.11.1 // indirect @@ -159,26 +156,30 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/zondax/golem v0.27.0 // indirect github.com/zondax/hid v0.9.2 // indirect - github.com/zondax/ledger-go v0.14.3 // indirect + github.com/zondax/ledger-go v1.0.1 // indirect go.etcd.io/bbolt v1.4.0-alpha.1 // indirect go.opencensus.io v0.24.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + go.yaml.in/yaml/v2 v2.4.2 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/arch v0.15.0 // indirect - golang.org/x/crypto v0.43.0 // indirect - golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 // indirect - golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.37.0 // indirect - golang.org/x/term v0.36.0 // indirect - golang.org/x/text v0.30.0 // indirect + golang.org/x/arch v0.17.0 // indirect + golang.org/x/crypto v0.47.0 // indirect + golang.org/x/net v0.48.0 // indirect + golang.org/x/sync v0.19.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/term v0.39.0 // indirect + golang.org/x/text v0.33.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect - google.golang.org/protobuf v1.36.10 // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.2 // indirect nhooyr.io/websocket v1.8.17 // indirect pgregory.net/rapid v1.2.0 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect + sigs.k8s.io/yaml v1.6.0 // indirect ) replace ( diff --git a/tests/systemtests/go.sum b/tests/systemtests/go.sum index 66dc7e1f..df5a502e 100644 --- a/tests/systemtests/go.sum +++ b/tests/systemtests/go.sum @@ -37,16 +37,16 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= cosmossdk.io/api v0.9.2 h1:9i9ptOBdmoIEVEVWLtYYHjxZonlF/aOVODLFaxpmNtg= cosmossdk.io/api v0.9.2/go.mod h1:CWt31nVohvoPMTlPv+mMNCtC0a7BqRdESjCsstHcTkU= -cosmossdk.io/collections v1.3.0 h1:RUY23xXBy/bu5oSHZ5y+mkJRyA4ZboKDO4Yvx4+g2uc= -cosmossdk.io/collections v1.3.0/go.mod h1:cqVpBMDGEYhuNmNSXIOmqpnQ7Eav43hpJIetzLuEkns= +cosmossdk.io/collections v1.3.1 h1:09e+DUId2brWsNOQ4nrk+bprVmMUaDH9xvtZkeqIjVw= +cosmossdk.io/collections v1.3.1/go.mod h1:ynvkP0r5ruAjbmedE+vQ07MT6OtJ0ZIDKrtJHK7Q/4c= cosmossdk.io/core v0.11.3 h1:mei+MVDJOwIjIniaKelE3jPDqShCc/F4LkNNHh+4yfo= cosmossdk.io/core v0.11.3/go.mod h1:9rL4RE1uDt5AJ4Tg55sYyHWXA16VmpHgbe0PbJc6N2Y= -cosmossdk.io/depinject v1.2.0 h1:6NW/FSK1IkWTrX7XxUpBmX1QMBozpEI9SsWkKTBc5zw= -cosmossdk.io/depinject v1.2.0/go.mod h1:pvitjtUxZZZTQESKNS9KhGjWVslJZxtO9VooRJYyPjk= +cosmossdk.io/depinject v1.2.1 h1:eD6FxkIjlVaNZT+dXTQuwQTKZrFZ4UrfCq1RKgzyhMw= +cosmossdk.io/depinject v1.2.1/go.mod h1:lqQEycz0H2JXqvOgVwTsjEdMI0plswI7p6KX+MVqFOM= cosmossdk.io/errors v1.0.2 h1:wcYiJz08HThbWxd/L4jObeLaLySopyyuUFB5w4AGpCo= cosmossdk.io/errors v1.0.2/go.mod h1:0rjgiHkftRYPj//3DrD6y8hcm40HcPv/dR4R/4efr0k= -cosmossdk.io/log v1.6.0 h1:SJIOmJ059wi1piyRgNRXKXhlDXGqnB5eQwhcZKv2tOk= -cosmossdk.io/log v1.6.0/go.mod h1:5cXXBvfBkR2/BcXmosdCSLXllvgSjphrrDVdfVRmBGM= +cosmossdk.io/log v1.6.1 h1:YXNwAgbDwMEKwDlCdH8vPcoggma48MgZrTQXCfmMBeI= +cosmossdk.io/log v1.6.1/go.mod h1:gMwsWyyDBjpdG9u2avCFdysXqxq28WJapJvu+vF1y+E= cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= cosmossdk.io/schema v1.1.0 h1:mmpuz3dzouCoyjjcMcA/xHBEmMChN+EHh8EHxHRHhzE= @@ -110,12 +110,12 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4= -github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.24.3 h1:Bte86SlO3lwPQqww+7BE9ZuUCKIjfqnG5jtEyqA9y9Y= +github.com/bits-and-blooms/bitset v1.24.3/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= -github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcec/v2 v2.3.5 h1:dpAlnAwmT1yIBm3exhT1/8iUSD98RDJM5vqJVQDQLiU= +github.com/btcsuite/btcd/btcec/v2 v2.3.5/go.mod h1:m22FrOAiuxl/tht9wIqAoGHcbnCCaPWyauO8y2LGGtQ= github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= @@ -132,10 +132,10 @@ github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/ github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= -github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w= -github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc= -github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= -github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE= +github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980= +github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o= +github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -185,8 +185,8 @@ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1: github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coder/websocket v1.8.7 h1:jiep6gmlfP/yq2w1gBoubJEXL9gf8x3bp6lzzX8nJxE= github.com/coder/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -github.com/cometbft/cometbft v0.38.18 h1:1ZHYMdu0S75YxFM13LlPXnOwiIpUW5z9TKMQtTIALpw= -github.com/cometbft/cometbft v0.38.18/go.mod h1:PlOQgf3jQorep+g6oVnJgtP65TJvBJoLiXjGaMdNxBE= +github.com/cometbft/cometbft v0.38.20 h1:i9v9rvh3Z4CZvGSWrByAOpiqNq5WLkat3r/tE/B49RU= +github.com/cometbft/cometbft v0.38.20/go.mod h1:UCu8dlHqvkAsmAFmWDRWNZJPlu6ya2fTWZlDrWsivwo= github.com/cometbft/cometbft-db v0.14.1 h1:SxoamPghqICBAIcGpleHbmoPqy+crij/++eZz3DlerQ= github.com/cometbft/cometbft-db v0.14.1/go.mod h1:KHP1YghilyGV/xjD5DP3+2hyigWx0WTp9X+0Gnx0RxQ= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -197,29 +197,29 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-db v1.1.2 h1:KZm4xLlPp6rLkyIOmPOhh+XDK9oH1++pNH/csLdX0Dk= -github.com/cosmos/cosmos-db v1.1.2/go.mod h1:dMg2gav979Ig2N076POEw4CEKbCsieaOfDWSfFZxs8M= +github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOPY= +github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.50.14 h1:G8CtGHFWbExa+ZpVOVAb4kFmko/R30igsYOwyzRMtgY= -github.com/cosmos/cosmos-sdk v0.50.14/go.mod h1:hrWEFMU1eoXqLJeE6VVESpJDQH67FS1nnMrQIjO2daw= +github.com/cosmos/cosmos-sdk v0.53.5 h1:JPue+SFn2gyDzTV9TYb8mGpuIH3kGt7WbGadulkpTcU= +github.com/cosmos/cosmos-sdk v0.53.5/go.mod h1:AQJx0jpon70WAD4oOs/y+SlST4u7VIwEPR6F8S7JMdo= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ4GUkT+tbFI= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= -github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= -github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= -github.com/cosmos/iavl v1.2.4 h1:IHUrG8dkyueKEY72y92jajrizbkZKPZbMmG14QzsEkw= -github.com/cosmos/iavl v1.2.4/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= -github.com/cosmos/ibc-go/v10 v10.3.0 h1:w5DkHih8qn15deAeFoTk778WJU+xC1krJ5kDnicfUBc= -github.com/cosmos/ibc-go/v10 v10.3.0/go.mod h1:CthaR7n4d23PJJ7wZHegmNgbVcLXCQql7EwHrAXnMtw= +github.com/cosmos/gogoproto v1.7.2 h1:5G25McIraOC0mRFv9TVO139Uh3OklV2hczr13KKVHCA= +github.com/cosmos/gogoproto v1.7.2/go.mod h1:8S7w53P1Y1cHwND64o0BnArT6RmdgIvsBuco6uTllsk= +github.com/cosmos/iavl v1.2.6 h1:Hs3LndJbkIB+rEvToKJFXZvKo6Vy0Ex1SJ54hhtioIs= +github.com/cosmos/iavl v1.2.6/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= +github.com/cosmos/ibc-go/v10 v10.5.0 h1:NI+cX04fXdu9JfP0V0GYeRi1ENa7PPdq0BYtVYo8Zrs= +github.com/cosmos/ibc-go/v10 v10.5.0/go.mod h1:a74pAPUSJ7NewvmvELU74hUClJhwnmm5MGbEaiTw/kE= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo= github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -github.com/cosmos/ledger-cosmos-go v0.14.0 h1:WfCHricT3rPbkPSVKRH+L4fQGKYHuGOK9Edpel8TYpE= -github.com/cosmos/ledger-cosmos-go v0.14.0/go.mod h1:E07xCWSBl3mTGofZ2QnL4cIUzMbbGVyik84QYKbX3RA= +github.com/cosmos/ledger-cosmos-go v0.16.0 h1:YKlWPG9NnGZIEUb2bEfZ6zhON1CHlNTg0QKRRGcNEd0= +github.com/cosmos/ledger-cosmos-go v0.16.0/go.mod h1:WrM2xEa8koYoH2DgeIuZXNarF7FGuZl3mrIOnp3Dp0o= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -240,9 +240,8 @@ github.com/desertbit/timer v1.0.1 h1:yRpYNn5Vaaj6QXecdLMPMJsW81JLiI1eokUft5nBmeo github.com/desertbit/timer v1.0.1/go.mod h1:htRrYeY5V/t4iu1xCJ5XsQvp4xve8QulXXctAzxqcwE= github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE= +github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU= github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da h1:aIftn67I1fkbMa512G+w+Pxci9hJPB8oMnkcP3iZF38= github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= @@ -250,7 +249,6 @@ github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vma github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= @@ -286,8 +284,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/getsentry/sentry-go v0.32.0 h1:YKs+//QmwE3DcYtfKRH8/KyOOF/I6Qnx7qYGNHCGmCY= -github.com/getsentry/sentry-go v0.32.0/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= +github.com/getsentry/sentry-go v0.35.0 h1:+FJNlnjJsZMG3g0/rmmP7GiKjQoUF5EXfEtBwtPtkzY= +github.com/getsentry/sentry-go v0.35.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -331,9 +329,8 @@ github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= -github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -349,14 +346,12 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= -github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= +github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -407,7 +402,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= @@ -517,8 +511,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= -github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= +github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= +github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= @@ -571,8 +565,8 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U github.com/linxGnu/grocksdb v1.9.8 h1:vOIKv9/+HKiqJAElJIEYv3ZLcihRxyP7Suu/Mu8Dxjs= github.com/linxGnu/grocksdb v1.9.8/go.mod h1:C3CNe9UYc9hlEM2pC82AqiGS3LRW537u9LFV4wIZuHk= github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -625,8 +619,9 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= @@ -695,8 +690,8 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -712,8 +707,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= -github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -721,8 +716,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= +github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -795,6 +790,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -829,10 +826,12 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zondax/golem v0.27.0 h1:IbBjGIXF3SoGOZHsILJvIM/F/ylwJzMcHAcggiqniPw= +github.com/zondax/golem v0.27.0/go.mod h1:AmorCgJPt00L8xN1VrMBe13PSifoZksnQ1Ge906bu4A= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= -github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +github.com/zondax/ledger-go v1.0.1 h1:Ks/2tz/dOF+dbRynfZ0dEhcdL1lqw43Sa0zMXHpQ3aQ= +github.com/zondax/ledger-go v1.0.1/go.mod h1:j7IgMY39f30apthJYMd1YsHZRqdyu4KbVmUp0nU78X0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.4.0-alpha.1 h1:3yrqQzbRRPFPdOMWS/QQIVxVnzSkAZQYeWlZFv1kbj4= go.etcd.io/bbolt v1.4.0-alpha.1/go.mod h1:S/Z/Nm3iuOnyO1W4XuFfPci51Gj6F1Hv0z8hisyYYOw= @@ -872,14 +871,20 @@ go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw= -golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE= +golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU= +golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -899,8 +904,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -996,8 +1001,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= -golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 h1:6/3JGEh1C88g7m+qzzTbl3A0FtsLguXieqofVLU/JAo= -golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1023,8 +1028,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1096,7 +1101,6 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1105,8 +1109,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1116,8 +1120,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= +golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1133,8 +1137,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1277,8 +1281,8 @@ google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78= -google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4= +google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s= google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4= google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk= @@ -1326,8 +1330,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1373,6 +1377,6 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= +sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= +sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/tests/testdata/escrow_0.7.wasm b/tests/testdata/escrow_0.7.wasm new file mode 100644 index 0000000000000000000000000000000000000000..668aa74e3b730f58faaabc8c6ac7ab64506c5e60 GIT binary patch literal 91577 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%0D$9KBEidm|aA|JYDhsIQ9%Hd*Tc&QNIj@dtMKb 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 literal 0 HcmV?d00001 diff --git a/tests/testdata/ibc2.wasm b/tests/testdata/ibc2.wasm index a5643c41a25b2a14224552168d07109b7b950583..ab33e483329b4fdbf4b8b5f04600de1f04756d47 100644 GIT binary patch literal 383624 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

r3rXQv}5Pqf# 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�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 aye@$HFC=L0ZC3(3G>|Zmc#t6_-2VfO2d;hq diff --git a/tests/testdata/ibc_callbacks.wasm b/tests/testdata/ibc_callbacks.wasm index 63519505aa2d7742653caa375a12758dbccb45f8..1bdaea162febb45862ac386aa43a464bc9de462b 100644 GIT binary patch literal 311144 zcmeFa3&5pyUGMwc*5!TITJNlZ0bZCPpS2kCrDkeu6GOx~&NGM0AgJW#wB4P~L4+xp z7ZHY$=p17P1tcXyBLyX$)CBW}hG}lhk+9=7GVFMvylhM=GAkpNN=Nhl7fsRlWk7BPC)Povx9!d6wY)!uNva4DbzTm~X z_awP~cP@Ux1-o}%cyUtbt;^fb?7n2r&Lq|AjD393i?7-_$$aHS7haZRvFK$xuioQD z2Nzy^@$L(*y71CVF20cRR^3`lqri(VyW}Fi{O>!HL?u1%3t#f03oonFhF9*q=<*-> z;gc7ie!*2ccVF^TKkJRmPm*`nX_%S(nl;zDO;-BAdN(aZ^7hj)#AbnMO^?TCyr@xWz`Jey8PyL7IFFx-l z|F{46(-*(+f4$_n7hLw^FFOCyT|aT*&KLaq%dfm*_s{&7^uhE?>6gCgOM>E6FfKb`LV+jQ|$>HX<{PX8eN zWcvH*1L^Oj=iQq9Y5E7*{n>5V8?#rXkECBq|2+MR^kM$}%;(bU(%ZA^)7NKLzahK) z%Fm>qPoMq9{HkBe-kLr8H}ZS(|1_hqG_vOElJ^MGa4`mG#Vg~Wwjfca3Jtv}~Q6tt(slHXL`KGbs4oT^!An zv-EV-SNVJ!Y5iTBlcd_RIPO*7POlgbs@dmIOKUXK@AS$+)jFrlx8L>~e|EqAf9!L2 z^LA@|`|&FVnHsXD)mpxN_L}ir*?af)Z>KMR={PUv&Zpf@*{RaSap&9tdCTtE1F$?Z z>XcpDX!WZ5u04=I9wc_EWJg)>ud{1B^UNy;nRn85sYwepld+3pyb1 ztC?pB1r3l|W#{Zc+Ru8uvZ%`4)t@G34s7&OC?hXthDVC7s4~2+>-F2c>XH4x^ig1{ z?iO_R>of6J*-;JjM2KovhUd0uXmyoG!>ovu&jfSv7MGaA;J^85_&xz3fi+vO8QS5JYZkdez%vzutsi z-S<{xI164JKO7UNPqA&=Uc)|OPJx0Fe7B-^z8KgpZLq`|Nj23?0qZk71iCDSa@k`P>q1j_f!x5 z^MPd7_vgu|tM+!#9<)SJA(mfn8Fy|AKs~zm1){kCjj_fwC;;Uc2b5lwIw?S}Zz!|% zKazK=q^EIfIcMHfWSyD`I~y6)(Tq@I=vl^s-IA8U0;mh5I}7PjrfvDV8n2d(*Y_{Z z#hzf1hz-(KE$N7=t) z+=5=tGPwh*Un-hSql>oxl1pr1=~NGd5uZ+N5_(d6`l z-K@JemqXReN4@RIcIi(0Z!c8bpY4@75Yue7J*kr65oNxR zm1hjPActQYPlg|p?Kx_6SylwPWkm=q%?erOBD9hRW7Cr4vt}sKRpvN0Rr7)u3D#0|1^f}8g84kLV~vPRsrmS+XyGt!&ADZSZv`w20Nh7X=HGUyrKl+&Wj2CvM+N^6N|HWG1dTgRX()Vf&M>%$lAuOAjAy55={csq z(ar%5Flagr;98|Dl5`iE13O@rUsFYA&ap0ZDr9v>l#B_c--VdG7$JD1=u@~E1@p3? zLao9Pgj(3(6x9k;OwS5QB!{4&dGg2CYxbQsyV-3!^@bZ%;>qGNY3{e@#Y%?Md1DImBM_?~85Qv(Z2x z_CEZP1|MEO>Z{uRR@GS!R42Vsojp(Dfwao2EwTWA3wJQso-O2xDc~xB()0BaVm8c$ z4|8scLBrf;h!Ii^;VscE^K3$9=;w1#qk=E$#6xT7pcQL1AAjsyNkzVCChZFJeb{@* zL^mBI(aJ=`S?Dnwwi$bN0VKmy_x{~YgPcSzY2JNHvw<3 zB6tq}6nLI-8ax@nP4E_EyPEV3;4KKoP4Gv5ZUyjWR{`%U6Y#v$A+a}ZojLHVMKCWU zrjRt%-&@57aO z)m!nC$@|WVpG>3f%YHOnp+?h-$%>y)Hcp2klpHTp?10iaN`he9_WZdp1#As;Z*u6Q zoffhklE36LJ#BRCcjnkGf_LbWy8zLmz@VuO3Kbtz+1FN6uTJBg(gsJx{j2No3(| z%hCbcqC6*Qz$6+axRnjVWqMqZ<`^x?X0V2Am=Dw0hRP=Up*I3C$Rh-6S@ag0UVUa# zsV`YHGSgoX1$xq*gbor5Fbq*#U_%C;xI|97#VITtK^vo#QtPV1;tH9Whh^HkE=yZM zjHl+YyB}qOkO7t;%xghtlCeK(<=cQN3x@s7;@l4<1Ys42UGm=wNg+oLwiDB|V;n3g z<{X&@Ij2>w_f%bp1Dnb{K%wBQxXC8uXOflK87L3xp-5$+m$Y)vqbx)bv7i|l@+*4i z{M5Ui;Z)Wp{Cl#rEi7P?HLxHd?kXW*qNp*ED}4zju;#$U#>2ox8ycJLebMOsMnGij zCcWQiy&sxR6-~+XsJ`VPg0wpNNSMGiG?1zP{qr5BxHC2{KkQ*M3FX{Vo3SS@2 z(@q0lMl(_6EyLO}`oRhSu>>I`Byqr=FxG0CfdB#ymSSy!1_V{B`qDJkBAGbKYBIs| ztLZD9&=<-mQe8|H;bPfi)-<~_?o`K|Q>A5RPxVXt_7zv0u^V>?6dK7k$Q@ZTp~1;7 zgHtL#ttJB$2-+d72T1azCIN_MDpyT0&0*|)shtk?8aufeo+y9`tjNaWEqR0}w|BF* z4S@=FRpV0=jLvHBm9i~~m5t`q`(2|oWj31CsOQ_T^gDWH+sZXqBeR$;=Fq4(>^dBz z)w`~Xc6MI2^|8(W`S~n-aN%%Ml2jkvd+tEuSV0_Op$ZHXi;5p%Cqk(KOmgsv7z}cb zf_(T?ejHg)CJwp$E*16;Vq7&!CRL&CxZx?S6{@mcV(rM?Q1nj}I#WGx+s6_k*8Ula z3lgrQXP{sVCjuAUZSz3@3(841o@r48rJsc}%{({{q0Wxx6&Ch2iWU;m~2KeJ!`e$KOCPN~zY z?tS@zWYj{bSNHiZ!i~S{zX*nY!haD2`K14Xj_>zhNamSp%@x&wfU!}F_u{I_`%LUn z)q0kXXw_ccr!j`>sfp~@nNt%yhU$x7``ESl$&6T0wRa)^s{_^^of#9oF-j1TRB5a< zTV83|`oSdmQL7`{C6y}*wJ5ZZRSto*J8HvH@VUkeV!xSIh96LfRdZ9-LUorCUMWAw zvxpQRgld1x_@OX?Kuq4^Esz)%e8#9(*hj-}5xuX{5%O9ZMA9$agJpugE{n6*kEOS} z&*BLYR8P5TR6sK={3#gAlz*;h-3EZ8u$*!+2|)`CbtwSVlcOw$zX%tgFTpR5zWxlY zWqXw&AeEW$P^gz87AxA0*`dMd0>y-FvI*NTwl&+3jHw&gCfkKNf}MK%GiFb!U-{a- z34C)L{RIAssNC=)=~#T;u8LjNo$ox5gn?*RZ{uYlNi?##z$H{V$eJ~@NVD<j2})U~M?dq?G^VQR+SG2vtwFeE~Z6!4g! zt7P{4rMt$U)2tGisYq45^~r>-0R~DQK%+OcgcNRhvsf6UI^yYu{dhk!(Gz>iX@J3| z0~7L~k5GkmgFneL*CPb;s(>t7Kto)GE*1=x0Vi@uBRNz>3;R*@;08hUxnKY6_nlo~ zT2m+xhDKP7C&J)QAPl`?93`SJ5eD?3J{e)W=lE>2x2+)J{>)~YvTge313<+x5i<#>- z^N3z=&j?8Xt;Ow91Z@3pnMuMI(!k>v5^0^h`X`wJKwvdjcijPBA2TZYYoVac$^1A! zV<1FBd@%Bujiu{fLh2NOGiiR{Tu1%d-VKfDyv~3+n0@w z0j7s=53}l~tcFajUdNz5PnmAcASRx-WTSa??bdAcRI)<|l9C*spo-obex{|q^KyK zz^gH+K4BxpmQH7(3=@wF`9lqZ)?6UHNtY7 z^$8M0Mi8SeVFXyG<^u`WX;!ddQ*gaUA8Rg^xKt#`c?0B_=!Blc8ZUL$xSBWP^y(Y1 z#?#`^L>4i!J|T=t$B{i+>w|J#wrjMW;`d;=9SfT*%a(7OuI_!QxOpMFdd$4KO-;k} zvIs4VfnIdJ6*vWwtt=GAAivm9Pe^K95z4UMGCVVr>h-G}ivVV-d~vP~2NP!Q%LJ?w z5+#7wTW>g!peF8D;~IcQ%77@&32-wi5nUQ{E+7zyc;(e+RWhd}Ak@U|S;Hq~RcPtN zB-#Gh!`J`)Z+_~J-v4*Wa|fMrtt0QuQ1w06QB`;7`GK++9*YPRer!03TFA6SEc6_( zo(r;CBWyol6TVGKRgyNxqFN)NnXow)S#D8^gbF2Vj)iDqLV2wH`WKZnqW|@@8KElI zTbujRiC~F>#sv?yZ$tx@eZ)c(DRKO3tdk{(lpK!7Zq|6Y_~>ZLY8gJ4N{%odXW=Oh z15QN@8vSuWl*0r#e?jjUd(O<1tU`p72J4TH6|0-Uf)FPSB#&q6G(;?EAYr^dmJI>` z`Qid#U%D01%kQUdMbh#_%iW?U(dV1>JmzG?Hcw{Fzo|0cb24I`Cjp4Z^kky#Q9X}8 z88yHY-}Mna`zNC&cy2fuwZU`U$=Mh6#7=ooPqh7q^gO|YQN$<)QJ~=yZ7mI4IQ%{d zrOe`^6BImx4zbQ-3AjeFZrdASzjA4ZrCZc@`kU|YAu89_?697-CntBG*1eitlWNIH#ZQP|u9l?ZRkue`Di)0NE$N{X$>DKC-#W)$ZE@_$O5fD z3Zt<*w%e*TnHI&=@w4jYw_~Urke`%Bqh-z1Bzd(j=8ypcXGwmPghpsl=IA^#^$vWG zw{;~I82}1=9)*|ZZv)!r9%rr;mXQUp zO?y3;+;HO32`VosaM z^f6X7j(`Hi3-0i3*i}Bwe-SdXIuqg^I22aBgv|nS;Cr{`^MHb7a=XAg;^gdBJ z=~*KB^gQn5>?S>#bhuH^(aEf`d6G!OL;s+a~VmwMspdgWzpn7B60dc9!S%R zc_2)m&jVR{9uGw6xjc}hJ9r>SPv?Og-NpkkdKwR;=qWr9q9^e{hHl}32;Ia33A(@o zJEhBGBS%&F{*t({e6(zgnu7hm|Y}N)z|9DDF(tV^y>S5o4yI zh4nOP!J+~MplxPGHOeg%#X@<=a(ow$rsGokJhjE4L0VD~HA!veBHN~a;;uqgSF74| z7E0gSGNaV3QJQ29q5)_sKwA!IYXYczpcMf{*#c$BqE=X_eMUYYyQ z>keQA;Xa6`X}9DJXH;W>Z(6Cp1Zz1bKb}j}Rj~&dunUclzMs*$CKend_F_gPs zPY+JOiJym27qasdsIb^UXklE$HfF7bGX^tt6L0h;#!PsqiB{C(N1JEG44$K~} z6((0Ukb(LVi28D3ejf3X1`ILx1co3K@Dfs*C#;&U%}2KestBO zgfr>Um_P;D`O>8`qhVRpSUwlULvT6<5a5ud6f*z>1=2(?1Y@TOrWTos($@kXE#4I! zMhZ%&C`e)rK~PekF$%HE;nRet9k>#~6ARBUj>P&Eim5(>A=ou)@oa&TSiBaB<=Zm- zi!sIc+-9R7(Z&MAgU1jA(NqlKTn{1aQ2gLntKHiOe^upq7CA_hBah58R&?fs$*YI& z{q(C?Y@(GDdi&(>zm=fr5z$O%y$pV5x4QBA0|e^LnI9`oaJ}9YCpcpuug1dxfB(sk zzw`6=f8l+9N;qIx9&_FRv{Lpa<@G=S!SuZPvH}Ag#TeFx5|7Q`uB5AZ(bt^V<{q3R%r10E}%=3VCYN;Z6`xR5ggU|w_pOB*p3HGdu(_>&cS z$B6o@i2 zHf-Fhd0=Jk;ekDHIZ`Eh-Q%vsd}IJiqR5oRAU0negV=m`3}W-?O=4pQAhD0RgIH-G zoD;P(ArPQIVJh9oM$*>9z1!rDx{;3yM)E0>Fr^%JS^6<@@91x6c$=b>%H1OOfRy0zD)(HBR0x!^I3voB z7-rZlB8=EX2x)(TREb&M=G^D*+}p&AocmlvCfD9@%D5ovW^8G}q?#pwkhz9qd6znM zmmmtoIxNCr4)v1mQ%~J{Cf}G3Iaove9!qi6YsF}QFra0yLKo!#pf;mx-RR=NF7F}a zM=ejVhcI^-G^{d^Oij6bMq~|dD>++=Wz|krX|Aa}Tb$sFdEi4opU1o=Z_I-}p9k_o zelCux{9N2t`MLPAr}IE|Y~z8LlAnt!EI$_^B|jG-B|jG-B|jG-B|jH0TYm1*;#ns9 z#j^?|$jvGy+@4gp{zc&S7!)W1xBK2X;-&Z#x6IUwm=12vw`AWV;LYvwwZ9#?U0pZl zyN74an|%_T!{{2CQmQw+nC7uKh71{b?%9-45Z*99U_Lk3I}LMvfhr`9NjS&&1+P$ca^_EX#G74d?rbGh(p}ee(_`*Ck1Veq}fEj<8MNbtuNt|pz z+XtPBwYiWjC?Le*$Z;NQ1|~gbw7i08Gt_5Ned9K>*IOpZS>KC$t}uocC53reV~c73 zBU+Q{5bnoRhidP`j7e|Fv5Y}kSa99~T0l%BYvoRQ7whRL^>8DC-=VgC(k})qrsQGZ zA}WN4+Cl`M85D{RWN%n((TKP)$rSM<1JN+HsbY~J0M=%p-Xao#r8c@)YB1;sd$KKB z*aKEXXFiAzyXX&LbZ`l1oSQ7P)I^83phxz(gUM+Q97%$AS1?6 zef?`zL@*wt*}fbPjakK7%)th~gH#N1meuQ_F*>Qp$|Q^-7ZM9leV3TR)CMdjLIv#@W1AfShu<^S3Q;Tdxx zJo2Y~8;UkT(CJK@Ab=CEvF!Q!X@?V87nXA8JuyjAkFBo~_3p`qohsJwU|W>AR^rX+ zL4(fJ$V8aeW4vwYFUG{he9;i|&)8Mn^>!2U?fwxHp@@EQ^T4)Dq9=0}JvoK2 z2}V&UEMi|$db^eOfX$ZitOIl=J8cXGt^bqB9Wu$BcAaB1c`)pvb1bGAv0LjLe1U*n zt78@9f?-f=VslHaRswXR;G20U2*g5#0g>?;bHJuXLQz<#^TGjm8_!IZI6Q^c>J+r}&oO35g;MshgeUi*rSh4sr|8h1W!{kmF+tCd8!; zc)N|10U{^B?`sg+F*mM##qy#4QRF`{Nw)vpCx79culxNk*}8?9+7YpJ3+?J3>u`mY z(Spe8WjD}j%a=veL!9Y*{Nzo@X+xsS$jiqov9X&81QzMH29fVhra68%28*@_Q)P@5 zu_H*;Fn9tTzFe`k=w{brj1v{ItMWBv&VD^C9jnX8SKK-?T#;<0uGm>7C&>;WG?dRmIo zrEybUvW@B-Ely## zHKkq~K1-a|Ib6@!f1B|`^@Uz2IJLBDEi|dCUau|v4P%GSu&$oQF?m8A(_Zh2*po42 z*n@v1jjX@Gjd3J8_Zr#evIXEaHEMsSxzqSp^`9h*w)0MmJ4f=QoM}G z?dFaEHxJhL>KmwOb?i9#!`LtTw&Ds>?GkP@N} zeQjO{dcr4EL&cg*q$6Xkyv-^+e-*~!GJkDSxK!7*ea=m#iR~VMl8Zv4UL4D7N%7kD zYG6(hFSfWeKMmKjpCPxDw^*U8cqyY$Y<&%_lBF}|BNg1Y|%}vHs(bOau z(bVKR9-nx#rY5OtJ8Q1+qDkt8iO4NXL^ATEEMTV66MzU4k+uyh=^a)J-+0rLXkoWD z0g6#$VJg+FTw*PuobUng*@Av2eyc5)6Wtk*IXHl{>8bcrkoMS z|CaujcH5JrmN{s)mAl=k|I5R#)Sj8Yv3&-b0AXw!&~U?oXASyhsw<5xi%0U^DWRkr zl2aHbo||6AeU7rRH=8J;kz=}VNM@e z!FRzX+Gyh@k3HG-S`6+@x8_yYX>~iRppw97D z*$7=jOo9z2RL#UKQzw#d0tg?ING_^0_!9EfZAlZmZm#yhrfnJ1 zhQ6s&#=tY=N>yin?4gU)j+hZ6u(gthJL;2;DPBP(;fR*54*9UW8R~6GZcYF}TRKGq zmTT!~FX5`t(J&i%puJ|a9;UEJvRq>+c1KP#ADYItm$JJ$W}R17KcWN80Tu!%i6l-0 zX56cw35>pva|DhIz8>eiOyB~g3dHoDg*`ugvJr=7ktUWJdEYpQfOin0MGp)JJ9cI^ zv$|xaG3-bx>+qtgo$=GeXiWpdp0v~lrXE5a65^wvQWP<;84MOkFa7N=8J)8AFbr11 z1W5hpDBIvPBRLj#dHcpA4I6`&VpgzjNA%5`h1%9hx7UM?Zl4--Rxd!+Ht5P_$~HwJ zRobQ@h67REk!|Rwb6uM#)p*M|f(PUvV2~JZgd=_cBkCPP_e6D36b4pp&e!iZlc z??TemDv}Y}E{A|7|H>(qwK3)FQyqW0e3A5EQD?Nu%kji*y0%Bqu`r`4VeNJA`vq> zaEEv!!4)J=CKtmh9w!#-Lh1k@G07@#RT-=y@r9!}Exzhw7{EUcVc45_-L(h8-c0Sr zt=PS*{#wQK_&BQ>%QI%brOsaCr2ypyqfBM{>8cj1KC6y>7ClVMESSoYI@Pgf+D2uW zvH~;)*=jjkA4LJ6IH1cgt`KRiBM(#>lAP{leLe)GHKSuJcLv*+AZ&4W&{7}_=6eHdXh~p;mc&xCkrFx# zU)P6uN$0Vv-72RR2rk$DN?{2pJdGvRI@L0mFom7Up^RE>Fl|9RUpX&!z)&G|POUna z&Uv14p6@x4A9c=ci%T*>zYE#vo)LboGcN3MU4dGuiD5x`H(6fgWKlE{Ds8%;H>7D1 zgLjN*GM6Q(#Fy!Kd2{?iC7UsB;sdX*(kTcbi^g1jR-t_^nr}+R67VR|wVK^0p@<23 z@iqQL=EJEV_4y$86@Ds6SZircFtFQ@bTN#qPDKWeSC^3sXd`AU_3zH!d86#)Wp{ z4T&2ABi&VP5)?uJ6Is3L!Ru(SJ;c@8oOGE-lK|GzlCGA2+gi`JWcaz#4}w9>geDKK zwNqnjBWXB6AN)Io;f7m*E35DlPvKE&F5AA#!#waB`Du#J^Cjd?WwE)4mo8LWNnv8*LH+*vYZ1e@LvJ@`P%~!7kk}cN&PXR?ohYe2 zfnj8c{0M-K9tH)wfNf-ztb-`*-JsB^quOk5BkR@BwJH;xVNn2YHr&7&imlB_;zQhG zyMcB@a+D|N1Q{A&l^j3ruG;`JJwRa*H3&a=GgYFUkJ`XM$J@QzI*tkFr+RyPwoU&K z1a$c$siMbD0YnBAwIOi8w=e=)Y&4+@nQ4u9opv(^wzIf`@1A(|>lh7?BC0>7LG`C> z%|&Xgk2I=>c|}B;-~s6(cw@fY#z9|fz_Exq?4vS7#D(c<>#$1I(4Cqn+(Fe0sd|~Q zW5dH7&^VIK#2Ziyw`h+Pjx8zS7?Y<@QrPjnkd?z9vJ@bkx4rttcX&GVc0)sIAcX>L znKX)0Ln5n|P9`-FUPfEmZDUd+%%~p*{#3-otx46ftxmFt8Ldgq3WFX&(`b^yOTeXy z+TNs8YbivS9>mo+h)qL{i&c*KVU@^HYgQ`nb5iMFf9-u=ZF8K0XkBAWIQ5&bhHNOC zncL_xV_~?#CDrC+OM^7F*ur?oCx{M^%gR<7#&E0U2dER&kk-HR5fHhNbKUTJVx6m# z8)!$7g$N$dfgSzn4^N^lbRG2&t~OE}%T%)s+XT>*!b+n)zhDjQY+ECP02n~{R9BHX z^|KbpiLy|fUX=xPDOvIQSHKWop@QKLM-kTh!>4mXYIco#M>?^?#FSf44KYQBQGC{K zjf}4WI9~6j{p{VwffUn&MoL~yEv9mdC{`czIjaruaK1SiI{Jy(o|tnwIMxjEUg)l1;&lDyPRXX&+1rBn?wL`=Y z^IMvP&#N!}GL(Q#qT@ze)y=k1e)!AjIKf-WtN)^}T3^d1+TpDsRRbX{h5BXG%r4m` zVi8%0W<(ZntD#rPGK%coMuwCLS$H*Yf@?1$i==vus53`gADk!s&igQKz^}_S|Bu8uHCe~Q3^$Dk zUp^(Xah57Ks7ju8Kn&Juq7?(dsw8J%xa_+Y5R;mV@^U_E)S??8r=|% z@w_I=zXQDTH|oQoWr1Q(Pn=hxAm9w>?B~Y4J0OCJwYuB0^NshjR57H0R6ierRTT$e z9}GmX4^Ei8m#n%kvXAd50)3C#)}oq$YX0J^4@iX!-)v?8#fX8LiP!`#em*RMY?89+ z53eSOTmY3OP9}b#izLO$R?@?E*amTjcJ&wPQjd{Y2@NapY!eOl#a=Q6L$3@CI!e#& zOnQGmN1m9vA(dCmfY+xh@wTy}go%t;1w`7_Hw2hA#;*jJ24<;vn~ctKk|+N(b=M8b zjs^6F^2t`0D9u4Ii=-t(u^4WqPXb&-!oe}tN7-Y4sy=A31(A{A`_yxCK?6ns8IpW+ z(w7AhIPJ*@CkqOTyqFIPmbQW9t3KA zetm3VC2?dC=ce6Kcgtopty{MnG^=2rC2Y$?&B3wH>cZ-+s!|IjZ7Z1fPwC70NA;_q zeWL&0qsscL=>JtLy@ODPEWLVE%)$fCEwuor!c`z*E+x?Ghpl_72Qv`yvY3i6oeqCshDoh^yza25sA*Ny zrX5j)UiFu1Nm2fTJDA|%N!T!MNY;D7nG}|S%27~eESp*Raq&9?f;AltOQs)}S(fe# zT8U4n1fkkSiEO13uuCvqKdBO(sS@c*C9sl0iBGFUf2u^XLWv&Qt-TaOD^p5{X}I&| zu@09lk0&DXKj0AR?3{gK^2ww?GnQsj@y|r=Gl!H0fbqmyH9R{Z;G6W% zbH^lxPNyqAaDj?X5*Ykb&x)lC1+`P?hGh*6j34Dj?ajlG%zY$itPXH^2 z*=iFjVI~{w5dK*zBmbKKf$kd;?+`NbTPo3-Dsc!I`Lfqh;&I8ypI3?LHdd37ta_3* zWr_jDkxnxfgW0h2>S=Z0PGQbZ#U1bF2)j+6m z;Sq)0Gg`?UmHHus8W6a;5udfi&iLnmbzSU2=;og~FNSrb)bCgdPH9wIc5fjOZ;J4~#ZVpUwl!e(i;X&2&` z#RQjD^NXW2x2g9g{TfDXayHU0Vkl15qDBHfYcgn%{>nu|fhpun>T4n=i^$Pp0re9@ zMNdN!Hf2N+rl)_Nd|QI02|KO~6UI=39hrm;SW2+TK@VrbvqsW3`Ye&UsmHlARe!v> zJHAeqcOx28hQv>6el&~UR9(^A_g&@3|15r#Me%R^cu;=)WyyMD#c6&Nht_Kj#Gy+_ z?El}47_hPmBf^*s4tzQSjOoK^IraZZ4m@3~&0^3ve}LFUgd84AyM(Bc-pew-@({He z779GRSxOg#Qg_jm!RW_91gADpsTBaWTuGtvrqPc^si8g8Oq%IR+Q3%O(w{?APe!xa zJ)2qW=B75mkku|1QhrYF?tlYUGRg5l!=m9lWNQlsD)vN4XJ)#{Bdu3Dk<1|$$WASD zvYnDBLIC6<53MXgVXrF-Kbui!y0EBGtK|w`Eoa|P;w`S0vxL&iu>zkTeT48Po-7*F zQ82@|WzwuVBc{Jq`vQr*@L`>zc3J>X4F8#Cc^R<=2sH(8s73(+-n25w-ugUPgQvA7 z^ipb_%V;Q!4j!s8-$2M3ip=Ckv0X$VGD? zYB?_K!n6=r3JhaQki~9SF4+8puwP1K;n8y3bURsy<;XYA;)mX~?Y$9eS!(u_KmnR&?J zRy$Um1MWiN@RX47S4!Y|?FF6f%irr#Geek>+nj9D5V2wva1V*R0LR2~3Z@1DBe8o& z_g+AM9M_j#%KsPr_>RNDtqdy=X_lB{*v!nwQFIDpjVh)wmPL$lsnDV!Oj!fM^6I*D z(U7LZfV4cQ2kA(|8q;~xSUVKmh>j*^cwC8~AQoq_fv&btHEx@Uc33p*gqRt*A(xEM zf}Pf&71(GUY$VkWQyo^tO?$Y(91=AuU;Tx6@u+{}MMiT4UcB`Nu*2%!71(Z%xbEtI z8K#5XI(sCUIL$!xgd1doeJHa0?y+1zOume@7PS2#BIY~DSKxs-Ksb5$uqgkqS*j#@ z1xsx}$sbn5hhnLJ7E2xb-C(K1vSPI#cOu?Ruc6TFT$D^W!orc*!GV?30mCF9!0Pyr z?wZ34DyseIrEFxD?G)${yrIQxy`&W3!QwPcoLMQ8ovcyshcXVJ}qf*(VAf<{&pe5N-0dzytUeW5Id#RQMY#6=nBxag@k8t^B>& zjTn6j>jOySXjlH;p0Z?7_ccgUYt=Nvx5U7);D#-R4 zi_ElS{o?fhL%`L9hK6E%2Qd1gW-;T`vUF0yvUFcRx%#qnFB=ftT$X;@jYzc0(V`$eCy205nQ{xAn=lJoe_&^>kPYPnx<6TIUPOQO)Ylt_l`4mvR5QooiS+j}#ITItw8 z4!M#U!l6uC7DrjW4Ow7Fz;cnilAIme!_Y|3Xd-?!?^JUr8I9vjX|v~u%4nH(7!^)+ zP%GiwP?OS{GnYJeneG6pEd>x112Zc~9bqiUCZG39n$4*dVuHTV5=W0twR(SCaR01t z<>5%*C2^LFZdLmlv6jpZmeCZ4qB|Miq$MPyXqdfe3dDp>b~>;q#$tfe%s#DM$*Sfi zyRemqqG2n~WNRs6MMi>eva=4G%NT73&9n%2aaWl8lM3{}8)iNVN2?Wac?n$2?RA>? z*99j}c6%MBo0`U?o2E~jUlCTMiB0&^345Oi|H=Fc<=L&OK~&c9<0-7;9~zsxtOEV< zEn_l7z+5o0C%QQ;p%+RUGq`F5M`3q3IZxpjzaR27WZ0H-s z?jisIc?pJsgYeWL5savb9lkowm94!xbZm8#SrI4QecOnXj1=l*qTg# z?f^%^j5#}o7>6G(-Hu0d?Phhl>}lM!mYGJ@)G2gB7v|oW@+AB@^gC$@mRR@o$Br^F z=|l_*7(=7=^n7@CK$c#Ro3ZDCn%|3gci@f#en&3rva{;jaN=nW4#(n(Vd%JaI75Yd zjP^D{2$z!pEF4*DN9gNdPitRv7~S3AARSIok?w zf;hTG7KKj#)HYMwXHcgMIO?dTCP>J0F3@e;;qk>+QL?9VLuWA*0xfXcjVCLcsymS* zNx%B#-+JpE?|JZjk8yX34)KrMRI5K%UcWu%2!YqQLBx6U0)_jCzhzzDsH7}43HA$K?&Q})>mX(n@}$L+#oespw2O*}SJ7hnXM z)fTU;(rH>I1(tBu^L2mABm3bQyQCqonRG`OW*tZxv5ThiTR5ZytlNQ8oKMgQfh%z* zE2ggazpM-^&ha-uGHI&f0&8PcI8+ddk(42c$rHYA7SlO9m{D|lmYRhGHG&DLH2q}B z>=`v$ck|0yk0*=TIZ_;K9nj|;!&0qp>X^zHu?hLgh(;KkCN*MLnwN2*gzG7Gxam5L z*jX{PY&%G zVlStGm|3AqB37)Wx=ZVqc8Q%7-X#vpef(X5Y^J&dfOJXr0vBk|vi1qiyF-xaz&$k9 z3VbZR54oHo<)|~QbDi76uPvjV*#dqz7M8#ow*=NSEdg!YZCC<`SF;2NwoU1rZFa&5 z2d((&5=3^)ViQX3=u}O09;qWTIP=!#IKy3;Qlax(Z9;VIyLBi)eKiL$&n>(ip&3Ox zXmukGwpEv<-Mov>pK#YJomS)W`I4#_rH7|Y6#YRbW;8wGYQ05S6DdTHWOT5jGdaM=-#cG}RK@a0lOoBD99xd?b*?}tMtaxp9dwJs> zOd(SCTnYC(u@g+ZHld(64rDrAN32A%4lmx#Itxe3tb-a__?mE&5C=G`{=T;2bmPYn zvPW8GUSXVCS0hQPXCkJ-cG>4BI?pEmL>L)5$r%S3&5^CIYys;EL0P@p>t+Rv<~A@r zX~+v8>7e&E9b>F#?~sUOt$FMZR?Xx-0G&eOR7!@>2{LR?)Pq4F%)uRujaIzOyj#Xq zz^3ZqK>H~Js>D7-PqZc%mW%1dAbwSWI8uVkNGK9e4MSApgEsB!HnGUJoT*qh)40+s zi{G1IOipoUu0Gm|PP?t`Nl)j7XWA8DPckt7FXR1=h*bwO{IHPupAO1FH}wmeii##YkJ=X!_C`KVTgbMAwgFe@LvM zo#Ksz0*LobjCGETf{eC6La5C8N*O`Jy8>o4h#C(Rp9BpPioRfp#-$AqLek=BVnT4H z#g!SgO{=^+=dxLkaZIVaxZBB9AAu6)JpBG-Q+>7wi4&Mnec*c% zz*u&FvT$y~&kmbl#h1;AvJDD2~Ln8NjjVvIEe`nExl7-oWr?AaGoSMIb0V~t*scAhN~E3 zuVM>JilLPJq(Q&(>RMPJ+&%;SYWdeh5|>HlHiLzO7zei%6zo*c6UwaqfH|Cp+*oKS z9$}gcoi3z}n=KbZnYSOhW*6h=}R_5-_$ z-Zn_p(anf()vU-XhV$?pVJZ%nlXorP;V~4$bX}ggs3xTztLnYjMlT;0JyI!2xL4uViq5$~8#2i77&Nz@S$+MwUn@cA?!Z|ihz2$;fA zPca1Wz=MQq=U^vd$S^N&r4ipbhGCqJ?=Wgp;T`I9G|kEoFh^&{XvS-`nssh0`(Q8v zvNZQ=k-}?|%2Ql`nI5_K_kV|5Z!0#aT6|iF^aakB`jCfBxbKHuf%@2@MBET8tzK^@& z0s#ssT(PhyMsB~HpZHByOdg=3%?y_cpx%)x_eLl360C{FEk0p^k;pGkb8-$L4DesW z8-a|W0R)r)HwRnFlu&k1VJ#W{Wy_UmD=O0#tP)KUns32o{c>=fqE9F(Xb_NfueTyS zs+5$;Z6$=*8p=NKr8;yvH?4~7%s)qfgZuo(;1ui-wov_ zYYdM8k^m@7^#~LREx&C9@lz8`~m|Zzp-rUFh%4WI&72zzG2kCM}Qvm^2n8Bye^M? zI}-930ya8o7(&oOZTW+%iFja=h;O?;=rB!0yzp)sb*b-Hsw;vFFBG@S5Thzc2T|l<}#M5gpl}sqN@}>3Sy~e)uGyk^2it(0IXRHZzr;u8WK+qh(v`g9{TTlkA~e=p*2vCbC1TC z=hA`J4g}9fV!IeYN1EM5?1<&C#>H}q{BUIX0*U*uS()tBN5o;A-Q7US!miPvW_ipq z7d*Z2L#w zZi2sUbB#8ydlF(Y2`M$3F=d(FNLga!8o~q_|`>j z{O4Ey-X6ubOOhR$CBqLGBP1uDKs3~))J=Mx;@9Jyt~)VgkcXKPE@9F84q|a_l$uvb zCTRnoMvc9cjMccV(n)VTOrmb9C3l<+omDHrboQ>qiyONcqaMd2B8JRUCbZ=6VVcmK zX%u2 z{f($~q?Jo?yFJ*a5jF7*c@`^=iNxa!RWXm+xQQ?{r-;ZbrkIDiYO?U1;7ZFk*Vsgdmb68s2eY!4 z1b0%dW5*^FaIBfo0f2DNUhFSZxZY5$J>{5kQZERlUz?MY#PmX)kK&&TLpL8 zPr$NhZJIZ-(Q3PzY;4^hM1%vy;j^$b&y$yn2AicbYfTJAgj zW1hCd+B|m8N_l=fYlI!TiFzXnl_ko9H#_M25Lu)!Z0+3d z&aiea*Ho%5_+#yyhCdR3dC1)8SG&x_73DH3o=kkgOs0+qVCAV)t?u`W@hqHNhkefj zTaEF|M3JK6iP@Awt|r2ky3HO6?O-?&0TGz;hQ(nbxT%>t#?X96H3oZziM!C!gg;km z2?yk%w?VE46!Nf6;2)%F!ks$ItrGH=tIV(xpc7%mC4~F9IC3LNv@{l3Ae~uPCjow* zXo=0WyNTj0u+Xb(c;v&6$zZCnuwnQsfWDBOC#quA-8g6ni_zJV1+DU!j~k{lnPCG` zhPzJ8*c=WCV3CdINZ|;lkWzN+*A`W{hs%ta)3};Nc)V>a<$(FZT$rE2+;yOf#c&Y! z@&(sDahkLRj(g1f4pz=hS*COb*&R;rbNCSLa{Q`$BwAL9Sg`L*4V2YNs1xVfVz!CbYLc z`Hf!T4GoLEsbz$PtpUw6IHbA&qg(dl!Iqm?`(4SFNtoKS&Y4zS)y~2Uw0X-z+F4ok zW>yF9n;2R)jRDlg^6Ch(xv`>YhjbXhNsnBx7EYoH85fo`8FPABL%X@c0VCSIfOlfX z6ZyG^NX7c-3^Shi%@$X*p3UXknj8WzLMHQKnlgbShA%_sZBEK+Aag6O9^JNRTX&>~ z9uh!)?67M!t=i5Ix^)gy<{CYn%_8Bf6(3u3`laifS?ONAi-Ux0rTg}5YxYv*Fa=t? z+u}h760UTMGr z_kjAue1SC!RWcP@bpYQYOP|O=YN+vHpxwD?Cozx-L}C6v;B7 zlEIfIl%i0fq=ZVwMfcD}pNCn`_QnjSoFI>B z3*CCdk-LkVSx~{o?mgA~OW4Yn?4V3iJ>v>aB_h;hUs<~rzJ7G?Gx=OpPr1Ue5VGZ~ zWLr~bqpm`ks?HTvd(ZA({YPdMS3YHXD=uwA*K#lKan&{YIkcZYSG`m(`--#I12f*0 zMk3(~)|}-F>YOc?4L$ql-gB9_U^GcTtL`KNv#5S2&&E(l=o2r;$ua;joHj1- zNE~lnE%-20uGM2B#w(9?V`++_?47+H1Hv%jX zLFL+A4?n=%P!hB9>dUT9!=Vek?NT6jRx{D~lL3s>= zai*q+XUg7UnJ)s-aKJWV=o{h~xMG|wXOw6=wptwf01ThTI6^nG$s|>PNyeuhGkrd{S zF$)yWD6z7F^s@%GIFVmx;(eraG3d+2t<;>3rLe5mg=ef`(^6m&U|kpKstXB(j4xY@ z6(Dmf0olg=6WLj^|93y~)z7`>jUOzZt7MD}+&gZpMlI-U2x@1zfuhV+yOj2l+Bri> zkdl!+X34ny8})k=Uez+t0#a~Fu)I5HOIGAir|LFRf}?uX{@Xqlc2y+)&Bxci-4(x8 zcikFtRS(5qC0FnU0MC`ARg9?b0NXoDV#uKO7l*%XQcXus)7P_|4_T#1M}p(64g;|w ziCPR6t7(ay)mO&K;ydKP0n*V^9n3E1qER)RTHq7wkb$(!&W7ravN{1zbl1?sz-$nE1?vY98?cX zr7)hXeGGXjC?ilUnNbPJIC&0T?;!XNRCZ)v)acHJimP5{aZCa7SsGGA};Nq%En@*C+!1VCC=?Qy3wUswtH&mcz~ zgQw@rWhk*rL8LqLAM9YjixyY^r@h+AT%Xg^i&neSotf?R1(+5SHHJc;sMO_Nc6-f^;Fb)0nU0`Vsfsfn5=0clIR z>PeJ${j(bU^AZ2tH2Qe(Z@$o~P(9IFW$~!5haP{w?EY|aiVxt^zy~mG^A*XEZ2#O} zJ@&~De&qA_exI!?-u~adcHhh2zyDMJxEm*^H%Ia6&c8xJ4u|i~{q^R*=CxnHzFn_J z*RQv*XM;ncW9HlSb@KXYRb`oHXd3zSsnjd|?AQ5lTwUyM^m;`7`s!EQn{dxUtn~hu z^IA+^)y5?Ab$`Tbul{zoyq-|MzFM!}Tfe^ky}YigUmsB4y7lX|0%&dh`dYnCko^HcQ0i+B zbRr7D=v7O7sJrvt2^z-Nzk|#-Y#co@hO7cRL! zE&No*qrCzX87d$@jW&*-E?+$wiukzoYxusE_SVH0D-Lh2I!PCy)d;G0zwde{)g zwd1_rlK1XRITgmp)n|5O$tJ`9Ln%Xzw7falli4VxA5c}W5(oi^qVpi^6|kCo8!q|A zN#U4!^iXHiG!?cYT^z4oSlnDEiVt6kWEC%%1;Y=lMQ@__x~|)V)+H&C%& zg=+x_3}RZaLtNone%+pm>{Ro_nyRp5IB8@&qib7d?-ls5V~0+`%S;v(TJ?;U~--w*W!7k`HNp3un2Af5w^NfITc>EyD(lwA^c%Ux!^4 zm}eh>Rb@cJg|-?FuDukwhn?$_94mv*rPemPMMnab8s2p|qw6ha?!cj`nBLL#mMoOP z0ItGC)70tfVrcn=5#N_abgMIaV(Qh+)aS+2pKPY?W5^ui^%@J7&ERs#a;C0rvDE3Y zRCPcO37^ijZb*QCH6S`bs=rHmH~*JyaQ1mh-`hr;JUh>_SZ4)J#3a zhwZc{Gi)cxF2{YN1Jk1hAX6w2TLQ^<4J@Idpto_dN{urPfo9@B$dhz*t_+?6ZG4Yt z3*)&elI3hPvWH3DcG>mlI2@mh6Izn@2EQAX_jpZN0q6$nj}zIB;=Npd78cBn6UGgx24m&{ABR^G zgkNm6Fp`o4i61bH8Xtl$;@s2x0QbZa)<9jAuxL1OlxsDe(9P?}iL5Lp-rL2RQ5@wy@#ejgq7TZcmqOb)V3 zzXw&v3=J4-C@280N1Ve$0_UnfwT;ne-&!~*3>8f-Yr%(I76n^G>R^Rd3(<}%*U-Vk zXn+n5U!GFe{uNpx#$v>p@HI-ITb*&$mT1ZtmzZ%Jx0-g9VL5>+bsEy87KIJQG@9*n zxM?f{nF&!uN|fBa(~a~kZd8YT0?YP2ToG8W!HZsr6Qu^Vt^^3`h|c4#rOF9^c0s+6-Ngno2-ZC=@UP@H~8B19Oc62?_B zk{QADCPsPM`=vB(tqg;4v%#QsR0ac)PB(7s5m>y>kJ#eku|Q4uYn=|ZaX<+P zHDMCn=EXlC6l$YXm~U1e3rxC1$Wv-xRl{02Gr|1vsr(#da8N)t+?sD8aY5QH=b#F@ zqd=*BJ85fP+PI5Ry?wrDf|wjQ>@@G$Wh?|NQdm)Tg;RSEPiSZbRHe&Nm1+cmwi~zB z1XQiFB@uj>uQ4RDGL%Klo-M;nU0dMrmGHu1MX!i`?2RsF-MWi8=IUy_wB>&mLwV>; z2NJez5-C^b)99M>ooV4)U$4vyN{DGn5RioOXIw$1 z-KQo@vGUfxs(MIo9012#`>Oi$pbB&8lM)2)r}NZR#5!5ZPL3n4(!}MXR&8bLA_X=Z zA9y61U`d9*U}ggR!c2bGyOuNcK!m|8N-CMI62K04eOYfrhpZ~Y#yDTpG>3>wrz)x? zEvDuP>B+rjK?K1ub{fN0q|lyw3mkTt^gc8Z2B}TIFVE|JRQiGGhvV{{E3!0uAVv3*t5{6XO@Hk%gEZw1lU;oFUQ{J ze;5k7qM^1gcF&#vQi|47_3lpVwa=@LjJ&2)%Skx&EvvNhQ6r+2k1e?eNNB*-gCjIXKK1bloQn^UK6?NNx0dfxLlkB&U(<5`)|k zt;JwP^^G@cb<~g`AgiNvxj=!E^`%h{Xlc|IOX@aOMsb3dIPEkZ)WJ1S6j^}Hbs*JH zi=oT9_)9#Acm1iY#0)#59tN$zC(w?FpzAN+A(pV2506l4wp(O5lz_P3K64eS}U`PIZ0DTTloi*uxro{feV zj8b>xk|$fkR;=2tVx2`bt5ChVOI4XxD_KQ!6<=3&mAnn%{%4@#1fwqXS7x=~Y6mdl3OPxh}+903~#aLsR?$y$Ek zPB4~DX=~ZDRAo)T<~CS_&uEE=y3vx7?eIgrTO*{vErEc&nwo&k*yj4C>kinZxHb^^ z=7d$j3dw*s)-UN`A=$qWvadH#9gUl=Li0|_*1S+vld?4*N%@Ht^|P!4tl{WRyTz9QB-yMyoort1K_$93 ziia*^!!W4fSc0m+>#>&@iCVK7MM3Tsl|}$B@g3JQQmo6-!T1?`k%Ys#%1%sS_;fh8 z%>E}dPT|6iI8sJTheBeFf=FgIR;r@9O#p{0w+}vCu|>la9hciqv!$!e6q z@F07B`qu3%j2^Yx=$ZX2yG-xKA7)8&jC^D4DqAZin{HUEzqDHb}&)Vf9g|>~D zC_;ki@KOA4PU3m;_bOma48N%fJ0?}s6WIX;qadq5w~4c0k+#Fx{nj=fzibT`g8)oU z^tqx)lOZY0MlM@Ry;+tf|KDx5i-I@1BvLE68~=G2i@VX6u7DCRh+^gT-u0`D&zkC^ zdMNtR-&NhL-yhc>ok&Q+etr+%YiA!ei$0_*!>OVVtX32!s9AL1TPQkPz2+4>aCX(m zqpKBV(NVMLD^+xGcty1>pW5d`U++}WHPr|8K#syx)vfydQT=I?FboOme531k=@i5% zAU>`VhY7z<1fcGS@IO$|-r>OywKt3Yv5I!9KhXn*KPc89tY*$cBfycZ z^$1LN9V4|_(?6(+es%p@d5GKM&>coi*fGtT_N$8SgnpPoy;(^sksbo3S@c87*PkkS z=W0a}ZYrv~Iz{lGQNAN4MNu^Otx{Ag4>O2DlB)MnY;TD!Y~--TR7M#S{(20@T?LIa zvpv2s3*2kf$>#u3#IGGM(^IG7`9P7$t=4 zEkvZPrP@QYanJ%fems>XY`S{G^zj}GK8d|CMkck!oiiG2?m$aNs+(@53nyUj>;4EG z6vRWVunM={*tpR;KqERfiVsXA#6ySdjg5z1ZW|eSRF1tCr$^{OOS1>2whpsHe z4`x)29`wN!dg}eU^1Tvo#-k!AcDt!TX0}CyRz;b2hJ>`$N{~uq)VLqfF8^vMf1tFBBCqaKgQv zotsy6X*)G!rg3V>Onv^Xdb09RYX@luoI&~VL=E~750T*~b}K}XbINT%Y7u*&Q$sil zLpLY;Hc}mV8=zU~)R0Y_&x}0{iA85rJ+dF3(bm(+$y6*p3!K!^B3LJ=*l|)CW%j+D(g!FF zD}{-Zm@)RTUZg^7AmGRuNTj~XIe<9NlT$$0k1cr+Cm9&1W#xSf@Z>jwc6V z;YeE@@@i%7LO9$S6(H7lsEH+q_KnhM77a1jsWYuI=X5 z5ZS?5|5!wCe4;|cI<7_ta7&H&IR(-mOsw&ZuG(jaqBO_HMEe@p+HO5&Ky(gYK- z#5YV9z9hudigpf7HcVn7Gr)=d)JMQ8q)bObk0s%#NNZVYsf6H9t7Ldo*#F5QF&39? z&z}n#wO~vqahF{dL~&wJmM~tO?a6;M$(ZSYG`LOETH3D2pC8;+-SRTX=$o1Vv)Z;JK*SL+t2uDxNV^J8=U;`l%}m1qsRVeCYJ*?GdWpo z)~%S?X)6Z)gr7xjuz7>rcF+Sup>NTJ(zJP1qiniLC!c7Tn+wn;+9dvhpQjHQ)7Vi> zwg2r<&M}-D#05L1m0@ie90(&$6A+QuSwp7uWwi(zt$mZ#(g3B_%mM{9V4Z>FjcIc>b0>&DBDrt!ixOcUefK~_kc@xq2MkaHf9 zRc}TobEp}we}@)*(Tv#94%ID(Zvq({9;FY68UB1RsgKOid~-%vbCR%ak%X_?Ditvm zs^-M(eBHH?6JNs8@y6ZLW5pn-#rrbUYWpepK!_5q6l$lhZxCu>=%uKIO=V;GC^JeC zwdp}nOHK6Hv>AIwBa&1RX!P^dKEwSg(X=V@ZB8h00LWM#{5}DZ;M9cz_4xE;*MuQx z+BH45Yjg-2w{}LW#?C}@o902;H0`EM^WY7nG!7E3>MXKp?ACygB2{fyMAb!Xd8(g` z-W?J~?Zp?An(FAL{mYT^b-4&(Vv0 z+t8kN7eIhg#tuZlF)bnjG^ts|)k9)u+CYsMMcKt57@Zt*mLPyow2XP|)J#=s zLc^>=*_2Y*I=GTpnBCtaSt>p5M@&e?b4H|Y{tl!g7oB&fT;-JKq4^HcEAih2YQ&0n zDr3nT3tYb3Vdly%(K(>Wmgd19jqX- zsMXmh1@LJz!o?F3yi<*3lOnOTY_Qt@Yo@*$hg6u1bswx&Jtu(#F#YSuYBq<*n;uR= zm1L@n#M9)U$iNb!Pv-%m`Czg_vq;xcbaS#pr&Ms}R&}#20eA$h5YC(kSCqlYbqZ?+ z$;oLIb;>u4&*9~mA~xQ!H5WqA;kT<(epJP+{M2mh+XRvIblg0w;zORiZP90Gw=hY2 zmnU&Y(#hF=epk1q^=TE5)C8e)%(m7YMo(4EzpkF*(21j#5fD6_F+xBogHX%H>rKp#@yIJl1Aygaer&hd4LrqtgIrUy5>VXhCO6Clafpdib{-&k8An& zU2k3eJzxiOJk*Q){ZKGlw`KgBGFdxy;LRd&ei%AdXzezw5_oHxtacf^n#F{bB{Rk0 zQZh?99QqdaQ1pwm~FJwmRmQ{_`|A)Qz57O&8>pbs|_kH{Ae!HbtQrng#*}3m)C2l2h(9Rmm zIGLia%64p$RFtfX@=W;;?^J5bBY9cdWGU}#h&w?6F&I{W0kH@oW`v`Foe1y*O~ydS z2u2XYXm-3co>{{RFoOanXu!jYDueg)eV%j9y>E9*mV@(SYe!D{-h1A2?>Xl=&+q3s z=j<9D&G%>v2}ZkD8Y=`o9_%STfU9kqD`(_o_1PZ_nyTf7nLdfe8Kpn(NT0kpw1+;4 zQtBSQ2_@MS&0WKvhDz1Qj5QM4r7cA9WIKlbjgq0aZZ<0t>>kZl9N#C!FhbI7RVk{C z=hE!YU;=>rlYmTGDqAd&+7RXzT)#PcK*~8I8 z;K5cL=xj$(3Gq4~;R~)muA2NissV=SU_uG=mlorpoZeNOWUeuS(V;s>!8_qNXc%z( z{q%}f8JYRiz-t}6p3u5yIrgwG#5&!k+hX0 zsJMiKpg?-Lv|Mro?G0C#Yikika?Gr;&wQjM@k#Ml#MR`PP@kBM9R3n#LIquJ)h4c( ze#p$uC3HCvgmKm63}b^7OB;etzQjf~j29PMIui;W9Ah_OPZMTv&CNmSQ}B(slGxsr zOzdw$gkX}jB?wRszB5-dy_4ZPtz)53pZ!=U8)EIpLJ_!V9SfzCqlg^&_G*4C6xju6 zjQoG~u~6~!C>ysO3#G2YTzh^jl=st2!<`uIOsa@E+oQe7j9Mii^$MEA#4DA?x1Cow zZl&R%!W@ltk^kgxYJ5&>d33Z{{27;vX69Xv+d+LnE{0Pzy!(wFjJjD0@(tNHfi{S`^Bz%RUnKWBuqCNEcXovX`mFYja#61MwLXH(S-U>FV~OM0 z0J}E%$e1i*2?tAPN(l+>l|wBu7uU^lLQraE93RJ`j|UqqD=?!CeoW&M z8fs_x$9b|}GHENqA@k7NK_tE>lTIdfHv&`0Oq84{EuiSuju1xR@})!ik{RmOxc0YY zVpn`nM;(L4QFMe@iUfu@r_D28(>=SPDoTcz-Ux>V?#abHjL~A=tYQ#?2qJz` zEHrZOQ)NCCGKN^g(qumjNcEOL^VILkgl00r&037?RCdeys`;^t5!bw8(hScIh$ zV^;dsX$ls6$#$D5;3>|Na|)*tuJox)NseR|AuWB(&^Tp~mPt^Pg;Fm< zlSGWf-9r}xcPByExw~b?N&vvi&07%;{R6w;_xwL{cR~c1&8ilKfJ-$U`bW;01W{ky zy;OJU4B`RkICpQr9GSePNlczMCttIHC`dF=?r4-!nXT}j zW@H}jX*0D-j!%gv(cooo61sq-h|Uu*`{I%qQ8p=wWk{^_)|eaKeN*Tu=3sESyp}r# z9~DYM;DnoHC23@~X{g<6gMwzu(Cy3=Qm~>MtniXl?hOBm`M)7ssOQXmBVW;7{Ctp< zqnnDoRRQW0_wZT)P#YJ?eO7WVW2*1wCkV#2^Xv}yin8d#F7L|D|0A)B7fDWPp*Cz}Q#SicX zh?6j%w%u+k3ML^68LBBa;6WmQ($^oOM5fT+6~>thMjE$$NsU0;S;ROx&s(G&N%rP; zD5Q=rO&VNhPu^$ zgE5MM(*q;;DsP7vf0Fg!O=@Rh+MbhrV9*yKd%Vn-18#+$Ccv#;G>ki_-yQKTtqTF% zG0d&^EFDvS1a1ZZ1jxg87&j-DhA&DgL?^8AeEUM6dcLt44#)+5W^P-IKcqp8Az{Orv}fIEm~4?XTbeke!9)&9YYxr9o5eF)8FNg%yeWu?m4`G~ zORXas?v*N1)K9S%9|ogfuXc9jyoSC7^ASD&y|_#Q#!fH(M9|hW0K^6a|}4TivZJ{uO7_V+?DI2xlY?!C=TU1xnZGrEFT$Y z4(A-Y!1IyZk8(Jgvk5NG$8wH1;Ceh~BV4Xe1jV2?Y>)AneZcS#CM4M=!_=b%oz@ zVtR#!snW&$)h54t=e}yA-(kIN@VguL`56@KdbBT|8L@MpP6^VxXhw5>M_BH9?-prj z)?2OraQxV1eL6yT=q+BEP)+q_zkQ6`?S8As%XNPHD7Rz3Wv`2Bsal)-4$h)fO)mHC*ktxL@Nq@KF0eNSlz* zK=s}UacjQ{S!)dmNi(}QS!5r)=;;@{5l_G9ij}v5C7O0rc8CyjNDeA?&?w_JAyX7< zzb1JW>3}DsmD(aiJ7|>FBN(2%0ljD!vd5M_X1|6VG+ga@?c*@IFxb{{7b09h#tJ4Z ziMdp`QF!)Puv7o&|EDV5I#cQD7oR}1uagFmHQLt)E0e&=X_KvviOZmuHkk(`zELm zo)qmUm-6uz3y|UN(rsp1pPwOJvI9r&0_DG;59(LXiC7262Yq#0tVwYuuQQLtds&%NMP~u9iG*_lPDlh z3o*ma68J5#fz@7qw1%YvT#=q6xHf@f4z7wYczh7d@7)d9nL2LwYP}ZU-i2DRWwbRc z1~{O+DI9kZd4%1laBIaJ4R=rtCvhjKhPECcVmGwWC)3;sMSTC_xC97TQcl=`ARf)Pe=hCC__Cp(06La!BRU0_MX^ALw4;d9nw5@}mrk%q z0fZs$Qa-*y_K?jys5|HVvd>?kshg8SxJc=9{+N6E+@Hxh(gFZfQ}?YM{%%T?P#4b- zO;zLx*2xX*_J*emn`W*KzbQX#quf#HWm^%@I!9Es>A4Q&1pbC%9Y-L|r)HU9#E;YG zS-!|@P|k?1R?ncs_mAfQjFB6EMSOVF0v<^-a^f?*Gg6dZWXT)jd10TGK?{^g#ZEZr zXa_Y$w1Yyp-L@No;EFo;qOL@I&gzO%cScua>9e{L+&--<>C>llMdB{&ithNdt{f6( zsW&q>6;J6IMbh$aQ2(CLGw#CUx{|?uP}eO+0Szo7kd+5$kQ=_$R>eu_Y{rka*$^CR zri~aSt*D`}6+V}UY=+HED z=8U;(F;KN2D|k+1U~Vu?Up3z(q1oI~(6Vr(Xmb8r!!qZMd47dCX0@qp-fXfa;g*p* znwes!-<{1z<|k;_<@L@Bk{T-twNWR!x#aSXAX{b?q5|>tHsIPi5omA15L#h@!yk$? zWmYwrkGb27P#)qZDV7^C)?C+}=4l;^iu`GYr}Zok@+WDgLn*(uOauLrlSZPF?2J}i zX<(6#!R=Jet3ix(bZB&|$J7a9gKlIpO4M!Mr)lo^UW8wES7SJQA6!e_AW7kk#$tm0!~wDQhnvVb1u!U~lSals|_02dg^eO%xpALIfX zxt9xEWG@$($a}b0f=nhBaw|`8kVP&qkau!{f85Lk_HiQ@xW_IoFpr&F;2jHG@WA%D zY?W1pt64Z}i(+!SyQ|8yu1PDO1G}^gP_3M{-+9M8b%E4ilbMp)Q46D;Z&Qg-VnV}_ z_6j$>VYAvoo3r;j=+qHlGks)v;$BJY<1Fc{rEEpre1&reBl_m%V&-`C>}*Vxj+} zI?MT`5XICA)%lD@u2Ubc4%!cS$qXx4ts=z`D0*Mrj;%wNlvr@zI5&EywvAwQJ)XG`rMQD&x^>_q(V|x=;__o%LJ_x)p@^HB zh$3z(D2li#DJbIRHbW6NSJ$%C8U}JIxY16V>uUkUz!iF2U(x`jZU~B(P{e2SnHSCb zW}@az)i&aQ_`jrGURnV+lVO1iPKQA;)04)D`U#d`mzjq4^}((YR6r8&|yj94(0M`bKm`UHIvJLyCvQ-*+@ zj@2sR=qY$nOYiT;+Wv)7(-!nq_?9&hx*wak(js1#5F(Y-0G60W1XWadQ9ppW@rDjq z$J&%!3a=%3G^%D9*@2i&WCtHWD)&a@Sh((Vt&MM9k3`?qymxQ*N+E^!qK-JND-#w+ z3Ikqe04lAvb?6%PBXzT5Fy)H@&LpYGP-)vIiL%6n_ysrWm|TTmi!}C0Kb1B1Ng`3F z%2oEsn}U6U3)<`x6oj)m;t5Bz*(c}*W}o1oHTwkp!|W5B&C9BXu448HnuysaC@p56 zK(}U}pp2M(f?ZOS=>NaztTWhAG8)VP^~v@{a(%FaWg?Ifbj-%^6JW@7t!RE*5qEz(YYp$VKJ1m z%5WmE_h)WngC2|uq#M4~sS!%dz)QJqxv?!Et^m8Fh2wCF96+g0Ih-aWg33Rpo6)DzZvsdCVuvW5Cm}qIt7CW_jAc!IJ(o$J0if z7ydLYt7KC$VEVU3I*hBm9ujMa@H2g*Vz2#1pI zvVCAsvVGuBcW{9{$@YOeEpmZ5$@YOa$@YOY-N*&bB-;nZB-;nRw7>~SKIa}SJ*y^4<=j4f>w#fW&21disE*XpN9U;{Z|Mj0BR%~ERPV@ ze@#p1-*(sD;GkHP(UW${DQ&?{u!8uFe5tfn=k;uHVE%Sfeb9hf#u1uw%Qo5!PimV+ z;uDt4V6OvF#ut5?7%6$JjSUvXM^|oY5G5Xv{6Spsp-k-d|F9OX>mf8HCgP%BCs*c4rcyZ8BWlT>!^mSJ!G=<3WQ~0T)b$t|X?-=>X8u*F-6bkzXpj&^$bQv2Cu4(Q--SG+yszFq$g`&` zGf#9GGCXa@bxg&C!>#WQw|=vaiTI&onNwJjDNvjSSB1f~(6rLsLEF&NAUhlGsu1 z8dbC}?*PU{#_h$^)XXTjRGM1l($4|!MkQM2X8WU4O{!`BXvz3xp>A}JYCAY z249VYwN?E|d1|3A;>T}fn%dbA5K3ukua+qhKCM`CH4(8ZskD}wh+u3b!lMzsS1!V& zCL;YQyIpJBB&0}$KV&+CbPb3}x{+n7laTF}kS*dNY}D2ZEzPvO0%(-G&L@kN_||JD z!rK>6s+9V{hm;7gU-E0klfEN5C2xxik%lXLi)K3QqOz_VFmPlmF zbAK-6xkrioLO!b0*KI5)m+_=E1V3aTswA0vE}2JbOXiy|DVawwp0Ax`UKm|R`)^E! z`PhdKc3mXH{JOP7_h_Z)#=pu=#6s$xVxqQ|qd{mP>)mpen_uUilyzPSRhb}Px@9DA z@vQSoZX)I}WSz&1b0yWJyzZD=<2mVMox>x>UIV!)hLLJmH?c9r1g2uwwxv|`gYhuO zDA|z;lS`3(Th_F4xC?V>ZK`Xj=<04rMUUN8GDqreOd6W#uGa|NO*K|`mvjQHloh-^ zYyOggpSh9y7VT5sAe_0cou9r+@V~RYF+cnaCN>LGzVOcxBXjk~Nn@|Its@(zpQC8_ z>2d^vhQ-+S;*XOUDNhsI`gc`eGs7QHAWJ7B5Z&stp|yfsB3br*z(W^~8X`_$&-*kI zYG_l4dZ!FUGl0#%gTE0EBK071I~L&*M-736avG{1Xf4PLwQbGjNYcwVZ0NFHRX_27 z_=zP12Xwriecy(`Itq`n0LfhyYyk_>gC0| zC;bsfhfjD11zq%>^j^^nOG-4z>*oU5Tbz4h2fhF=cdQE60Fd;6DZ}!?*&^Y1C*t^5 z==2YI=Q#d|j^7BNwc|I)MS(sXw8C(8;LF5t>pS{5UvM@k@V1C$zaRG_d`@RM;r6m; z!*A*u`o{xf@Waw0b3`R1=M0fBgxfhnkRLt2HjP2MKq!X}fOZFV7UmC#(`?XLnD1T5 zkr=i!rKL|%=c?uuhqJ7QsK4~j_#^+H&UDZMiO-a67WIXq{kcg$c(EA&6T5;x>|ZyN z7iFj0o9a)`C=6UtNaGByeoBoG;t>o5M`P5-D1sv@?wi-Ys^9wzK+)g4UQ)Ma^oSog zum81v)$kM=WzSAMUa3b#S?e$9ag!eLZs+w!f0oC2J<3w5e?*V7dIU%F`lt11mBHuO zL!B&rNSCDb6V=uH8g)kAl zYk_@{L=y_Hym8k`C_Z zk&JofGj!=Xx}?Dv*kf~?&#dOgv#CLPq~@gB+2PH!_jAjS2yKFw9r?1t@+U`R)tiZfAK0MvJFE+_|n&+phGMU135tKKidU=R3`sf$ zN?#SUz79Wm^51ZFGkXkL>Yt{?AONmvoUOs9K2ay2Vh79|$UEgPXX)jLcnNZ;pVYCJ z88Wde5(j;T*AWb2IQAXG!qAI^d>o5z7#zl-y_Y!TUH-E5{C}tfz}Ug@dLvh~tLKGh z!~~6AQI{ds*pcxN>nC*UYEx2%t+<$9FupwjO0 zP);8bQsxucSYgalN;M0RSE`vajt!_Ya8fS)@kUUHbJt*vU6w|7qvfY`qi$Rp9hZba z%UH|ZYNO21jb?`O4K!|jgX+=0ELs$&xJWyfZo_&JjA8EujnYa=55x0!$zDVYQ@iD9 zq9Q&E<|rjIz8e|jtepoPBK$R0;7q`6|A2~0vm0v82XR)&4wy`zBSz#*)6(kl@Fexf zzF|3IhSzbE{1vCY;L*dsVz&^F;65NQfTnu_3;{XG>YH)d3lvkP!d?O`Vv1FjHG zMs}QA&Kn=0-BQ}0oKJl)&1d}J#C&>@qTQ^Y|}8iKRK z$0UNESc%|}02sdt!4Y_LVAog(#?6hQbK^TuxH|&rH)esxgWM}H6zVzK)JQATjIzRz zZ3$ah({L)VJWo34fHRIC)k0RyscEHuOzQNU_3FtV#v|D0g~^eni5@1LBhY57eXSnX zGI{FjVBp_8sOH6_HnCjQhr>s=k24?S0%HiJ^;z3p{dW2L zU~Yuy05`a5sCYTPA-nn=S*|-fAw*UhM_$v~R);-c>i`ZxT3NQr$kB1{;h9X^ZEzLd zrg=Y&Ys!o}ZC`1nv*S$gF+<;4@3458fZh46#k?=!TV`)6Oy1$YD_V+gO#C!Jng>xC z!=+j3N*cC1Jjb`vrCB^Zzmiv2DEvX&86lOV`%IZ%h@cQbIqWdV`dZ-H+RbTS)~Ae3Ph zfh5yB2_$V$#bpJbs7C;4qn-&MfuC|`9~C=;%^lGd`E*!wdk((P9nzT_viruH94mNx zNeQi7Kg<#|E)TPX1eXtCiF0{??VY&X&)WSA5S6k|OrS+!2>nSI!ftNK#6(p=tw%H4 zT4uiswuj2i%*M@aX11kSu5&YcU1Megf8jrF%aCAct1N?@s}4uhnG0ml*z^)QCQeH4EMh6<|vorX&8 z!J|KnD)UoXd2%G(JrVC(M8BweGBw?kqBK~xTLkiqN{AY4q+iABea2lXwn?<3n25hY z-S#WPts`ym%dherfY_}UQaw=qh)*(83y~G2x>Cv$%(1hYQ6#%nJZNLY!$z`V}0>y#RbqTT)iGw(kJzs%^L5R;M!AGLn;x>~=tG5-HF6Odf1kpH%`_vi;SOjJ zlMDj6j4ZRfR_htxgAJ*W??q+8SY!Q(f4VI3oJl+@7g{GS1vw1E4D3?IAkCa@m`1&9 zB?O7vw8dUDvH|K7oT|?97m@#qhjjajN|){SWo|3BAwH+8?;2t{=~+ErwVRAQuB>P= zhXKX~4uevQStfMWvIe!se0WKi$n}D1aXqhV)M!!1%$G0|OqZbFXq}CT2sC8ldeH4i zt^l|R($1!LR1oacsV*6chhgSUwiOm{Qo_e}?)%F7$k=;cUfcA`ER{)%z`3ZU_$l-z z?4IRu_)9rBLkMD*LpHpq&pxtS%YE!a%Y5_>?mN3xSxvCKCpEE)APc(ik1%h8;d_v6 zA2SJ^Sze4pb(%pQhDbRs^A<+$vdG7@+D_fkiD+XPm#8C(fCUwZ&I1YpgsmOkX2%8f z6i?d~Hh7b^P+2KAWWt2EdB~#tj|O<~6c?H#)WWZCP`I+y2G_0##2Zs-CNcx*AlCcZsubDoWqqiTWy}-> zjnpq$lt%$_F;b*}IVt)*QfPl4(Mn0X0Yob$E$u=A_JOaKE&&IB z9jb)6w$LC}3<{cGF(@BqYfxWfmC3Ab5^gU`W2)vL)pNuxmZ5(SoR z5G8?F7IG0!8rdD@@R*SyGL45ZQM~*X&8pL2xCbJauHURr6|-O|zx9A^g60%aL1;*Pw-^<{s%`T2xS!MPSl;M*~7mQV~>X2-b?c}hz*>|uQ$Dja{Z&2ayIjY6o zwoDDD>^x~eJ~L{-0khZh%(Vj*57)w{_L=xLW}GWxK$DDKVU}T zyA;-v4x_dN5FnYMlPtpXIh-fuO$59X#XH(M@JABMnzvjC zERVldJDTTz0o>LIwR^RnB`+hW*g67VZC{_3(S+-CO|uDy_9Vi?I4PlC~K2h$g≺AuL3p-xksYC0RYJ&Ri*;6 zmC%gwhg>%4ZN?Z$P#3gO-6p%ZOI_4L#8wvxNk{WL__vHP@Xc35B?L-EEh6lMG-Juh zy)o}WhsGJOFJL=2bF)y~P763-ElJ+GO8>(9rPg!$Cq8B0 zdZ)YnZnoXKQiI_IBF8MetVn*;8I_5>(f-f!vVh2^wx_^S3?i;9sz?q@xK(IJ@9iB|_*ckM;QsDWKN3Q7ttwEskk4sm|GHkbVMA|2 zhrLJh`gaa2EB{S-6v(^!RP&g#U1syfaM&FdBt=ZT(QUsmXQ$g6N^%x(jSnS$ZDGU& zL2cR&xqkXd8uU${EMuWnG6ymcM#cSOZ-<)kZEO4sdV9_@GS<~4Yl^LED2`QaqbMg1 zrbj&q!)z)rvJA#X_%+~P7H~fTG#>S>3Qk11krZ)uu+ZLhu3&Q#U!Ei!C0R_36q{%C zZ2dz|{7vhXvme>Z6gt(s$EoHHuwga;jYG`YXf3s=IW~0w$6BBjm_1a;hGojqc0QnE zo?@yJZG~Cg0a9W}5x>jpf?YTSz^#0nd9fj0t8i?9I(2>bO%jQtITF4NII|I&F~jFZ zSpq~o-0!3ug#c$K$`-{?>A@moM|EsASPaO=m zD#tTSu#7f5nskwy)KSeCXOKnsAo*otWZKgOb+Z{q#@7_~g9t7)n%EZKl(q^?ZNmYN z)lX;x(R2DD7+%t%drrremblt?ihPBONnL7ur>+FB_)HQOPlv5wPm&>pFegLJ1G2)C z=iKCLP>Ap|O@3e~4EO!`fZ?TK79~uS-ze2Ca{yOXX{gN*rR5AfAT)>uf$v7Y<^Xjt zNOTTk?@-4=g_Zu2ihk6M9B{dV;HLjN|U4 zkK(b$Un*EuE47tMpwPYo!lspwz?qonooe(}{s!*oElBUZm33DC%J;#EuLZeqJu9)P z*=iS*I-UoMtv*{wc|V03&Zb2rytIDaN}g_&oUsy;S5loND>>XK@AW||!DZD_=NbC$ z^0XNpmbOw}5GdSzeM;JuyRV+(wS(9>h3lo*ddrnvOijujhQ%KJ0%3&jB=`uah z(lvMW38KU9t_FEY;6hJpHm4Qd8F0e!gLWCBc;lU&SK#*>SuZ=%DyeNUzs*pe`o`ks z(O63mZbXmbvI}oAyZd8JDZ_mDF~)2M&dlg~UK^Xb=07XPbEl;{P%w{+AQz|0z7cQz z=sHEwH|x*PmJH}m|GW%u2aI ze1y94@^$3b%V8wAy3Cs|$D3U6H1FTf<=0d4B&Num`StjSr#R?S$+ySMk{7|-+-y&6 z@IcExlIZAjSDtNzoG<|I{Fq(qVH4wdLkXRK#H7N51EpC=WE~~scE#if&KulF3Arz! z#IRs@SrK=su$*v`P5Bqb+pE!@rN{pCh4LdG9*?T+cWIc?YB@wy#}f)xkN(y&1>m$| zCPNCC*$b2nKkkbZwD38iW3>Tzge_h&5$i!@sPavTSK$P;n394nCB$gKiP1EDIwW(B zPUYHA-e>^ZCXFzc@nY+7eKdkR&uMgQ@VmRbqe3CF;Vy8OW2g?7ih{x1kfD)^G^RzP zjDYU&E>&hjh+MTuI?<9~x}d{tZC`Wl-kGo|S9D;zS?lam2#w}UNq{cXXa%hfD_m~b zcCp9jt)S_$S_BIB)lWUOEN5q~REqkkQ#>5~O+f3;PPv4}(;l1>(i6tYfRF6|4OXgP zmP*c0vPsjUhtoWC71-jz-zBQHEO;;D_d3Llb_*Wo;+eacRk$=T)1)xDx&Q@*k*eM0 z&D=qI4{*UGzMl&@QuonY=4oRZzEtFO=}BtiFg+2(tme|wS)SSbY^~BU!@Q$h zgO{s3tTMb@$8;rWlb5%}#D<(c7W2E=>Q8q%s$)sDG&z9C*0<{00F)BnL|;z`$7(~6 zWEkT-O{b@m_U^eP=`y*X!lXzPf#uvfSZ}HAr`3Bd-bxdYK`npUjMARE)W=cl@S=JGfNQK z9wspn*vtfhX?C2#bjW?07)?{JVIjEU9{mXZ7w-$}fBpRDpi^lFqG}A6*M;U<AAduvU_V%w#(GE^ql#x((~fd zv!Px|&qiKKdM3)PzpkYxl>9nOfca<`$PSR!A8mubqmFMudUStT2yRB8f+%P$Z**SY zOJiM2VW8x6s|1aK5;VNPElLyNlMzO77|XBMnECb>Pw+)Eo-rHV=rG>%a80=>JZ5QGDwiL!G`FS?vJE;o zF<)#C>)gs=eXWDDmZx&r1Ff#a-r2@3@s49G1tde{G80u;ezt!+G=ugEC8}(yu4s(e zdA@XYT4Jza(thQ)&9eW@7?%;fC8Ww!BnX5=6{QL&QDxF4wedD;I=(AWd(oM#0l>ANSU_RSiKE7w5^cIAHgm7u zKc*!IT#x32TevQBMuD!Uavfx2XExgw!0cJYepx}m~xuEBhy3Cgrf7@pYR7WNI9?U>SBxguDgRa%k{;3(vTG{MT-s*hqbKb{j4 znc`dcadBuAa(7N9i)i1uY9e-Sy?hE(w;giz7TdjiD!i=mVjcoRENA5j_d2qtV`VA%nwHMVgne-EU*5vuJVGg-N|g$$5eaYgS{Y>S<$ z6h(x*70!AB+u1WJo{o2Djh;u*%mJ#mfgRm+5{8CA%Eh*LE-fjM;$&Vd7Lb93Fq{^e zxg@%7v&r;We35>Ne`q-38)1V+rjl%STa`nq(!c@=1Ise9#EJDDQdr-F6bJ!?1}$d7 z`eZfPntZtiCi}ji7AUI1NJe;??`OcirB4DlM9|bp;0qDN6%nA3Rz$#r zau90^3%BBGh%T!kzz$YJa1dh(XSTwkDH>_?8rMN|w8@$Hrk>DwsT!+)*7< zD~yppEEigXX9Rp~#MMe1tu$f_$cdgW`bBtR{iol%jDwPtEP`&+U{B<9ymv$Pu)Cp+ zpN~bx=^1jp=pmaF*vNLOUxsKk}A z1Z(kN7#77?g7GZ<*QRgUG_EuJY_6$eV?#6r^Sx*Fzr*w(kvD8RcvF_~^aU$p?_``m zA`!y?L1+vOEc-cGjDoc>ZeHCu>La=J1F9iih8NNQq+%aI?!EN!=a3_D#J^J{6 z%RN7`wHiMYU%RPTv@UuF!42wZ$ta;wEg6*$q|)ATd_{gBRVeQ^-?%$t+VHw z&2-B1Pl0^6(f^O+GMBLzh|?*=XG*I_htOKLi)XvqOS>zgLl#GG3`cWK)&Itz@BZY> zc1bel`WVhu|7TjK%%EXWl`mQWps*rXaaRAn7diA8VD=Ayu3`cj;*?%DNL(FG(6WaO zg0bCA3+}pOBC?!IPk>_}mpdY>EQqI3uerz>4Tso}CZnJHkX)H$)6ANxP;hvxOhZ)<)E1FgJ{aD zD!Bj@E3ALuN0&1;hbCGr-NUzTG%Pttki^i0IUW8pi8tv<3&m2hQXUjIb&r?*is}QI8z4f@O!Cw}CaL-yd}jEKL5^x?4k{kdMwfcQHFdR@r|CBP zHOw?)b#)Id5+hAH2G-IY7MSM??@3GuYDtSo(ju2Pp3I`xz~f4u|9g zc>WkO7#EV*R+c5DV)Q{lrQa8fe`6=|MqyzWH;oL&IBx_IGi_~m%lK{U#LDlJw+Y-y z!2)|5SZh}RN?Opb4_QfjhLpI4{Ak`1pbs%aOVIF|P{eoeFh5mF1h5((;^K~j2fW~3 zzuXPv3|7huT`5q$&SJ0zC=n&1tmW=!k0}3hD0YDb3BIU>&C^IreXWfLGZA>^kbdwYUcXA4WR1OH-sHC}@q6gFw)J*-6VW#0Vsjo93 z>vUq`?F*>slV3>2EP@IsFe5sJldmpyT|+>|bk!}l8W~F`mcMM>jpZj(`O_2Sr&9Up ziSje4{JDwp7gG7zR1QxQ%fp?~l_SE?0zjvlucVr)1Wz{I27l^A`Ln6~%tZO~sr-eB z@)uM2xm3=)druD16SA8FexkP^R)PdIjUX^gryU)$*vticm$Z>+G{bMqu+$V`k>zZW z_EEaKWA_kUPT`10`@)sw{kEe3Bc4^grDwUH6+bUm9<)-+O&#mRQcYG9w!VBKm6MR$Dt|haFHe-8PUX)|ls}ispHJlphgeHv`-=c{ zr4zSt$U3+7q$#LbKl**kS^f8LDt&WR>?wDbcWWgB*@Zwm3J5H0w=&Kd(?aH8|G-s+ zztT|5X@OE5Y(SHeV{lO#ODc1(%Zp+@o~jIqAnMHP0^JsJKtR`)o(i>@H)UB@4C<4* z;*EJqS90f0=!zHSF4aCjA9Dmn;-7^aD`kALXsOo&rt`JPY#&e z5+)fL1!i=#89oB=xZ`L863FP8YFk=vln`2lM+S zv1~qM2dLsUuRrhgIqBtxRi9)((w_NwGp|j3NN!j|)%thF`Sj%H1>oq2NjSxn=E&&SGtMgV_cs z9l3PG%edK2B^QT0WatZ~r9I>q9YaZR6c`!~#zgR&8AyGm+$&}aN%EH8td!r(GGPM= zh9j(?`A}e}^f93DI=X~3X}V-@?uvtv`4enluqt?&mQc0bPCsrM*|EkAqkt{ccBF`O zfaYu^Y_}CC0~)mw(P!{$i~Uk^zEy(xK}q8;HO`3h z;!;CAD&qnpBnBxhFzIGU3~8G00~%P8auF;M7Ka!cwUHutFhyKYypEyTcDCy(92lnm zh0Vw2)b z$QB%{G0MalEi_nVLQf-a@JL3VdeM|LnANx^KnizHJS`(@GN}Ot3R3qyID9z&gb$wY zrlf{wax@+dgxm^`#&7)n;w_JK<;OVDX>Z42z6-2oOJleZKEfSy$zpEZVIAy*cvtx@ z;EMdHwSd${xlF!`vIgj5G1{GYFMztzM2az@RaT}ZtyEGwy8tD4ko$yiWy6i8MEO#3 z^4+Z0nHbwcV~HKD^?bA-Z-VQwLYrQY@lcFxb^KF>Ha^@@o-9T?_#A^^4-Dy*T6vC9 z%17Wnw`7(7$XdAQwLpqdhV&fiyC6W{H;)$s7{Aq%smUT?9?QC6Q}ozM8aBnKtfXO6 zEVHs*0n3B79-6M&PK{3#zD>x9!nc8>>$domuCq*l%u!kdQb*8*GEg=W#mvfx?azZmA=`@;ZmDfE)++~QO{?7 z8{|*H=J6&B4LUl%Z*-js=11GhMNoQs+*$6;Zm7PwF;qFzK~e)&X|5bwNwy6j2~G4> zO^0Es?m?z88=}>x6i?crWOg@Z9sdz9sBc$AZfbsZaZSG@Dm0IPo*R3h7 zJ)L0@nRmskskk^48;QW~QM0FJfSRxzUIzb62rXiOW3+agiz`2$6P(?g!dfKl(#$DL z*s|KetAG~u$K|gpUx>e~%WnSp+!&L}VMIF>Fef zT8c;Mrz^NUPZ60vQf}d_Kw=)o%4Im(1bZ}l_a1&0u&&jr#C2eHWlL6vQsMc4j|4&* zBEBlc?ZuenyDZL@x+Moqn-wLEr`h=?4wI{8H6j~9!Vt;9USh+`F0U(CcR|j%cATz9 z=TJ7gOdq(TYG=AKYkpTa-tmatnQkjWcBac_nNpAKK$Q-Dv} zY6cJ4^+xizBapfk@VrGvpH8H(m>pfv$M}1K-~LJsPZ2DH3-Q7^g;hYCm+-D>dkhMd z%JUqBGN;dk9`obh*o%7Sh-rUEOHQ`y@&dsH{bap6Za+N{f1>gkc>yfQK`YPMS;uHX zeYSzXXwu!-G^9(MDIDvj%tq-`W}F*KxW>Mv!|_OWvT=u3z#)$g(w7rB zQF%*<(;s*AGP)vDd5x9mWqx5p&G?G_ie+n&k5{^alqMiX4P{(Xu+&pfcOrC1oftc0 zMk05^Q^Th(d=J1HRb7uAE_W;wS>GX;WDO8pV*c6jnqvoqmYTaw6`!fzgoL%zt@QJ` zPHhMLar=@TB2T!BnscBxW3+f8>m21jSr$5hoQ9|Lb0g-)cXtFb=@p4uDnv#v4~3J+N4{+;j^hdP|{B@t@clxX5~M@ z0ypVwt1EmWz`QHOeA-harv`wOZ0i~>+JPg`SO*oIuN(~#$77w5z|Pbi*X#g_W4fZP z92ID!tv{g~DjeY&_4UWPj0lO2Sg|v1stp$M;4rxTVDVM&uA!E;Cds-iX_9tsw>NX# zLV2(Pn*w<0Mvqj9|IoiCQq{F{I>a=N)2M+m3n`;wiN;#$$MjbHnclwosBctlM^|~4 zEd95}fi)8sHQD%G8)aU5!fLy9bPxVX*T@aTvR;SR$1eI9FNlqn24jPB z95!v9hdUu1%^a}pUW5@G&nR#PLI%yqBce+!-rL?1r|DSFU6;@RXd+*?8V2qA!#Zo&uF|;5(?p zVUQCuY_DH19x6N)4}HN=&&bNT=(4!z2`@%%!1&QyFB=#U49-b83`D|!{hjeE zC?p;oKW$Eb(%w1P@cyd!hU|--cVs_qRDDDCr=44}pRjvuO8R+R_r{U=9vf`9oWb}; z4>;BlKb>W|%?gN+V=iuh{|W0Y$-AqZi#_Tlzpc#tiEjfU|28}Fhz!%W3(!N%zN0;s*bGaWjL|&V)m`^k zo<>>ZVB|L6S*GYJiV|fY1SzU0YSBm6c+Uy3d?@62*A>QNghu64py+6KG%6)%M$wxv zb{R0f92tNRA0sXjO(DYR=T#BSB)n;{iqFD}6DYHi8+bmt>P>+2x87y`2Zdj!eD|OM3*yd*@X~r#cngP#TO>U zR*JJTOH5FfCJ0Qj&dN09j?PBytzZAaKZP5<70vCN>rATImDJgg*0jMbW@z$xOpv}W zksi}Wcx!#eiYgK07>iOxr{%7p9qkGXDEWg*j$jdfcOL+`yACSy)_rQ9Vt&i7N*T^L%PEDp2#;17*wrFDSru$s> zN*-++{vfspPj~S;XU0iIp?<2ZkHP^JlgGg1#VzPe#Jr|uJgL`EZnsp734b0e!U*$diDuWYco+U($i(U7^vHw9SW_#%6a?&_*B>$cT>xunPzv6=*tunQ3#6qr-V#QT=1^B;l*R?aAY2j6hXI z{nxxqnc=gWBmdb-BC)t2{i2sS#nI>N_e)U=(6Mf3;j=wOWQ}Dp?4BaB3(7?ADI&YW z?x2>8jC9E)+Zt~kxB--dy_9tzeQz@B0O3RyL9z>gq9-egbr{SLt^p$A5)A4@tH5A( zyj5T@I~ogwByH9dxYcRnR1Bn#{CPPBG^AYDj zg2Zw@-iZ_dr~-z4$1umfU?^kn+71%-RnyOT8Pe< zWZBH+Qz08UHB@MCdSI8*Ca}vK^%RdP*|ydlb)_xE3kMU*a4$6;^O*;`!UEIgQcnd; zuAO-o3vehGcaim=Y^<_AN<0sbV~S|X^Vvi*Bo!Xd9KG=EIjuv#+|5iGTz4szuVa>h7SnF3!L=mgv-X`zz>X_Tx*M=^YDxbNZXmsW?b zF>sLKzD~>r@=y32935_MFCuyZHv6^l$|;bVYG8N;}*6}2+I%lg?@|JQf(M5whM?BkQV-nrGB&6eeilc%_| z!loyTaOXq1*4phvg!?gLusI7!fsgL_i6L>M1_%HuoAN}ptp0HQu)zioK=~l}1U?v) z^^H5XD$|l$U~gsnaU)FhL;7)xzgrj?2w@sR*mtL`q!1ZQLjzDKUtuFprTo7p8N7Cl zwc!C&HT49Vgb_A+2c_^*aY$H#k@H~iHlt-DY!A9=htL}`!a05pH6%rk%PoXP27lBk zru~#vcHQi4&m!JO><_L(`B1gqbVR<2jA?|8Fl;#PzmM^EtNwnnGtid^R_e`C7&U7? zgc5Ed35HatH9^ z4H(I{eES^eum3cJd8}s}$<+Ih9^B2^2Gk769OIpO*M4=so)($3y99AV&Zr-FZ0hQv z`j6z%hKEo|f!yigCYz4*_zbC4AjpYjIwfPIep=nLyBFeJHKk9`wjkB34bY~o&dA5! zlPF~MGCY!Q+TwK39M3=VDO}L87E~fRVji<%;uT~FG_=+$wAY4CAL!&j#^$V^7VFcr zR?{|_tB2X29AVtSAdpsZObOhu9(>vtfgO<$;QYS1(lEYP+5Q^=VOV#@FM+j@jG(5wwU9k~7slGu zyC3553wr#P2Zg>*2*YRhR0ls<&3=+>=r{e(+WVgf2#7fDzDM{_&EQf1hYHZdO7mtPcp{L7yg&4e$bGE7TTr7tiDy5)-Jx6_?&oqY@C zy>I#UtwMEbDCuHF4bh!y42A^ArVKF#zt=DNzDp3?p+uQ6*3xCVv*IHWEqF5WwCw8P zcuFoylM@J6n_r(vC(~ZN3&)MWN`qDzN7*C^&xmh#>bEQM)Tw_xyPdyKExWB_0X{hz z?8)2_BhC5|j-~OlXR*8h@t&;ChMz}3VEoB@0rSTPV>XEL`%R9Oj4suECf1!=UDtFK z$h1P_%ggDRJ-o~}n}c_9_U$xx2=JjH^O4m5P2fgi5crt<8<>7wVXSq4Z&<3C?_ROi zH+JneHagOj!Sx(_BedAwQS&U0J#AFMJap@~%R}BZm~|ayCN$%SVHYjv;PP1s9hl@q z-2|QP>bhtI(~=H@3F**!`iCMIO`*J@LWP0RPSp$2fq1|_G>n~!^zu@o7xjXKebOl4 z7#;o}L;<5TY@5=>#2QeSFfcZSJY%DbedC!MGS1nIA_4lAltKoDegH#b+!S^zc@T```#<<&+7gXH86I zWLSI9jP;;H^O6a%LtwBdwRsk|c9hOnPXryeW5k4}_>v}2439zFWMu`4X_K6)d|SEj zO(kT4ixc92QDQbOaQ;p{*pn-9hhYx}f`4h>0>rU`oZr%}e4tk9=s!8 zvNeCw(L;uZ8ix`hMGkQ9UqfE)C|T^Q^`)2^bnmCUd%VFQ?(jXg@QO+JiTC;kv?!68 zQ1Sq^?&E7*K3J1F(BsH2J=||uw#vc(5Dl{aXpIiTG$eRT(?(2-E7dcOv0 zXG1k4@np53s`;@o=IFE~Je|RTBJYYr`B4Wjli++2djjfWPi10H#;<1m;4cJ)Yp&D# z*ZsXL>vZ_v%71GVg(@Wwz*v;P!eW%vDLo#BiLB>b>PUokF8vo7XnAuoHv|xWR}pM8 zI_L4cF#f!D)tV?ac1nEFB&dvz0Rk;I)vqeB3X%!*=>m@sP(b6z&Ga-Vh_yPS4v^4N zTkF-RGzL8h36vFJvHdb&(ZdryIr>g(^xNqo)7OlCyN#X$2YdqMMeX^*Z4H=6vfcn* zwqIOcd-cl#7Foi27nwToE(cn;Om%oklug3xb7el&f>(l;Ahrr>tMI2+3b2@wriy64 zwJ#HD31`5e0E3lKYrp{a=+?jMwsC}7L=y*DLK94zgkO1sUx*{L1aDq96BH2IdzvQ5aXz2`NHb9@VN81(2fy3P=kUHl zPUsh0LaM6#`5{#mb*oV(4S@1j)MLd>%leUTw|wV(zcwDJ$a-eK5m#KwMbuavmNvbd zpj^$MP?)~1*CF*GF41F8MJ19DvwrOHe{SE4ktrDN%(D7dA9>H5SY$=6IgT({zMcK@ z0HAAwsjZA!>|t~ydyyYl>Pi(%D^r7+@J?%hNQ%~*c$YOCSKcK`Xhom0QKExLmzD!Z zdiHdE=Epyu8M4kQjS5W%_YKG8;88;7k-4V>CjgE;wTAI6W+torT__k-V+DxD(XG~D z(TA~yO8shXpR|x35S9T;ACyqBV)WhC7($nQ^xZJ}4#vOUM9Q&E<|@jh53_{R_pjTM z&FWvy|8d~jzmmV?f%Q1~?sLDmOkO6Ewtm|0a2WlH-{H?%_B*WnXZ#L4KIM0C=IMI< zgY|NN7+EaSb>};pXWuoK`K-I{$Rb&I^_W;?jeM3?Iekl}p#2Mf^7)UJS|>pDeenPK zq_xLj#<(XySVxjNj~^{of3)g;Lzcb6zESKO5NHvGnj=xbs)qEnKk7kJ(7EOeWIsqN z!+#+s*})UbY?W6ZSAoI`p^8ueM5qtPit9wSFZ?GeUpIWR9N6Q9KjQH%>G4rLzBN4_ z_(L8yrpFU{Y<^uj#pBlW>ya0Ed|P^aRSmsej~~F-iUb>m)ftjcO2&|)tAmLS|0^m^ z*FUWb!l%CQIc}b?Lip0`zWN~d!_Sl>v8kcObp}5GW;`>`k)NuAqOt=p4*0K!7?&}S)SP5(q;f33pI>d8F)Xo1(QSVTPq+;(G zO?f|Ro}RLIRp@Lb&L#RFH6ryG4DjU?Y|J6%kJ8EZJW3?FPxF6M@xf~2-rHEKvEcw6 zwWAi-b9!Y*yWo<-fJVws73UA>)TpKLrf_`JcMgAB`7ew6l`F7!tn610&H3-c-_oz> zgBxuXNVyp5qxw;Q7tmFj0AO!dhxxD9arZmQ%B$-ZkWtq%CYrjoKUDUepF~UT)HC0P zu$sAlKe*3cX9|*h@b(Tqry6y7`2D#G?!z?#Gsf=LWHD^9a@0&9L2ZB<)_pW@d~hWC zkP;3z7UzeZ&OG36N5AO()fz9}H?kJ(eS4L#WrwbO+r?gA)l=!f`!G{^?cCH_uU%%J z5h|Vf(C=KlWleB1;#D0dVWv|b{r=usU9f>)q~|2ocIxE=e}Bb$_}v1ynI~n2wHyCn zSYmS@bHU)J^ogY>|Df}2Zp8$^LwH1;^c`F>D?f3cX3XA3kL2xV{{1(6o6lGC+J-%^ z{xE3#t)f7L{w5ZT4#z_OdG=?@K0wTl4e0?tiA99xY~e{he6@ggF8va`Wm#O5N%dXq z*6oGdpc0O5-7~W^UXSDKJK2oMP-^uEL-#-=cGMCMHofBYyLb<>tJne};GK^~T*W>( z>KBW=QV^Fx^z!a^jHmXGW?*V0!E#EkGz*xxBtreSc0lWBmcGGvu)@&*2q~E>(Vx@< zlS_*6Pchz)eEUA!BC5w?c4QTB)>~fBlIHNO=<7-u!O7C7tri9o*vB2cPQW&N@)3QK zL;?Emj-0P>s|p zqhQtoy3xU`@E^R9+`i)_6xatI%Hs-29P$##H9mNzQ}jG`f|TjXofV`Eoseffum4;E zrGq$#eL&U zR)`!U7_zubtFm~c2A^)o`g55b>fIUh#ch~j9i4K{Z`Rl^e&Ly{{$>7Dovn32X@?MO zYI!c-!W?pN-^pc3%nf9~(RDizIK2NWdY{fsyrPB_=V64mWLpI~J6~;K~&{-rNf=;lrSnL+Qoasw2#QrEN7DWOwI;cA* zWj5mkP9Ujpms*>zm(`lxhgk!5KtMm8JiX#4Umq6qh!Ip5b&Bg4bp6+Vyqwi9^G9#f z4vNawdQgKfrs(`mk(Z8IyeUYJ%X%0NuCMG$@$e_g^#c%N2`#(>X6Q4ctXu?-(BfZ3 z^l~=05=V9s(5-jFIqI1^w+j2gf&KUaGJflP2QBb%f_f6~qzeP3kLL27>&x|7hCKXk zQIJUFyo1{splZ#h_KRYql=7@jypAqGtY4iz4X$=L`wBywKvLyrLG{4`fQ)lc7awBq zOMkxXiJnZ*m;6@RqkSix=gC*x!-3}uh8Q!<>;dJSvw9ErwXLom?FYB5Xl0j z4%+YikG#4`Yy&MTuaD?)vmUV~^7<(~-lRt;lNY7XvOPAX<^t3zk@-r~DqVLccNzOu zJh?}~v-1Peg)1wn_|XkwBV{U)j`di{HmKa1ha(^SW7nbSFb9T!NWxCF2F93^sy^~r zHH!YFMp=f;FS9XSd6uRYtZ0Fz%tE&qFA4o1KTUxr(&~gJgI_H#38G@L{hvtE05+2s zWe5ALKRp9Va+KwtOu`_*M*Up{ibLw(B|)JmBl{%r&3Yhcd-;R>G6*HlY_j@B*vjmqsF07(ev41;Il90IJAcO}f2{v(W<lLSCSu1uH}}DB8xfNUuidpZz=^w}Y1X zSRdV=%j|gC>JJw3MNZ(_+sRYNvt$b!p17J06n6432 zuv4yQYC=nl9G45=nGqY1U>lS4oKrfhO5rsLuK1hYNWXoE>Cm$392y+uQn~k&MXGf{ zbPzpF9n_Eaqg1P&XBt$~uDCNiTh}h51~Q11N}I#MQl2+5*MZ76ZTWb&E0(LbwKb{k z@PFC>jTeU>Z0gewU`U@X+FQ!&W=!?G7YuF8e38W5X3&Gd|3n9za1p11oXtd`P(?Om zdr@hgZ3v^RKUE8mEH$ZI)lKiwUPMxJ zaJ&q;SjWwdkU2r-1`@#XScObstFOY;e`UWt2Vwjax|ZQY;-!WZg-wd3|Kyq!3UXE?|MnG0UJIh7Wgl)_LK$nzmr*5dFYXBkXqmWqJ@G|%WE%&xjCG53!q zq!trqGgC1G%KP>pVSVmjivB0`ugJKUSL$D;b-k}Gsy^aP1oU91hiCLP!wE+So`elF zhHh6s_Bs8`tZQ}Jb}&a@bg^(ojooZTZBeqzN_N4KDk_5%-n@)3biT_P;Yn-s%N^l& zBNP(x6}38B&A7z=H5G_Y;d>flZc1JmN_T~@RLurS@5IOHAdm+7i^T+QuB zxz#v3hHZ@VyRXa#qI+3p#@h=JefaCSXcmlDUsNJAGJY}~ca-regBP-)oCvc})6f$m zzYO=WZ1P$m*(@|uD318%Jn#4U-^zb^zt7{lrc!|i732%``iYrf*UAAsy&MCi8L?|L6}T` z5^21mmL@65*@C5PR(AWGxpAVK%J*5T zo1Rc(-Nd6$m6hF$2|=xHdd10ZDjmgAKSDRPcxSSkcdMKCcsDmR(6li-O#)4{#WlO> zi8a>Exi!1F3YzSx!xj+w8oo9&<|0Hrv8MGcPYnuKRcj>5J5lD60IsD<}l5k+qI8SetQ zJyV{95~e)m_Aup^oyKU0e(7V9kCH8Bj>8Vfz?BO`$cysFZgfZw2vHatynb{Kv8s)O zSgrvTqfNs~0yU~`B-*YKZJ+}U$_RM6ScFKZH#_$5KKpB#v$>+alv>B*W?;5SdmhtC z`$|WIXh>*8CtFdQT*cDnP|#G1R8*?HV8v!d$^l?;1cxpQIy#M5TLQrM=!{QKyB;|Y z>ab`hRz;e5+JpI6fkNntjXri}JP=M)1Eru^z-K^CYSS-3Drz0P7ky?j51Slz%0yBl z9~-$|JOdD&=)nx2MaqdxxVeFj%zXX0U!R@!?0#C)#H5TJ=cSrLWOsc=K+FEdsf^-#CnL+E4!aPi@W|Lp+wa_=^jRGNNK=m~s2EC$! zCM$+}jD<;UWwKhC4r~ag7A$>bT5}Oob}S%o)5fIbuHlKL@nkyCy!4AS>DXNplRnf; zdfu^WxqAnWRFk=H1P7q{BVTnUlIy!gGMD~pA+1Q`(e!BeI5yAtU9ZO+Y9%E8JCX3YryJsT4awSNrr(dOAR zn&T0M3V@^;r3ROS0ZD~$9!AENnd;Wq_g8}J&_Qya>ykZuAPsR);+m7}E9JS-9y)yp zv_Gm$X$!O~wW1~!BYl_=;{f-an_~4Nsd|EoX+Gn+R4rb3kgMfglsa zK*6BIW-aGTi$6lLSrkm3cGvG`jb0P))+h=;m58!ch%(XbYGt=84O%CMw7Ly0soTOO zkgG@U$&xWnbH5@P;~%>*9li#J^f4~Ebj-pb zT%8Yp9)F0N*i!gq$tX37R_i6qtl`g4Ut)&25JBTJQ=$uXhL4x_kr1x=wNBfNcE)AK zwC&%8p$u;g%V6ZgZwyrb4mNo8+M9vQP=tWo0! z;#5sn?RaYfx2uo0R`87wpJbhR#4j=cuv7zpW!M^;ruP`H&NI||Qm6O~2tcou)HL?3 z=ioPb8PZ$va;29=dwO|dO_g^_;Sw74*CC}9ubabS+a%-^>n_CMXmMqIdhJ9SAYCZ^ zP(6c}t@tzsstZ`EiUrUS(8{B0GIt06XX!{3oUs=ES&c-t^1+aZr4B2R$PVItZ6qSK z&Jh_XVWo?uw2=rckgm2tQJZhVazO!xqmX3}M^q0e)D;SabQkl-BotD&(Rd;X**Vv% zPukUz=r*>ej)E+7)ES>J#k<&sK3#82x`WNU zC6pSX8sBYRY9p$@6cL}GvZ_gm8vH=l6Q$Qm1jC(%e^`^ui6%gZj>8>L6Ev|LYXx;e z@}?u&9*;o;$6X#pqd^2q7%%Lr&)}aKo&vc93_MdU&Jj`6~oseXB zR!V5kHW#5UySy(u8wVX@QzvgUZB^ZnACOMjQYZNBSE+mO0#6aT+P{4pz;sl3y zKnV^wV2B_FG<^B}{`;JB>sEEQB!7@MZw)w0rIs5Fh_dfgVz0W=aqo*!P>RC`q z>#P4H+jOA$dX__{2u*Ba^HSzA^2jr%u&S0}Rll?S&{lE{fnn?cL8I5~S@Y};RdUl%82jj>2c`^IiUjZPBe;#@@tyhpUHf)xxnuLNDGQO-Fck83hf1MK%0gOedzkzIdzC^3h2&NnC4NpD zwn?NR>LCc&hGf)+ghQ`=o`?;K&z_#U{PyDFxvOqp>P;8h=3c;cTk*WPncJ6&t#du@ zwia9FwsGAu*E}c>=-J8Jc(Yl*zt^~JiEn23{e%2As=D&v($Y(l1j7PK+m_;zxlL44 z%ysN@D?hjScIxxhKqX6T(SAun7=zB^V>q?HS|e6pF_>-?vBA-u!>?^XSzC?SYg^e> zzqX;|wN9pOkj7-FavMZmx9zp%Sg3w&!^i7!dp$n;(^oF5h$09bEj)(9RILfWFuJ|m+l`)Egu-;y;AO1QH!UlW2Vfb|% zgeiMHHT*gb!bW?&arku{giZE()9~v!2p8Gwi-uqK2Z8*1KO|m2xp^AA03~fUC@Xv| z^#9B_Y9ZShWDtqEx94uinhA;x)og;=f8W*cpXJ5F9<~2Im<#sj#lE7x_eDt^<3wL7 z)J-br(~4klTUZP=$hRjFsKDUIICop^_159nevETBZLg|1q=k5}FeaY}^KgKzXw*H4U#+#nr7^gsLwoqbj&7g={eEdl? z#bpJPX_DiFg`;|KP!CoaaJHnJZ@@|T!+@hCPHAGresy#7Nihf4w8w-K3Nd~$&t9^J zKlvWb#+bv<)`|@}34+u62r*{X=e(TtP!Stmvi;gTHL5kB%YA*CmWwe>*c{O@-&EHu4|3l%F-L+FE9Vidx2x@xjoESd8k?nbwQFQ?J2QaOVdI zrCw#mIE^NqXHd{0bIhZ<6nvPj@}UhMB8ts(gnzFG<-JT_X5E};9ql<^FDy=|f{ZbF z35qo(i7BUp#ROZz)gNdncem~u=Rhq%!1^OmNy-WLgsAMoq4vz4`mqEcmX=he{4YsM z@M$+Wr&zIdt(V>~zR4|rD-KJoPq~5eRKBQnwfY8JOvyk_FLU2ZdqZvOMK&!xwN4Aw z8K{OPDepVnVoNtQq&Xi$b*)NY31==l+u&{4-3xmGpK{XB)ZmBkF2OlKRPDTM=vlvu zqk*|(B}FkFD_ZIr$4LVxpYfEgwIbbEXIgZ|)!9U`-mzJP!C|qWK8cGt1Bc@(oVaZL zJk8to02|D$T2n~*NnX2RaCWyB2XJO_##%EQ;t+*qF*GXtJ-!TGk6UU85gU~ zr}mK{_gEZCb%WAT5J^J#bsd8qq+qEmXPOPQenCH#vb+g(mVb+?>rL>dJ5;H)!%M0b zcGzeLe(}}t8!H)J9#2ticclCP>NAo9znO7M2jp(zKR$+@f(=k9yono2QtCkZ2t=HO zw1SLg8Kz0RjtdEL{;*Qt47Y9Gvu~OaW9!Clj#Y0X z-W?0IVsbaB2*DaQe8tgm8iPqj&a{GBR9Z~R5>i@+F^J&`K&Y#aFMzF}Y%VjbwOj7g zH^G?AXsK_Ig_{xxvdOD0{{^f5Vv>bl=9m;19tN)y+GpVZ5d&s9KeNjgXNWm^HcGXhWI*DaU73}h3@Xic(5uo1)CIi+iX25?@- z6Ftt{((Bmt=~5)Jq7}ibeWAn5u#D<^ec?`*wLkogC|P8od88EaBgK}h&6paNYg{e_%9ZF&Z z+FmqcOzbwEU^=~)OQF~rd;c;nimH7PNV5k!{bi<*=TAY8S96`gY25eGmz#Zg1Bx+) zC*lS2l4)i{m|)%2nwDQoL{}x)T;;7&XxH)Ys40Bq3JD@csHl0fln;NtZB zL!Hm4p1{*c3Jf!xDyYOn(6{KH(py9?iMXLn>BArM{e<`Z=Q6m_y?93m&slP85)%+=2~>*9{wQwrQq2ZwA<8y(L+(Y-_E`H z*T-T#tJny3^kJ>utYa1W9hz*|=@ZymL5o zsFK?C z+E#gVW0o=&6Yh@dX~Uk5Ah6IARQ5x9y1@>;(JZMDZlVFS?`G19$}oz;{jiFSbp9Sn zil)~p3I^N=C3ZwoqP;{5WT6Y$&20{sWB32Y@WB87Xvnju8Tf(Mlz1WIuC@S z_+#+pUF3o@U}1ukrK5>Om1rQm1J?#3W4BCMh`_=G6(zONsuapK!Pyv+mcae}U!Yc@ zDh%LXdeLAB+03gWBswTli0~>5w2dZZMGlK!TPCs|axl?SeXuHhlw-g;`R^p?&%liunp`4_9<6W<*cIiTRV zo@16DWF#xd9QG0#X?n5o4CkKV8q=pMjIa!;*X&*|g%PA}&PPAP*n-JV1<6mdnyX~n zkW{k#6{(`UxbxaU7C&SrIPZrHar|&V&{R5xKie|?5}HI4KAp9uRP9U1$v9 zy)TTs$Tq7pgbBbQbBHjDYYG$~zt4{OTl$~9znqI-QxI~e4+?*wZ~VY*%IaW;mPy)} zto?PJ2Xa{>g->)}I>gU5N*X>QwUO+&SE2c8pK9C>shsKE8-QBk7Rkn9n& zHd^FMS{*Gq)pC`Q8TakX>G+&JLI~xZYFLalxI-mb zh+K}u=bS={g@>G&K#mIz5OK|DG#oQ5D%l?PhcLZ^Rhi3QqKOv+o8q@13~A-|kl9>1 zx*nRUZVyovY-@-J`VI`Bp(jKu$|o_31jbi1(s>)dQLPxRL`q4M%a~W3xl1S~BMchT zV;Je&W$w-oQPVqw6DcL%w`>x0=njm1maWEp`;RF1Pu=$(h~-9$(MwsaXJ#DVhR&0{ zl$co4fbgZOv5voMyZfo!acU#5xx4jyS*_hgYyaoq7F`8MDaia7izw4gz3o_PZ;Wa@ z9XI7B-kf|!_XU%9MiI5C6`lUD%0}%RN|JIF?e&*4!Llm75)!gCXRwG0YkB~JqRsU! zbssM8_xcWUmaQhlT9hH33Ro1#(yvi*F|8BBstp+Wv$?Z~OfLul({g8V-0b&)z80+E zhx7=wT)5c5<)M#xd#mjkzT7(6q~e_e9i53Cl^rqlp{XI?fSh_PD++Z{JHKU8e9nM- z@>v6Ci>(qkTVr|5X}>f>AQT)v8Bt&+XJKpG5Vm- zh@v$zRV^pZlN=03>M_5bi%71t_}JPl#!)|4i}WIHi2jFm#gN8wwxnrKmxY4kv8U>v zThzeIfdH99dg8F0hsIy*c#`bNg=tua<)ft^h)cIA%=_6Z5Zt^edJTTtc`g>h&fWr! zYWfO&Z-<3jQCZ&>%3PG=1<=|plWW^-4n*W*2G(-RykFuDt#9?D3qI|hQL-JD+=TV* zGy61ljWzi;Ixa(gOrk`PgCqnix*VxNKfbPhG@iSDu+%G|?{~@?Q)e^{T}WdYM#P(H zBzggM9UO_$n0CG^Ul6NtlBsF>puWv5*$$pIZojXwj{}2+GQ$Z;Fo2DYE@px-=&M5% zx@LxtO4sNW5~Sd5Zem1&t);ii)FS=qbrP`YD$^j3?by56!yo@j}Z9ynUR87 zNuJrKYg5tXo{Fw~`c!nG{di8OD3{xyF-%2}y(c8hRl|hTH$uge<&81%Z=ep9K7(P?}47+?Dd%o4a@7h?NgoB0^YB`pR? z#q4Z;PWj#Wjt`_vsfIAgX*08;_fy$%9XI94p3^`^?#Yb#vJ9Ykel=JjPL54o9VVEiLh3UWRra8is z*i4z%M%;#tXuY}~HnMVsqQ zFK2PXr?Xvh1!EpCM}Q4S58Pu6&4qIYD&SZFb%tYtR0i!9$o;yBEz zt_3{*E=!OPKT+gjgO_nR2~SB}{^PmfmY`B&KvTQ zu_G^9Iskg&1yp`%cDYZ^*N-vbl|;AkAu6+~x;jWhMK7e}x7W(Elsx5+f-Xqlu`Y@c zE|PE3FBvqB$Ko-%QO?8i9s-oYQpt{tE82D=U z(cswYZ$)FtBq}mK^C05mXXN>qJRfQx`y5+X86`Gul90 zS<9aahs`kZ2>UqRHi@Y#@`0e-W!hp2h?+*ptyJU+q_1n%VBm-{h1ocuRjAL*VU)8C z4i@Gv+ovV}h-^Tjp%A#Eb08cp9^kRffEBl@o|!^|^bUn;QbdrE-g<+YX2t|aLUfkz zL+opu(WVI4jPdg9N!h=bIA|Udy^SnHi?2Z@bvx=rM}TR<^4h#|7V=toMWpikSq*0k zpV_$|==O?rwP?OZkq1Ab)sdSk(LQE^3Ln#7Ql z{v=No?yX>l+ND|T3aK#)FAupR;tIg}s}(Sl51nz|iYX|L(HF)pU4|(G`#bh4k&VXpIC?9x+twY3t~x0v+W>%0T8?GxGFJ(s<~DF=*@O)mR`HOOpYbER(B850Yy~69fMO@lL2X|3nKc!hqUX6t%@}CVMZnjAwxu* z)f9(0RHGv?#G_0`B33S%|7>bvdW+dhZ2$|8CJiUBF`Q~#>-UH0iP_bq3A51W(dMA7 znA3qpKaW_GD55?UHA;@GrmmQB2d~;7OX_SNR##}b?7eBiG87oYL30@NdWkF={MrW6 zJkN*KJ1mcdAxaJ(4(=HE!6#oo7vT(&jiiEM(eTl?B)jFlaAVG#Tekejk+$eN)YVW_ zx|j{?pC1-}*|rON7NQt!aH^!Yy(GOpe?WT0yj%YB(mY_Kc%1txDITldLyAYM_eaW` z3MmTB+XqOIyYrGFq$ER?bSRM$x{$OSbf*=hgrpKFfx!wX9R`yBaY#u5Vt|quBN3Px z!7bA=vWTv&q%)+nEy$quLHa6JX8l>`cXE!{U@oZG-K2nlm@0*VRJfw#^K3Sob)Sud zCP3#tTcNXz2cFW<G=(voYsJBPKvbiiXmeF2>bD zQFEon_<3l$roN^w6zL&fhb zi=T6dNb0Zo*N`-8OS{VSOL{)NWQ3IFU+dk0mo{@p;XnA&TR1CbuKwh_+OG>+J&hxA zZ1wc*f1R!KhSO7+y~>$GiZYCj;FUUkc^p$+!QtieoeArMNe=R6Nt@zGNoiBs`|j72 zPRhC=_zrNQ4Z8<*UH_tNiK|=0s(460Aksyy(KUAqkCrgJuCvBEA%ULHchd|xS;>Qe zb{uoEN`)XPE4!ko9;nrvJB)!JY`e4MMmx)c%aX&XqTDV^-j=d;eSO9q?v-okGEy4z($mvzpjH)G0Fcca6X{cvxT;jWZKhdti_`rGmVN9uIL>RV3fFuEoe@$z~IA(Wzn^^JM>#w84xV zTARhII?x&~Lu%lxy;0H3l0)JL2~r)ZF*MkKY|Mpq6qm0tST?SF?8qR-zcn^mM{6A7 zurYC1+sq+Q8uU=5G)tyi%ErCSIaT7p$309ucQlhob$ z7&!Z?dFAXmsq+|rh=uQ3;5aKNin#wznR7^F!2US~6BrdBfH5-sZJ5T>ag%Yqok0=l`-8S#-7 z-Fn2j_2_W7E?fq!ltL>>E{`(D7k-=OT7eI*#2L zLFNzwjq;h{TXtXh)AzrV1l@RFJfkuby5D~k5mW1UIYD*~T;Tn;0hv5&dg*}ZH0jXn zbDsI^k#q4Y2{o8QDyfOQF|8HS?s#lT4DUvy)is0oG1JcZ7_@Wc+#CE=z`WFDs;Y0`=b^|+LXL&LRyQFXh_K)>p2WEpESO;L&5>T+) zDUQzqb`Tn1XT1mPNNgLt3hd(k5t6;};w&s>NQ#JXXY2|1iBA;gwwPU!Kh83hLuL@G z+lIxbEz3-4tggp$iO(@FKF8J;pDUJA$5*iVabxob0-HBl@Ir#e2^fKj@x_`3&&&-?_Q|Fx z6RC;1Pz#K~^rEU(f#~E4h)x=YBI2Vj>9zo_Njk(iu;wMy6O z=RyeQ$ckoIx*s($qYk~P+70RP>Zz@j5H zcbJ5XmJ;{y7lX`)t|XK$%~1@L36&kVt4dIDZAlKWSd{)7ui(py)Q^(W6UH-=`U)io zQd2=jJB;xAtjkmYy#TZy1wSvHi+hi*7=)vSp?il1!B=$wt0hwu{RoUFYbqoaHZ9K0 zrg4-?W*s+8;Rt7XXzt3~@5IFocbjfv$s&mm9!ecy6fy1C8yi9`Qap=~TYkgbt0bCa zWS7WG8j-EdkNsTQ-2_&vH3#)WD-Qc?<&vPJFaOKz6+G2gq|NY#X z(7&fO_ZFIaSp!7j)f%3I`-Yq6VhMA21p#B97GnnjR`dM3kR{BSQj9?_#z2UPZSXcE zwYIh4;0gdR@dLme0e}ttC5+APYqAjb-YCXA`;>E^rVw7PzJwuXnXD1o3`>cygki>G z8B>S&Gx?H*57}KxO~bhPoZULKqFXpBsOQe%ZuzR#>{aNKW^_%svZnV9DJ5X#s(I}t zOvP~Wd`RR^z!N(hAF9UqpK`kuvk4S@yS9ticibFT-E*h;uBtZ z)^_j36>Pp}Y`zrOT+I*vThj`DtQ4R+6DC-}&nrMVoM^}h^|O)-`@9M2!o?@@Pg>x! zwSt>fS7P+Jv4W>vWL4i19_$$=jhm3QTk_m#il(IWxvk*ZNM(3EzW~SSJA~F-gw|V! z(0bwGdq{W(lRt)7Kf7pao}Y@Cb-Xov?7UWRbo*XknEPd_sZ+yN@aSl`04sPcuML{P zYvi1j9Xu!Aa_$=+|Kx4o{^Vc1|8J95kXwccF^?AHhjMQVA1cNMI-NTmCfUrrU9&_} zhOQhF2**-m6|U6LH;B`>zCk=MZO0XZI2!}aARcO$I?D+_nqvY6c{Pg~lqBIk+SlOjDBz*W|aM5Za2mAv0nETpcfkXgx<)XrDx^~4wzQI~ZDuY%c?I@BcVTHc4l>LmWZkze`*DfiN}`93Gbj?m z;+6}t)DaYajGh)8v3#$tOdCgaCHb^j!I)N7okpI`TJ8cB^38s@@r(8QW7}$r);0K9 zI61pA{m~Db{^*DG2c8<}Pn;I%*Q)&))wI}pR?}ij(_(9tX%SE0vzivM1;=R-RE)uP zB{f86PifWlt2Ibw)Cz^wTOWZzfAD%wsXu(QuRlbBfDjCUAaZ~pK=7&vG=g}BdPN`z z^a@ffg21@Cj3!Ze!Z7C&2qpesoggOuCn5+89f2UErm)642ft%j^OodeW@u+k8|}vK zs6D}+9G__2|9CoNy)m2p%9xiG)?|zBS!sqN4#?ZHEI6kUzXD+`O2*pecpdA`t~~)X z!{L|w(OJw=IL$ez4S@*3?_2PJ#e3MN1oSc2S3kX0pI*SebNJUu_j=5fE1p(&1V*eqF9KLia}TrTm3LA zlwS))Ve@*7^=fLbt2gGVsCQ@MsA@)?fNw6P$GwdTbVk+Ncn@AGHba)|%U9mP-2X~5 z`zl{yuHvhRLK))yxG!tmJzkrF48)YAUNgF4{3RSNNa6>NNGrhf-UT5Mgw3}C_@_H&gjn$5ipcDStVO5UksNoR9-{h6K-L@MWReg*S+&(yPA6;PuN; z>d>JYVHD5|LzE~JoYe~Z4A#0?wTgXMlgKY23ggMO3iYrqULSNVs0>)ho!~`GtlD=1 zeWDK%#g4P$v>jhT*rpDjR*$p}j&P{>ECQ!&FxOs@zO1L&ST_jcql(M{RqTT9 zBUO~UQufMxwmM2#d}4QNzyTr}YQ8i-j^KZ-I(olUe6GhBHeHGD0?e80mfonx#H~TO zV1tD|e66xpB=YsLw@p20b3ycJ#{h8GxBzxiSVjlM3+smCa+FJ>pV1#N)xfA6gUrM*yt^NYESV;CnD`kODi-7l3E;=Ap+tYbif{LD>JCER zww+V8W$ySx%Y+7}N+ARiWOmbF#6V@71(4-c$!oY2I<47C{3|X#iIBp|`GjC{U1*vg zz|#XqujHqUw<4Tgrc^>8n}}%Wo-017%9t?LSLC;>*js~yutYI7bUNg?H>PdAw8VI5 zL~aQqc{sHsK?)2TtG;K%1mQsfI$KpU|e)Cn9q&WfDM#fu zn^}4w?)u5LCo#w;n_c;@AeB6AE=;ujey2urbgb28R)W+79f!00H=&E;jkL?OpjYaI zr8(r~j{C2IMsfJ zfbi9^i(jLJ{o%5Ka}3w{V7Ji0fZe6fKL^M_r7Tf!__?T1@sEKLE7(0zR$amFq4QyP z^SQChYHgLKp7>!j#YCRDgQo`(9;lMuDv2HGMJW^c?#y}Ego!6}N1jH7ixcN&WK&p< zQlVSlxevEF9A*3Dilp_{)MqQ`Aor_6$C5)x#N^s1D6#fSf64dj_+FYz>W=7klWtAn zc%N>kbW3BAh1!&RLNCVLx9n2j)0uY<>G$Gi`6B}ni5ec|LFYXIFl_?@uy2j54%pL? zhSr?lXm;mc(cGkar!LywNUKZwy$TrKVJb-drw^!HXW-L&*ZS0)1^rJSQn@kr7rHQ| zsMRB%;P+~+nn9)i>0j!b@eBJjNG-91P<~dQPP#WK3Q+r9*}?v}9{rLYsPkl7um=L8 zG6KhPIp;NavFpF4FD?*%iJ!`+@6e~M3xi*Rrt;~3HNZn`A)e$X1P zd|HkG+fmCA80>nG7_p{5Q59|X=g*)f34}^_PJ5V2(qrmB^(R!m8WD)~E1y2@fvA3Z zdaX|b-zoj9h+v8N)vfPSEqwQ+YFnjMFAxIXU0r260pqKCRMKPI{hcm>Yailw=iRwU zlko8k!ynsBDsYznnh!7Pqw|RF!!Vf)IK~5HK()3BbTIcB6_nU%eIl#YzLtJe>PBOI z-AI~I;UzIU?%czFN0qIJ8s)@xCwN3(lRSq5XJ&NH!Y;f|^tgyO4m5GqdH zm-Ouh6^1fX*B6VBSL(i_w{5*O8G8GdW8pCFKH+KV?$wJ@T9J8+6qP&@gwK(9eJIF% zwwNRL3&Q^Tg0(~;={<5b`@ko6|GlQS8TU_RN6Fl$!tG1ckIcR0jDPzvbD3xEPy6=* z*S+oQ{{5#D47p0Rjh3R6N@wgjx|6h2lvN(h1l{zAKdn=bd{(Ebdb%Rv`Ww<*%5!=v zI|`Y}a%QriHkb2QmTG@^@?*IYY~;2tUk=-U#z|)&KOqxdR|&+3g=D!{)KKY!>hd{e zh4>tAMv;=fjP02`LYUfobw@xb`3`7a%Ai)6l+*$!C+B1#K^)f9B+(NFa`(tvKMY<8 zKJ;0x2!Zf9t(MjO89rB1RR8Fd#|YDiRl-R~y!5zHOmgQ&gGQMIm_7e*{A`sG6*fR` zej_W++$Gm*c~|7~)?@O?r8!HfqQ+Y@88Yqnu)HDpuVFWZ&?D9M*j*nEhm#Ylx-gUI zREYyWhYj=1cOE^J{G5BkFDx||_P9l^x9l-9fUnYNzY$c!8CR8Rsg>aX(VSAip#?xS zO7pqktdlRTd94!DaP$>MoaO>+FSb?CSYy@3D9RVAg(D))SD2MFleDVt*2-?L4x_o` zSc$GE3DFPsMpi;numLz5g=I6Uk^5Aw=xYp4)Xz5eZbpNYGt}-B|Ak~nSIeECzY?$ z@`}w-MVr>)YAv5VER_nrCfzP_=!IWPUf$dn?XC9s#AIjP`VCVXH(j(D*%25GD%owf_|zhx@86!w#us~C{9bi{$K*}zbFB{pvQgh z*B(qR^=YgU_hkQuMYOFU3!6ag4nZfgp#lY>ro00YP zh=nL0O2^wduvV`e%3vv~8Bz8)i>hR*g;eQe+C{``9MtxSH^;UaAK!M&Ky^e7X)T+O zT(XzA@6lOL0o&~1k;C!cL$mf_2$HGbvd13~r4dOx@5{T13Dxq2A1wAguS*i0v6fjT zltQI2pG=wcL`m%2=YHkGSn6y*x%-yxrsLf&|0;J|zu^ zFAUs$OLr6T-O`=ayI;{=S<7z>yt{Yc?hkcWw(v>am5_Z&cQ1`C{PwSLrv;P2@_yZ2 z9`C-YyB+cFZNJXl_IURJ-IZ{DLU(0*pVQs8Sn@l%6V6!V4cnG9B#8#6Ef+JK+Igq> z1&lx?hwiqC398X~;>^`%@+h!)hzVrlfOaJ=P|kHHdJX9qPivm)6Kk_dtXP!>R-fPM z=A8o#KX1dMWAJE@3tk7wb=FCeB$~R%w3Ava7v|8hFcHqc-)J#O|J!W#T>q$O25}%E z%<^{K3QS)JQA^j<~{4>bGqh$5| zvzG##nryA~|HR6wBTkpk4=aH+)MOMHj(%})@QvKs(!mx7hjg3ktt}3IRktdRpMKZJlh^mAkq(>UH|%dWj~ zE`6QtS<(8^-BEVI038_w5oDqI0b<=9`<(z{-5rlV!Nr1yQs-fu8_E&4iG$EkJ;7+P z;hqKHtuNl=e*R{Bhv0nu-2GpC=xy)izn^$L%G(H0Pr^66}t`=q^i?-#Eh zEN5ye=)Q4$6ykTMz8|zt>fWrg1lE%}KXnh3-K{n_7g~Go7n9em-FV{y8o#f%zSs!N z#l~ViSQaGr#wMlKYejY7jm3sr*XYKp#^na~-L)}YtG6k8RVuwKlA;BM+D+claLg^I^HLzo%cz`qh6{Vh=V$gR@if&|Qm- zbB`s9y^D%Xc3rQIZh|v6b}uTXx*MG7Q&aa8Q}%kpJ?^dpH_y8tzmBBQc#1R4gT+O2 zV~f2_j5n95SJ~)pfQYA*At`kHr)-?Z7U9WF1Em>bLMWgfx1V}z)Y~fH+hW5jirQYX z!t?8u943IL`ynCSmLZRpzeu=5cj_&G*r;mN4K5lkktIFZATXruahnU+jXdf@rFBSB zY!dAXf?a#SjY5l+W?~OxYdxpN^#&gcsP*vb1{l@)d=Vp{=3eDba&%8bzzi*fgeFw( z8G~Y*R0j)Q14EEi!KgO6{+@u#*eG3CQ4!m)5#x+?Y*V1Mim77rJ@o0o&+P?`Q?J-V zo;rGg7`$nkm7#Ua)pzN4eOkQ)XBGxBcK9_= z|A(b_W_CZW`*+;=+rN0R-L`f6>A(8pC;i)&Za?;(BR^s<$8`6rUwJgQyHVYJ_%koG zo2G8={hONIG`RWD(o5|32*2O)izD{C&hKCPRARpw(z!1+?5F0DFZidhD>tLBnr`*b zO$*K(9{H)ClO{`Gms|JKd&hZQ7=z}#?ED@`D%wBA`-EHg*6qZ8^C!8^h60D~-KULz z3Eq^$yQPfkGOiH6p51^1Jqt^F(mo!4X?dc$VfKC6{v`ddUs8c@?K8VDVCE!%-vb{PqM&>S?YIDki-s8OWzpg=RsQhBdIwi}x!)Lg(e3=a;20LLlfx4)q zA@dpuQ8+vS>}=jc-J>eV8LQxuHtP#|x~}N30<+d+wCXAG%({Kj=&-95ll%9|euJ)J z_z&m8pxRmODFZ)&H0B+^hR^loD&N?)_XhnI-GD-r#~dJXI~{aXr}`*k_XQ2f)2w?VD4LyxQ7$&lK;Ta1ff$2MWkn{ zliF$bvE=3jH&B&@pQ^RoTFVg^i&5e|UP`1jK@EV4$rK#B8mLwz+v|%klFtHEtBQk< ztu+*f5>y?%E>pbh818q!yPUXp^M`37`4_!x+Wo%2@v9q_H#hb2=`M>i2Uez$rTH|z ziR}ck!$k#4BQxKRxw{U_K%W$2TKBhkJ%-KQulvtFft!{dsLFl$S)q_EFA@Ca)Hz@#dFcnlAtm7=<%=r%}3ty z)^|Ueym1b<#lb^ImKW34@#42m9QM|fETUf`I^#LBp(to?B&tEM-pNT;KWj$>MV|vBG#>5-` zAz0NcQ%Tyn$6`{OOl9grk2qW!9<_?~)LXH37Ppm>(ik3}Q`o9cz}It-e|2Kd`RxX@(Y|`PiZYDAePz z0;KanrOlpEs#?6DzInx$g}zjXv*X8Q1o+rIg$t%}en0RHL zR{mG7{66o`nw1#gZzGg#ave>_GUk-JFhfRJS*Ii?jj|cmx{fwuV?LUs$BgZdcbt=< z^t0$O5M!kn)J-=)pv63NN4*u@T-Q2ughQ)3_YFh^L^jv8$X}RlxAoQw(|^)SIH{hK ztrm~xyO8?nbj-&KZ7eFi^;1vj?ODr8n{;ja0DH0!7i=)lbi<|A!;ECf%@EFho{?M_ z*U4lyvmo(=;^qyoe**>*lD|oTF)NT68|MOCU>kTkyjai?$2_}G!l1J+6T5@$-h-49 z^i?34e$4DEpsfft7R=W}pdy$g#;TxtNT7y3s3@EjP>~Y!WmQnIQmq7a_qZ92OX!47 z_9gkQjP09eorYXfF8~qCH4HJMG3SgsI~dPEG~^oeo_oL$& zh`g9 zk$R*B>-PE1yKOU%_WS!XUYe6}aj*=UXl0;55ydMHP*a#n5&BZha&J9P)I*zrY?if? zsk6>6@}WGUVb&1zj6x5MS|auWi$AL6hWd7aMUpqCc3rSPM!;4W$Czf#{a1^oD1 zlkZ;q@o|kkF7`s^AxS0Xm(^wdzyuHk`I;ABSbyVZ{&y~!PntE~0a#QWFi9ReU=Byk zw0zaSFYdYOKB>uauLSLp7!M+6Ew$U(rg=Dg-aDmcq-xH~&Juv(Owp_$~in zuj}k{o&U(8jd}%XgjX*}lf8P9mtX4%Q;pf@h-Wl_HBeq_iJ%%I3rSrmPD7w3E(x%| zIJJc|pSvSM-Rk)HOesh0!*w(1|b|>SYLHPzr6<2XcBaIQRY%z z7i-dcPR=!-Uq0g~Z`;egaw?Hr3(ekY9Q5284PF|a{&!K@)Gcgu--f#xU+ zB$$J;8eE~pIVca$W{*Ehy{68yZfGY|!O_o5sdjss+lF=<;YsXaO(RPtr!=FTu~|sZ zu&|B3>b_gqyZH%G5AR>2Jvs@w)D(O0I=&gXuQ&QH@pUf#0D@Q+X`KFk_=Utoh4o4t z9a4@+)N%zHKJhWd8ZgWH!#EY*<<96c9Xrym3OG^X-U8wefIE+R(HQRUL zCf@_UXKC}Lp-*8qBlFOwlApz7DWy{4`f+owR-__mIF|Jx&x_f&FY*wd2Oy^IiGi_EBMe(MzD|ogivNJz{`UXlX4z3&h&t_cwSp^0cr3ES{Px>_?-LKd=Z`tSJ*8c+O=w9=;dp!` z5af)7&}0O{7$B2H=Jh9}u=E=KD7plW(E{8U=3=_fm%f9Edw{;^bDjzn|C$-W-kZ5h z*r9`&hz=>=?VqB^F}eQeS>=Bv+~q00mGw)zWuZTryM*4M+Mi6liHcw?oBS<)E5@5V zMR>}GUY6MZ&K&sPwYFs7{k*^QCLbr2`PeIP=nb%^eL#=AV8ek|n&lYg$ScfF@)J@Y zR&_Y{ z!d7;A`mxNj+5SH(+pBSiK$aq&Q-+XjJ-5?HLybUOLbVSv(>v@aI49sBZ8apil#;e{ zQ3%^kVd)*phon&08O7e$AGu zbqg%PrY)4d1+Cy`yG)r5!C^A;CpDtl1GFGtb3lIC^CW|-YQRTku$%@vx zeu=Xts25yIrqiks4~baF9X9~m{F=~&nz&CAnFZbZGAU&kZ)u%Al$zy*Navs=4-^3X zxuo-17)GO7(n->KByb1q)V#6*G8!hzy&?v>=G_aZJnOulA+oA=c>*`J^#!}|T|?Nr z_DYqPW*eSl@kth+hg_4uS7pNzyOBRmm}L*5G0thwYGgtO_K>bz*g zhBwHZOXxUAc)_k!3U_|r0z#9DwDU5(l!p@Oza4Pnb(?IqNRbahByGi@Vzl}Y!ES1f zWVI-#^G9Y{?etPxEFu!8G^1hol!#$oi&fzDVnCobo{7iAG~a(J2S9$B0dufAt%yX% znkT}dwQVCzUpwy&^UYD@f}d|b$GT1{A3w`z&Oi*)iTi)W=7CX7oLZ~sIWRH0*mmu0 zDa&iPv6wROXCv2fTD6eU6s7(TW#);sX(=t;_h3mAhw5Wm4S73kyyPn}Vzf!JOCeeY zo}Pf})eSNAbs*lLi4Qzf)q}wWvJG;rbqn2NV9o~u^ZB_Upl^U-5M%}c59qjmV5p!Y zR1(f~Yqe%r1r0P?$v;-FGlpVOPJXc~E#NBVqKTEuHlhX+I)kNk zkJiPQTK7U4BjT&MH=t%7L9E(*2i|a4ZxbElbiN=0^*Szf0>;IJ&lPBIFOl}(&z)(u4!sjhw;z**w}Cjn5Vu9%Jhft-0Q8f|Fnm) zCG32q`ndQmAh@;adr05ukN=Lf=YIRn+b=Yg^2TI{_)T%(h6GMg;`x*gQlv&LA(aw> zsyDY<-(^n;C@-9y>jWl&bCXBZ+>hTqsddIT_gD3sqtqJTgI2fMOq zk>{qR(U84(JsmU6&85(w34+*DR*xT*W^V1OFzwQys&uDA{U+dIV@&-La`^0S7@+bqsrZ515LPEM%BQsDPJD$i20I5L>V+O&<@@*b>|8T@ z4lKEk3NgZl0u}FU*p}ZHq%#-$@iYW!Jk?3PN!%m+vOi#&Zpbag8yX2+i};QmvNeG{ zv|rRE9QnF51U3$9)D_XxYMt=>rhQOQEFDyfiy7f1Tiqr6RDkt$-0%~Lbk6yk& zv zyiRARF$|)#9QKBhQ?~^QNr`|4q3)7vruSL6jH0zJ-j6Vxhnai!twjcFSt+$sqRiJ- z5cnqd3AYwU&}TA)1V9Ny<2>+ToW}&FVd63B-%tlyizBSe_z*Rbac045P>V{9Y}Az@ zev-U^pLk6J;-@r@@9O+yZ4dC18jAd+x1!Z5I~f9>0ZUP@SSnTyc&sJW^Af^Hf%bTS zrTQ?HpV@o?JxN_jU@4b$Q}?9kQ-8n$6HU)!cD&{ufYF2*6pnnB7QMXD7$v60*oRL+ zn7n)Hk{hP2-=2xYFM~{kSoVNNOhptIDM&W{7-Av;`-BIpm*dorGDs0tIgpnOin-!a z`sD5h-fjx0bWdJ| z5=7*vkAjF0u_%Z*+lQ|uh!QV|067RELe;{2tg%oOkH(BCRTrw;fd^p&-8ky05W3R6wVxlT#++P=WCMz5LH3j(%ygV15N z1B-~Pa^^tKu--d7(fYA_8mm{nznAPs1}HESh*ILNC1a&nC_FRqGf)p1C z!Yv{}Xo>U-x>cE1;~*15tD%KS0ph{6Bh^x)07p)vPbWbxWV6zq_aRiE zng#qd-0XSnb2apgXdG_sH3}pkA`hc3vcSkH`57dV-*DZRJEiC!(1Dm$nbstM^1cLO z3N{I323E;Fr2$MOb1?IH(PQ#RYPrZY(x#VEE}OAPQ!A;Ni>I1ytkd18~|sS)YABmIt-YGfB3xnyB= ze8f6F((gF-P3yRK-&@BeBSf=`Qz&JwBrx6dgbYf62r(Y`Q4?>KAK_)w>dL_}aOt-3 zv%K`Qu-6MZVi1akWCb-qM58Dl%v!}Dv&sy>eEQ1AjJ#4-Mz*%QN+-0#{{T; zO<_EzsDjGsyL+&l$Qc1yG>~;7=*-W~TEqmLSjWaTOja0C0tHH}HTK1Nb`~Y;Z8s6wy7CWPx z$HE(3%VKAB^F(-~YguejboFF-qib30px%5hywSBRc1UlQ_@gf9S{6I3n>)fAUCUxe zbaQ8Tqib30sBZ2GZ*(n-9n;O-;f=0kvE#bAH@wlcEVith`@Jk;NH>v;L7oTRdWcxje&$G{0GSRSCW++u^Jt7BJS>NvO9 zQ+d8rvJzdlu@nPK_|kNbU4g+W=p@q@W3h{6l!YhOf_8QIKwtc4-l7G{Sbm#I z)z@#TS`DK}8!Hx+vKupq(z`VsThNqO=b#!*%%wU&ujYXfao1r>Ur)ivKCl{IYW4=?IejV#9Q6E(1jwvDJI6ksy}Q>8S> zrKB`U7`^C_T64kWtuJSoOS4(of@BPVpgK29W6nWi)Xbvw0Old!)>XoFp5#59k8{wj zxi1hREXQUki0Kf)VfN+JL_UODBc+Ds2Cd?NJ@@V?lh^db8Lcg-K_QR|GR#d{&1p+4 zcnpy5*~{Kz2`-_QM$825xe`0Fb|lbxC`2`~m<|-;N#|qUR87%ts(O5NDhpwXQ z37aW*?|)V`qV3I0>gzHLL0dIQhWyU&@kQrd=2(~eO+G;ko;-AS@tt`D-wk|&fw|jt?3b-%H6r8AH|deM zhlmNNKtUPAN*v}fzu10jzcM{L%h#RXw91Ddc+x`vXg)&Hir=Z?ijaJ$W?LkEt2m8? zD~%4gVf=V}I`Nbco#0xcrA2BZs6Wc|#nyAp_i?Z-@O&F=VpF~PsSw7+lcyS%aSL#L zn9K6kr7pW9@g@==Abw(J^c6W741~NL{-Vg4v-b!M0jb-00M1{{1(EVfDle|cuICOp z^D=+Anu;=aH3(BKF9j?qAjp!j-v4$`7lL*SWHm*@p$)!NWRWsZ00}KxSzj^e4qsob zprTeUmvDeedv&c_3msC=Hajwm9ff4B;LFdmo8nI0Jjx%-g%95>>Vc3ZtBUh_lJIDr zSfx0V#)LOBG4dwEr1*(VX+hM_WJNd0XW@HnQ4}PY0t|AG02LGppV1%8MnsShV1s3` zc3HxSZ@MTdPbE0J_ybU*L*t>8hs4ftL9*eXq$fy1rs^Ky<%}vaO+d--l*!0%QU~s< z8~0`I2-yLR`@Vv0$D8$!NY+A5L3{|t{%>^%u0oh3DZ(IizewgjOX013Dt+l8&X)AJ zk}EbGB^!;>qm8vDy)4;gkqkzS&F(tTY1N&T6xj$arCuVFZ3b1KJhKzQUwWYE`}WQA zd}I4Fm|C%I{*MWoZ$|l*~Z;5z}BV&shv87peSl`_OAm! zs#{0HUp-Gon%phnCfSs0pw`hgmNpTLYWuhL@isnw4G)m{S8{=r7d72N1pFn#D&Se1 z1fSruJC$|0%w(_WrIM6n<=}Iq1mkA2htC<6CF4%dv)aI{?k^>w9B-(0d+*H_!K4Ql&`t z0FX1;%X)1BRa{c=6l>x__Y!up^1IV37P<}n+Q!16rHJkA8qxm0VtbJkQ}aKbBnOrF zh9TAwiDT>sMm_Ta5>)^`s$Vx_F!Ow7}6`$lE`EH-O< z4++7hbTu@p^1=gLG`a~5jF0#=+9-#A*>oS3SL0$!Kv2vT2@^ z1ff2w!%ljnS$FuqASrC~YMYkEh4Q3m@1Ew>(ejn@2^=i%7+Y~0DMbX_^YlquYuXl= zuD3^E;BnedxeX!98-H z7PV`}wJ(wvvTW;;80UgJaHQB5K42Xcvbm9!qKk|K5hkiHOH#ICKq#5JWKVaT%fHd6 zjk}S3MPsj(%woxmk{Ad^_U*OuKMUOz4T`pTpel1KIPTW(gF(+EIQX^d+{iPC~OpA2w8oSp9c4`PK`rt5KUb~lX#-Rs14Bwy`E^u z#}kMq5z%PqjcBq!G%D$dhLQtBlej=M%w`ac3VNc+`b5Jw6{4{+A{Kf;J0D3*(sV6O zQ}ck)6SOj#>ors~dL3g$*TQ|T?RPaa!XCvI<4pI|{o(Fqp?idrTldDOknXi(_uA^- zn4kvNM(UKb?u{8wsJwM=4DsN*hwf(u+x_nGjdjny*$WK54`M*;rc8qDb25oRmK$Sg zy3M$YXd3s;jlI6N-Lfc3VQuXyw%^l3#9$sQ5*Ucsg8yMUXPEMx^4+wcB#9lA?}ctl zo1`IWOVMpK{rS6zTS|>z5EkMXov}uOo^c4gF76Zm=;UbQ1oDhumL%>^B~oPI3U^`= z_|`Z~(T}jD*j>0BcL$gZy<~yw;069W@teb3_i%gyd&l+=5Sd%zMUWsK&b(4TTIV>T z!BpTV1nw_u64aUdaKct3l96p8>P*6m;iW%`=S~T10Aijop0cS*gevC5y+jSd-3U66 z7G%u+y4X?gnp{V8@Lz}5SZ0&X=QHHl2n*Y89mZjXk;9WV`L(&n<%P*cie99d6gS&m z?X0ZtRc_B50BrMa3F}rpo$_Cs|C9&cM0=PP>zaiGvJmB`MJ?EiI+R3ZMFOGOd#lL? zM_P?U&xzj(1D~Ol_$kL?Szf?;gT}P4Bylg0T>x@Y(*j2-JA5aV&Ga1jjZJg=+~)u2 zH=Q!)ne^!J80j&_g#qtPxzF2vFtL5n(FDqpbzYV6feDe036VxI#r{b@vyPb*QAwl- zCCB>+dZb6`!%dO z%8gD>uv%dJHWU-VQLzC9y3i4>bA;Fs4M$=89!dwp?w-UZaJt#J*?))`m^yK(;_LcJ4MuBCOg?ctpgRjii zbSeR0R#|wE7Z<-M`&U%A?M2zExzPNTI#9G@iym(f;qheb>k?hDQj1!v?NnuPsa8zV zDkW|60arV1fNNV-mFu^iJ@dzu>o*)U3Y^`6;m!nmv87nYC%tvL6XK-69AV9AYi;2T z;~9j?!WG5T)_;1acropYaJEe-zbxrE+ZVwrBC7zPn;KQ~E5y7qplRWECCH9Y?n;oU zU~pFgb*3VNYTM#xtvv_Yww3sE+;%DrH+M(E9@+oa&Klm>a0VMy14^QEwJt29KC%T_ z>w=nPPh=uvCBsakH=|yAH3@~f-2}zn9#z;bEE4QpmHb=(^=n9(Ra^lzH0Fe6nd)xh z4di<*7ZzAo`@0=nj$s6mb-)Dtt)6&YT%y|@PxUTHU|maykeR)N|m zZ3iAm9o3NeiQC|%^)a3Lsn6qK3WxlG25SKO27v9H1J)BItaN29SOb(R0Td~Q?zxAl zi3rQkM<`M@TQrW)g@|&xFm7Ea4{2!3op|$ui$^ZfuBfNm3lJ}ip96Nob05pYI2H{< z#j^Zrp_160hdElf8zyE_M3f1ag!T}cu&0-F$eo7HlI4LHb@o78%;mm_pA;OmiDbIg z6CT@I_y_{<r#KTSv8>juzay~Ipq+V4M3Cj+D!GY>jllAZPPH9?n4dnZgGfCF2I>cqcz zK#a3&51A|b97)d?a!YJOMhaq^mdJpa%&!nXljW7+#s7`E|VMJycPb{7uKui^R+PI!z zKa>5m<`QkcvAh;cC28y5msv;>*|BBnPp}WzzQ){z_42Cw8qK_{xk&pODXIwx<=6H# zno~sk8dK(Ab77^ef0tk;-HDBEJC3X`o99VWszgAW%VSvTg|9?7*FG#0e+h5mxtp4} z3SK0E(alSA$FHI&$i>6so#f4L_fSq7fO9Sx5&`(@@v`^e03h%#FqNyPeOjYV$T9(lm7EltL9F>n_(jNm{^ z^f}HDFYAbwrW?NZHQRFprMM?!*OJz|vMl#Xz%0H^4V?NT3cf{*&0QO=$gpAe7-2C) zW>Yz{qg+d-u$2N_t|FvGDZhcx$t#J5iH1b?tXlCF8!R=;X$r6q zMaaL7Hj0abdb)(0#I^y0GI&5$)OG`^4pcTF_U#}Rb)P2qI`=z5KaloP^+zcb;9!+i z8#J#EIXoMACk>w$292fvW4i{P2+Lydfi&U?LOTbZrdHw!(xuPfrGlqoRXoW>hnpY>qdn=m4iaD8cQ@Tc#U057~#i8BY+<4 zhve|Ukl0xGj1n6(V1sWt%Ri@_F#Pc2#mQ7qsGSTo6i|xzvpe zJ5dNA+Od)ZLE*oQ4Pt#G)}4i_2i2M1Ts}wG!smK4%+nTY+i#4eExGScq0uwa?hT74 zFfN&TrXlXxNE11*8~Fi@@<>v%$e!1z28zC5-3xl+Kj_xB|Kcp<#0L2cr9r?1HM3(n z@`AWxZ%_M~iL+9b?yr*t3(@P`I8GR2U4_SD;ri-@$B4L5Va(1lY4)1Yf`Jv-ObK1= z*k-rj#L$!kh#20+X!$h1HF=ta!sT7OQmpc^KiBN_S-r**=N8||$j-QR#F3FHHYV7<4nFllZNHrmn=f>;>xI8ebh@44jo8mmS z%(fSZzRByxaoLOreLfQoxE@&@eT4g6M>r@@8v>QvYTVZH2W!Aa)M0=PUf;**AXghPOwmfGCSo%RE{V-UgdKtXa1s1`^}+^zA6rczvd9xAFAaJzrtG<>D?2sG;`fv+ z(~m0^%@*Rs6i0VzjM?C%A7O)28d`Hu;7;4e zh7yPyZ6%g8;~V>b@kgkyrJA~luQb+2L17NOqwzwn=6e`v*`&e{p?3ET4ztFp z96e{M!I7<~a#z};xY9qSM+C*l9(6rmqsdEiIexb$d?qZNV@FU7k7Aq)M?pWr+mHdx zBq%5l7BVG4LrJPJ8y%M{Q8?1SuSR^?ObY2roC3dmC?J}^D?EI3(x8w+AjMa6{mHjc z%WqTO_ZLJG_hJ228G^N}5+AG8nqiQvW`rYdEcW(BSoZDR3&K1%q)Lk$yolbEAt~dJ zT3~s*Yh3dHz!6s`>g78#t3k&(?>od_6YMHQ9-qSCqd`N67;D-3358|r8>43+A zeQEM_u-|qJoGPPusLi{R71oK@pqIv4;FiD;%qps$HpLM~-T}$TrOZPP;zbS{tQh8K z(CXl5k^0LuYS-+=>C(niVqrdh`oUy@Gg+KvhDYB+^KB^!EzM{^VMvA$Vk;(hjW<`7 zZcqv(#T8MyjeF@PYlTU-rp9l4uV`vWy2+cr7w3MEZkns)pHx9F-J1PTq;~Tx*f-J) zyk|kgB3B+r)Xs;jBJ5zDMgfhT=4a^iV{z!hSg;fXcc9}&A4(>@w?6`HzLV)o`{PrF zkZ2Z)T3ClFl(;z&D=hkjAvOv_YW+u`i$@#}X#s2fRun7aYrSTi<0|z6?q%)6$SYYd zQHGibn4q>pm0SwVx#rt+`z#gleGf>{&{P!B;H z$(VSRcz{Gj0owEktsqn3eSZEMoON6E(uP{08U*BcNzU7!g;%7Elr%xXnuNa<+}koY zsIUvqof6BMt&#vb4gM?(G?`~B?1(1w|C0AEz;;#Vo#%d>*FBG`BM=}<5btxW#}yzX zY(Q8zM*C(ksIeQIW?aNgjV+{WjII#o>O$fvN!-L(Q75Fsl$kV@a;N2V#-iKEVG?@A z<2W6e&@mnpLML`eO+1O>FjI856RQ)F_DtDke*f=Vd!K#oLx7W1PtQmto&8vQJ-+q5 zzi+KYVV2_n3({e30SpvPtSDUsSv3JD?mhvUXDQRCtJGrj^VQ`nxB< zvMB!-{uIf`M8>v5zcNfcODEObATLAD7A12Y3Z6VCLB#6UuRmUHPKsUP9}BY?kIw!@Y&ThqF6D##Qy0Gi&3 zM}dZUz>krsUoj2R>Jrk^Od)aIE&_@RPo{_L(QLl($QK@DysmY!Ng@ncTwF$6N3!nG z(?13y%F#0OZ=V5=EwK}3yqf~AqR0$TWcWtLLbv}pIem>5q~;bX$Wx^tLfJ6MqfH9M zJ%lLo{bdF<7#iQy@`p-#aoLEjQ`Vp|QW3sdJju^U!I6z4{xm7!plk_~Gn2~oQJMrk zKs?K&NJu!uDI;bg3}D*3im2`YYR( zorksw1vH!H$3G2|f0O0g>-Y<>m7OIG5-J4-*78rONSsC5`cWCPMMH~!)mnL6OG`#B z4bTaB^VEaZ;tvv;yiM5>=tECOvy*GnB+{Rlf6azn>c6J65byO3Jq~sIALtL>Y+EAG z>1tCrZb*c>D2qu8zCaqwcAsTV*mqRC{>d?UPb%= zMz^}kpD5nn(7UjEQ5c$eN^#xtU=hSG6iJ4CktZrMeRRou3;wV;c_amY7_vc^6(3sF z%q?aXhbpee5#Xl}l3Ay6I8Mx>3+3>ODtoegJ~Z~zHlEg&vfatWJjLSHN#b{^DP%2f zFToZQYInq=2GY||EkObtWbAaF^`@igcWNK<3GKVgcFR~$_-%(A_jYRf)%atFhvZ~) z{%S`$TL5#fSwKbejy7TIHdU+Y>`gz&rp*$?k+C73O&eF~O~;2jgDw;dcbYw=LtW*f zRHYIIfjsK@D=DkJ2n~U>z*?(QlsaI#6@idOKnaE+Lc;cYXM)KQ{PgCtGH66Mf`;hc zzQ?q}A(UdTYOdrwjY7-paDn?3w{I1dkZq$zg;jK^V%*DaVGs<@E(Y?gF zY-$^%w1}#kUJVl`+Gdu=C|b%sAzuDpLegNib=WdUSy~|;@b0-Adh5!*tgH4#yQaa) zy6YW&;)?4EYz$mc5nDjZE5o3)yKXTRzlr%Tt54SDr^Ezg5ZOW}tKYY`gg3(%^nkAK znl*M)VHB1j%>>oa;_x~`es~_0ibs~Ik`tIvP~AS3;!x6Tq==rt@fPfCX#!2ZsF%H9E6u-dR{!%(`z-K!*F>p^D z7-E51R)!!lRtdeyt;9cAWr8lWOc`URx_bWG#kL!+(fs7n*+nS`$vL&=m z&`W@UPzt&a!2W`|6+5LE)9MdIuP7ti6&?_$f>z`H7gBO9i>@~EKPSPp?5eGIvNo$d zlFH`ofdEV18Xl;>8@m#Zft8&lnMz1grw1lRw_hl z+p#Q{fTOgzUyBi7o@(HDAB@#77D+)d=~ogR3+*ns(45SKJnF#6MxR&a3W4GiCBb1W zQw-gf2p6+e3jqY%1{^mM-haG>|0wO8NaA7}aAg-Hn%{0XhKC5KAH%~rIf^hUBFY%W zG89$ft;N*Lc@j>|L09&H{&guC5Mm6l>JaXy(Sxmxp9R8$rGI)xc>TgpwEmRdY-a`YGX_~)U=Ri^4 zzGb0yUEIb87VU^(%=y;~yuD(Mc0GQEEg2HC^oBk ztvxXQ)F-#K=&55FI51X&V^)9BQ{*W1u37X{>4)*$U3v1r5HF1dy3HP7nIYj-W&@*} z57Yg5eSiK}e;sq?JqVR-i5oj~CDD`QlRBcy-sC8sfzh;u;>6AKM{(}EWgYh)(>gnN zf!p8<(1I!7|9^xIQhXdbPG~v~C(i#^0g*Zs*m*~p#b<0u?h9l(2NqMHm!HxPYM3IK zk8s`pY>M$8NH*%c(oEJ6h8&TltWRm4^6pKFlj%Z!>G+V6E_iztv2cF2dt_aVgFPZ~ zTx1Qoqll#y(PXSBTb$k?m?efz34Gh~LF)uyTP;YyN5Oc@8Vo{(Ko$F9pB8i~POu2W!Fwm3Gy8I~%WTCLX zw=8!ta4u7TrpSD4H>$c;)Jl=!b3Rrk0&1eL*s?s!DtT#}PGi5bv`(NRCW{a-Xdzh) zV)o)4L)Pid4p+-8bXiF50x>}rUu%^R$0YB^2C<_3VQ&^kDRr!cLlcSbV=bn{oyet1 zTLW_!Y(QUR<##)4U^g`fsp*+S@MFzub|K{1u{GN#we^AKR*PhG^g)s-cd+dSV=qGu z;xEg!v-Wx#Q?zmdy_N0zi&!x=C)pYcG*hyzy)JvE*TMm`2-s^zA+<0D*$Bi(1Sr}g zM&XAZAX*$yAQh@!Hi4^=T1i)!6fp2pW~;>MG8|g^wPo9J#yOA|XDzziSC_T(tip$U zrjI0P&(lT(`gS0nz4=HdRm}xO9XOT!02`vR7-G_GX|b|moBg!Z4e)|6zTnK8>J_&9RgV;(C}!0$ZvXV3OU3(y7F-_*gyQozx%BT`=h{r9F|q zLOQ(iV}()XEU3WGa2F+zwuvWeH@S;VMJ{M%G<2&#<$_d!(%~qT-f-m5hb0(b{1HH{vW%C6GcX61fb|@PdK@hI?(o zmQ)KomFv?KX3z;XEECQd4w;Fh)r;myvQYyDJ5R_`=CqWgrPFfQSO`y)0%2IC=xGB9 z4WNd=ar>rALvWPc{MWfz8}YSu3u57t<>2t=QXXN#I06D887+3+COsm+rRma20dtds zSYthJ$tUF}Fc+OcomFQb6ph@pFdJIBbZB(b29~vKXy^gs9aoRFBW#21U_q9#?m$AE zgsKTU&V;FMeT^z+Atg;TIaIHmg>eEjBm@v5OTOsF!&Iq=Q0oK5 zY>}K$((3F2c50yp8EeQ#Cf_n@_z1(MNTBvgxR=k?Zu+W`_@Bgx-QEC<4 zp@~qJR;EIr+4(3uHfIBoaKt!j*_wlV+&HL2q9lLTPF7Fs$V(f5!8gfY{7!VU;p|%u zDlVGA#DFZGtNlvB5xN}6zoTQ$oB1X`R{Wr7v@cZe6IC}nUajJ*^F({Z7_EC34OHy_ zr-v0udl<0Axc87e@?Y>V5?iC}YKV+XL(IRbMY0NjiGd7C=t*~#rGI20D0uy%t>Ud3(ijz^AtosyT0E8`-C@S}Oe2V2twPO!~0Z<97kFK-x ztmeyhV*_FAXf|#66#+#{k<_VLE%FRazM33|B!v5| zx=GW7Ot&Z^FUcIx6Lx=)uB3M&J4RyE%;BdXT6n%qDz_v9!j0nC)TH)B` zbk)MKYeA0@C$Co>yG>Xrj$K>sQ8&k~s}O=d8h{qIPZaSl`Eupe#l^1p7dlYz>asnP z#lLXe$%iA7@<7+b^n>q}(4>y|Fz6vZYVKaVC|WR56a>_8&dBo>KsLWpWdgl62V@>i z6Zzg^pkiJLo(@aema%A?F9_N?QN#fHm)eYjx~yFh9TQs&(We9G*=GTWqbZQxz*bW} z1vIo$IVM3uq?iQDLAMNW_paN5h|wgZ)k#25Y7*>BVp~Enz^HZLtT+i^wod|kub6Ay zCc!t$Dd7s-i8Km-4YYXt5SALc1<3>lP0Y|rNt%JmX!PcCEv5{i(y74z3-zRB#{3xa z7WQQn+^tH$iI_gDOPgXF1zgnNLtzM9vjb>tb_#UG#6+v%<>;fVflg^?LuVPY{xKQK zbpyZ63Yyqj8K_#kxGAT z5Mdy23s{t!q{gW*fu!(Yxr>8_BhuXfb8ch1Eul5tz(5-B(Ge1`jl!A1Mobzao3F5{ zlmSIrsVGT|U4hmn#aw&`>Z4R6|6IXmfQ}OP(K=+V;YUE>!gl8|_{iS};T()W**&#E zm|l2>Qq&SLN48-yj_NE^rW{?sv`T#Oq<_R(VxO zdNDW@Z7B<}Xe(rxfCU`bNS%nlBA)tNpQadIYm3jcx*_CS_Sh3yig2(7LHk7BF0f%+ zcALdt8Q^oOi53)jQ-h=|eJd$q$O;{@iLQ#oR)pKK%W(jY5*)+p9>dYv>p{XK6OTxC z1^mIXO_>kfwPbi15{Z^-#;J;+lvEw?8@5YX+KwDJa@iLlsdRBjieV9wf|@OJP0ZBP zcbK(QdiQNJGvL0#fkTyAJv&KJP<5Z?)Wgs>$bmDwV)(kJWEwVO-1puBGe9)f- z!ZjxNHF}S&qU{twV2TR}koIQMS%JAi%znw#H05oGWdMZ)M{x!tlcEFm8K9Kt17i_; z;~(sQLSXg3da`U;{640N7?oPA+g!ks#$umPtxIE>XJfH$)LTho%|{j)h{b$5(?{ON zhv@l-#rHf2Zbv0)60Ga6pUz@k3AXLILaiXC$wz*_#Es9f699>SFf5Y9ENshuVgS;m zv8;75FjJan)a3Sbq+SdPW)ij~j7O+uF;SDrg&ZqTEo3060jd__Q7<6_`$TsMm|Ay9G^@VOr~C9;;8)mJCS1*&5_K+oDTH z+}b|KNi@_pH7x)T6`48$02#VL z?%*t0Y|nx!f}RgLH`i4nS4qS(g~=(bY5t1 zb@x0s^&DM#t4mm|%DDuxl0u|X%<26Kt%hJ~; zA{LbmBEp_Jrv06Z2uYBTPRbq>W=Sg$4cwO^#7Ml6Mt*vHMCQZsBZk;Z}t*NtCaBF?aEkwhdzBac;!o3b|E&ad$AHi+} zalsYU5D$c(_A2x?FjDx8=ZVCOK2f8AHQ0!76VOo#O1j%eQbJro zwVh23ODvah3~ctXt<~Wp>E7qegK9cMNjuM%b{X8hnl!%4IYhey#s(UM1n)M1Ya|f93LBHzQ%n&dzr}ySuGhA(nr30Wy`4s5eFm*X1~=k)^CX1mrn--`!@9$BX5H+dw-q{Mj*agNJE z<>aIVn1wjU@$ce1JonW6lF4csNz{=Z8cy=<)nNg+4{Z2`rw zI~~7|>n_h`!Alug#`>4Kx=had^1_$&FDNlSXH|V6swTErVf?tc5<_Zw7?JX7REwo-0pN zdvA!3hkW-3g?aBrB?c{-AY((QUWaacMRf&8QFgJ z6+%pm{5x8FpYEdnOhaM)xNl?Jzk`4p`FEOpRGGJsa_k*t_AoD*LN4Tw!owq1szj5F z?Ha-Xc`OGh3qR!)hCLJ>9?&uaxB1yn@$dllRfUJA7)pUOlZA)J8*iX7z2;o7;|Y^! z{bL2&WFbMke@u{r0@h-#E`CeKDle}j!|&mLOw)uNs#K`51O%p z{>E*&06;iVohjkUVqDOoV_@o|6fStf`t+wnG4Af@^`+{x5ss)JEfvSw zx~d_ol4EME6a^ty;5v;0vy23EDkRwk=AHgC0wELxb}h*=HXJL~Q?j$>mZZNU%}Q+H zEz2nrEvHQKpB3h~n~H8h6v%KRTDiAF^N83M%Y)7Mwlj?iz240wWrXQN84qG5#gNPn z6Bd{Pu8~Rimgk7F47Dwm& zO#MYN4wbv&0#Z(CFDZCP!2c;qr#Qv}x&vj19O+ANp9d7?U3-Z0cPm>9f`!V4i1+V| zF!EdnH8T;ChFN+H$dc)JsTeR?HnB;%MISqw2g&Gx`Z~0ScIJ4c1=4AtLiAnfx+Etk z;HY+}UCruCTY_HH$ZUCy%o`Ar%g@n(-_?GK{C!-3B^TisF?= z-%~z;Eka9Km&Dg}JFp0ALGd@~;8o)n8so#0`JZV2;2K|(qLh-NGyrOzZa|99cP8S7 z_EJ0(kwzlSrc)*s1XsW2n0GzGEOqJcDF=D!W!xm0&=s;%YMZJ z94tpl>8J71@KM3!>1l&ZQY3*p#k40zWHpc^a}Xt8mJr!kSh$XQQdteq; z2bE$PF<>z|W7XD?uL&t2B_T!1H}J*r0$*1F60KAqp#VL&F5Uo|0H};Rc;&@IGnDaMSw5)5JN9P3-nez-LMeny3nPFCW-N= z7ZrT_YrQXkysn_mK;Pbux)TTJnT>$cWNn z2@h;^Wk9VUPjmhjdb%kFDXFw*rQ%T{K;0Dl$2CRgD9XU$rEwnl8|A!PGW!2ZqX&8- zCfmgukDcPj?5G+^mqv<@r-mGcx{RSYI@%$TWK7O(-KcF0KWR*50(Wl`CO znv`SrvS_7Dv2^^iXB>9`R2P7++g!q#!mgXH0!7UYEpWgSvsS^Lc^88%KWJg zRt}P)|MFjON2NhqWCTp<*bsynZ+r+rUoe1GhtM1ifpL!lTr`{(`mtGFWsJZkC)Mt& z5+LQ|RDBVCa8ZEc7{@mcvKT(Z1K?bVMSJzhF1flUPEaToI;#h~)JH(W9aC}V<1y=E zN1_*9C>qhDQI3gTX434Rf*w=HG*F)@7eIV=^?7w3tP8Si>1JVfC!$Fd2F)|>3A4L9 zkEi1qoueKV#9lSqB7`*wVsNC0%s4aCEy>3mtjT!VVItGbc6KEloQ*LQVK9^}@)-zF`Q9f46)ji=%aiFg zLFT`w9kN3T`3!)#_*9K8224ew1HowO7F&<jZLc+Dl5^kB zl#%@OhNle8cG)SbEuJ!^>Ml12!`AIiq((kY73S?uOK&%faQUb;8Ax5|ptU$^{Z|QG zVY#R^1|_ubgbK-WrgSAW#@xlmh$>7-Dq>D`rls2M0>TVzW~)gSvtiGdm%$!I-(vd~ z>6l=%3Z?#-^Co=9PVa@Wi^{GJVi#)8H3`^*6q48;&~=E>CLhi*lFOiEl{Kj}SYEIv z+lpYso=iWWfr3R9s*UYK0MHh3rlM)S5O?(uedk1j#CvyU$!Z}BG+?lCv^xCUI>@x? zg7vjrG;Ut6HJ|Lcjf7*)_9GeSrnHKL>D|KWaD$T z8^A{mvzkbBP7wNZfhJ`Iv8&eZo-)mgl>DCMUhx=>M%flt0N$jb!`#9GQ**s%I%*K$ zdd;%2M*6-&ntFTc%Nmv^~E&LZ&bSggs%dysvtd zvs|7L%3%KMBj&?BBfPs**2vcAvRiN;AUT+*ozbPhfX^*JXXZ873fzoTq?vDEW@9-= zNXlZ?3s(l?4?E-P^Zb{zDE#rC$ClAqc8pif9YtKhK5N+ec3HX3!*L0ti09UO>H7hX zh&X^dp&_ZK3P+doWMDB>-hnDPVDn%EGCohHy^b5La+AvjLLMZRHZ2ryj+SRUT8k${ zAyolULY{V5JOJRiD99L)rk;IhYgW>*%9JD$nfMygkTV0d?=fVd_-I3Jx)$ANi$ZLJ zVqcSiuWk{Aw2VSf#f`W%m$Xf5A@+JRxeKHvh7~I~kN^eDQ;Ssa5pi|1ADh5N2r35f zn*`v*_gg0cykjq%4)#=}DuB)8Sfkf|>eEbUjB0C67fa1Z^8fB65BX5qn5^bd{*AC=mo@}7 zde>$p$)e3lV0~kom2k>O%H)G1P+7uyvySha@Xf~opH`#k77ylUo<;)bKor|o;oD?& z`@RaFlV0mMhId*37aPJdN3s3eIWRmDzqKNy? z<7c4nh*g;aI_@H#HXa_Q?B-ngKkKQrcr686Sg4 zN{y8$o>YgDREA=Ju$rW*(4Gwep0qz}de9hcWtySbst26a% z*f!7R6zWiyr^)I{6;-P(m9fsJXlEISP4C3Kh{ zX$E$#QU%BL%y3-dM;flN6=q6s1Dv8xc2OxGayXLz?g(Vsjl3Sq#NQ$uKqiW`5`@lq&Huz={zU$BKZ;5+hGw&n-wqO28{=i7YT5 z&_rPh1{Lj1v)=h469V8v8X7<)ap#1j#JtRpk=*I>xn zJ`6mvoH5`o@n-;Z@rO-ghrLMrsTLh;DDlUsKH?4hz+6i4r(0MfN~%!IWd)y@_~TY; zo>8!-g&ksWj~j(oVdM}1j>U#*3IxVBP@C4Fvog)3@iCifD8r^2rXz-JxTF0On0GZO z1|j@p*8iuZR38Mtgy#xH@e^VM2_qefyOdD?Xz99GK!N*k>`h2Ki$-#sQLm+wswDVJ z8M^>x)RGDiAn(QMkI8!y)S#l2?hF#=R@j>w0K5KxhxXUT6E-EsyO%>M!UM(qY|ddM zY;$7#B*arncF3p$@;<{sa4K$V(JmfJrIcQIN&kNn(*!soDI|m@i{*0XDt&hn`?)x! ztQLC~wyKWQkBr2*@w}@r>2#taBU3l%fTskxAGC@6l%=}N_&NnQOy~++i77fuTk<9} zC>ktUdg03}wNz;)H2S(*T6Rp2{?1A*z3wsnavffi?DDB&w+%7Ibk5>svdlCUwtiG^ zx~Ah~Xev@*_(5z)u{N)zHdKhgGFFFT9Yud%DFT2*X&4{W23g#|?uu=<1auTP0%T|z zNDBM_I0H=BK!3y`vKkew6UORlXbA=gXDTy*d z0$uQY0#Twd)XZN2afz2QI1bEmEH&MXnp`(S28#ogGFW0QsBK*r!1e?Hcz=fKu6iWd zQ!J6So65mi98ytq+(mL7C=BVhM6&IPrlA>FLB*m%2B#`vULzpUHNY;mkK=}X9f3fw z(nM~>mk@Jga}-NM8K|E&UsUoys7qIveyOU3#mEA*Sjk#ug1a??NCVT9fCI1<@mC71 zj^yCSh*_o8S0a2~0YlqnX>}5r0Y!7Etx{%kEww^3@9m6NV-3*5-5pFfwQ5yyu@+3D zw&kC8rpse5O)-}=L^C#hAELHx>zR^ZDv7Cyl-EMa5m!#fryEI~y&M2moMW6y`{J6G zPsGDC-(u1f(F3QX@)NdoL?TP}_|q)ly&5eI4Hn?o5wUD3lQ2BwmQV(Su?;C;pW=yi zwp`IEvI1*xFeH4RwT@=Z!^5WBs9>0wdaZcOdiL^-vHNA;bXWL>qq2{i4%wF?2YR^% zC!9|6sr;osL2)`RPY>P@rWj#av|BccI!H3O*E5E22+5NqREo~0-Zdit|y#!3HSdC2q3pFOK* zweak89|a2eat(x>BV-(>e{L z69q`Syt9-72}kMzLp7%(pf=6{RLEPCCo`1En-EYZN}x6js2mPsRg$_+-2y81H2cXR z&slmYby&Nh3#fDsrdHu<2AX;SDC2SCcT`*fVniMx==wbMiH__}X5t^p^fJ`M-fBw{ z#CiPzZN>%@b8NO)2kf7*)aYXtVL~gqEN{!`9{)6wWY84EB}1{N;n{*0Adp>R3LV^E zp8^xYwG3Irq>VJB5ZL}vxFYjRs!Ejmq-uvg6PI+_G8S7Vslu8lkC6;ii1|$r!-K!N)*Gz|8;gH{cVO_=BIa zY|QFw04Gs|jI>QhQf-R`x(86TfFm&Cc2>XvP~Zm;YRwxmDhKI-IhQcNNWN`3D6u%-u8(JhGt4M?yjPNsC0#tuujB(>gL2g4dr$bSmCmV@AdbPnB}L4|S+gld#vsfTCFhfLjd zG5&EeQ(>-9QhK1(-1$Vx1OjR@#ytwWotTMO9UF9)Q-eKiJqFkR9_5Ifxf%E>o8Ku2 zpbaDH+AzB-GeI`La(UGc!UMD)LdcBAD&}DCP*~=j3jd2|geL-s!guacjXG*<}I7s18%D`kG=E-}rFY7&$fX1DT{bVOKiG>CHKrkIA}#IHs~r`W9=#<_hCe14JplEr;^UMq(kKjZ&?pf(;ut_7y&Y+SR>`)R^g-Am4R-H9@>T^Zlv|5c% zJPaRqu7evhxP<;kko6}l^PlO;|CeVC+v!d)XxNJ$(X!&H32F7zgmk4-6Qn5Riw~&qV=Zhyg2k`=SPLB|v*as3)$EI2 z4$DT4UO7R-%UTwbj%SKbnm=0f1Q%L#ADo9zWV1YYh*UP16qXDd&c28e$HN!v@6pi$ zXsolQ9>hMfuxnWU$(Nj}WtWp)6Z3UKcZZ2gtqg6#`30(GoDV7occMS_vOEEmhBhx?FaA6&-^y0#C!Tq{?)I+ zZ71|5ucv5lfGPj{pSNc@KV4eBI{8dAo1gvIyn9{qU-?5yPvt-H zb$(8;jO&m1J(YxyJHKB~8ty1H??jS^UB9KfuSfJN^iM!qGl9!rhMe>844fAe#VfjY zK3{vk3{N|@1DzE=spO8*0j0yKBzCc(fc9vP=JJIf|A~iw3)@_)tw?piX6>HlVQSahkb zto%mKL?2XkCCBgGgsBK(+LZ^Xz41b80M+XGS+tLO97U1hW(|eNRatVgKKuJ~MGa?h zQt0`1fG*9qmj5gr;6l`ox2guc8bFk@R~e!pC3leKC`;r(8@+vZukJH)M(1yZ$q=4dLE zVqoJC3llx7Jmb2VOVw;<8{EPyN;f1IQUU<6whrHgPGn1Anm`jPrY6p^HL5dev>-et zGD%t-t}2z7n>G2bN|k?-|FVhoIqrUb?4aPF;hMVUp$v)_`j0=&7xXRGU-gCDLEwEC zP1yGgo+z98S1Qi?YH@BZ9w2{lsO*f^qs4MQ=$ajrh{->fUdMj!)_1>C zatJ1G=r*t6?%VUv`RKU5%7HO3Wq^KSH7MmqHuJ7ovsYvfUdiOe2zl(m!>$ebY|sZL zOV%#K!P=G4tFbVVeQMx`Zsrf!Xfe+f&&7=8QGfp_!>%VUCWfm~YKgKxI;}_B?a_8X zlktkI#@Y&DUD`!Ibd-TU)R{DY_IKPr^fw3~uOg8}y76V?Q_7hBhd%7WX!Bv4eP$6R zx6hvA3o{+GgRtxrvBk=$WZ2=IV^qq!vb9eir|#9Dyjx%(a!oe)XA*DjEIFHO7zExK zm>Uje+>dGxUz8eaWf*U&Hz1cL%cwcR}QU{@I>F`CrWnX)MYe9JU->(ZvY^(;W@1|JfXC@N#Bpxw<$;d(` zFI|F2tOtP=7?gXC{i(dNO({l{(0aZE)@FOG5j&I^RW1zf5Q}o_d&o*cG)L^?rx#bm zJ~M?ysn6KREakM|q;3WlV32cNY-=L_sYf4wAv%;JN?Wry0UtbcpJ;yhH>JpxCmM56 zzH3i4(Q!9s_zf0yh!A15LmGw#7_Q%SQ0y{I6vZ< zV%Jm#G&y63P7z!PJ(Np~hX4|~0SHYToUC{Q9TmgTaEoeauFiqIbf3)%EW;QAlb1=z zkS0{BBnqU6bs{Y~frmn2?a&FT!^C@+8KN}EONG}v|2iSUT1X}=V+~L>RwR?%Ybqhg zi-DTUCgqG8G6iP%XIe06vXbHuFnU(sYpo4TSOG)pLe6aOt4d926A95Fe zWt!+4VTUFbY7i^noGZxzyJlgaB$HipK!G$1yN;Az8>#Kg6^Ooggwo|(QhM89(uAf# zz0rR}ANo(E#I!+adxmvl&mC3x#0Ht=+xZgbo;Y(&Vn9r?K1(jS=z{+<6buX?NT{P3 zpzCs}J zT`R}kp^b2i3(w^U(h-56y~Uw~EM0s#B1(fGiiM(Q)=g+ae_>j_P=H>blSfkP1_?tj zy$)o1v=-h6tIzi9d8D;#mfxdx5)?&G%#Q$#jQy`i|BMqaRe)N!JqOueFHBP=orq55nMo8E|P zixji2BLYb-eL-5-rAkYOusQ<~jnKPc6lzOyAh{4cy$H}s8t2{Cw6B{NVWKi7cqS}6*|yw zX(6J`u;A@l3naoGTc|u4Fw=@Y+#v8L;b~KS5ISVZyM!fv39HQydorJJo-&CcEv2yF z3LMMQD$=G^q)o?>)>5bvah{Ae)EGvi)mTD4jN8Qh`9o-%AF703MZ}X3lwgI_8)(%MsHV zJ>+Vbzl0Yx7_NGfpKac!C@%n0*Cn%TB~bGLxKZPQIn(6sLr>B>RtzXjdip6*wFoF!ab+V6grS=J8V)W)bsjk25@TVzG9 zn;Z`zh5#9OV@f;^ou?6pDB)(&XKlGc>I(S^7L=w8dQ_;0vm%O$a8`Es*1C2v-lwHK z6E2JYD0mzT6E)2QT@Xp4+E}Y7>cClgAgX6vBAtk`a#P`yR8ziT;1YOnN^>|Ms>CT( zmCYWyKv4%J1Dz*gIF6;Y&f6o1NT+nkABP^A0}wbBQ!8O++jp42veZbaQhH?s`Q6kP zItGP>It0jiQ3ZHI*Fs^dN4k~XtDqJ?V%{InnQ$C~3%;ehM9oIgX;nc0T&Q2dvoA)% z&>{u~(A3xb^S_Pic$&7v8(R{j*zRC^B(IA=3`C^VSV4`+#} z&>0&6cYo_6=oBOP@@NE;D~@2&M=4MwI*K}LN>rmK*i>f13JhDZeT{4U z_s>&R9q*Gd;-A-@`J$e0#FJq?9ImK5Rz9e3Yt3*XAL?T5ut$BvNwGtbsk3ualJiIb z2R24TUy3d7-Bc3TIrb%|S>`Adra_q&+@>!`-d72G$OHbVcsDF?_^vtrCsI6zVuv{( zrNCoB(A|EqpSIM6CJnb?<**EkUvyN3n=8;o#Cj`ev!jGI`&J#o19=s6^T_JZ^u+tRZeB6=EtWI!04$G9yl}36(PfKF1UKNt8eXBIi#%rxN=( zQMQ_tw(_8LE=LEgb3?R^gVwEIxNcr=X@mmP)XMsqLRrWthT^*?2_%631So0;J_0jr zG*Y&t&Vo{lL8pZ;Q3(={s_;nLTT1##`S4_QShcNiMHPU0N^sj3DGzy%Eh>><4vzfE zvIhb!3Lgg3tie@K#TT(Kz}rs&k>y;n7B)h++a$dlbHB4omM+c|m++0RkYn{c!qQjz&# z!Yfc*Kb0^ukd20$LCNvZPWw$o&`S1DjvO7JJ}s>$`4ULL7DOq?A+KwQ(@*X_6v2t0 zw}G$H8NzN#aux{gC=rE4VFi*<0G{CmP$9+&q>BsCov{K+`xP;T8k)J3Z_r1kG$cS@ zoeB+uD&vNLWI<*L=Zf2}w)}O&Or=br9fGwt(a(5mWGB+1)QeLw_xT3|TyZ0vt?j#` z@)X`iei%9khB+VE;k3mu+fi}MHp)rCtI`p#qIe271RvpWb3>8mGo<0rH=7wMrMYvH z@<2!nwoVCy7=uNpa(rt9wDRL$Rj7gZ&2)W7qF9x}H>akx%-SM5AGSwD{Kp=B&>l^N zQfK71Xsp(?$RBF^HCKog*O{vEp9|EJ1AtQ80Qf;1pb zNskOm8>SL1v#5;4K03gkIfxZB`b6w|2BKNADm9N4d^RnCN#1NKf>Jv;JH!Mvk`!4W zwFGWs(n%ZXnrs3S5wxc42N59upI%Q6Y0pFeH;DDwVm+C-qO~G!2iOwlcD2rtEVH$5yhw(Z)Nqg?nbMpb+>f&G*8h- zom#42_pGkUDq+!gwE#yJP$3Jc&-&tQ-BqfewAZv=F1*fb9cDt+Ff{ze2KAt94KzHH z0deP(O7Tf{`ClHpdj{bz=EM(v7XXf~ujSV86$BL0$5a~JQs(1B+9@0&vqu(zJ4DbjSn)-FnLVseF)jzf5aJPOsolIQ$!%~5U9(=q~u z!U2m%O1Bhx5`tI~lJ}DCSTCi|SYS!PraGC_V7s&^c)l;Dq+bd>+lC;!C>WF+e`d&+Dl0Z(eVJjy!5YNB|lqC zR*8J(^2J+cEzcC~NLbc1HJ1R1fQ-c`Wm8uzxyq4^xCSM*+Oq=`&T#aZ#i`UP2dqma z)r+ho`MS1?oGT__p-K7Nl2%Nf9vL9ef_YjTz%<@ zToaBHT96B5#_H}KIb^_38h_U9Kc|p~f-}S*8aD$gQgK9HNjjPLP2 zKl>rwHH}yjh!lXmGK!9IU)OK8>LFbMZ{7KI;@1yhcxXA*$V;xx22_h2N|g#IrwW)7 zKn~#;I(JcpI_rHNA0!UYWuhN+d@*8TQW|u$!^EH#b0{~IWY7mNvq)ER-!z}f4An*n zQoK9(-}S^|0u{`fFwC-J`8ah%pLGJo(jMKIQ25iV9JMHP;0)z~M|&Nu@LQtT3@3zE zlu@EfTONKH+tPA{Qq^7yoyuNM3TGDgT453I^~9_rophWkJyZ~G(tABI)@xzg(q0?M z1!4%j?iIc6E$%hF5>Bz8W;Z+JsRK>d)V+Bd&I2X z81_tn5MYnHcYN8m_`r(j10w;c4ShIHS;`U0!%DnM%QmJcLa=HBKk&88nVt4{fDe+( zkP*L-6zM9O$jV3UwT@tiM`EMPFZdiPy{DMM7b`@Q!gYd?9Nvg zbNBVK7A++DW_bttR^F+F^4-tWh%QLFnL|?-NT?KMi|m1tw41loG80h*(>%41$xieO=l|WvW{4sn%l~Ui)0`N~|C{jqKME*$&kE?0!yaU5 zSF-yWR-kS%G>pD7yU$koH!Qoa=$T^Um;~77OGcY`-&F$RXW0_Gs#ze@;Bk(+q~WI+ z%qb>wokUoKw~1F-y&!Cq!BEjb6f2Jn_a&mLv8@ z+CmAI1EWiJWrbnHRx);eM!xX9^gcoY@P4yo?1U8U^)!&HQ#KIegT&uyh-%o~c%*4rhMoa5`h}G3-rVZ8R$^LzHOnhA)GAzlk7}lqLC5(<)SX zhQwT_4pEie8FiHH=>u4?OguQOqEmF8WoiR8Wx^w3q}o*xBi6CK=8mW!eF2)rK?yW^ zTwDME;|%y~+>+1vQ|iMn$N&K7T2)}#l9;lGkl0eLtP9-V*ZFBrJ<;%szgaSw)FP_E z&1U1xFVlHHEWvOv=9ftWD+3(u-6)iT&QN}2maYgrN%7$sdZQEq(+>qWEmTVK350~| zmI7DQ!a&*tD1>RMi2hMa_!96t-1T{V^f?983TnWQhP+Ld zIV6PJ3D`g{;s8Rrpe;)Ki#q3CDth|2WVR8uSh7^~+~0lk`~2>)FRj$xPB(-ylEF4W zP9hvwyf0~mtA+0(@2A!R<)2#sBa|TcTS<`wD_~;VZT94)Y2p;OF|EirFvu`*0)Hc* z%kj?9hzcwWTlzVA1fUwuDmJ1x%Y6P9xcv9CW1RMjV}Uek3+(Krh>(kLdvOWai241lGk+61X2- zmPUi?X`M&thcZp!J=}B$=Yz|UJat%89FCb?|LcRzxa5-T`t15U<$l{d&4LI0X?|?D zWm+x{{6y%09WMY$$_3P3!}!AUj`Lz(jrm zkL3B1Whf%o#h31VpfYy~kk6*TLX;YBJ zXBWuiTUa;>4xT@oozG>$(u>$Q^ayej`3oqbtF<#Y^Ga3abT4FV=x$pOu>2rfy)7mQ zhh1{BC=}`6Cj7yNFpDVOIGr8KHnIoiu=xIT6yCS|eSgvWg@rg2fH$au){+863vdDz zs4XerZSX27UqwFxBFs9V@)x25`I9HvT;citJ#_xxM%qIG;LOwQvroZnH0(`AHLE^0 z+{^$rPCxi@u;UoR$c_)EjzUM-aZs9@P1)4Z!`UW^h>|G3@hIQ2=}xvKJmLGzN9{>b z=V7CT)?qyyZpz^);Mup;G9mN*=!5ubP7OC7KM6e~`TreWzy_eCZ1b_<)HFvOZJ{Yh z5nkB7xrfEB#a0h#Lm~M?2%F1cp%AgVr%pfggS*N4jdE>g!=t=KOpv=r|HIeQ-NPEj zjlJ;)S#3QVYv+v|FLu6g>KnCCf=cXG@6kG={3X?%LnB+0Gi@&uRd_(?n`5-J0|90_!um3H}BYuMqv`Edu^-+G}XBwd~2BkMk8njysy4L=Y@3eWX5{E1fZyL=hga?F4ds8=Wzvv>p61AMeGWxgfpF0i_GaL@tI z@bEK8nR*A{OFU>R*KNCPlaOc^7V{yY@G)UBEhHv(^CdqA5kfj8u#-QjeF^@tl&7BA z{L)clCbhkQs=>r&Q~jS+3U^Tl7VE4~VQ}emJlI5cHf5I{H*)NmMypAnYeHY^&_<~% zU>khgdq&kq2jFJ51@4X9RNsd9_=_I!NIihZW}DPBMu9NtwE8J|$hx@kaJ8?} z$N1od(Fd+-7Z4w;L1K{d_K58&GLfIgF1-NQb`V&n+0~$W&M?Ad^f#;U9xhwMO~@2I z><>5J3X~b;;cVk=jC^CZ={BG*PQ=7CvW@RV`)3l7fX;N_7cq|aCuCxYOQFpnZDg!A zw6{T&Kc;Pl)^Ya~C==zMEN(GjpVUYEzJLfmHNE}V^!A^mhWN-wk4!)P^Iv?qc655- zQ@?%UsYIlF5^dPfY|v-W1y@d7!EPwp6!m|GjWc3Y^!!ORB`mcs^jx|Hp=L!`RG7DY z*KqnjZN6Ij2DnO1;SrTg(Jj!pk$+O#@>-QAd~e=HHhE3*1@t78TGLiI{) zUJO%hp46sA?Ol+e%ghht?o93tjYE8mi zsLKPAUBw#X`{+HK8*R1HWN47)6dA!YB+cG5KxNA1kA2peq_QA9eQK52`| zmVkju36<-ZYR=~fqtE2XJMSB; zhHL?s&|rXv4HOL<3zBdZ4e{mh1L6Sjn5@TD(qIf3h^?u>MNFW1@a1)dWA5g^RX5M^ zg-X`5i}ZlithAv_CbQT0Nwd}PS=%Xuk1L~0~2T$mB5EALyw+mB+4&4-etMv@J$}G`u>A?6K)O z;SH+g3UBbqFZ)JZ+lT-~R?3DbUibhr>I;@iq}QP#D|UsiLLGA8hlJgYCx;R2mJQG( z-ECG88|+-gtUw{ESj<{soF~j_(RBeuo32kp*_uMLxM_Ha^yGfFW~5UvC9YG{-C5xg zj{K|OjHZC89HPBcSoSMO<2*(h41OT6ca{6L7&3z{OVXdmAR>0>qvV?_C85nFB|$Hi z)-jZf-xu)X4ETK|-9H%e`xwOh7HUdW(*|b`1KKP^%T)48I=D#pkJSf=NHNR7d2oW& zhMTJgy#SHex4BegV6d7&h=)=P6xLs+1&q+%QwC%j$4v)ZTOVMk;el$e!A3b?z$+4t&!Yhh|G^TTg@>@ zbbg_cyM;(_>={?X(>=m$m04SGH7lk-_=UUquOr6BEQu|w)q@1aCS|b7*j5qY0u#FK zGNVuT!E<;tZ^*&OL<(v|)o#$pi@v~&3_+=uS2eL51y5i(j7G@&1j)>dEE4+0nbM=z z0h~la|03ZHaMd`KPp+WXu;3^KlNo^(mDj;)ZZlY5Q`^ARElP(D+tZd{+}S2yo$P|F zukE%jP}HEtV)!Z-V)U_GFR|s^Y0s^4J`$ggMDuasXgU;p}0tUn!7R^U&-u>bF zvH6I>I>1k9&4&|pwq6h7W#;3;vH74+<$O4^6Vc*v!PiR#Z!YJ9+QWRPT3%J>1OGo- zw<({i^4i=0zhIIv1=&Rfo+Eyj;`zWP1V8c83DJBn&*lpNCrEPU9nMw)xQg%<0K<6~r5GHDeKCNSU~u9Xyc|av z2e1^wf}<1|Tyhk*Cd^r2T&0S|aFu1S*n}WJW=H^8;RyyT4!|?FHVxds1vvRmlU>w>S!ql8}WP97T(vuGBNhxyXEjSmfg^i}LEz#u4HzWP2zPu`@$IGj7 zi{Fe?x$!sWP~|4`>Xy=Dz+Kdx71cQbmuj@a-BEmU1YIQn3?{{qv5v9mW3+Dm!A?!< zMu%O(i3|PJ{H8EB3aCXPBD_dj zBQZh`Z4pt=7Yb~X-XwHW*ibn?xUkWuvbNk@HcfTuQ>n&erZ`HivOAP2ANKOZ{;=B3 zNkzWZEM`32r|2y*$}e?n-Lu`Zx^9A1RT%9rpI509{w^m$E!0_rvFf4xU}2 zFK?L>ek&M;S*PCN&oZ?EPrI!4Qb&MmTXb0@b)szT0;L*=0i13S4v{k~tzre&m7QWm zM{cx<9P?NH1S@V`#fqEApT(O#kv~?R-a?+n7Q9hA($nmDvL>6jB7T-7VRE`mpq$B7 zbsCTRRPqct4B7cS#L?b=giTo#YQa5E_yt;9r(%o)$hgEXb=r3 zA)GxPtj0OFpjfF#lQxb;libe@n^_c1!YfvdCT%RENt5e`M4A*$a(5hIAd4n#G6WCN zB>X-8hgTL&+BAwL$@5o!V5#X`_NjwK9lQ zvmg>2hEZA=iHK4zYYqk=y|D}K%qqq*2EqPSqjH|x9tn#gH zA}mpOS2xSMTF#HcKlnki$O1o7_G^^id}IjdKq#P<&GO^r&GU-cVX+{BB18f4yb>Pq zxmKKpTY~wsXvCYQi3N?lw^)!BuvpM0#ex-UgKu3$kx7pN@WngLT+# zE?Dkur7#dc$Tnx~Q^QR}SF%mVhg)`}eV%OjVf05v8wRQ|YP_4KuO~2c3?OYju95cz z1BxmnR#d!Pn5hYT2s06^h2L42$%C`2h~-cz;iR`69bT&6>p*dSwq!hb2eBmHO0-jO z(^2S&S3h`oa7A|MD8{tOV@ySbl^E0Dt<%Vkj47@JnJmO~*)dv+j|{fa|0z{!m3u?> zD6~1{bx&nmjuL$Ght&qI0=8R@4z9LJ2G>~M2Rmr5j9tYH;qojw1MHoZseLH zk9k>%GUmm5+uU+-%*#r7%*%?5VqWd_GJ!+P>$E~x+M_8C{>m512f<%?rhE|ml?z1> zED!$5v!{zX7P!i{=1-OnK6i=-m*n5($68?!E5*&M!$sUIA#RprS7dJ$Hf_zeeGC?f z#UxdMgr2S0)!B~2*)@l=s}3I-zEe=1Qkl)DBJqf^_*J?K!cPw3Uy1Y8a(l*PAr9r` z*pB-abpQ?|he-DT>d&bR+`C+i2F!cEOs7mc5b`Mv$8c%|6E-3=HV?L_zFQzs)dw9A z?4pnbDl3jWm4#Z~0 zqa!@u^gb4D;pj$2!O1{V^=|4mAfqpbmof0crF=MbTgJ7%*m(OK+tnr6HG#`p_3|zrW2zZk}zapz(?eMMH_Uy{ThqJdI9w^GZRaEe{?Ajv) zl(!$rt~`>x^~hk0;K0Yj?b&6w(S<8i=<>tww`EPLb+D1iNYwjP8D0^#bQet28K!b` zw(al$!pOF3dwJ;hFyI8@e5K(Wq1~x$D;v&}H^#;L7_rwW#Vf!y@kk~=2YKz0%+o?V zi)3n2XqEJWE%Ngcp=9`5vrDrpbgS`Ihpe&k{D^|)a2+6jWUzfYvQg?&;KwMpWH1CK z&_~JeOb={liH2uWz6D?nuVfYn5yQDmGHFY8DbNCEs3*Hp6HhoZU(Mea)L9vDLZtjm zaR)kX%r1RD86PODml{++7+oFFFpk`&;1Y2Y)KLXSH)ijgPLJFUnkBvs|L9dcn~;F0 z8^om5BAPc1He#*u)#dNcBDHY2T0^eht}C^0`B)2lA|8DEQ39JZ!sVKyW9?92)DDg4 zmR@@1!pu>FJcsqRD@ff>|_U8YK~p1Vr_S#P9La2dk2Tvfugu#RfLws(27Zg4@? z^SCW~lcENoTwaOWCWL8Eh$%43hz+uHc%U^V+H<*x+Y&*4XYxzNI{3EKJXG`eoc!o>e)uyxC+5T7|xTS^AsOg^I7AQ!!lVm9O)&Byp87V=B2O`KCVO z_hHg4ikPu7HkOYWqaEpZfq?*D#Eh9n?QR--z?j;83B%2T$6P;~glkQBoPSg8v&_}2 zDFVruo3d%teKvjd*bYJCvMRgunmoE}6+vJsYSCppohNYB^2K-Hx^WSFh~>@vB%~-; z=*#I)X%DvkN1;R(R=7XHqJ|iMq_)cjlr>(Lb628)>IRx`cy`y;kZ3``NP1!fu?pW-RuyHM`}C!l|o7X&P`$ryXrTgp=Ji zAgW}by!2#{lZ7;Xl$fE5=OB$wmk)w8K1~qOO9W~BZGwm{YbS8CDgS1uaWOuvxzVyD ze!_ft*BNT)F_ylZY;C#j8)B)z2d9NlTi{llI)n-f6B_H;01wz7u2V4(wRDw8K2BNm ziny3(Ai^Bg&de4S_x`9aU?a7IF6O&v-^llEd>5^%?*a>|1tNlqIPryo<+|e($2Ht{ z%$H}|&j`|XL|II_UgS~2@|ZF-34dzytfT-5g(5^~6U;b@$Iw{_9*RxT;bq_0vYln# z1iunAB>ZY?_-zRRs06XNpOq+#p=BXLaI0vuY>;4-Gnv6gPzX8W3v3i3)bu1_dblXP zbpV7w7DOnTI1vLiCg+)CNSsB{CO#s-Vtay}6K`Pl@sHC#A3Zh(HK1;HcVzF zNlTXKrHJmu!pMi~#>StrWc5l(koK$EJkz4cmsCpr0V~+VQOY_g`E4yZuqg2l7=NJN z6S4T)6t7^<&1?{Q7?;u8)F@p zLae5OTY5N`MQ)`aB12qUv|9)wDdJ(gOrg3hYohC6~{xKuYi;Qb6f~$wX zG|v^d)^EhWq0RW0!WA+EqKe=)s}WoWEUZv~wFs^Q7IYg2ERZVzi(DT87B(-yo;LsWt+vjlZ6qrw2+AS}f$p0ZU&L_Zk5kPUO`ldUGS_)X>xc%?kmC* z1?M&48B(rBh-&ckl&f>YlfI0@vx2A>FAGmY)Nyz+g(u{}M(G2dcEBI$U*Z@RqFqY& z0V_*|1qMLYp)duQl5_eRFs=D=;&T%}%FyeBX~3Xy92M~!t&d<@6OR7Ph~E|QYG77; z+t|<|24Hv!1{+*aA%JV!9WU*SUArf+3M~dBHj7rmiI`arsF}jpr6`}AOK(IgF>o&f zc=Vc4ybGOCI?!S>!L?OPVlxx8`FfYeCuAlNis$%bX-K}dJsLO@A-*A`pAgayy~Y8P zzSL59ORyBq+dte;GHBAAgdG5Gv5 zb!+vq#KBP0>RSaTQKSW79;_a2O0AyiZNeZ4)9N{0l)tM;KM&IrEnzSPLCC%^G7v$O zk^#yUx*aUIOoE-z8?ZO!RO z`+6-UA9JWsxJO!)X_5FJ>Suvpk|&m_q%g5buPlyHIT`ZeJuH^%?xED}(rTL4UEh_Vs` zz-(6zb_!!}XY-Ju_*ayF3~oCvrG^B8z}li8ZJQy~$vLeihDhLi@Dmk~vV`jxdfOU} zk`~xKR+crYls)#NNa2V3@mEj*2BeY?T6PF2bJVx=gshF^P%1F5+J2^OEnlrga7n&h zV$gj6h&|@Z)h$T!L`jkqma%Yt#wm0yevr5|emK)aT=qm;4px{R#quZhk@5{7x(Xe0 z9qx?AN&Ozt_|nXT)Q*NAwL!dGjgWn^CCS))iKwnTu(#^J+q7%x?J(z*K(Epecvb^m z{FuMj!^XVD-KcP~=N%|aoUuZJBn%<>9sKbAc7DhOph~5`+)7@(`FA}dASK{$838C2 zNww$jki^dqC^7;RJRZ~#8d1umY7MJS%&eW%k(t1Hj_-A3rlJORWM-J++H_y>l-hLd zIBEwP1n`U0Dj)eVmkD>vA9HD~P!vE!wpx}4MTa{Zw9TYB5P6%w`Tk*Yh_vfdT(e>D zn>mO~=fPkQ9#w=pl9e@m{Z9_lk7wx-E~6ju0?#EjPOHcUh}S!eIAmNQPcBA`_+g@i zxwQd5s1hCp+NOpp@a{xm)%!KkFbnb`nR(6O=`Iw4CLt0@ntdWIl zADfJWwI{Rz+khV}X$E<%W}?oAV-n23sv^ivCBj4_VWk*Q(iV2h>Ew5{~x z3*Kq-3pph3Ae z2}=lw2~3xrqfLcpG;9$Ffux;Zs3rBIsWyFN^?z$aGV_FX9TTy=uh@t`ZDPYh1hy#lm{0%8Ru4O#RfS=|kk5adkYaJ)|%kWwT^q$TOBj z#nW2C;-3s^$*%nR{2M^zqr>{iS@!lDzIXkwT|l}Gq^IQ=Hs~Jnj{rP}+3^Huho-aI zF%uA8z{?-wB}@;^EwjmHs|%n$P0U)~9z$oGz+-KEgZwi1V?Eua>BwqF=q|W$WJm=+ zVu)C$+n6BDhj3%0O1w!mowe!fkJ00pe&8_RmpW_uk*s3W-kSy3S3>|1aKidIQSEX7 zg#S-R3huK{fHG8A-6n)#o16W%^%xI?I`ljf=WnUoG5DnT3DiDH;_U zBm|PSt=l4i80i>3ktl>Be4|-*o&pu=FIXtbW*wzY0s{Hu>S9M1QJ$y?0&j`H@x&!m z4?x(hn(C;hnMdyygg8o;M%OBwl&YvUcvU{6;$A$3@(_sD9^sU10;bPBWLulJqux>X zh4(rb68bfw7u2kFC~pwcQL|J{5-(F4&#o_uO0_Q+pW>_0?2>wEV-%$o+>3_77^;wjH>4@16tO_U@Ux>)vg1Gk4v6XnyXa+YZg`-FElEeKS9H#ooC+^D~F8 zxclC%*L>*89sAz;);sUqbLG|Bw_o|8ZHH#&_RV}?|Dk&iZoTq~?N?lR)pq-C-^>+r zhoY&dAN|89icZvE5&RbSKga#1%Ki2viq=-{H*mkca=(%LUgiGH+-H^h{}@NnWtIEA zygxt6AN~m-QRiLMCU&ZuPfhBsQz`m2ieA9|-wham4sf_C?nigf#=Bcl^frEr`|G*i zRk`mqqUb#C?-<^3#~pXx@u52o-Z6K_{Iay>l}@hfMsoJ^S{2 zgx^EkW)9we&y40%6BI?y(>G1gTlqJ^zxla62M>K{W)2KFcyQ*x2kzcCfA0tO?Atdt zbLh~Xd+xpe;QajE_sraT|NK2O_uPAE=HR{$d}Pnw*_ru$d*=7-J;0L>gfGFKeKUvV z56#?n|IER?Gk1bwv-x`48MlGlzEW z+dkxoht?#w=Uli{@Oga?a z462qLcAYY)M$pj08p9j=y(;|VI3`rYk)81S^S*L0W8?Ucup_$s9z+<`4ey`M>-`Q84^rZbv;H4Jke7>)2d?Ee04FjNM|Bz)&$VX(Eh|VsL00Cg@E< z`Y+OgqOkZpNC9;*7LyCh3Et<4B_|Hj9hhE>Fg+qXFPX<@#uA}nnSk(e5XKvlW5lph zSnNnT3QKffOFD^k7Q)aV44cEJvtr|7uqlBVPV$83;7!tm2_DU31U+I9O&dg?hp+>~ z-xx%j4hsKO=r0LZn7&D{l3`1e6kO3cI2mx7;80w&?x4;9t8xhR z7nlw#Ed}gEE+bA;D}>Hr(-~}fh$EL9LQi1C2$+BI8kk9FHid~Dzry=y8crr@LE7cu z)W8w+Az16|2him}I}D(YVE(qXxv)|yLcOtKsyQkd>TQ!qw#U~%LMkXBZE(QdU`>abR2Q5cIDL}s zV-#q$Gzw(^jzM=|@#0|4?|=Q+R88kH`2sE*+7em~>)XKUK$|eb_{{K_8wNG_#zFp{p^^jRUljfQgo^(Sx6Q5alBr6Dmcv18t20UVxgmGX!!J`=UMg0N$L3+u=ZkAo5mQyoxbQYVB}hp-Gf!F~x#Vu!de zw1EAw%&L-qQ5G!D9}DCJ;nA=braWMA{A1W82#d-i3`;OL{RJ@~nuJ8!`FmJsJKNv+ zKRo%q7!42}O)J8*eGvbOuaEu74{RIKsNc#xXt^GgIHao&;n5T(Odl`LfaMyG(f{^C zApC&xKzOW3z)};D2FD)_nJLOgv` zFA(4K4fT!mjrC3RP4&(6&Gjt|^bHIQ3=ND7j15c-ObyHo%nd9I^$iUS4GoP9jSWo< zO%2Tq%?&L;;xI5WG%_+WHZm~+Aq3O`2mv`fhrG63A8N_V}p?p25e;*lSDFwFhqPaxc6d)abRNi6oi5(1rY{v3+CWI z9hMg^D-3*`@d+P<4=51$;PW<`yDh*8eH}nv^=73oiMIn&hJXkGlHqQ`hGu*WE0)E|%or47jgiKQ`|M7YI%==o%D z4y*)LIMXh9HY{4mgQ&9=+`~i(v5sfUh6#BkV}FwS9y=;NuV>i<-n?KvuIrXh&Hg&vD4pae${b z=Gk8^Gd%F#-9%BQL56+AbjYxeaDoi`2xmA)u#a$o-1>+aP_aEkYOYYRKEe$u)(2rnNX5(bv;6vJ;KXxpvlR!_09>QmVScOL-IvUbm*+xc!Y7pyPb_{-46vQBg z3&@+(U~**eg%7-0k)S^jaGAe7#fR>1kA#Cd8HN=jRv6h6@ie~ptmlMM7O*jK7nO)8 zPY~RDGFXTqcZ`Q|%i<>^?>_&za4$>(ipfMn1LHggRB*b%K*G?M4Jr}_j1I`$7SnU# zOoSV#dVq^!hr>J$PhyfmE@RR$O%R>Wp@U2i8402}EZMgr54E+L0YcgAo;1!pk?dJ2F)6SQtDS*SXvTX(BBAxvn<90PY7lI4rNCRN;r=n%Hcf5-2V+qdVPi8mGlHnDCr5BP|_1Lp`<5hLP<~1gp!`1 z2_-#23zhVFhhgS=G6cxro3B5e(ynjD4;1|3(u}lFE zqzyU}VUQF+PmE%+=`g6n1Tnx;fk+u@YD~wQ=AU**Ozwg1Z)m8C%e1in2Ff_pA;zeZ zNr)fx2M4;#KH3xR(faDg45PDnbX3%Eq|S#bBtY>Jm@&zuLWrvbVgBx#Wl0BZJ;XtZ zjsHTGU=NT<3~ACQ$OrL!BGAzkg=Iu+*}rIRK?JB|u$n@6B0lN|Xzfk|Cj$=kmvnGK z)|Bq+GtHa`n*q-?!2QFz{ab;%L2aAz12bx-b6w(l&%^=be$OElhNPtIe`8&f$B6Wd3;zQAokWtVoH(2mg z7=zCrXzoBi5fFK52r(%GM4mok0f<(JFhM~Vf+Ls+T!8GS37L`bCuGL+M6!!O#_A&$ zLxz3C63DQRSPB{T5z9c9L&P&o8eR_B+{Lq+(T+5UHfkyb)GBB^UA zxGZo3=~cpKnPbT$dw@E?c48dT?SLQ#+qpcxB^`zjOkriw-v) z_S%IbMk7^@V?6T**!cvL7D+F9*O5NRcW&IEtNr*Od$ z>v#^_|3&&B-eS94SmI?6R~^DCfkO(qf%Jf0f#yI^7GM#Di#e<<5SKO}jyc>T#VL`7 zCETMo`8!ge50-#;hG3kwwDiXI%<fC+dyM0zMK)V_aFF5x!$fbDV!n+a)X z!IcFr;NQmu-~rllhpyq{I@!U?lJ1B0=jpLXSA=GgP^PeJ!+xSS-VT+7J0KU+tGXa4GBtCXv zse##w9s#^3764itF>t65iOiT7qCH{qV895Cf-(Xt%I53R5lc$vM9@L)4*3W<3hX8V z8l8vAgc1p7AvOsqiqI}aD3hPa1iqC48L)MjNq`dsFFL$p*mTD?-mwvll}eZHg-~4( zG*O$VCQ1?jTS$q9l_r!4IxQ9|0~BRojdbZg96D?{^IL{32q0hX5J|qq@-UVS_ zLURk6Z_p2|K*;5SL%P7V;MRd7!m7cXg=Ss^9t+0U2h`k{{J;!{*~@AozPhm3anOVK z92f+sOQ4$m76l{V)p6LcvjPa3foY^d8fgCdt272i!_tWo#4^~wr*T184&iRE4~K(w z&AyHw#fXbzvf<^SHiJI~^!P~B<5Ac1bJJ~y_-Otk>OBG4i#mX|2O6zNguk=UACt@A zMTIkAYhJ*H!2!O3WZ}Qg}Lz+I5$bcd4PkWm%Z6R-ushTk*cKPUMb z4C2Vn!W9OnFf0h_eW*k%DCrLPqk0nIhgT?XjbVj*KfHE>~2{0#Jj+DuZilha1|f$otO;OPvT+{=n0Ta1Uqp!JK9f&Glkkb zLBF^|q(UP7gtDXlCTW1TowD$%4OhfHn!^>?{gC*p=!fdGK)Dc?|F=@WOZdMLbZ~AkUJdb8>0c${&hds< z0dE@<4E}ydJhwjd73nDCW$|z7M&yO|+%TZspSE^?sKI%t8j&%`$iIp$Tn+wpkUmlR zZ@kh0g10dA;9`+VpT~7+MUShw(ueYl}S=GUo`RDx3;|-N3ip z2c+ZC~t1ktVsj>NA`&pPm9vCkMwj4}4ZqG5Gq;U)$a8^*G{yCut?*Dq{|4+8` z|JC;WfOL!De$Wp7fNY345g;-q_?X5Z2l(UPmLp=lfVB&tRG298JF|hk1cFz_)P8yp+!8!sRo5ZZm`Fqf z&AKr7AoL_Bn)K5YUo&6At_#wP2m@k6gt%uX2=B1k;5Z8e)+7=oK&nD|0JK#2gqXHa zB*+6vS;!$tVzM!rwJ=du26sWj0Zs}`NqX^yYG|LKmx?;DtZZl(4W z@(6@?YX}b0?EEv6MO^p(`vw`dn-qy4gvhW=zy+u~Q!gB2G;!@>xCI%*Cm`t+@s2>+RIZ!mzK4)w+T8E?h#Kpke)Pvwt;)40kj?5qxVCEM>HKh`=1|6h_l89O_>$G z+l=;IP+uU{YF=_|C?^I0ZJdY*q!mTuN7)+Z@h8C*g*Aq&$bdMw)(ThsBKgV_{E=)* zq#46NI6XY!IPgQV&R?Y!2WvLW)+}~}4mfv)`#+w%U?l)sJDBgeY^Zr9iFTy35e>Tic@uIhzTjc_#{-yJP!Pg?NU zEcv{xJ*lX9slRc8J*n0`GWOg7dy@5}^(6CaD~fb?|)G*4R#);js3uo7j!6 z1rDEGo?ITHQ|VB#)9TUzv zj%j-S?Xkfp$Cs;$ECQxzP17h7&wRH!c$z$WSY_q$b<+y#rl~*OT{}%QwfSX1!>?(J z+%9t&c1F{m(vxrWP@|?RvHb0i%Ws`tUMx59_VruSRa^=`EnhU;Y1f?d@3q3LojMe0 zX5WIiPK=_*7m~VnJ0;gDd~Q7az{xf3M!=2W_neX%M|v*n3#$# zm+N&hnaiJO%&`5TIPZnx>>2y4J=+XCb7x4qwa=aseqn}x$d>nRX+1Myj}K)RKhSe^ z_*m24{vym(w(O(I-1d#GN`-N|1S&UN*DxZMv$&#e-91xZhg3PuZi*?jH?>YTxoz8MIgMX3$~}Br`+?dlJ9q2L4;!m=6Wt{()~{lHD{;^j z&kVf@_s8Y?dIo>*n)&X>N>8ONrt4%Mo%IZL82WXyY`5op-(g2Z0w>Ol^*v8{k`ywt zcA~MLVt(Gt6q9oYT2Ix@j5#-}UP6xKb@{#SnQSFvFN=d!v0QbQ*X01M5u>BGd8ss? zV7}OX+e^b;vwBCCxOXYz!@*Str+7=I`M;6Z;dy(^DeVmUy2m^0NOP#*^FwddxXVE! zs;EBWTrDcIqNe-kZd<;LJLywZOdX_KsN-jf*a|)HcsDv2{wKe3uG1r>XPm zvU&Zz|k(I=IA?LUteU%n3H0Gj7GzlY;y` zABnmBG7gGuU+?tTdS1|lgF!ka5k)})TBW)Ff;&M}Mw?h{(TKSRQr$EhhT6<+ydR?D zJB&Z~D)mItezARXGyFT`e4Se79@^lkYqDB8IPg?^@}fAWVD76Rg&nKXgC`uZeD_TL zNbvjM5z(y=JA&UFt9SIjs}l0bYg?AzF0YXC3Cnd$+?T`X(6sbdKOHh8KVV6M$%l~h zKRDy=)Qo3*`d+WQf;Weels5IWN$na&6-+noswwY^w)iWPs8NF?Vj+%Y<^!KHa zccaQ(N>d`wjbt5iFDZF^+=ewfw5dsABVgXL{XBqRvcbe%KzdJH-QQrY?57ZGgh)@Wli}Q zF?J4D$4GVmWcH@WAFW<4@$8I+-}5^Pcd=U;-_phmz0cN8JM}iNjm$|XjGkzzTBYQ#IHm2s}h#a`P`*v`qAQ@h~QdBwOJ7HJK>G|xEu%tD7(^d)gV`_Idc z*E$jRBG0&h!+RG;c}O}pZtvK5KN(vCy|uIAqXX9btU8(<|FkLPk+I?V_y?;MQ0|IPc`NGJ`P>5r-(JmkxyF?UPUWq3AHutq5ZIvKX3AUW z!yS5ha}2M6e_8$L<6_=WujB(yXEpMc?e^cG{7!-|Q~UX0yug;Pkiz%9eoMgLy7A`A zh0_o4!+L8B%O#)it*Ut$4?ScB5{Eon@9c09M8>X_VD4TZI4hp${_94C;QbYuwx6Oe z1&zO4OW_kz39F_Q%~JLDNzikzefunOMZ!r&%DmQd)d{j`tF}+N_c391p5xKNs6575@(WnD@o+@oU3+9!;=>o@iU~`tdb3i_UgHg;wD?yuARIscXzT|O5(`N z#t)L?N>)bvD59jS^4D1~dBn67PN{jw%B=Y*%$TvMre@_S8Pm0uhAw@UGB@DM7{}+d z`S9>%7(1=_fH?BAZ=!fjA~>eG~-n=`as zY2v7is(XvrGcD~hv~tH@c~+Z{VZ<-7Qk!3rQB?bC>Bp;2GX5d2_!me>CPL8ypXlf@ z4e2Og`=8jgVbEhh)A}dRVFx619v}z)#7nqM^k+WU24kOAHpDWd|6Uu8W8l(5g8uj@ zt^W~bP}3J@P-^NSgl>olCNuq3>7Ydk1*rl14`2*TZwxxV$Ud`m0c_=??Jn#erp&~) zPe6V`!T>1G012TvM*!x$`a0-hFii`#RY5}dLu27gJ_2iC`}LsWfn7OF%|#RqD|7!Q z9i~miRaAiZz>5fb`SAjPW$*yS43Lt6sYQSe3{VT2k)UG+p$fIwBt0ZyX#rRPKpOyM zK{_&?0A46MHwUy&fZIr-;|&7)5Ud#F56}$QEAFF+O7i+oa{x>wz%U{PM24MX0k+`@ zJpv8~0Nr{RlZjB5P((ef-q7L z<_cVq*)9=Q*j%Jecs_c7Kh`v;D%k77&4k5W@x3brxQaknwjd^ka? zmw*&DguesOlLydqfF77$9MDKnNQ7qtjXDWIe;38+|1O5Mw-;@l4*_Glp`gwegKbuE zXqDgd90`L$6537*2Ep$>e~k)&fWkOotOAY)GD@5KD8@u|fl-KU%{!WKZZT`?i%k*f9*kyZsTdTz?{kH66+2OmXYBNQ2o*&L@ z9N#ISOW8SMX8ppbgN?_kPB-0aO;vhnxo5laoA-}`*M}!R$@nRIvUX|b=dKAEijXtUF-4gk7EjC{W`WD z5~Z4%7>vHww3IdJ)QaZ(!?%=sa%WF%YBd|PV#A$j)4HYPzww-|IzA8XC^}$&>t+y_ z8nkRwij{T5F5{A0M?LBmtCVkT$_vX^of$ONZmnc-q5QcS$qyH`rnjVd6iAJ%cuI{b z2@JitF?`~NXLIGrbPHAQuC|4H9v^+{F!M0g=7^5MzVRN{z1-H$nztu=@1`1mY1^IY zWyj`wPT1d^*3#YZLDkrkc{aFix7SJO`hyp2Y7}yJzue?{=ap35XsZvVo3BeR7)d!_ z>YZF}s~F;W=5v`^q&R;_)&re$k<*Xt{xx^DqF0fY38zfMc-gj^SHEUB$=p|boBJU^ zC3kB^)Cy*!1vyx&tU~4dch`KwJ$vtt{j7MnDj=xbWP^1{pjuVpiwiQEp-<8#%sr6r z=j{4@?eZ<;QCp(wn(GdH=#onLdTiHv+7$UJ%ar0%fwQ@~I_s7=$ksc4*R7>pIdm{P zYo*;5QHtY;wdK3NJUHyqp0t0b@zYhU<6YNr0E95-Icj zt=gJ84!o?PkSE><30O4u!zI)4yG!;DJ*s$e*MjL$3f<8cXTI|D-Lghz!xEC%o8*aO zZ|+fVeVE24`wchV@g(Qr&4rRT4L1Dnra8uZ?xgYB_ZVC6`Q-3(wCq;DuikB%D&9f) zUP1Hn?~z0OSDz5Q&v>Q#!E-&ix|`PNxbyN2C-+mc0$U#LX0DN?M=y@KcRN0;wC#z! znyM}38f9Cl<}&4NPD4dMhKCg>N!(XB;~ic0Ol*ruj>-#Jx$Uyk>qoEn_%hmM4Y!?s zfMRwkKFRg|affO9m6pVcI4TE+ox9X1ds%dtue0cx&0FLYUtEiJd}MBFmN=aC>!3XK zoUPon?P2HqX3gSC<(Gd@z8-nt=0atW)@14Kcxtw${I1u&w%6s1GZ+tY&q*~eqq3*_ znWSmZnL{pjM76KlsWQ$Y>5IO~f|nvOC+I3oN9C7%)9(3Lw&|qtScaQ?$ychym+6|` z?sI~D%%fyKl+0Gu)xLc~Ad!|~AL8v0xY9{s*4PJ^zueW|bVG5UY3k%y>G8LExT{uF zWFO9vdfziiR_(a0ZqAP36SZZ~rCB6~azln8^a!mQlkuUdUPF-9nk}31Hl)tv@ z;+&pCWbF};qISPYb@q9=fRm?rgr;$)-TS!z6-%=3=IR9c9NEPQD)u4ClS6s?5BAPo zAV=AHy7p#7_oOYy$>oOiM*d0};jy+}7fz*xjQW(leNL7-V~K;rd))BopXa`_iaCG-;FN4FDW~U zMD5&cGf()hKlzbtctH8Z^C3}9*DM&xi9c#=0^iB`cnzT^$1^%~dg`LC$p%oDd2ZR1 zT^Y42H86oM>ldhUYq!gjDQoC6f689`{Lmp)UP^5{t=GnF&lLx=wdD4x{1@$2K#wY`cI7CEnvTfyB&JN|Gyvx|R3dW#^FHhPKR%PPGo z;vLJEs>#nSn$I;|6FhSKMzPo1%oJPO6*mNawNbpgWZJN<3~d?Lm(vd%x3B zEF%Xr@1tyg8myHwO@DNbX*?}O`sAL4%15epMSpB=o;yKSZ{PaYo1bci&RmgG`gq1` zvb^Bk<1gk?TRNp&4{a`yR!W{2KwGENT;|Pf9M|TzPgd7=y3^=0$*Uindvt7}qYowZ zq(n>lh8)?v!u(Y?#H*C@^%`Y*DZ3LB%32$_vAS}}s~*|+?wQ%M=Hua{?$c)|*`+^k z{hF#=qx|~VZ1u2k<>r;)c7{e}BJy3qvXzxbVQ?-k$gT+xDG7M~F!#bF>JCwhVELh+ zub0&9_(8ivRaso9<66R+%ROD7e8tJ$PQLKz%ElEw3f({3UgzPiysK&faVu}Q`S&PX{&YHR=EKH}l#j(zr<8n?mUydI*QtA^_x$lf!=K4t z)EYHD7SXE>B22%@)%?7?RxwFs4vlto!tuG^4~W#q2xLOqQ|BKX;k{0w?o{OVt|0QJ zqP&Y`cCS=F@$;t6>(HY;d7dzI!jKiu=1hEOn5p(rrsLJ5ElaN#9V>fVrdgCxLvC(u zWpG?X0xDeG`9@b8Xr->tJI39;_E>BCl-!&~p6vU^nagG-#=E_(sK3We(xPcG)rzB^|YJn16dQ7XgVbza-hbtuK?ffFUz^+5VUb8mrpbInR> z9b!7HUirlxl}@ew2O={%tlhpgh|4d3C{I5*#_xpTiSVW#UMzLj`c)B=SYvBmp0oT= z^LoCD%A-cr6;+F_pEM2)9OA!0UO}OC#_&*+T|Yiow272Fq6T~nPi`*EoSgT5xtXc7 zf$Ed)#h0hK#Qu0NTkO&ry9o-kNupxg*#7$Rhqm6_Q{W|?`{<@secCwMI0Xac-D_W} z+C1B%Z}m&X=~(jYr%U#pR3Ob|-OjFEJyA*-i6>3RFrj!`W$+Dd%ElmcsJ$K_ey3TT_i?b@SA z;a_XnyCk!7dvddBFURiO^rGi>*0CM&HjI`jvL}^2pH$`Tv+7y&X%kJhmpqAaq~Jo8 z;Bxj&`uU)f21+YvT5|K&U$`Y9)e%)5dQP@@eibD%vEe>virVrCiy|onYlD<+suyTK z58F6pYD2Sl<=a-!DYn35mI}AbH74cGpzu#Gc_&%Z*c>ZSKBJ zoMO=1{eC58&cTerkYFX%eDu8Fl&Sd+NIJt+|E1&xUv} ze6A8BDdUkf+qFgRk;;v|n_tPV+_7)h_W3&wCZ(6}qPM9_?;Eyn`@G;=X%q4*w{JGx zs_Ju-z9=)}e!g1C7kAmU=?aN^7F-vLNKJMfd#U*$f1~t!36b`ZaXLAr(K{w=@R_YP zyOHF%JwQY9%)3gpB(kictmEc;3uRQ|etr0IxaS^OCUM?;nF4$Hv%dl_Y3j}&MgCyF z_RWQ1AFf`}9x0VJ>5yVgq12fMv%ry@)5Y;u)K|$|e>$a}*W)C+`kWKH|~tlD*=tMR-M& zyqh(>Ec`_7TiX4AoyVn?jvYTe=HtRPqeK+ zOU(EFdMlo%^d;c#VXZ^u`KQ+{+c<7GSx$R?Vt3WJ?2`NkTcuTFc2lG;&QhN=A}ys_ z=hyMNWNYPwd8O{}iheS#`qzgP=jF>?e0y3VfcC3ng!G6Gw}(`!W%&=sz@V_*50*$Z zANu}MxpuXF^dT4JrDY9Mq(6qL%in1lf9eDKX~X!IdO=O+Lh7q^*b_6x=mWjRHaGbsGGf3QBscigNg?`*SNGwuRIjJH)2A@?2s{x;zj%G)wWl^ zJMn6%p{!elTSdW1j-vafRg4ukv-ex)?)=;q8XzP2q>)y*-eDvhe_6Yni3D;;-shMwL>3dMNlsQuZ-9kL^? zQ4goT@=&@kD*o-1AhiRrBS&i*uDB<=W#{TFro7@Qe{o5==A9Huo@FZ4>cc1PfKiXH z-aGL{$$tHY`#(ON?|N)~B<{)OU^!6=RW3isbT+NNd;CI+=aiwH%3T^i{Bm<2sY{sT z>`-oa{dARze(Sy6GZt+Rn)*VnW$a?>@_>vdueM)zFE{j|&ap7ptE{PyO1_!a?!LrZ z<*80cb&yG;cix_GPp)W!ymHoaX8FXVeF?9R?#{k(f%?s%iBq|M{OI@6Sxsq&hpUFp zYptHB?lpCSJ*OmGQ%u1buUL(7@bv}ymQ3z z&&BfsmW)>CeXiN0u;J+Nn6DjgOHJ=pbgwZvDDCGj`S|11bZ3q3D)q(cX=;uojjo@2 z!|%MvUEdkisjql*MUwT`-o^HBc@A&9=@Vr5#q07fT`j!vK1cNZXg4*o*N_wAc1~wx zC?6TtnQ^dQakRa_3n zC6@$ArIypAq8O)X_hXhnh`zgKhwP#7Yp$oohB>d?_VnGuJsy;D%eIu-k>Y#pd(EHg z?LMsZNw@R6#dZsCR_{91k4rS=fV9BdBJ7pzQ zvJ^j0C^#|q`(xHAz9+>>zAscmIpC3dt)BFI5;cT^XjHF>7DDNMllbD>}y}`L`#{Yr?%MPjrFlJ zN2(Ub7ae4jeNZsnveH1?@UyPzx#wp(0=lKU7>SFdRZh3BC}_%``uVNeYaJ@>kDu6_5Y zXA3UA(WJRNnk(Wz_nFCsohp$-v);(uEmsgJNk4XhrIPN|Aby6desp$0a{jpD(R%vF zj_j$UEu1Us%qThLc5l|luQh6H*@77k!xxUd)KvPod!5O14a%gF+fxdLSqC^9`z=$q zW-Faq@t|II>(9rr=PAP$U3o7XR{WGhQTTO4gJo-0FgcrYv*1=nWkA@n;R2I!7ca^w zOFfk`S|jt~=B?Z>o@QH<w()>7gMo)SkmlZ`7i@mhbsje&i&0&hQJC(1p?ex~i zV#Q}S`q%9Fxl<}v{`r*|ZnqYYrY9G?zT&y-9(B7zvXjbnQgimjQip}&TB?g0bYkV3 zjijgE^xv}iHeKQRZVip(X`lBp_msHECb&tb?X)b)wm!}0>`F<@^lMWM_gw#cia~hL zs$<_Ticu>Sj_uz6s($rRmpJVWH>0I4Nc->HPnDL_pwOmwbyDSv)LLJ>m3rW?xJ4%B zqqkkFtKxz&)y=6}hP2s_)v}Muu$D1eXqfUdEy~?g8Q5q;1M>0fp1JGmY+O!XIx$0Q zW~bsMi9Nd$?-+?2+`7zJ-f}`Fdc z?U!Ege=+|<=<4Ct`6p$U_m~Wwm%O|#yKuC~)&s zeqq?EnSDp>UY(p&nsYqwDLv;fy*Xi+%w%e+?&w8JhZUs1ycY0&viBsFD`$3zY&APn z|F&uRC%p&0^2HmM7|-aLHKMvC=KLzT15}djwmWDu5$v=NVK*|MYsGF9Nw(L~%@7+k zz=L9Unec(1x7gi01(NMgbSJuCi7Lr<^<8w^Kn4FT*zJ-gd6I1@cFVk`Lb5%DZifN_ z6f(Su-2(~~f;_fB-v<-u;V&NCGG>C@d@Kr2)Zf58rRUF2Oj0{K>6ThoR;BZ!Ca7$uzpEyvx6N9y? z09iE0!l(Yra}3^!!q*;|u63p|1cSLEka$(mrXxB}lQ6g|97kirA8M2PWAzLi_6k_? zHN!kB=EvjkR|vneTP(b|WfTsBRVFQ17O>>e&b_sP7#x;DqIYt}$z8uy#l>K;vLwy6 z`hx`vm$QWMSW-ajR5y|GPsN)sm@LKSkW)^P?ZfzyI9yhie4lnie65evC>%CRds*AX zalHRYQyhoSk~O}+u9u@48m+vB!DwaPSahZrZunLG+6IHu(u_4`-Wa3W`(@o;3|33F zjU8vd|JkqZ<5Ub@E3>xt?QNND=|+(_%vSMe%1iN&=oINVn4@T#?rPOmMCoN(B! z^dr45ezW&D*UrY_w+fBlD_-kU=A@L(V5ByYpUz z#IahR`i-tw0xPMu%8EeMDEQj)cpod+ty zhgZsCuwS_*UV2;O6KiL69R8~mA)ezlzVuRT_eKl`Oj&T{!(+}Y^EyKu4lGMg)4P|& zUN*mXE(Qyx86P|yDL>4(G#G~mlg}xZ+6IX&+-Qcwgk=pw6xM#4UYve01%nII)T})2 zf4!=~IT?e&hRG8o#!}5lZ(Uwq#^A#;UDpmYIxN`tuss=r5i1@InItx;YsE-C98OGb zH$QsWBu4w1B@Qc=QMtUs!hU(;f)O~pSh4-Mq__-g{o@%p%vde^=jG&ktWejdC z&FymDEnmf-eq<~LJ66bvd62WEbEaZZ2?jq_y?6daa;U-W(d`l#3|abyak#?CpO>W{ zx?^x;c~QHxM_NBm%*qSJV96?W&Qg;sr|^#zs^IYCwfApU*1FAnCW^z9Jq3d~Q|tsX z4RncupZYl5S$6GO#i1{*iCCYeV6bPUg6}!o%jsjL$>H#4%A#*Z5|5(xHQoP-!JuWw z_K>n=&#$}Yg~Op~M+?p-y$MJ?>y5*r$vbMg8l&P0$~rSJc(jb`#}diKt~C$ZS}~Zk z;%J4}9XB~Wb#JmTxHMT>wS#e~KGEvMTMRZWv+-HTw_|74XYH7W!KW2}srGzj>dt4o z;xKBp;3EYmdw)n?^uXcN(q=`A_D{9)JUSMKRVz3+ja~0CqkTt-F$S+zoixhyH02Qc z`Kz-S%vxHIyI8w%_Q=QMak#a@I{waMS??t`#^JDQ)d#hgyuQeZ2S?!WYpV48qzRSE zS3YM5Vc1QZ{Nmeoq<#v<;n*tU>5a=`pI`f0V1U80srq}fI>kdoz6`ky?MVXHqz9Tkb~6qt+^&rCV=hVeoC`bCR#> z^Q@$IgyAr5%KID7ew~m2wKNXrmV0ZzEq$-l^@CZi7_3`KuyU-2R-KJolO6`|rch&F zZ|8l_rC*zm!MtVtGWTS8T2@A#osGf0X{MD<{#=K6+v73FmT!zlJ&l(!p?V3&tq_Kva#)|b)zn{y?VgMVBs1D88sX(F0-++aIKf;htfUu7;Idzx6R%xvYowY zO*#f2S8I)3x#+C>vtF7IM(#gCXGh%jN7YYeV{meX(ivatC1*71ZH~ua<*KfF^Lsnq zJ_{n@@N#Lj?*YBV^MVCuyD*r!d`Gf=hKu8|wOy}qxVgS-dX9V6;XpYYc22cw4Kh;K z-S$BVho8$!_?w*F-!tu9C=NqciS!$DeB_)}cY|;^I#r}ZD`FJyolAEO21}O{k*}z3 z@HnvL@J9@ut{jrxkl04a+U|kF)G0mX7i0q)b+W>6xVl{8Ba{2@XY|DWkicN;N+S=5 zXeHh_c_9sluT!qc+I{pn|I#D~hq24r6j1di@|lY(ZewtECGld3xtpWZZh7LccCyQg z?C!I6d&HPHyj^z7qz{Ji(ledTT*qMUG`qm2>hUFpZ%lExJDF;Djic|Mv3H39278yu zPd}UWLwnn;XFoCcyP~SctR|Jz9Xk$f#bNNzLv`K81+H2Zh{NG!wtY`7dK-U;^C1y~ z#VamP+2}OSy+GofF9wfS%X1Bm9YV2&Q3e7OuQIo`=KdrN7@q9uB8h4L99TF=xeV zUZ)iXtEc`vfAYzZ10A{QIJ{o|XT`*pq77qACgCu971i?DnHs;0Mdsshdnz+1et)U; zqI37mFxb6Zb;T%I#cOQ_4NEcjz4Dh_%~HLyI%?Z*V=#P*NhNpVWc{AqD>E@TzTBeF zoOGAeW1giiF<8Fxnk|Ys2TQqLB~%QaPx(Cbu^}yBbfiBH)0Z_8+gKfhwCdn z7OhS!{JGf43Wx1enlBt&FZy%m>=`(GUsfuCHs8U@-QZCf2IHsIt?0VC|5?MMl?O36 zKY4PA_5xY8r5ki`Sig)*liA~zi19y;cVX~;TK04Gt4^eiTX;CkpKMq(sdqN%*AlW2 z?ms2-^O^Vs*1KhJ*uSFt#0uT)$5(IM<6`iCwYbgt4`)d}9#cCUGXszwbuLwgGkVs< zsu7qufP&}yf_pB~Z!0u~W&yVnL~5n3%EWKd!^{Jum)#Lbq4ow`%fQV96!tnVQfNvq zI~$Cf3#g7@&*V(=U^mal%?6~i>c&YZJY8{}hMNz_zn%PU)T2P{MGV}GKt-^$vUc8y z!1t-RIRW+7^R|?Wdk*V7xQLk*$S*4@xOa4>nuRxRUZCRRAmT(_cSJN#9Wyhavet{V zG$s}ewZP2{bXq>_EB7YG%u}pe-G!d^V4y&22t0j)tqORNvgPc16ee0%EGws~Xb4vGmCdXH7aZ!cQjiJ3j9)itP;P@kPI_rc8{q<=V!^Y?#b z{AiyqW(J`!dBa=nH?lRpGPpT}>N6Ets|vSGm9N_{vk2+AOxlbw#l3BN?qlW=@<)F? z-ojc@eSeJ?W+tIxu&rcBTcy8N!EMZ3g8J){|Kiy@NJ)`~2(>bQf=5fSFY&i*)+@Dq~sf zV&di%lp*RbtyL~8m&(A+EaVpL4_~cOsda1XQq0^!Y0b;I&8C#u_KT%4vkQvpu7vC* z>-A;Aaq|n=#qKhPpH*2Yrr~B7O4M@KoEx7m>Pg||7!<#UYCKWyv6D9^<7OEpcRDHX(VQzL3`ESRZg9`r{!b>W~MP1^^=5n4lZoWZ|&oT8%oWk<#%)-n#WZaD|jF-(`9NwmjnR6(r+X&(|$M5{Pxe7Du zP?L3XUPijS>`{>nX5Jx9+kAh|*(6Q5x&X|~L!o%Vt(#pN4hK%g%{|n@bH^_B+v=e> z4mbOdPUpWK`+Dh);Dd)S^ACkBYdW+eBUgRd6o{FDs17+vPAxin%+dxo2ce#SAyZIW z#&pg-hM9%P8)>wh`=(qS$j8k?REqpGPbhQ!PekEnB2=dsZpRMTPqM?!MdW7>_juyE zePi*ug_zlh^2YF+l5xylhadWw`3UvQ>0#unQ>OY&#?46NbajTyWJukZw9*wbCsDRe zT@o{z#RzQV;ASPR1-qtupSSo>pM{y1$f*sM+TC~6N&BaY^&FjnnWvDiym}|M{>JoUJLh6%Dl(^^ADEMJ zUh$b5Zmyze8uuz$o2GxLs|Pb%A=|q~Y&=H)(Gr83ugLhcW~4vUJW0vCgqg7@PHa+p zr20`yZX#~ZqL%Xfw#!Ge7B?Dh)*`L=I8&wTqUV#xBQWz81vQ0N8ZlpXDhA+YE~?V+ zsQEi+!^@5x!pvQyoA)=Rx;_yv+*N>?y~t;;A62+bQ9?9l2xk7GlAM-#PPFSeW78AN z42IfN__BOxNk~=iJJ)n%6%P7~m|Manb^5o_FZJ5~%W&U=n{i^~tGv8jWiip&=k)zeu z-+A|r)cYctWwX$#L8)tQZ+rLpkg0~RZEG9Gg;GjPr_SY_G`}$=((9YUp((x%#7n1w*O>+-9{N#xJQjtM^x0CpDv^>mZttYPXxpnr_ zB=P(;M?QuwqeX0P;xGQ1q{RGX>Dl~q9htOnl-EvE|IlBjox|OK9+$Csk{jVR^v$<4 zojE^?tvVEISJ6Vs)bE^P7Y0muwp5?|O>a!noJk{MR*H75p1a3N=IeZ|4MqtP!()fW z7?|Fiq4>Gw$o#Y3*PSwlT|T||;#RemC{MRppBCr{!V3Mklg~?&7w-&V8$3z!O0|FO zKC(jLe;jBU45ysHVJV<}G&L9I|9RJP$0^1Ta0@5NS;Q#D<7UmBpmh#~n zeGJHd)&e|#WZi?_D?y{vCJ@;7zmq@qjS+oaeW)+w9|-xNeub=u2s#SxQ9mN+d2o-) zM9_S=M@m+L_Jw=YPtgz61r9~PzU+G#u1COCfI~mRuM+N$f;)yD!jE`<9PYuGj87PS zp`#P&3@(?E9LnK=l}&x2#aAhS3)+BWPTb^**_5kt?zM=~+^JbZGSI7o(c zAL=$6>h=s?08&a5btkU4Nn!ujFY)272S^e)g(S6^UcC=h&J!%hc*vy9?+df_qXxF}8-I{Qf16fd#x5e%3=9y=0;eY0eW zHFkI>eG(l$)*H-$qeY{@l#g^4%BuzG?}ZFe|NN`yptr%2f#{5+{^))24?=u2KUfVo z`*Dg@IE%-Cqn^X3zy~?GaM+0+@#%@a17^`&p0NZ!JrwnIbUKb5@%>2r2u$n@6?Eow z-@$+Q!P9UEAACWYj}D51u>xsmLR<}S=m&OIq{r}VKym1OnG(h7f6`ZmmGF|#X2b<> zXj28MMY;&?5;)@h!OVybmqSIuY&79>jo4>%;HVe)8XJol4z`_a;ra1!RysQ8__rr; zT22%klLkj1gFze&FlZq*oXO4MMh|>6APOTC4k~AcqYQ;lnc>0{>yY^+WI#|T2qOV( zFb5_Y4qqM(g^wx2nWAy5I5_$nD?TFznd8A3dFTLeUf)5a^hAyTzKR-(j&H+KgJaOZ zFcTeHjvWQvNA=xc4S}7vh7#1lPJoX93t#-qdt^Y04n0R_n#VH3S%TOBelZ+4^&0}f zH#xCP&}lii?WZPFH&PcJ1q6nl(Qr;SCr%5#eF75#(NZWCIF^_l9@A%Ji=Qq8cE$Ly z!-Rn+I=B{nJr1l*1^h%VvTjAExU$hI|L4ne#5?f3P)x0lJSpe_a%Wn3x~ErZ5qbq@OV1m%mh{#Skt1)LH*%u zc2s6K5geAjWb84VXbV#*oK%kTLB4R*oB*Br4!+QLu#DmK@c#FPW_d1G5CXDWh8ZzP9{eL4uU*`{l9c(^AW%@f2Ju*k&M0tdLFXO{R} z9F1G+T8(X1{!xEMd*33enQKHAvzg)5p12j_)FhJ5(ok2Xxhq2W-Og!P6s zhZTVz9Eh!J^e7G|8b8gDA#7b_j*Ne#rx4OG{*yegnCQfN$fp^?pzn4p1Bdb%3GOU7 zVtu&`_vlCP7PUCpN7n&;1zbJ2tKhDIBj&{GaDM|_1Gt;u>^MnQ;mK^eEj#%SlfAC4 z9{lyqzSxR|AMyp=Ot{p>tiATUj_;1ddPB0t^(V&VG%Xo>_Id{_d|It0CcK<~AJ_~uX!)MkiRMf?N0M-KIO zM5BI!_)64o(0f7r6}m?b@z}@@g&hwLrG+-~<-wt_#5+alp=Zbsg-2<6wWw)wZTx!9LpS1OO2#V%hIoySy?i?pS|xr{H~}y zzxVzA@jlOceU|%t&e_x1d!N16T6?qB3{W*_HE1{JFz76(0dx<<&BnJ6l0iK{aiHO# zEYMugr=WV!Z=hC?W)3{&fV@DxK*K?4pgd4H=ygyHXgBB(=pyLfp!*%KcP3!E!gx*_ zo>dIf#!*qF`BRG03;q1T@xpfqGp z@e6S6Yk>=KO}R|J%Dq>CE%Vp|OlJe-`CeRG=J^J2 zg2nT>xTcb*5})D_(9;(8=nC8e6zK2QC&nirR*73d?^(pF#B~=CZ7U_t9P>Q{Y}Q3L zaNmHG=k%Qifl^b4TL>{v?w84-raqaoz%=`ILs~jRDVWyX5_e^|->tP6y}vTw+4Z=S zmYs(&%f?e0Tp_+-Vrnsk!|6{kd+M2Sfc(%VEs^OdxY<#4d~B zR|otSlWUGIG+Biwi%fo*C4^q6hc809o+U<@fGKl&xp5vyQ#FaY#GnSwh5(|RbF z`Y@)WQo(b8Y5mF+78=ZF3GA(vwKp)s#ILN(>3w~%c*pdCl%6~;DynQkZUM~OWEH=V zlNZ%lMzc}&lS*FTyQ5{wysCn>#r#`2Xtz0b6PMLbgE7OGkeOh_3Sr&cQYP zLePxtSH>iFlU${|viT8<^DTho_hRBX(~{6=71_dOU!sG!Ya_Kphci{ zAR3QSDd=_3Veky^n(vh%tOl(GvDpXZT>&X8Sp%-W1APyI1*vpsvEYQt><$L^mc3>A zwiMZc$qa10DoUS{3ctPR`aOt4R~@=iVBNm46*J#$=6m}p?xdUj@i6~l)B+QnmE}Q| zMrB76-wGvfX%RSFx{7Dfr5i@3!1z*A;;=ZCRg^o8${F~Iv(od>)tQvZeY8H9VA(K? zUt*GGW}vz0ObKDh-``@!h2{tXtn3HvL0WoAnp_Os9rd4<38PW;=3JzwTxkhH%EcBV zq`ma0CJMHoa!b->XtF|;>a?+O&?Sas=1fav`b<`@3&_V4`3wP3PFcZ2&6ti3%7Ia- z=Zu=;WITwq5;%JNmEEt=~_d)6|QHFYo-K&S^&X4T6uy&qH~f zUZ$}Z=*TO<%aZ4uJ5aRx(#1I;ojM#%yfUdU|C!S^7vH*&|I%)so!LjXc}H||8+)#Q zjP;1t2_F}aJn7K*SJqv>x{-e#t2fsFJOAFP#`@GhlcYAu^P%R+&MoN%W9ZPq6;UC7 zT1Y08GR#cKqfMO|Om*;bA32nBTxQGog;Kmf{rVmoIS1anSZsJfG{>L(5Ah3gP0^LO zXyhm4ol%+{jNyYN4Bh^0zvokv5(cKmB@9d$k%Tl#`j^e=75oV>?Q;eHjcd9}E0|z_ zQC{w`?}8T(p727}1n4qgQ9Z*CZ9!kppPFtihQ~RGAxb{ekjE3-#4;b~=a3J5ZOd%h z@|kMRN6A-*`q6w9tZ#=6?eI&$-WKsE1CO@AGlA**D*0srTeinwU@wd3*1(qKQ+M+e zHwMht<~|XxcTU^^XVj3>&_h)UR>jr~`IQ z*BFjznz3M;$C-J7O}7}HxqM`pU&?dm;+yUr439qb-neNUVk&kub!52bs0YtREVe!Ld6O%{!g??O>Z%Y-!BYpNQteQ1+$=H^~4DWx{ztDTiUkxQKD;ci-;Q9xv z_cv^)ZmD5-@${0{PN#0ZzqzHB;nOQNRlivn_u=7|Jq%CkWOMNT9nBjJEp-gP7Z#Q^ zvdhjd{%SeQaP5q;Ge@uXeY<1pNrqL?T>}o=roarsd4|s|D$aS^+j~nwYdyo(pK&wq z?w!*-q4gTWH=XSkWooY1z1n(<;ghc=7HCh_RlVJMkKw>9r>oC9ynpsztxc_5zaKxu z#3;qCJk^Tn_8tYx9BkL0zj33LuBP;tQG4X()NKNr$2qQ2yZHXpUVY2m+3JXWwNC02 zWv7;Y9BJMaC`|dK>{Pc`tCLK2^tcy{KX0vx{PIE`)1<)=o!4>)AKziCUt`|2!RJ0W zd_HX5gnzH&;#g^$wjHmE%(}93KU-5EznXHE7muWT82|rFMGFW`O!b@c`8$K+^GXUk4QRL|9%)> z$MDsDUUwaSYkF-6f0*I*Q&Y~ZI3=IV=1(%*kmOnR+gST$<@|Yuqe4BF*6&?&bp>C~ z@REQ1kdk!v(x&(LYYfN4ZLGQU%8CbP_*)Fy#?@>bGGy{cH~D)EJFkp=uW|m?xhkQF z;lRq#8*Cdr&d7p@`3IgP!WRB~y~cJ$v_R)S=#334*FIQb`_o9Fqv`p*=!{FUUu~h_ z%J8hy8($tjIL}&nm{|{tsw-)}HK$SV6*ES_blaH- zZ-C*q_2sxVvk4d5--a_TSq5hNcZvIKd9;$QJ6J!<_l*FyeBa!5_y=IhH7e;FfvMh1 z!6(i5AIF1vM|r_oTaNOQ^b33Z`=iN{L&t%c%J2>K<&^mQpBNweU2tOD#v_Hp?}53D z1Licrp}|32VapXpTtgr2qlY*wZ0;f_q*L;sTs`F!%zG3l?4LX>DFQe1oMbj&iw#Pu z5XhfswmsXnWkwwyWiwI0(ovE{tTwkuPmE>Wt2AxsQMm`AN`4UC-D~f32@IIY^P7dN z<@v5jj4$Zpou@^Pz0SzT?9&*C3w9 z!+ApIkPYX`%;oY!k&h#;H{vp-4%#!d2zGd<(nC>ECPTovIm{F<72=rXVL2_iTcF%M zVq6-wPE4kR?;(#ErGOo7ee~YKb(-JFek+` zB~2XS(zGMYX_U0cw(b3mc!p1f{S5e@*86ABFQA(snf}V4VUo*qfx7APbU#0Y;~tqZ zAXSIp6JYDbr^u7)b#g!spwOxRS5B=_JJ-G`9QwdOen3L4CiO41^^w2)%V&^dXfc{ua|^&ECa zkR||W$p7*Wf7*Q(40?C|AAdr-pGbdPzp5{hwA%5JUd23Txp!vRY??2JW8tLpgC(Xq zc?AzpnfNOO7q`PDX3Ql+?L00c3qGV|XsKu?`q2x2lRk`g9aV&-r6KPMlx>Z00Ydt1 zFGfiFxdtJf1KBw|Q(w`^%ye>wD#K+q`QhwSv`p7JI1fwRef}!Z%G$1je^_|bfcS)Gh7QZjN_p>n7gx1Lr|;+x(JN}x=8KoKJr^w8q}E0E z$WLJ=S@OIp9(8(>T?||nvY&`kJ z8nu(NSC>A0f4bG!dgQ1mckbfj*F7?7&@)34lSYnuer(G4v_{T6d|d6en5-7`LdrMQ_nh6Rscnba_v$ zy-wp8J)oB`L8A?|mpla*iNr>VgQXBrr`D=tWna;tjS!+FXSHZhCnoglZq;2KtkISG z3?JN86JYP`~q*FboB9g5j8RurW57Ow28^(JL z(CbuIPerM85rLwE@xz$RB*P%BE`ET^AWf20f?8+%BVOkw3{2=LSZj2uUTR%=gp)d2 za2-W#x>?O!kzJ}c9)4rU1gpwWTl?xQ6$96PSkX%zAf~8%bn!Yr>8XmH$ytNNUTV8o zIwY3f*HnHLpk4PmTs(EXbarw-PqMcwROc7I629ekp#7MlHpT=uw z`3Qp>>Jp)`MpUiZ_<0vyrHUhhB&k%qTBT8I?R2hsCxf$ur4${B zli;j&A+EfKy)1MUg7m>8R1D+0k&XOjev7zO^EdxMYUW#nR_(T_)8@`w7dra+xm62X zzqPg*Jmf)Ba7f>jaj91;=gnWZX!EXpA00V*;;@!cW*IAY*Bv-`;p;oU&YU&3X2XGlM~U6@;VWY>4PknuU^{)5c zKlsVfV_)0ZJ0z$4@n=h`G4G`-4b~p{1+H$X(_h`bW5!2y_73hI@dJkrqvQY88GDbM zzfgbY*WZhZt4m6k_ymV+-0}XwW2e7vSkA>RT^3sH@#XnbtwV>6O;&4cY<)v+H|7`g z?A^EjfCUSaCYByQapvsBOFy-=!poaiMT1xor*RQgcICC!#;uZvw%kQ<(hxC33>Vb` zQLEH;xXB+ebk%7Eji45IEH(yF67(u!-ANj%c2SR3^C|~JqWH8Bg!#!%Wn+jE z-MXa8dE$#*jK`&lor1HfqFETDw%0mp>4xP2>O-p3W1E2LuAY+r zrfa%(DmVq#bp3cFBa3q*%aE4N{m+7^4Eso2x*3y^Lj^vzU>rt#cf_m3Iz!jWM`h6b z0-SIyD!|rad!LC+k}QTIBm6Ol}}DpOydrT>56_Os0!* z#x!;$6m=^>T)MADHx6ftGPh7lNO#H!Y`h-UJA1kri+^tSrG=T__VULlTadxg5D5Bkl0?U2~;^u#+au6=G;f#>jd z>edeDPNyejon4#6UG^NoefRyy?N`%B-@4{G=FE+?V`T33m^);~SgsJq>Vv@8@%Tpu z=|el&k}M2io+n~w;_i~HkJ4(1qe!$^Zl$h5j3&U5$S}4=L=A?jTF1MQD4JZ$1q>(;)7=K=c$#h(J2>_E@zM8+mJpTF~+CBpPWANa=^{k*gr#qfzsEmMg6i z3gszw<$IxiN-1t+5D^J7CmQk`;nfCB2H~}Obpr2#{0Ql3O;DnwC*E3;EfN(f#XIq$ zU@KbTQblYC+Fo$u-SID$Cu$Ah^;&`tmXz{dWU?UgTA~uZK_j5HYMLXjQR#RR>JcV} z0!zeCYv5(PBoQL<5DA4S4bLwVh!s)O0tNnPEJr@|Cvihj^tu1EeHpD4uZ!^AQYVdIbY)Cpn8Q%!mc-V)LDAqGBNiv^3M3bZNFDC8X? zXgaZ$CB&Xss|D#(4Sg90+N$U)8jtWdQ8yJr7k;FM-g%L>2cBjL=u`>LIQiev^B56i z0m>7Jtn*W`o>K8bFdCdwqd~}UdsGFvysSb2XmgAVS==pF-qE|#^!(kTVNMG?e z>PsY;cYx3#h>}LbtKG%L0@qXQrXkkEULrQg)sE#TWs)^W(_2IfsPoiZn(>ZF7IVWV WM)_QYa@S#h9kc^<0rX&rlI&s7quD2><8LeX- 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

_M~lYa`~Y@dWbO^A)PZN?1?lhZ+vWQZVX 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 Bma6~& diff --git a/x/lumeraid/module/depinject.go b/x/lumeraid/module/depinject.go new file mode 100644 index 00000000..53071585 --- /dev/null +++ b/x/lumeraid/module/depinject.go @@ -0,0 +1,73 @@ +package lumeraid + +import ( + "cosmossdk.io/core/appmodule" + "cosmossdk.io/core/store" + "cosmossdk.io/depinject" + "cosmossdk.io/log" + "github.com/cosmos/cosmos-sdk/codec" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/LumeraProtocol/lumera/x/lumeraid/keeper" + "github.com/LumeraProtocol/lumera/x/lumeraid/types" +) + +var _ depinject.OnePerModuleType = AppModule{} + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (AppModule) IsOnePerModuleType() {} + +// ---------------------------------------------------------------------------- +// App Wiring Setup +// ---------------------------------------------------------------------------- + +func init() { + appmodule.Register( + &Module{}, + appmodule.Provide(ProvideModule), + ) +} + +type ModuleInputs struct { + depinject.In + + StoreService store.KVStoreService + Cdc codec.Codec + Config *Module + Logger log.Logger + + AccountKeeper types.AccountKeeper + BankKeeper types.BankKeeper +} + +type ModuleOutputs struct { + depinject.Out + + LumeraidKeeper keeper.Keeper + Module appmodule.AppModule +} + +func ProvideModule(in ModuleInputs) ModuleOutputs { + // default to governance authority if not provided + authority := authtypes.NewModuleAddress(govtypes.ModuleName) + if in.Config.Authority != "" { + authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) + } + k := keeper.NewKeeper( + in.Cdc, + in.StoreService, + in.Logger, + authority.String(), + in.BankKeeper, + in.AccountKeeper, + ) + m := NewAppModule( + in.Cdc, + k, + in.AccountKeeper, + in.BankKeeper, + ) + + return ModuleOutputs{LumeraidKeeper: k, Module: m} +} diff --git a/x/lumeraid/module/module.go b/x/lumeraid/module/module.go index 628155c8..a94c818c 100644 --- a/x/lumeraid/module/module.go +++ b/x/lumeraid/module/module.go @@ -9,16 +9,11 @@ import ( "github.com/spf13/cobra" "cosmossdk.io/core/appmodule" - "cosmossdk.io/core/store" - "cosmossdk.io/depinject" - "cosmossdk.io/log" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" "github.com/grpc-ecosystem/grpc-gateway/runtime" // this line is used by starport scaffolding # 1 @@ -170,62 +165,5 @@ func (am AppModule) EndBlock(_ context.Context) error { return nil } -// IsOnePerModuleType implements the depinject.OnePerModuleType interface. -func (am AppModule) IsOnePerModuleType() {} - // IsAppModule implements the appmodule.AppModule interface. func (am AppModule) IsAppModule() {} - -// ---------------------------------------------------------------------------- -// App Wiring Setup -// ---------------------------------------------------------------------------- - -func init() { - appmodule.Register( - &Module{}, - appmodule.Provide(ProvideModule), - ) -} - -type ModuleInputs struct { - depinject.In - - StoreService store.KVStoreService - Cdc codec.Codec - Config *Module - Logger log.Logger - - AccountKeeper types.AccountKeeper - BankKeeper types.BankKeeper -} - -type ModuleOutputs struct { - depinject.Out - - LumeraidKeeper keeper.Keeper - Module appmodule.AppModule -} - -func ProvideModule(in ModuleInputs) ModuleOutputs { - // default to governance authority if not provided - authority := authtypes.NewModuleAddress(govtypes.ModuleName) - if in.Config.Authority != "" { - authority = authtypes.NewModuleAddressOrBech32Address(in.Config.Authority) - } - k := keeper.NewKeeper( - in.Cdc, - in.StoreService, - in.Logger, - authority.String(), - in.BankKeeper, - in.AccountKeeper, - ) - m := NewAppModule( - in.Cdc, - k, - in.AccountKeeper, - in.BankKeeper, - ) - - return ModuleOutputs{LumeraidKeeper: k, Module: m} -} From 0d79ed9ca57d91eae441a3a38b079d5476f5d76a Mon Sep 17 00:00:00 2001 From: Andrey Kobrin Date: Mon, 26 Jan 2026 16:24:00 -0500 Subject: [PATCH 2/5] fixed tests, removed claim tests --- app/sim_bench_test.go | 4 +- app/sim_test.go | 10 +- cmd/lumera/cmd/commands.go | 2 - cmd/lumera/cmd/root.go | 4 + cmd/lumera/cmd/testnet.go | 15 +- .../integration/msg_claim_integration_test.go | 222 ---------- .../update_params_integration_test.go | 167 -------- tests/system/claiming_test.go | 312 -------------- tests/systemtests/claim_period_end_test.go | 122 ------ tests/systemtests/claim_test.go | 295 ------------- tests/systemtests/claims_params_test.go | 116 ----- tests/systemtests/claims_per_block_test.go | 399 ------------------ tests/systemtests/delayed_claim_test.go | 375 ---------------- tests/systemtests/main_test.go | 4 + tests/systemtests/system.go | 29 +- x/action/v1/simulation/helpers.go | 40 +- x/action/v1/simulation/request_action.go | 18 +- x/claim/keeper/abci_test.go | 76 ---- x/claim/keeper/claim_count_per_block_test.go | 56 --- x/claim/keeper/claim_record_test.go | 289 ------------- x/claim/keeper/crypto/utils_test.go | 304 ------------- x/claim/keeper/msg_server_claim_test.go | 141 ------- .../keeper/msg_server_delayed_claim_test.go | 145 ------- x/claim/keeper/msg_server_test.go | 26 -- x/claim/keeper/msg_update_params_test.go | 66 --- x/claim/keeper/params_test.go | 20 - x/claim/keeper/query_claim_record_test.go | 109 ----- x/claim/keeper/query_params_test.go | 26 -- x/claim/module/genesis_test.go | 60 --- x/claim/simulation/claim.go | 16 +- x/claim/types/genesis_test.go | 109 ----- x/claim/types/message_delayed_claim_test.go | 48 --- .../v1/simulation/register_supernode.go | 9 + 33 files changed, 88 insertions(+), 3546 deletions(-) delete mode 100644 tests/integration/msg_claim_integration_test.go delete mode 100644 tests/integration/update_params_integration_test.go delete mode 100644 tests/system/claiming_test.go delete mode 100644 tests/systemtests/claim_period_end_test.go delete mode 100644 tests/systemtests/claim_test.go delete mode 100644 tests/systemtests/claims_params_test.go delete mode 100644 tests/systemtests/claims_per_block_test.go delete mode 100644 tests/systemtests/delayed_claim_test.go delete mode 100644 x/claim/keeper/abci_test.go delete mode 100644 x/claim/keeper/claim_count_per_block_test.go delete mode 100644 x/claim/keeper/claim_record_test.go delete mode 100644 x/claim/keeper/crypto/utils_test.go delete mode 100644 x/claim/keeper/msg_server_claim_test.go delete mode 100644 x/claim/keeper/msg_server_delayed_claim_test.go delete mode 100644 x/claim/keeper/msg_server_test.go delete mode 100644 x/claim/keeper/msg_update_params_test.go delete mode 100644 x/claim/keeper/params_test.go delete mode 100644 x/claim/keeper/query_claim_record_test.go delete mode 100644 x/claim/keeper/query_params_test.go delete mode 100644 x/claim/module/genesis_test.go delete mode 100644 x/claim/types/genesis_test.go delete mode 100644 x/claim/types/message_delayed_claim_test.go diff --git a/app/sim_bench_test.go b/app/sim_bench_test.go index d517626d..a4c1866c 100644 --- a/app/sim_bench_test.go +++ b/app/sim_bench_test.go @@ -51,7 +51,7 @@ func BenchmarkFullAppSimulation(b *testing.B) { bApp.BaseApp, simtestutil.AppStateFn(bApp.AppCodec(), bApp.SimulationManager(), bApp.DefaultGenesis()), simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simtestutil.SimulationOperations(bApp, bApp.AppCodec(), config), + simtestutil.BuildSimulationOperations(bApp, bApp.AppCodec(), config, bApp.TxConfig()), app.BlockedAddresses(), config, bApp.AppCodec(), @@ -107,7 +107,7 @@ func BenchmarkInvariants(b *testing.B) { bApp.BaseApp, simtestutil.AppStateFn(bApp.AppCodec(), bApp.SimulationManager(), bApp.DefaultGenesis()), simtypes.RandomAccounts, // Replace with own random account function if using keys other than secp256k1 - simtestutil.SimulationOperations(bApp, bApp.AppCodec(), config), + simtestutil.BuildSimulationOperations(bApp, bApp.AppCodec(), config, bApp.TxConfig()), app.BlockedAddresses(), config, bApp.AppCodec(), diff --git a/app/sim_test.go b/app/sim_test.go index 09b1239c..e727bc2f 100644 --- a/app/sim_test.go +++ b/app/sim_test.go @@ -99,7 +99,7 @@ func BenchmarkSimulation(b *testing.B) { bApp.BaseApp, simtestutil.AppStateFn(bApp.AppCodec(), bApp.SimulationManager(), bApp.DefaultGenesis()), simulationtypes.RandomAccounts, - simtestutil.SimulationOperations(bApp, bApp.AppCodec(), config), + simtestutil.BuildSimulationOperations(bApp, bApp.AppCodec(), config, bApp.TxConfig()), app.BlockedAddresses(), config, bApp.AppCodec(), @@ -144,7 +144,7 @@ func TestAppImportExport(t *testing.T) { bApp.BaseApp, simtestutil.AppStateFn(bApp.AppCodec(), bApp.SimulationManager(), bApp.DefaultGenesis()), simulationtypes.RandomAccounts, - simtestutil.SimulationOperations(bApp, bApp.AppCodec(), config), + simtestutil.BuildSimulationOperations(bApp, bApp.AppCodec(), config, bApp.TxConfig()), app.BlockedAddresses(), config, bApp.AppCodec(), @@ -267,7 +267,7 @@ func TestAppSimulationAfterImport(t *testing.T) { bApp.BaseApp, simtestutil.AppStateFn(bApp.AppCodec(), bApp.SimulationManager(), bApp.DefaultGenesis()), simulationtypes.RandomAccounts, - simtestutil.SimulationOperations(bApp, bApp.AppCodec(), config), + simtestutil.BuildSimulationOperations(bApp, bApp.AppCodec(), config, bApp.TxConfig()), app.BlockedAddresses(), config, bApp.AppCodec(), @@ -318,7 +318,7 @@ func TestAppSimulationAfterImport(t *testing.T) { newApp.BaseApp, simtestutil.AppStateFn(bApp.AppCodec(), bApp.SimulationManager(), bApp.DefaultGenesis()), simulationtypes.RandomAccounts, - simtestutil.SimulationOperations(newApp, newApp.AppCodec(), config), + simtestutil.BuildSimulationOperations(newApp, newApp.AppCodec(), config, newApp.TxConfig()), app.BlockedAddresses(), config, bApp.AppCodec(), @@ -404,7 +404,7 @@ func TestAppStateDeterminism(t *testing.T) { bApp.DefaultGenesis(), ), simulationtypes.RandomAccounts, - simtestutil.SimulationOperations(bApp, bApp.AppCodec(), config), + simtestutil.BuildSimulationOperations(bApp, bApp.AppCodec(), config, bApp.TxConfig()), app.BlockedAddresses(), config, bApp.AppCodec(), diff --git a/cmd/lumera/cmd/commands.go b/cmd/lumera/cmd/commands.go index 48e58400..ee70a253 100644 --- a/cmd/lumera/cmd/commands.go +++ b/cmd/lumera/cmd/commands.go @@ -23,7 +23,6 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/cosmos/cosmos-sdk/x/crisis" genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" "github.com/CosmWasm/wasmd/x/wasm" @@ -66,7 +65,6 @@ func initRootCmd( } func addModuleInitFlags(startCmd *cobra.Command) { - crisis.AddModuleInitFlags(startCmd) wasm.AddModuleInitFlags(startCmd) } diff --git a/cmd/lumera/cmd/root.go b/cmd/lumera/cmd/root.go index 9c3177b0..4c00b16a 100644 --- a/cmd/lumera/cmd/root.go +++ b/cmd/lumera/cmd/root.go @@ -16,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/server" servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/auth/tx" authtxconfig "github.com/cosmos/cosmos-sdk/x/auth/tx/config" "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -32,6 +33,9 @@ import ( // NewRootCmd creates a new root command for lumera. It is called once in the main function. func NewRootCmd() *cobra.Command { + // Ensure SDK placeholders use the Lumera daemon name. + version.AppName = app.Name + "d" + var ( autoCliOpts autocli.AppOptions moduleBasicManager module.BasicManager diff --git a/cmd/lumera/cmd/testnet.go b/cmd/lumera/cmd/testnet.go index bf51ed31..ce96c1f3 100644 --- a/cmd/lumera/cmd/testnet.go +++ b/cmd/lumera/cmd/testnet.go @@ -36,7 +36,6 @@ import ( "github.com/cosmos/cosmos-sdk/version" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" @@ -244,6 +243,12 @@ func initTestnetFiles( nodeIDs := make([]string, args.numValidators) valPubKeys := make([]cryptotypes.PubKey, args.numValidators) + // Disable state sync for local testnets. + nodeConfig.StateSync.Enable = false + nodeConfig.StateSync.RPCServers = nil + nodeConfig.StateSync.TrustHeight = 0 + nodeConfig.StateSync.TrustHash = "" + appConfig := srvconfig.DefaultConfig() appConfig.MinGasPrices = args.minGasPrices appConfig.API.Enable = true @@ -487,14 +492,6 @@ func initGenFiles( } appGenState[govtypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&govGenState) - // set the crisis module constant fee denom - var crisisGenState crisistypes.GenesisState - clientCtx.Codec.MustUnmarshalJSON(appGenState[crisistypes.ModuleName], &crisisGenState) - if crisisGenState.ConstantFee.Amount.IsPositive() || crisisGenState.ConstantFee.Denom != "" { - crisisGenState.ConstantFee = sdk.NewCoin(lcfg.ChainDenom, crisisGenState.ConstantFee.Amount) - } - appGenState[crisistypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&crisisGenState) - // set the accounts in the genesis state var authGenState authtypes.GenesisState clientCtx.Codec.MustUnmarshalJSON(appGenState[authtypes.ModuleName], &authGenState) diff --git a/tests/integration/msg_claim_integration_test.go b/tests/integration/msg_claim_integration_test.go deleted file mode 100644 index 931d77a1..00000000 --- a/tests/integration/msg_claim_integration_test.go +++ /dev/null @@ -1,222 +0,0 @@ -package integration_test - -import ( - "testing" - "time" - - keepertest "github.com/LumeraProtocol/lumera/testutil/keeper" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/suite" - - lcfg "github.com/LumeraProtocol/lumera/config" - "github.com/LumeraProtocol/lumera/x/claim/keeper" - "github.com/LumeraProtocol/lumera/x/claim/types" -) - -type MsgClaimIntegrationTestSuite struct { - suite.Suite - keeper keeper.Keeper - ctx sdk.Context - validPubKey string - validSig string - oldAddress string - newAddress string - msgServer types.MsgServer -} - -func (s *MsgClaimIntegrationTestSuite) SetupTest() { - k, ctx := keepertest.ClaimKeeper(s.T(), "") - s.keeper = k - s.ctx = ctx - s.msgServer = keeper.NewMsgServerImpl(k) - - // Set up valid test data - s.validPubKey = "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12" - s.validSig = "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3" - s.oldAddress = "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc" - s.newAddress = "lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp" - - // Set up module parameters - params := types.DefaultParams() - params.EnableClaims = true - params.MaxClaimsPerBlock = 10 - params.ClaimEndTime = time.Now().Add(time.Hour).Unix() - s.Require().NoError(s.keeper.SetParams(ctx, params)) -} - -func (s *MsgClaimIntegrationTestSuite) TestClaimIntegration() { - - testAmount := int64(1_000_000) // Amount to be claimed in test cases - validFee := sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, int64(1_000))) - testCases := []struct { - name string - setup func() - msg *types.MsgClaim - expErr bool - errString string - }{ - { - name: "successful claim", - setup: func() { - // Create and store claim record - claimRecord := types.ClaimRecord{ - OldAddress: s.oldAddress, - Balance: sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, testAmount)), - Claimed: false, - } - err := s.keeper.SetClaimRecord(s.ctx, claimRecord) - s.Require().NoError(err) - - // Fund module account - err = s.keeper.GetBankKeeper().MintCoins(s.ctx, types.ModuleName, claimRecord.Balance) - s.Require().NoError(err) - }, - msg: &types.MsgClaim{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - NewAddress: "lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - PubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - Signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - }, - expErr: false, - }, - { - name: "claim already processed", - setup: func() { - // Create and store claimed record - claimRecord := types.ClaimRecord{ - OldAddress: s.oldAddress, - Balance: sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, testAmount)), - Claimed: true, - ClaimTime: time.Now().Add(-15).Unix(), - } - err := s.keeper.SetClaimRecord(s.ctx, claimRecord) - s.Require().NoError(err) - }, - msg: &types.MsgClaim{ - OldAddress: s.oldAddress, - NewAddress: s.newAddress, - PubKey: s.validPubKey, - Signature: s.validSig, - }, - expErr: true, - errString: "claim already claimed", - }, - { - name: "claim not found", - setup: func() {}, // No setup needed - claim record doesn't exist - msg: &types.MsgClaim{ - OldAddress: "NonExistentAddress", - NewAddress: s.newAddress, - PubKey: s.validPubKey, - Signature: s.validSig, - }, - expErr: true, - errString: "claim not found", - }, - { - name: "claims disabled", - setup: func() { - params := types.DefaultParams() - params.EnableClaims = false - s.Require().NoError(s.keeper.SetParams(s.ctx, params)) - - // Add a claim record to ensure the check happens before record lookup - claimRecord := types.ClaimRecord{ - OldAddress: s.oldAddress, - Balance: sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, testAmount)), - Claimed: false, - } - err := s.keeper.SetClaimRecord(s.ctx, claimRecord) - s.Require().NoError(err) - }, - msg: &types.MsgClaim{ - OldAddress: s.oldAddress, - NewAddress: s.newAddress, - PubKey: s.validPubKey, - Signature: s.validSig, - }, - expErr: true, - errString: "claim is disabled", - }, - { - name: "invalid signature", - setup: func() { - claimRecord := types.ClaimRecord{ - OldAddress: s.oldAddress, - Balance: sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, testAmount)), - Claimed: false, - } - err := s.keeper.SetClaimRecord(s.ctx, claimRecord) - s.Require().NoError(err) - }, - msg: &types.MsgClaim{ - OldAddress: s.oldAddress, - NewAddress: s.newAddress, - PubKey: s.validPubKey, - Signature: "invalid_signature", - }, - expErr: true, - errString: "invalid signature", - }, - } - - for _, tc := range testCases { - s.Run(tc.name, func() { - s.SetupTest() // Reset state for each test case - if tc.setup != nil { - tc.setup() - } - - // Execute claim - - // Set fee in context - s.ctx = s.ctx.WithValue(types.ClaimTxFee, validFee) - resp, err := s.msgServer.Claim(s.ctx, tc.msg) - - if tc.expErr { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.errString) - s.Require().Nil(resp) - - // For error cases, verify record state only if it's expected to exist - if tc.name != "claim not found" { - record, found, err := s.keeper.GetClaimRecord(s.ctx, tc.msg.OldAddress) - s.Require().NoError(err) - s.Require().True(found) - if tc.name == "claim already processed" { - s.Require().True(record.Claimed) - } else { - s.Require().False(record.Claimed) - } - } - } else { - s.Require().NoError(err) - s.Require().NotNil(resp) - - // Verify claim record is updated - record, found, err := s.keeper.GetClaimRecord(s.ctx, tc.msg.OldAddress) - s.Require().NoError(err) - s.Require().True(found) - s.Require().True(record.Claimed) - s.Require().NotEqual(time.Time{}, record.ClaimTime) - - // Verify events were emitted - events := s.ctx.EventManager().Events() - s.Require().NotEmpty(events) - - found = false - for _, event := range events { - if event.Type == types.EventTypeClaimProcessed { - found = true - break - } - } - s.Require().True(found, "claim_processed event not found") - } - }) - } -} - -func TestMsgClaimIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(MsgClaimIntegrationTestSuite)) -} diff --git a/tests/integration/update_params_integration_test.go b/tests/integration/update_params_integration_test.go deleted file mode 100644 index 2e6a1004..00000000 --- a/tests/integration/update_params_integration_test.go +++ /dev/null @@ -1,167 +0,0 @@ -package integration_test - -import ( - "testing" - "time" - - "cosmossdk.io/math" - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - "github.com/stretchr/testify/suite" - - sdk "github.com/cosmos/cosmos-sdk/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - - "github.com/LumeraProtocol/lumera/app" - claimtypes "github.com/LumeraProtocol/lumera/x/claim/types" - lcfg "github.com/LumeraProtocol/lumera/config" -) - -type IntegrationTestSuite struct { - suite.Suite - app *app.App - ctx sdk.Context - proposer sdk.AccAddress - voter sdk.AccAddress -} - -func (s *IntegrationTestSuite) SetupTest() { - s.app = app.Setup(s.T()) - s.Require().NotNil(s.app, "App initialization failed") - - s.ctx = s.app.BaseApp.NewContext(false) - s.ctx = s.ctx.WithBlockHeader(tmproto.Header{ - Height: 1, - Time: time.Now().UTC(), - ChainID: "test-chain", - }) - - s.proposer = sdk.AccAddress([]byte("proposer___________")) - s.voter = sdk.AccAddress([]byte("voter_____________")) - - s.app.AuthKeeper.SetAccount(s.ctx, s.app.AuthKeeper.NewAccountWithAddress(s.ctx, s.proposer)) - s.app.AuthKeeper.SetAccount(s.ctx, s.app.AuthKeeper.NewAccountWithAddress(s.ctx, s.voter)) - - proposerCoins := sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, 1_000_000_000)) - voterCoins := sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, 1_000_000_000)) - - err := s.app.BankKeeper.MintCoins(s.ctx, minttypes.ModuleName, proposerCoins.Add(voterCoins...)) - s.Require().NoError(err, "Failed to mint coins") - - err = s.app.BankKeeper.SendCoinsFromModuleToAccount(s.ctx, minttypes.ModuleName, s.proposer, proposerCoins) - s.Require().NoError(err, "Failed to send coins to proposer") - err = s.app.BankKeeper.SendCoinsFromModuleToAccount(s.ctx, minttypes.ModuleName, s.voter, voterCoins) - s.Require().NoError(err, "Failed to send coins to voter") - - valPubKey := ed25519.GenPrivKey().PubKey() - valAddr := sdk.ValAddress(s.voter) - validator, err := stakingtypes.NewValidator( - valAddr.String(), - valPubKey, - stakingtypes.Description{}, - ) - s.Require().NoError(err, "Failed to create validator") - - validator.Status = stakingtypes.Bonded - validator.Tokens = math.NewInt(1000000000) - validator.DelegatorShares = math.LegacyNewDec(1000000000) - s.app.StakingKeeper.SetValidator(s.ctx, validator) - - delegation := stakingtypes.NewDelegation(s.voter.String(), valAddr.String(), math.LegacyNewDec(1000000000)) - s.app.StakingKeeper.SetDelegation(s.ctx, delegation) - - s.app.StakingKeeper.SetValidatorByPowerIndex(s.ctx, validator) - - govParams := govv1.DefaultParams() - err = s.app.GovKeeper.Params.Set(s.ctx, govParams) - s.Require().NoError(err, "Failed to set governance parameters") - - claimParams := claimtypes.DefaultParams() - s.app.ClaimKeeper.SetParams(s.ctx, claimParams) -} - -func (s *IntegrationTestSuite) TestUpdateParamsProposal() { - initialParams := s.app.ClaimKeeper.GetParams(s.ctx) - govParams, err := s.app.GovKeeper.Params.Get(s.ctx) - s.Require().NoError(err, "Failed to get governance parameters") - - newParams := claimtypes.NewParams( - !initialParams.EnableClaims, - time.Unix(initialParams.ClaimEndTime, 0).Add(time.Hour).Unix(), - initialParams.MaxClaimsPerBlock+1, - ) - - paramChangeMsg := &claimtypes.MsgUpdateParams{ - Authority: s.app.GovKeeper.GetAuthority(), - Params: newParams, - } - - proposal, err := s.app.GovKeeper.SubmitProposal( - s.ctx, - []sdk.Msg{paramChangeMsg}, - "ipfs://CID", - "Update claim parameters", - "This proposal updates the claim module parameters", - s.proposer, - false, - ) - s.Require().NoError(err, "Failed to submit proposal") - - depositAmount := govParams.MinDeposit - err = s.app.BankKeeper.SendCoinsFromAccountToModule(s.ctx, s.proposer, govtypes.ModuleName, depositAmount) - s.Require().NoError(err, "Failed to send deposit") - - votingPeriodStart, err := s.app.GovKeeper.AddDeposit(s.ctx, proposal.Id, s.proposer, depositAmount) - s.Require().NoError(err, "Failed to add deposit") - s.Require().True(votingPeriodStart, "Proposal should enter voting period") - - proposal, err = s.app.GovKeeper.Proposals.Get(s.ctx, proposal.Id) - s.Require().NoError(err, "Failed to get proposal") - s.Require().Equal(govv1.StatusVotingPeriod, proposal.Status, "Proposal should be in voting period") - - err = s.app.GovKeeper.AddVote( - s.ctx, - proposal.Id, - s.voter, - govv1.NewNonSplitVoteOption(govv1.OptionYes), - "", - ) - s.Require().NoError(err, "Failed to add vote") - - s.ctx = s.ctx.WithBlockTime(proposal.VotingEndTime.Add(time.Hour)) - s.ctx = s.ctx.WithBlockHeight(s.ctx.BlockHeight() + 1) - - _, burnDeposits, _, err := s.app.GovKeeper.Tally(s.ctx, proposal) - s.Require().NoError(err, "Failed to tally votes") - - proposal.Status = govv1.StatusPassed - err = s.app.GovKeeper.SetProposal(s.ctx, proposal) - s.Require().NoError(err, "Failed to set proposal status") - - proposal, err = s.app.GovKeeper.Proposals.Get(s.ctx, proposal.Id) - s.Require().NoError(err, "Failed to get proposal after processing") - - if burnDeposits { - err = s.app.GovKeeper.DeleteAndBurnDeposits(s.ctx, proposal.Id) - s.Require().NoError(err, "Failed to burn deposits") - } else { - err = s.app.GovKeeper.RefundAndDeleteDeposits(s.ctx, proposal.Id) - s.Require().NoError(err, "Failed to refund deposits") - } - - s.Require().Equal(govv1.StatusPassed, proposal.Status, "Proposal should have passed") - - msg := proposal.Messages[0].GetCachedValue().(*claimtypes.MsgUpdateParams) - s.app.ClaimKeeper.SetParams(s.ctx, msg.Params) - s.Require().NoError(err, "Failed to update claim parameters") - - updatedParams := s.app.ClaimKeeper.GetParams(s.ctx) - s.Require().Equal(msg.Params, updatedParams, "Parameters were not updated correctly") -} - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/tests/system/claiming_test.go b/tests/system/claiming_test.go deleted file mode 100644 index f157154d..00000000 --- a/tests/system/claiming_test.go +++ /dev/null @@ -1,312 +0,0 @@ -package system_test - -import ( - "context" - "os" - "testing" - - "github.com/LumeraProtocol/lumera/app" - "github.com/LumeraProtocol/lumera/tests/ibctesting" - "github.com/LumeraProtocol/lumera/x/claim/keeper" - "github.com/LumeraProtocol/lumera/x/claim/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - - claimtestutils "github.com/LumeraProtocol/lumera/x/claim/testutils" - lcfg "github.com/LumeraProtocol/lumera/config" -) - -type SystemTestSuite struct { - app *app.App - sdkCtx sdk.Context - ctx context.Context -} - -func setupClaimSystemSuite(t *testing.T) *SystemTestSuite { - os.Setenv("SYSTEM_TESTS", "true") - t.Cleanup(func() { - os.Unsetenv("SYSTEM_TESTS") - }) - - suite := &SystemTestSuite{} - coord := ibctesting.NewCoordinator(t, 1) // One chain setup - chain := coord.GetChain(ibctesting.GetChainID(1)) - - app := chain.App.(*app.App) - suite.app = app - - baseCtx := chain.GetContext() - suite.sdkCtx = baseCtx - suite.ctx = baseCtx - - // Set up default parameters - err := suite.app.ClaimKeeper.SetParams(chain.GetContext(), types.DefaultParams()) - require.NoError(t, err) - - return suite -} - -func TestClaimProcess(t *testing.T) { - suite := setupClaimSystemSuite(t) - - // Generate test data - testData, err := claimtestutils.GenerateClaimingTestData() - t.Logf("\nTest Data Generated:"+ - "\n===================="+ - "\nOldAddress: %s"+ - "\nPubKey: %s"+ - "\nNewAddress: %s"+ - "\nSignature: %s"+ - "\n====================\n", - testData.OldAddress, - testData.PubKey, - testData.NewAddress, - testData.Signature) - require.NoError(t, err) - - testAmount := int64(1_000_000) - - testCases := []struct { - name string - setup func() - msg *types.MsgClaim - expectError bool - expectedError error - }{ - { - name: "Successful claim with non-existing new address", - setup: func() { - params := types.DefaultParams() - params.EnableClaims = true - err := suite.app.ClaimKeeper.SetParams(suite.sdkCtx, params) - require.NoError(t, err) - - claimRecord := types.ClaimRecord{ - OldAddress: testData.OldAddress, - Balance: sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, testAmount)), - Claimed: false, - } - err = suite.app.ClaimKeeper.SetClaimRecord(suite.sdkCtx, claimRecord) - require.NoError(t, err) - - err = suite.app.BankKeeper.MintCoins(suite.sdkCtx, types.ModuleName, claimRecord.Balance) - require.NoError(t, err) - }, - msg: &types.MsgClaim{ - OldAddress: testData.OldAddress, - NewAddress: testData.NewAddress, - PubKey: testData.PubKey, - Signature: testData.Signature, - }, - expectError: false, - }, - { - name: "Already claimed", - setup: func() { - params := types.DefaultParams() - params.EnableClaims = true - err := suite.app.ClaimKeeper.SetParams(suite.sdkCtx, params) - require.NoError(t, err) - - claimRecord := types.ClaimRecord{ - OldAddress: testData.OldAddress, - Balance: sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, testAmount)), - Claimed: true, - ClaimTime: suite.sdkCtx.BlockTime().Unix(), - } - err = suite.app.ClaimKeeper.SetClaimRecord(suite.sdkCtx, claimRecord) - require.NoError(t, err) - }, - msg: &types.MsgClaim{ - OldAddress: testData.OldAddress, - NewAddress: testData.NewAddress, - PubKey: testData.PubKey, - Signature: testData.Signature, - }, - expectError: true, - expectedError: types.ErrClaimAlreadyClaimed, - }, - { - name: "Non-existent claim", - setup: func() { - params := types.DefaultParams() - params.EnableClaims = true - err := suite.app.ClaimKeeper.SetParams(suite.sdkCtx, params) - require.NoError(t, err) - }, - msg: &types.MsgClaim{ - OldAddress: "PtqHAEacynVd3V821NPhgxu9K4Ab6kAguHx", // Different address - NewAddress: testData.NewAddress, - PubKey: testData.PubKey, - Signature: testData.Signature, - }, - expectError: true, - expectedError: types.ErrClaimNotFound, - }, - { - name: "Claims disabled", - setup: func() { - params := types.DefaultParams() - params.EnableClaims = false - err := suite.app.ClaimKeeper.SetParams(suite.sdkCtx, params) - require.NoError(t, err) - - claimRecord := types.ClaimRecord{ - OldAddress: testData.OldAddress, - Balance: sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, testAmount)), - Claimed: false, - } - err = suite.app.ClaimKeeper.SetClaimRecord(suite.sdkCtx, claimRecord) - require.NoError(t, err) - }, - msg: &types.MsgClaim{ - OldAddress: testData.OldAddress, - NewAddress: testData.NewAddress, - PubKey: testData.PubKey, - Signature: testData.Signature, - }, - expectError: true, - expectedError: types.ErrClaimDisabled, - }, - { - name: "Invalid signature", - setup: func() { - params := types.DefaultParams() - params.EnableClaims = true - err := suite.app.ClaimKeeper.SetParams(suite.sdkCtx, params) - require.NoError(t, err) - - claimRecord := types.ClaimRecord{ - OldAddress: testData.OldAddress, - Balance: sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, testAmount)), - Claimed: false, - } - err = suite.app.ClaimKeeper.SetClaimRecord(suite.sdkCtx, claimRecord) - require.NoError(t, err) - }, - msg: &types.MsgClaim{ - OldAddress: testData.OldAddress, - NewAddress: testData.NewAddress, - PubKey: testData.PubKey, - Signature: "invalid_signature", - }, - expectError: true, - expectedError: types.ErrInvalidSignature, - }, - { - name: "Claim period expired", - setup: func() { - params := types.DefaultParams() - params.EnableClaims = true - params.ClaimEndTime = suite.sdkCtx.BlockTime().Unix() - 1 - err := suite.app.ClaimKeeper.SetParams(suite.sdkCtx, params) - require.NoError(t, err) - - claimRecord := types.ClaimRecord{ - OldAddress: testData.OldAddress, - Balance: sdk.NewCoins(sdk.NewInt64Coin(lcfg.ChainDenom, testAmount)), - Claimed: false, - } - err = suite.app.ClaimKeeper.SetClaimRecord(suite.sdkCtx, claimRecord) - require.NoError(t, err) - }, - msg: &types.MsgClaim{ - OldAddress: testData.OldAddress, - NewAddress: testData.NewAddress, - PubKey: testData.PubKey, - Signature: testData.Signature, - }, - expectError: true, - expectedError: types.ErrClaimPeriodExpired, - }, - } - - // Execute each test case - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Set up the test environment for this specific case - tc.setup() - msgServer := keeper.NewMsgServerImpl(suite.app.ClaimKeeper) - - // Record initial balances for validation - moduleAddr := suite.app.AuthKeeper.GetModuleAddress(types.ModuleName) - initialModuleBalance := suite.app.BankKeeper.GetAllBalances(suite.sdkCtx, moduleAddr) - - // Get destination address and its initial balance - destAddr, err := sdk.AccAddressFromBech32(tc.msg.NewAddress) - require.NoError(t, err) - initialUserBalance := suite.app.BankKeeper.GetAllBalances(suite.sdkCtx, destAddr) - - // Execute the claim message - response, err := msgServer.Claim(suite.sdkCtx, tc.msg) - - // Handle error cases - if tc.expectError { - require.Error(t, err) - require.ErrorIs(t, err, tc.expectedError) - require.Nil(t, response) - } else { - // Verify successful claim execution - require.NoError(t, err) - require.NotNil(t, response) - - // Verify claim record has been properly updated - record, found, err := suite.app.ClaimKeeper.GetClaimRecord(suite.sdkCtx, tc.msg.OldAddress) - require.NoError(t, err) - require.True(t, found) - require.True(t, record.Claimed) - require.NotZero(t, record.ClaimTime) - - // Verify destination account exists (should be created if it didn't exist) - acc := suite.app.AuthKeeper.GetAccount(suite.sdkCtx, destAddr) - require.NotNil(t, acc) - - // Verify token balances after transfer - finalUserBalance := suite.app.BankKeeper.GetAllBalances(suite.sdkCtx, destAddr) - finalModuleBalance := suite.app.BankKeeper.GetAllBalances(suite.sdkCtx, moduleAddr) - - // Check user received the correct amount - expectedUserBalance := initialUserBalance.Add(record.Balance...) - require.Equal(t, expectedUserBalance, finalUserBalance) - - // Check module account balance decreased correctly - expectedModuleBalance := initialModuleBalance.Sub(record.Balance...) - require.Equal(t, expectedModuleBalance, finalModuleBalance) - - // Verify event emission - events := suite.sdkCtx.EventManager().Events() - require.NotEmpty(t, events) - - // Look for the claim processed event and verify its attributes - var foundClaimEvent bool - for _, event := range events { - if event.Type == types.EventTypeClaimProcessed { - foundClaimEvent = true - hasOldAddr, hasNewAddr, hasClaimTime := false, false, false - - // Check all required attributes are present with correct values - for _, attr := range event.Attributes { - switch string(attr.Key) { - case types.AttributeKeyOldAddress: - require.Equal(t, tc.msg.OldAddress, string(attr.Value)) - hasOldAddr = true - case types.AttributeKeyNewAddress: - require.Equal(t, tc.msg.NewAddress, string(attr.Value)) - hasNewAddr = true - case types.AttributeKeyClaimTime: - require.NotEmpty(t, string(attr.Value)) - hasClaimTime = true - } - } - - // Ensure all required attributes were found - require.True(t, hasOldAddr, "missing old address attribute") - require.True(t, hasNewAddr, "missing new address attribute") - require.True(t, hasClaimTime, "missing claim time attribute") - } - } - require.True(t, foundClaimEvent, "claim_processed event not found") - } - }) - } -} diff --git a/tests/systemtests/claim_period_end_test.go b/tests/systemtests/claim_period_end_test.go deleted file mode 100644 index cb1afe2f..00000000 --- a/tests/systemtests/claim_period_end_test.go +++ /dev/null @@ -1,122 +0,0 @@ -//go:build system_test - -package system - -import ( - "fmt" - "testing" - "time" - "strconv" - - "github.com/stretchr/testify/require" - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" - - claimtestutils "github.com/LumeraProtocol/lumera/x/claim/testutils" - claimtypes "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func TestClaimPeriodEndBurn(t *testing.T) { - // Reset chain for a clean state - sut.ResetChain(t) - - // Generate test data for claims - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - - // Setup test parameters - claimAmount := uint64(1_000_000) - totalClaimableAmount := uint64(2_000_000) // Two potential claims - - // Generate a CSV file with the test data - claimsPath, err := claimtestutils.GenerateClaimsCSVFile([]claimtestutils.ClaimCSVRecord{ - {OldAddress: testData.OldAddress, Amount: claimAmount}, - {OldAddress: "lumc4mple2ddress000000000000000000000000", Amount: claimAmount}, // Second address that won't be claimed - }, nil) - require.NoError(t, err) - - // Ensure the file is cleaned up after the test - t.Cleanup(func() { - claimtestutils.CleanupClaimsCSVFile(claimsPath) - }) - - claimPeriodSecs := time.Duration(20) * time.Second // Short claim period for testing - // Set a short claim period - claimEndTime := time.Now().Add(claimPeriodSecs).Unix() - sut.Logf("Claim end time: %s\n", time.Unix(claimEndTime, 0).Format(time.RFC3339)) - - // Modify genesis to set up test conditions - sut.ModifyGenesisJSON(t, func(genesis []byte) []byte { - state := genesis - var err error - - // Set total claimable amount - state, err = sjson.SetRawBytes(state, "app_state.claim.total_claimable_amount", - []byte(strconv.FormatUint(totalClaimableAmount, 10))) - require.NoError(t, err) - - // Enable claims and set end time - state, err = sjson.SetRawBytes(state, "app_state.claim.params.enable_claims", []byte("true")) - require.NoError(t, err) - state, err = sjson.SetRawBytes(state, "app_state.claim.params.claim_end_time", - []byte(fmt.Sprintf("%d", claimEndTime))) - require.NoError(t, err) - - return state - }) - - // Start the chain - sut.StartChain(t, fmt.Sprintf("--%s=%s", claimtypes.FlagClaimsPath, claimsPath)) - cli := NewLumeradCLI(t, sut, true) - - // Get claim module account address - moduleAcctResp := cli.CustomQuery("q", "auth", "module-account", "claim") - moduleAddr := gjson.Get(moduleAcctResp, "account.value.address").String() - require.NotEmpty(t, moduleAddr, "claim module address should not be empty") - - // Verify initial module balance - initialModuleBalance := cli.QueryBalance(moduleAddr, claimtypes.DefaultClaimsDenom) - require.Equal(t, totalClaimableAmount, initialModuleBalance, - "Initial module balance should match total claimable amount") - - // Process claim - registerCmd := []string{ - "tx", "claim", "claim", - testData.OldAddress, - testData.NewAddress, - testData.PubKey, - testData.Signature, - "--from", "node0", - } - sut.Logf("Registering claim with command: %s\n", registerCmd) - resp := cli.CustomCommand(registerCmd...) - RequireTxSuccess(t, resp) - - // Verify user received funds - userBalance := cli.QueryBalance(testData.NewAddress, claimtypes.DefaultClaimsDenom) - require.Equal(t, uint64(1_000_000), userBalance, "User should receive claim amount") - - // Verify module balance decreased by claim amount - midModuleBalance := cli.QueryBalance(moduleAddr, claimtypes.DefaultClaimsDenom) - require.Equal(t, uint64(1_000_000), midModuleBalance, - "Module balance should be reduced by claimed amount") - - // Wait for claim period to end - t.Log("Waiting for claim period to end...") - time.Sleep(time.Until(time.Unix(claimEndTime, 0)) + claimPeriodSecs) - - // Wait additional blocks for EndBlocker to process - sut.AwaitNextBlock(t) - sut.AwaitNextBlock(t) - sut.AwaitNextBlock(t) - - // Verify claims are disabled in params - paramsResp := cli.CustomQuery("q", "claim", "params") - enableClaims := gjson.Get(paramsResp, "params.enable_claims").Bool() - require.False(t, enableClaims, "Claims should be disabled after period end") - - // KEY ASSERTION: Verify all remaining tokens were burned - finalModuleBalance := cli.QueryBalance(moduleAddr, claimtypes.DefaultClaimsDenom) - require.Equal(t, uint64(0), finalModuleBalance, - "Module balance should be zero after burn") -} diff --git a/tests/systemtests/claim_test.go b/tests/systemtests/claim_test.go deleted file mode 100644 index ec6e4b35..00000000 --- a/tests/systemtests/claim_test.go +++ /dev/null @@ -1,295 +0,0 @@ -//go:build system_test - -package system - -import ( - "fmt" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" - - claimtestutils "github.com/LumeraProtocol/lumera/x/claim/testutils" - claimtypes "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func TestClaimsSystem(t *testing.T) { - testCases := []struct { - name string - balanceToClaim uint64 - setupFn func(t *testing.T) (claimtestutils.TestData, string) - modifyGenesis func(genesis []byte) []byte - expectSuccess bool - expectedError string - waitBeforeClaim bool - claimAttempts int // number of times to attempt the claim in the same block - }{ - { - name: "successful_claim", - balanceToClaim: 1_000_000, - setupFn: func(t *testing.T) (claimtestutils.TestData, string) { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - return testData, testData.OldAddress - }, - modifyGenesis: func(genesis []byte) []byte { - state, err := sjson.SetRawBytes(genesis, "app_state.claim.total_claimable_amount", []byte("1000000")) - require.NoError(t, err) - return state - }, - expectSuccess: true, - waitBeforeClaim: false, - claimAttempts: 1, - }, - { - // we remove zero balances from csv file by default - name: "claim_with_zero_balance", - balanceToClaim: 0, - setupFn: func(t *testing.T) (claimtestutils.TestData, string) { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - return testData, testData.OldAddress - }, - modifyGenesis: func(genesis []byte) []byte { - state, err := sjson.SetRawBytes(genesis, "app_state.claim.total_claimable_amount", []byte("0")) - require.NoError(t, err) - return state - }, - expectSuccess: false, - expectedError: "claim not found", - waitBeforeClaim: false, - claimAttempts: 1, - }, - { - name: "claims_disabled", - balanceToClaim: 500_000, - setupFn: func(t *testing.T) (claimtestutils.TestData, string) { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - return testData, testData.OldAddress - }, - modifyGenesis: func(genesis []byte) []byte { - state := genesis - var err error - - state, err = sjson.SetRawBytes(state, "app_state.claim.total_claimable_amount", []byte("500000")) - require.NoError(t, err) - - state, err = sjson.SetRawBytes(state, "app_state.claim.params.enable_claims", []byte("false")) - require.NoError(t, err) - - return state - }, - expectSuccess: false, - expectedError: "claim is disabled", - claimAttempts: 1, - }, - { - name: "claim_period_expired", - balanceToClaim: 500_000, - setupFn: func(t *testing.T) (claimtestutils.TestData, string) { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - return testData, testData.OldAddress - }, - modifyGenesis: func(genesis []byte) []byte { - state := genesis - var err error - - state, err = sjson.SetRawBytes(state, "app_state.claim.total_claimable_amount", []byte("500000")) - require.NoError(t, err) - - state, err = sjson.SetRawBytes(state, "app_state.claim.params.enable_claims", []byte("true")) - require.NoError(t, err) - - endTime := time.Now().Add(10 * time.Second).Unix() - state, err = sjson.SetRawBytes(state, "app_state.claim.params.claim_end_time", []byte(strconv.FormatInt(endTime, 10))) - require.NoError(t, err) - - return state - }, - expectSuccess: false, - expectedError: "claim is disabled", - waitBeforeClaim: true, - claimAttempts: 1, - }, - { - name: "duplicate_claim", - balanceToClaim: 500_000, - setupFn: func(t *testing.T) (claimtestutils.TestData, string) { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - return testData, testData.OldAddress - }, - modifyGenesis: func(genesis []byte) []byte { - state := genesis - var err error - - // Set total claimable amount - state, err = sjson.SetRawBytes(state, "app_state.claim.total_claimable_amount", []byte("500000")) - require.NoError(t, err) - - // Set claims per block to 1 - state, err = sjson.SetRawBytes(state, "app_state.claim.params.max_claims_per_block", []byte("10")) - require.NoError(t, err) - - // Enable claims - state, err = sjson.SetRawBytes(state, "app_state.claim.params.enable_claims", []byte("true")) - require.NoError(t, err) - - // Set reasonable claim end time - endTime := time.Now().Add(1 * time.Hour).Unix() - state, err = sjson.SetRawBytes(state, "app_state.claim.params.claim_end_time", []byte(strconv.FormatInt(endTime, 10))) - require.NoError(t, err) - - return state - }, - expectSuccess: false, - expectedError: "claim already claimed", - waitBeforeClaim: false, - claimAttempts: 2, // Try to claim 2 times - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - - sut.ResetChain(t) - - cli := NewLumeradCLI(t, sut, true) - - // Get test data and CSV address - testData, oldAddress := tc.setupFn(t) - - // Apply custom genesis modifications - sut.ModifyGenesisJSON(t, tc.modifyGenesis) - - // generate claims CSV file in temp dir - claimsPath, err := claimtestutils.GenerateClaimsCSVFile([]claimtestutils.ClaimCSVRecord{ - { - OldAddress: oldAddress, - Amount: tc.balanceToClaim, - }, - }, nil) - require.NoError(t, err) - // Ensure the file is cleaned up after the test - t.Cleanup(func() { - claimtestutils.CleanupClaimsCSVFile(claimsPath) - }) - - // Start the chain with modified genesis - sut.StartChain(t, fmt.Sprintf("--%s=%s", claimtypes.FlagClaimsPath, claimsPath)) - - // Wait when needed - if tc.waitBeforeClaim { - t.Log("Waiting for claim period to expire...") - time.Sleep(11 * time.Second) - } - - var lastResp string - // Register claim multiple times if specified - for i := 0; i < tc.claimAttempts; i++ { - registerCmd := []string{ - "tx", "claim", "claim", - testData.OldAddress, // Old address - testData.NewAddress, // New address - testData.PubKey, // PubKey - testData.Signature, // Signature - "--from", "node0", - } - - lastResp = cli.CustomCommand(registerCmd...) - - // For multiple attempts, only the first one should succeed - if i == 0 && tc.expectSuccess { - RequireTxSuccess(t, lastResp) - } - } - - // Validate the final response - if tc.expectSuccess { - RequireTxSuccess(t, lastResp) - - // Get txhash and query transaction - txHash := gjson.Get(lastResp, "txhash").String() - require.NotEmpty(t, txHash, "txhash not found in response") - - txResp := cli.CustomQuery("q", "tx", txHash) - require.NotEmpty(t, txResp) - - // Verify claim_processed event and transfer from module - events := gjson.Get(txResp, "events") - require.True(t, events.Exists()) - - foundClaimEvent := false - foundModuleTransfer := false - - for _, event := range events.Array() { - eventType := event.Get("type").String() - attrs := event.Get("attributes").Array() - - // Check claim_processed event - if eventType == "claim_processed" { - foundClaimEvent = true - for _, attr := range attrs { - key := attr.Get("key").String() - value := attr.Get("value").String() - switch key { - case "module": - require.Equal(t, "claim", value) - case "amount": - require.Equal(t, strconv.FormatUint(tc.balanceToClaim, 10) + claimtypes.DefaultClaimsDenom, value) - case "old_address": - require.Equal(t, testData.OldAddress, value) - case "new_address": - require.Equal(t, testData.NewAddress, value) - } - } - } - - // Check for transfer from module to recipient - if eventType == "transfer" { - // Only interested in msg_index=0 which relates to the claim operation - msgIndexAttr := false - for _, attr := range attrs { - if attr.Get("key").String() == "msg_index" && attr.Get("value").String() == "0" { - msgIndexAttr = true - break - } - } - - if msgIndexAttr { - recipient := "" - amount := "" - - for _, attr := range attrs { - if attr.Get("key").String() == "recipient" { - recipient = attr.Get("value").String() - } else if attr.Get("key").String() == "amount" { - amount = attr.Get("value").String() - } - } - - if recipient == testData.NewAddress && - amount == (strconv.FormatUint(tc.balanceToClaim, 10) + claimtypes.DefaultClaimsDenom) { - foundModuleTransfer = true - } - } - } - } - - require.True(t, foundClaimEvent, "claim_processed event not found") - require.True(t, foundModuleTransfer, "module transfer to recipient not found") - - // Verify balance after claim - balance := cli.QueryBalance(testData.NewAddress, claimtypes.DefaultClaimsDenom) - require.Equal(t, tc.balanceToClaim, balance) - } else { - RequireTxFailure(t, lastResp, tc.expectedError) - } - }) - } -} diff --git a/tests/systemtests/claims_params_test.go b/tests/systemtests/claims_params_test.go deleted file mode 100644 index ac911fbe..00000000 --- a/tests/systemtests/claims_params_test.go +++ /dev/null @@ -1,116 +0,0 @@ -//go:build system_test - -package system - -import ( - "fmt" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" - - lcfg "github.com/LumeraProtocol/lumera/config" - claimtypes "github.com/LumeraProtocol/lumera/x/claim/types" -) - -// Voting Period is set to 10 seconds for faster test execution by default -func TestClaimsUpdateParamsProposal(t *testing.T) { - // Initialize and reset chain - sut.ResetChain(t) - - // Set initial parameters in genesis - initialEndTime := time.Now().Add(48 * time.Hour).Unix() - sut.ModifyGenesisJSON(t, - // Set shorter voting period for faster test execution - SetGovVotingPeriod(t, 10*time.Second), - // Set initial claim parameters - func(genesis []byte) []byte { - state := genesis - var err error - - // Set total claimable amount - state, err = sjson.SetRawBytes(state, "app_state.claim.total_claimable_amount", - []byte(strconv.FormatInt(claimtypes.DefaultClaimableAmountConst, 10))) - require.NoError(t, err) - - state, err = sjson.SetRawBytes(state, "app_state.claim.params", []byte(fmt.Sprintf(`{ - "enable_claims": true, - "claim_end_time": "%d", - "max_claims_per_block": "75" - }`, initialEndTime))) - require.NoError(t, err) - - return state - }, - ) - - // Start the chain - sut.StartChain(t) - - // Create CLI helper - cli := NewLumeradCLI(t, sut, true) - - // Get and verify initial parameters - initialParams := cli.CustomQuery("q", "claim", "params") - t.Logf("Initial params: %s", initialParams) - - require.True(t, gjson.Get(initialParams, "params.enable_claims").Bool(), "initial enable_claims should be true") - require.Equal(t, "75", gjson.Get(initialParams, "params.max_claims_per_block").String(), "initial max_claims_per_block should be 75") - require.Equal(t, fmt.Sprintf("%d", initialEndTime), gjson.Get(initialParams, "params.claim_end_time").String(), "initial claim_end_time should match") - - // Get gov module account address - govAcctResp := cli.CustomQuery("q", "auth", "module-account", "gov") - t.Logf("Gov account response: %s", govAcctResp) - govAddr := gjson.Get(govAcctResp, "account.value.address").String() - require.NotEmpty(t, govAddr, "gov module address should not be empty") - - // Create governance proposal to update parameters - proposalJson := fmt.Sprintf(`{ - "messages": [{ - "@type": "/lumera.claim.MsgUpdateParams", - "authority": "%s", - "params": { - "enable_claims": false, - "claim_end_time": %d, - "max_claims_per_block": 50 - } - }], - "deposit": "100000000%s", - "metadata": "ipfs://CID", - "title": "Update Claim Parameters", - "summary": "Update claims module parameters with new values" - }`, govAddr, time.Now().Add(72*time.Hour).Unix(), lcfg.ChainDenom) - - // Submit proposal and have all validators vote yes - proposalID := cli.SubmitAndVoteGovProposal(proposalJson) - require.NotEmpty(t, proposalID) - - // Wait for proposal to be executed (aligned with the shortened voting period) - var proposalPassed bool - deadline := time.Now().Add(30 * time.Second) - for time.Now().Before(deadline) { - sut.AwaitNextBlock(t) - status := cli.CustomQuery("q", "gov", "proposal", proposalID) - if gjson.Get(status, "proposal.status").String() == "PROPOSAL_STATUS_PASSED" { - proposalPassed = true - break - } - } - require.True(t, proposalPassed, "proposal did not pass") - - // Query and verify updated parameters - updatedParams := cli.CustomQuery("q", "claim", "params") - t.Logf("Updated params: %s", updatedParams) - - require.False(t, gjson.Get(updatedParams, "params.enable_claims").Bool(), "enable_claims should be false") - require.Equal(t, "50", gjson.Get(updatedParams, "params.max_claims_per_block").String(), "max_claims_per_block should be 50") - - // The end time would be approximately 72 hours from when the proposal passed - updatedEndTime := gjson.Get(updatedParams, "params.claim_end_time").Int() - expectedEndTime := time.Now().Add(72 * time.Hour).Unix() - require.InDelta(t, expectedEndTime, updatedEndTime, float64(time.Hour.Seconds()), - "claim_end_time should be approximately 72 hours from now") -} diff --git a/tests/systemtests/claims_per_block_test.go b/tests/systemtests/claims_per_block_test.go deleted file mode 100644 index 44442ea6..00000000 --- a/tests/systemtests/claims_per_block_test.go +++ /dev/null @@ -1,399 +0,0 @@ -//go:build system_test - -package system - -import ( - "fmt" - "sync" - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" - - claimtestutils "github.com/LumeraProtocol/lumera/x/claim/testutils" - claimtypes "github.com/LumeraProtocol/lumera/x/claim/types" -) - -// System-wide constants that define test parameters and expected behavior -const ( - // Amount of tokens allocated per individual claim - tokensPerClaim = 1000000 // 1M tokens per claim - - // Response codes that indicate transaction status - successCode = "0" // Indicates successful claim processing - errCodeTooManyClaims = "1102" // Error code when block claim limit is exceeded - - // Test configuration parameters - numTestEntries = 10 // Total number of test cases to generate - maxClaimsPerBlock = 2 // Maximum allowed claims per block - numTxToSubmit = maxClaimsPerBlock + 1 // Intentionally exceed block limit by 1 -) - -// TestMaxClaimsPerBlockReset is a system test that verifies the block-level claim limiting mechanism. -// The test ensures that: -// 1. Claims are properly limited per block according to maxClaimsPerBlock -// 2. The claim counter correctly resets between blocks -// 3. Failed claims receive appropriate error codes -// 4. Successful claims are processed correctly -// -// Test Flow: -// Block N: -// - Submit maxClaimsPerBlock + 1 transactions concurrently -// - Verify exactly maxClaimsPerBlock succeed -// - Verify the excess transaction fails with correct error -// -// Block N+1: -// - Submit another batch of maxClaimsPerBlock + 1 transactions concurrently -// - Verify the limit has reset and exactly maxClaimsPerBlock new claims succeed -// - Verify the excess transaction fails appropriately -func TestMaxClaimsPerBlockReset(t *testing.T) { - t.Log("Starting TestMaxClaimsPerBlockReset...") - - // Initialize clean test environment - t.Log("Resetting chain...") - sut.ResetChain(t) - - // Create test dataset and calculate total tokens needed - testDataSet, totalClaimableAmount := generateClaimTestData(t) - var csvData []claimtestutils.ClaimCSVRecord - // convert test data to CSV format - for _, data := range testDataSet { - csvData = append(csvData, claimtestutils.ClaimCSVRecord{ - OldAddress: data.OldAddress, - Amount: tokensPerClaim, - }) - } - claimsPath, err := claimtestutils.GenerateClaimsCSVFile(csvData, nil) - require.NoError(t, err) - - // Ensure the file is cleaned up after the test - t.Cleanup(func() { - claimtestutils.CleanupClaimsCSVFile(claimsPath) - }) - - // Configure chain with test parameters - claimEndTime := time.Now().Add(1 * time.Hour).Unix() - setClaimsGenesis(t, totalClaimableAmount, fmt.Sprintf("%d", maxClaimsPerBlock), true, claimEndTime) - - t.Log("Starting chain...") - sut.StartChain(t, fmt.Sprintf("--%s=%s", claimtypes.FlagClaimsPath, claimsPath)) - cli := NewLumeradCLI(t, sut, true) - - // Record initial block for comparison - status := cli.CustomQuery("status") - startingHeight := gjson.Get(status, "sync_info.latest_block_height").Int() - t.Logf("Starting block height: %d", startingHeight) - - // First Block: Test claim limiting with concurrent submissions - t.Logf("Block %d: Submitting %d claims concurrently (max allowed is %d)...", startingHeight+1, numTxToSubmit, maxClaimsPerBlock) - - // WaitGroup to wait for all goroutines to complete - var wg sync.WaitGroup - // Channel to collect responses from goroutines - type responseItem struct { - index int - resp string - } - responseChannel := make(chan responseItem, numTxToSubmit) - - for i := 0; i < numTxToSubmit; i++ { - wg.Add(1) - go func(index int) { - defer wg.Done() - - testData := testDataSet[index] - // Construct claim transaction with necessary parameters - args := []string{ - "tx", "claim", "claim", - testData.OldAddress, - testData.NewAddress, - testData.PubKey, - testData.Signature, - "--from", fmt.Sprintf("node%d", index), - "--broadcast-mode", "sync", - "--chain-id", cli.chainID, - "--home", cli.homeDir, - "--keyring-backend", "test", - "--node", cli.nodeAddress, - "--output", "json", - "--yes", - "--fees", cli.fees, - } - - resp, ok := cli.run(args) - - t.Logf("Claim %d submission output: %s", index+1, resp) - require.True(t, ok) - - // Send result to channel - responseChannel <- responseItem{index: index, resp: resp} - }(i) - } - - // Close channel in a separate goroutine after all workers are done - go func() { - wg.Wait() - close(responseChannel) - }() - - // Collect all responses from the channel - firstBlockResponses := make([]string, numTxToSubmit) - for item := range responseChannel { - firstBlockResponses[item.index] = item.resp - } - - // Allow time for block completion and transaction processing - t.Log("Waiting for first block to complete...") - time.Sleep(12 * time.Second) - - // Extract first block details for verification - firstBlockTxHash := gjson.Get(firstBlockResponses[0], "txhash").String() - firstBlockTxResp := cli.CustomQuery("q", "tx", firstBlockTxHash) - firstBlockHeight := gjson.Get(firstBlockTxResp, "height").String() - - // Analyze first block results - var firstBlockSuccess, firstBlockErrors int - for i, resp := range firstBlockResponses { - txHash := gjson.Get(resp, "txhash").String() - require.NotEmpty(t, txHash, "txhash not found in response") - - txResp := cli.CustomQuery("q", "tx", txHash) - txCode := gjson.Get(txResp, "code").String() - txHeight := gjson.Get(txResp, "height").String() - - // Verify all transactions are in same block - require.Equal(t, firstBlockHeight, txHeight, "All first block transactions should be in the same block") - - if txCode == successCode { - firstBlockSuccess++ - verifySuccessfulClaim(t, txResp, testDataSet[i]) - } - if txCode == errCodeTooManyClaims { - firstBlockErrors++ - } - } - - t.Logf("First block results - Successful: %d, Failed: %d", firstBlockSuccess, firstBlockErrors) - require.Equal(t, maxClaimsPerBlock, firstBlockSuccess, "Expected exactly maxClaimsPerBlock successful claims in first block") - require.Equal(t, 1, firstBlockErrors, "Expected exactly one failed claim in first block") - - // Second Block: Verify limit reset with concurrent submissions - t.Log("Submitting second batch of claims concurrently in new block...") - - // Channel for second block responses - secondResponseChannel := make(chan responseItem, numTxToSubmit) - // Reset WaitGroup for second block - var wg2 sync.WaitGroup - - for i := 0; i < numTxToSubmit; i++ { - wg2.Add(1) - go func(index int) { - defer wg2.Done() - - testData := testDataSet[index+numTxToSubmit] // Use next set of test data - args := []string{ - "tx", "claim", "claim", - testData.OldAddress, - testData.NewAddress, - testData.PubKey, - testData.Signature, - "--from", fmt.Sprintf("node%d", index), - "--broadcast-mode", "sync", - "--chain-id", cli.chainID, - "--home", cli.homeDir, - "--keyring-backend", "test", - "--node", cli.nodeAddress, - "--output", "json", - "--yes", - "--fees", cli.fees, - } - - resp, ok := cli.run(args) - - t.Logf("Second block claim %d submission output: %s", index+1, resp) - require.True(t, ok) - - // Send result to channel - secondResponseChannel <- responseItem{index: index, resp: resp} - }(i) - } - - // Close channel after all workers are done - go func() { - wg2.Wait() - close(secondResponseChannel) - }() - - // Collect responses from the channel - secondBlockResponses := make([]string, numTxToSubmit) - for item := range secondResponseChannel { - secondBlockResponses[item.index] = item.resp - } - - // Allow time for second block processing - t.Log("Waiting for second block to complete...") - time.Sleep(12 * time.Second) - - // Extract second block details - secondBlockTxHash := gjson.Get(secondBlockResponses[0], "txhash").String() - secondBlockTxResp := cli.CustomQuery("q", "tx", secondBlockTxHash) - secondBlockHeight := gjson.Get(secondBlockTxResp, "height").String() - - // Ensure blocks are distinct - require.NotEqual(t, firstBlockHeight, secondBlockHeight, "Second batch should be in a different block") - - // Analyze second block results - var secondBlockSuccess, secondBlockErrors int - for i, resp := range secondBlockResponses { - txHash := gjson.Get(resp, "txhash").String() - require.NotEmpty(t, txHash, "txhash not found in response") - - txResp := cli.CustomQuery("q", "tx", txHash) - txCode := gjson.Get(txResp, "code").String() - txHeight := gjson.Get(txResp, "height").String() - - require.Equal(t, secondBlockHeight, txHeight, "All second block transactions should be in the same block") - - if txCode == successCode { - secondBlockSuccess++ - verifySuccessfulClaim(t, txResp, testDataSet[i+numTxToSubmit]) - } - if txCode == errCodeTooManyClaims { - secondBlockErrors++ - } - } - - t.Logf("Second block results - Successful: %d, Failed: %d", secondBlockSuccess, secondBlockErrors) - require.Equal(t, maxClaimsPerBlock, secondBlockSuccess, "Expected exactly maxClaimsPerBlock successful claims in second block") - require.Equal(t, 1, secondBlockErrors, "Expected exactly one failed claim in second block") -} - -// generateClaimTestData creates a set of test data entries for claims testing. -// Returns: -// - Array of TestData structures containing claim information -// - Total amount of tokens that should be made available for claims -func generateClaimTestData(t *testing.T) ([]claimtestutils.TestData, int64) { - t.Log("Generating test data...") - var testDataSet []claimtestutils.TestData - var totalClaimableAmount int64 - - for i := 0; i < numTestEntries; i++ { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - testDataSet = append(testDataSet, testData) - totalClaimableAmount += tokensPerClaim - } - t.Logf("Generated %d test data entries", len(testDataSet)) - - return testDataSet, totalClaimableAmount -} - -// setClaimsGenesis configures the genesis state for claims testing. -// Parameters: -// - totalClaimableAmount: Total tokens available for claims -// - maxClaimsPerBlock: Maximum number of claims allowed per block -// - enableClaims: Whether claiming is enabled -// - claimEndTime: Unix timestamp when claiming period ends -func setClaimsGenesis(t *testing.T, totalClaimableAmount int64, maxClaimsPerBlock string, enableClaims bool, claimEndTime int64) { - t.Log("Modifying genesis configuration...") - sut.ModifyGenesisJSON(t, func(genesis []byte) []byte { - state := genesis - var err error - - // Configure total tokens available for claims - state, err = sjson.SetRawBytes(state, "app_state.claim.total_claimable_amount", []byte(fmt.Sprintf("%d", totalClaimableAmount))) - require.NoError(t, err) - - // Set maximum claims allowed per block - state, err = sjson.SetRawBytes(state, "app_state.claim.params.max_claims_per_block", []byte(maxClaimsPerBlock)) - require.NoError(t, err) - - // Enable or disable claiming functionality - state, err = sjson.SetRawBytes(state, "app_state.claim.params.enable_claims", []byte("true")) - require.NoError(t, err) - - // Set the deadline for making claims - state, err = sjson.SetRawBytes(state, "app_state.claim.params.claim_end_time", []byte(fmt.Sprintf("%d", claimEndTime))) - require.NoError(t, err) - - return state - }) -} - -// verifySuccessfulClaim checks that a successful claim transaction -// contains all required events and correct data. -// Parameters: -// - txResp: Transaction response JSON -// - testData: Expected claim data to verify against -func verifySuccessfulClaim(t *testing.T, txResp string, testData claimtestutils.TestData) { - events := gjson.Get(txResp, "events").Array() - - var foundClaimProcessed bool - var foundTransfer bool - var foundMsgClaim bool - - // Examine each event in the transaction - for _, event := range events { - eventType := event.Get("type").String() - attrs := event.Get("attributes").Array() - - switch eventType { - case "claim_processed": - // Verify claim processing details - foundClaimProcessed = true - for _, attr := range attrs { - key := attr.Get("key").String() - value := attr.Get("value").String() - - switch key { - case "module": - require.Equal(t, "claim", value) - case "amount": - require.Equal(t, fmt.Sprintf("%dulume", tokensPerClaim), value) - case "old_address": - require.Equal(t, testData.OldAddress, value) - case "new_address": - require.Equal(t, testData.NewAddress, value) - case "claim_time": - require.NotEmpty(t, value) - } - } - - case "transfer": - // Verify token transfer details - var hasCorrectTransfer bool - for _, attr := range attrs { - if attr.Get("key").String() == "amount" && - attr.Get("value").String() == fmt.Sprintf("%dulume", tokensPerClaim) { - hasCorrectTransfer = true - foundTransfer = true - break - } - } - if hasCorrectTransfer { - // Confirm recipient address - for _, attr := range attrs { - if attr.Get("key").String() == "recipient" { - require.Equal(t, testData.NewAddress, attr.Get("value").String()) - } - } - } - - case "message": - // Verify message type - for _, attr := range attrs { - if attr.Get("key").String() == "action" && - attr.Get("value").String() == "/lumera.claim.MsgClaim" { - foundMsgClaim = true - } - } - } - } - - // Ensure all required events were found - require.True(t, foundClaimProcessed, "claim_processed event not found") - require.True(t, foundTransfer, "transfer event not found") - require.True(t, foundMsgClaim, "MsgClaim action not found") -} diff --git a/tests/systemtests/delayed_claim_test.go b/tests/systemtests/delayed_claim_test.go deleted file mode 100644 index 2dbdae22..00000000 --- a/tests/systemtests/delayed_claim_test.go +++ /dev/null @@ -1,375 +0,0 @@ -//go:build system_test - -package system - -import ( - "fmt" - "strconv" - "testing" - "time" - - "github.com/stretchr/testify/require" - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" - - claimtestutils "github.com/LumeraProtocol/lumera/x/claim/testutils" - claimtypes "github.com/LumeraProtocol/lumera/x/claim/types" - lcfg "github.com/LumeraProtocol/lumera/config" -) - -func TestDelayedClaimsSystem(t *testing.T) { - testCases := []struct { - name string - balanceToClaim uint64 - setupFn func(t *testing.T, cli *LumeradCli) (claimtestutils.TestData, string) - modifyGenesis func(genesis []byte) []byte - expectSuccess bool - expectedError string - waitBeforeClaim bool - claimAttempts int // number of times to attempt the claim in the same block - tier string - from string - }{ - { - name: "successful_claim", - balanceToClaim: 1_000_000, - setupFn: func(t *testing.T, cli *LumeradCli) (claimtestutils.TestData, string) { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - return testData, testData.OldAddress - }, - modifyGenesis: func(genesis []byte) []byte { - state, err := sjson.SetRawBytes(genesis, "app_state.claim.total_claimable_amount", []byte("1000000")) - require.NoError(t, err) - return state - }, - expectSuccess: true, - waitBeforeClaim: false, - claimAttempts: 1, - tier: "1", - from: "node0", - }, - { - name: "successful_claim_from_same_address", - balanceToClaim: 1_000_000, - setupFn: func(t *testing.T, cli *LumeradCli) (claimtestutils.TestData, string) { - return claimtestutils.TestData{}, "" - }, - modifyGenesis: func(genesis []byte) []byte { - state, err := sjson.SetRawBytes(genesis, "app_state.claim.total_claimable_amount", []byte("1000000")) - require.NoError(t, err) - return state - }, - expectSuccess: true, - waitBeforeClaim: false, - claimAttempts: 1, - tier: "1", - from: "test_1", - }, - { - // we remove zero balances from csv file by default - name: "claim_with_zero_balance", - balanceToClaim: 0, - setupFn: func(t *testing.T, cli *LumeradCli) (claimtestutils.TestData, string) { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - return testData, testData.OldAddress - }, - modifyGenesis: func(genesis []byte) []byte { - state, err := sjson.SetRawBytes(genesis, "app_state.claim.total_claimable_amount", []byte("0")) - require.NoError(t, err) - return state - }, - expectSuccess: false, - expectedError: "claim not found", - waitBeforeClaim: false, - claimAttempts: 1, - tier: "1", - from: "node0", - }, - { - name: "claims_disabled", - balanceToClaim: 500_000, - setupFn: func(t *testing.T, cli *LumeradCli) (claimtestutils.TestData, string) { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - return testData, testData.OldAddress - }, - modifyGenesis: func(genesis []byte) []byte { - state := genesis - var err error - - state, err = sjson.SetRawBytes(state, "app_state.claim.total_claimable_amount", []byte("500000")) - require.NoError(t, err) - - state, err = sjson.SetRawBytes(state, "app_state.claim.params.enable_claims", []byte("false")) - require.NoError(t, err) - - return state - }, - expectSuccess: false, - expectedError: "claim is disabled", - claimAttempts: 1, - tier: "1", - from: "node0", - }, - { - name: "claim_period_expired", - balanceToClaim: 500_000, - setupFn: func(t *testing.T, cli *LumeradCli) (claimtestutils.TestData, string) { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - return testData, testData.OldAddress - }, - modifyGenesis: func(genesis []byte) []byte { - state := genesis - var err error - - state, err = sjson.SetRawBytes(state, "app_state.claim.total_claimable_amount", []byte("500000")) - require.NoError(t, err) - - state, err = sjson.SetRawBytes(state, "app_state.claim.params.enable_claims", []byte("true")) - require.NoError(t, err) - - endTime := time.Now().Add(10 * time.Second).Unix() - state, err = sjson.SetRawBytes(state, "app_state.claim.params.claim_end_time", []byte(strconv.FormatInt(endTime, 10))) - require.NoError(t, err) - - return state - }, - expectSuccess: false, - expectedError: "claim is disabled", - waitBeforeClaim: true, - claimAttempts: 1, - tier: "1", - from: "node0", - }, - { - name: "duplicate_claim", - balanceToClaim: 500_000, - setupFn: func(t *testing.T, cli *LumeradCli) (claimtestutils.TestData, string) { - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - return testData, testData.OldAddress - }, - modifyGenesis: func(genesis []byte) []byte { - state := genesis - var err error - - // Set total claimable amount - state, err = sjson.SetRawBytes(state, "app_state.claim.total_claimable_amount", []byte("500000")) - require.NoError(t, err) - - // Set claims per block to 1 - state, err = sjson.SetRawBytes(state, "app_state.claim.params.max_claims_per_block", []byte("10")) - require.NoError(t, err) - - // Enable claims - state, err = sjson.SetRawBytes(state, "app_state.claim.params.enable_claims", []byte("true")) - require.NoError(t, err) - - // Set reasonable claim end time - endTime := time.Now().Add(1 * time.Hour).Unix() - state, err = sjson.SetRawBytes(state, "app_state.claim.params.claim_end_time", []byte(strconv.FormatInt(endTime, 10))) - require.NoError(t, err) - - return state - }, - expectSuccess: false, - expectedError: "claim already claimed", - waitBeforeClaim: false, - claimAttempts: 2, // Try to claim 2 times - tier: "1", - from: "node0", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - - sut.ResetChain(t) - - cli := NewLumeradCLI(t, sut, true) - - // Get test data and CSV address - testData, csvAddress := tc.setupFn(t, cli) - - // Apply custom genesis modifications - sut.ModifyGenesisJSON(t, tc.modifyGenesis) - - var pastelAccount claimtestutils.PastelAccount - if tc.name == "successful_claim_from_same_address" { - var err error - pastelAccount, err = claimtestutils.GeneratePastelAddress() - require.NoError(t, err) - csvAddress = pastelAccount.Address - } - - // generate CSV file with claim data - claimsPath, err := claimtestutils.GenerateClaimsCSVFile([]claimtestutils.ClaimCSVRecord{ - { - OldAddress: csvAddress, - Amount: tc.balanceToClaim, - }, - }, nil) - require.NoError(t, err) - - t.Cleanup(func() { - claimtestutils.CleanupClaimsCSVFile(claimsPath) - }) - - // Start the chain with modified genesis - sut.StartChain(t, fmt.Sprintf("--%s=%s", claimtypes.FlagClaimsPath, claimsPath)) - - // Wait when needed - if tc.waitBeforeClaim { - t.Log("Waiting for claim period to expire...") - time.Sleep(11 * time.Second) - } - - if tc.name == "successful_claim_from_same_address" { - address := cli.AddKey("test_1") - cli.FundAddress(address, "1" + lcfg.ChainDenom) - testData, err = claimtestutils.GenerateClaimingTestData2(pastelAccount, address) - require.NoError(t, err) - - // Verify account exist and it is Base account - baseAccount := cli.GetAccount(testData.NewAddress) - require.NotNil(t, baseAccount, "account not found") - baseAccountType := gjson.Get(baseAccount, "account.type").String() - require.Equal(t, "/cosmos.auth.v1beta1.BaseAccount", baseAccountType, "account type mismatch") - } - - var lastResp string - // Register claim multiple times if specified - for i := 0; i < tc.claimAttempts; i++ { - registerCmd := []string{ - "tx", "claim", "delayed-claim", - testData.OldAddress, // Old address - testData.NewAddress, // New address - testData.PubKey, // PubKey - testData.Signature, // Signature - tc.tier, // Tier - "--from", tc.from, // From address - } - - lastResp = cli.CustomCommand(registerCmd...) - - // For multiple attempts, only the first one should succeed - if i == 0 && tc.expectSuccess { - RequireTxSuccess(t, lastResp) - } - } - - // Validate the final response - if tc.expectSuccess { - RequireTxSuccess(t, lastResp) - - // Get txhash and query transaction - txHash := gjson.Get(lastResp, "txhash").String() - require.NotEmpty(t, txHash, "txhash not found in response") - - txResp := cli.CustomQuery("q", "tx", txHash) - require.NotEmpty(t, txResp) - - // Verify delayed_claim_processed event and transfer from module - events := gjson.Get(txResp, "events") - require.True(t, events.Exists()) - - foundClaimEvent := false - foundModuleTransfer := false - - var claimTime, delayedTime int64 - for _, event := range events.Array() { - eventType := event.Get("type").String() - attrs := event.Get("attributes").Array() - - // Check delayed_claim_processed event - if eventType == "delayed_claim_processed" { - foundClaimEvent = true - for _, attr := range attrs { - key := attr.Get("key").String() - value := attr.Get("value").String() - switch key { - case "module": - require.Equal(t, "claim", value) - case "amount": - require.Equal(t, strconv.FormatUint(tc.balanceToClaim, 10) + claimtypes.DefaultClaimsDenom, value) - case "old_address": - require.Equal(t, testData.OldAddress, value) - case "new_address": - require.Equal(t, testData.NewAddress, value) - case "delayed_end_time": - delayedTime = attr.Get("value").Int() - case "claim_time": - claimTime = attr.Get("value").Int() - } - } - require.Greater(t, delayedTime, claimTime, "delayed_end_time should be greater than claim_time") - // delayedTime = claimTime + 6 month * tc.tier - //tier, _ := strconv.ParseInt(tc.tier, 10, 64) - //endTime := time.Unix(claimTime, 0).AddDate(0, int(tier*6), 0).Unix() - 3600 - //require.Equal(t, endTime, delayedTime, "delayed_end_time should be equal to claim_time + 6 month * tc.tier") - } - - // Check for transfer from module to recipient - if eventType == "transfer" { - // Only interested in msg_index=0 which relates to the claim operation - msgIndexAttr := false - for _, attr := range attrs { - if attr.Get("key").String() == "msg_index" && attr.Get("value").String() == "0" { - msgIndexAttr = true - break - } - } - - if msgIndexAttr { - recipient := "" - amount := "" - - for _, attr := range attrs { - if attr.Get("key").String() == "recipient" { - recipient = attr.Get("value").String() - } else if attr.Get("key").String() == "amount" { - amount = attr.Get("value").String() - } - } - - if recipient == testData.NewAddress && - amount == (strconv.FormatUint(tc.balanceToClaim, 10) + claimtypes.DefaultClaimsDenom) { - foundModuleTransfer = true - } - } - } - } - - require.True(t, foundClaimEvent, "claim_processed event not found") - require.True(t, foundModuleTransfer, "module transfer to recipient not found") - - // Verify balance after claim - balance := cli.QueryBalance(testData.NewAddress, claimtypes.DefaultClaimsDenom) - require.Equal(t, tc.balanceToClaim, balance) - - // Verify vested account creation - vestingAccount := cli.GetAccount(testData.NewAddress) - require.NotNil(t, vestingAccount, "account not found") - // Check if the account is a vesting account - vestingAccountType := gjson.Get(vestingAccount, "account.type").String() - require.Equal(t, "/cosmos.vesting.v1beta1.DelayedVestingAccount", vestingAccountType, "account type mismatch") - // Check if the account has a vesting schedule - vestingSchedule := gjson.Get(vestingAccount, "account.value.base_vesting_account.end_time").Int() - require.Greater(t, vestingSchedule, int64(0), "vesting schedule not found") - // check end_time is equal to delayed_end_time - require.Equal(t, delayedTime, vestingSchedule, "vesting schedule mismatch") - // Check if the account has a balance - vesting_balance := gjson.Get(vestingAccount, "account.value.base_vesting_account.original_vesting").Array() - require.NotEmpty(t, vesting_balance, "account balance not found") - // check amount is equal to balanceToClaim, convert to uint64 - amount := gjson.Get(vestingAccount, "account.value.base_vesting_account.original_vesting.0.amount").Uint() - require.Equal(t, tc.balanceToClaim, amount, "account balance mismatch") - } else { - RequireTxFailure(t, lastResp, tc.expectedError) - } - }) - } -} diff --git a/tests/systemtests/main_test.go b/tests/systemtests/main_test.go index ae964643..19bde2d5 100644 --- a/tests/systemtests/main_test.go +++ b/tests/systemtests/main_test.go @@ -31,6 +31,8 @@ func TestMain(m *testing.M) { blockTime := flag.Duration("block-time", 1000*time.Millisecond, "block creation time") execBinary := flag.String("binary", "lumerad", "executable binary for server/ client side") bech32Prefix := flag.String("bech32", "lumera", "bech32 prefix to be used with addresses") + claimsPath := flag.String("claims-path", "", "path to claims.csv file or directory") + skipClaimsCheck := flag.Bool("skip-claims-check", false, "skip claims.csv validation") flag.BoolVar(&verbose, "verbose", true, "verbose output") flag.Parse() @@ -53,6 +55,8 @@ func TestMain(m *testing.M) { } execBinaryName = *execBinary sut = NewSystemUnderTest(*execBinary, verbose, *nodesCount, *blockTime) + sut.SetClaimsPath(*claimsPath) + sut.SetSkipClaimsCheck(*skipClaimsCheck) if *rebuild { sut.BuildNewBinary() } diff --git a/tests/systemtests/system.go b/tests/systemtests/system.go index 350dc450..b591b23b 100644 --- a/tests/systemtests/system.go +++ b/tests/systemtests/system.go @@ -47,11 +47,13 @@ var ( // SystemUnderTest blockchain provisioning type SystemUnderTest struct { - ExecBinary string - blockListener *EventListener - currentHeight int64 - chainID string - outputDir string + ExecBinary string + blockListener *EventListener + currentHeight int64 + chainID string + outputDir string + claimsPath string + skipClaimsCheck bool // blockTime is the expected/desired block time. This is not going to be very precise // since Tendermint consensus does not allow specifying it directly. blockTime time.Duration @@ -168,7 +170,14 @@ func (s *SystemUnderTest) StartChain(t *testing.T, xargs ...string) { t.Helper() s.Log("Start chain\n") s.ChainStarted = true - s.startNodesAsync(t, append([]string{"start", "--trace", "--log_level=info"}, xargs...)...) + args := []string{"start", "--trace", "--log_level=info"} + if s.claimsPath != "" { + args = append(args, "--claims-path="+s.claimsPath) + } + if s.skipClaimsCheck { + args = append(args, "--skip-claims-check") + } + s.startNodesAsync(t, append(args, xargs...)...) s.AwaitNodeUp(t, s.rpcAddr) @@ -184,6 +193,14 @@ func (s *SystemUnderTest) StartChain(t *testing.T, xargs ...string) { s.AwaitNextBlock(t, 4e9) } +func (s *SystemUnderTest) SetClaimsPath(path string) { + s.claimsPath = path +} + +func (s *SystemUnderTest) SetSkipClaimsCheck(skip bool) { + s.skipClaimsCheck = skip +} + // MarkDirty whole chain will be reset when marked dirty func (s *SystemUnderTest) MarkDirty() { s.dirty = true diff --git a/x/action/v1/simulation/helpers.go b/x/action/v1/simulation/helpers.go index 0779376b..ba8504fe 100644 --- a/x/action/v1/simulation/helpers.go +++ b/x/action/v1/simulation/helpers.go @@ -26,16 +26,16 @@ import ( func registerSenseAction(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, bk types.BankKeeper, k keeper.Keeper, ak types.AuthKeeper) (string, *types.MsgRequestAction) { params := k.GetParams(ctx) - // 1. Select random account with enough balance - simAccount := selectRandomAccountWithSufficientFunds(r, ctx, accs, bk, ak, []string{""}) + // 1. Determine fee amount (within valid range) + feeAmount := generateRandomFee(r, ctx, params.BaseActionFee.Add(params.FeePerKbyte)) + + // 2. Select random account with enough spendable balance for the fee + simAccount := selectRandomAccountWithSufficientFunds(r, ctx, accs, bk, ak, feeAmount, []string{""}) - // 2. Generate random valid SENSE metadata + // 3. Generate random valid SENSE metadata dataHash := generateRandomHash(r) senseMetadata := generateRequestActionSenseMetadata(dataHash) - // 3. Determine fee amount (within valid range) - feeAmount := generateRandomFee(r, ctx, params.BaseActionFee.Add(params.FeePerKbyte)) - // 4. Generate an expiration time (current time + random duration >= expiration_duration) expirationTime := getRandomExpirationTime(ctx, r, params) @@ -65,23 +65,17 @@ func registerSenseAction(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, func registerCascadeAction(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, bk types.BankKeeper, k keeper.Keeper, ak types.AuthKeeper) (string, *types.MsgRequestAction) { params := k.GetParams(ctx) - // 1. Select random account with enough balance - simAccount := selectRandomAccountWithSufficientFunds(r, ctx, accs, bk, ak, []string{""}) + // 1. Determine fee amount (within valid range) + feeAmount := generateRandomFee(r, ctx, params.BaseActionFee.Add(params.FeePerKbyte)) - // 2. Set account public key - err := addPubKeyToAccount(ctx, simAccount, ak) - if err != nil { - panic(fmt.Sprintf("failed to set account public key: %v", err)) - } + // 2. Select random account with enough spendable balance for the fee + simAccount := selectRandomAccountWithSufficientFunds(r, ctx, accs, bk, ak, feeAmount, []string{""}) - // 2. Generate random valid CASCADE metadata + // 3. Generate random valid CASCADE metadata dataHash := generateRandomHash(r) fileName := generateRandomFileName(r) cascadeMetadata := generateRequestActionCascadeMetadata(dataHash, fileName, simAccount) - // 3. Determine fee amount (within valid range) - feeAmount := generateRandomFee(r, ctx, params.BaseActionFee.Add(params.FeePerKbyte)) - // 4. Generate an expiration time (current time + random duration) expirationTime := getRandomExpirationTime(ctx, r, params) @@ -123,7 +117,7 @@ func finalizeSenseAction(ctx sdk.Context, k keeper.Keeper, bk types.BankKeeper, // Create finalization metadata with signature metadata := generateFinalizeMetadataForSense(ctx, k, actionID, supernodes) - // Get supernode's initial balance to verify no fee distribution + // Get supernode's initial balance to verify it doesn't decrease feeDenom := k.GetParams(ctx).BaseActionFee.Denom initialBalance := bk.GetBalance(ctx, supernodes[0].Address, feeDenom) @@ -151,8 +145,8 @@ func finalizeSenseAction(ctx sdk.Context, k keeper.Keeper, bk types.BankKeeper, } finalBalance := bk.GetBalance(ctx, supernodes[0].Address, feeDenom) - if !finalBalance.Equal(initialBalance) { - panic(fmt.Sprintf("supernode %s balance changed after FinalizeAction, expected no fee distribution", supernodes[0].Address.String())) + if finalBalance.Amount.LT(initialBalance.Amount) { + panic(fmt.Sprintf("supernode %s balance decreased after FinalizeAction", supernodes[0].Address.String())) } return finalMsg @@ -256,7 +250,7 @@ func addPubKeyToAccount(ctx sdk.Context, simAccount simtypes.Account, ak types.A } // selectRandomAccountWithSufficientFunds selects a random account that has enough balance to cover the specified fee amount -func selectRandomAccountWithSufficientFunds(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, bk types.BankKeeper, ak types.AuthKeeper, skipAddresses []string) simtypes.Account { +func selectRandomAccountWithSufficientFunds(r *rand.Rand, ctx sdk.Context, accs []simtypes.Account, bk types.BankKeeper, ak types.AuthKeeper, minFee sdk.Coin, skipAddresses []string) simtypes.Account { if len(accs) == 0 { panic("no accounts available to select") } @@ -273,8 +267,8 @@ func selectRandomAccountWithSufficientFunds(r *rand.Rand, ctx sdk.Context, accs continue } - balance := bk.GetBalance(ctx, simAccount.Address, sdk.DefaultBondDenom) - if balance.IsZero() || balance.Amount.LT(math.NewInt(1_000_000)) { + spendable := bk.SpendableCoins(ctx, simAccount.Address) + if spendable.IsZero() || spendable.AmountOf(minFee.Denom).LT(minFee.Amount) { continue } diff --git a/x/action/v1/simulation/request_action.go b/x/action/v1/simulation/request_action.go index 67111e69..f5622ce7 100644 --- a/x/action/v1/simulation/request_action.go +++ b/x/action/v1/simulation/request_action.go @@ -74,24 +74,24 @@ func SimulateMsgRequestActionInvalidMetadata( ) simtypes.Operation { return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { - // 1. Select random account with enough balance - simAccount := selectRandomAccountWithSufficientFunds(r, ctx, accs, bk, ak, []string{""}) - params := k.GetParams(ctx) - // 2. Get initial balance + // 1. Determine fee amount + feeAmount := generateRandomFee(r, ctx, params.BaseActionFee) + + // 2. Select random account with enough spendable balance + simAccount := selectRandomAccountWithSufficientFunds(r, ctx, accs, bk, ak, feeAmount, []string{""}) + + // 3. Get initial balance denom := params.BaseActionFee.Denom initialBalance := bk.GetBalance(ctx, simAccount.Address, denom) - // 3. Randomly select action type + // 4. Randomly select action type actionType := selectRandomActionType(r) - // 4. Generate invalid metadata based on action type + // 5. Generate invalid metadata based on action type invalidMetadata := generateRequestActionInvalidMetadata(r, actionType, simAccount) - // 5. Determine fee amount - feeAmount := generateRandomFee(r, ctx, params.BaseActionFee) - // 6. Generate an expiration time (current time + random duration) expirationTime := getRandomExpirationTime(ctx, r, params) diff --git a/x/claim/keeper/abci_test.go b/x/claim/keeper/abci_test.go deleted file mode 100644 index 5f9a9f7f..00000000 --- a/x/claim/keeper/abci_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package keeper_test - -import ( - "testing" - "time" - - _ "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - - keepertest "github.com/LumeraProtocol/lumera/testutil/keeper" - "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func TestBeginBlocker(t *testing.T) { -} - -func TestEndBlocker(t *testing.T) { - keeper, ctx := keepertest.ClaimKeeper(t, "") - - testCases := []struct { - name string - setupParams types.Params - blockTime time.Time - expectDisable bool - }{ - { - name: "claims still active", - setupParams: types.Params{ - EnableClaims: true, - ClaimEndTime: time.Now().Add(time.Hour).Unix(), - }, - blockTime: time.Now(), - expectDisable: false, - }, - { - name: "claims should end", - setupParams: types.Params{ - EnableClaims: true, - ClaimEndTime: time.Now().Unix(), - }, - blockTime: time.Now().Add(time.Second), - expectDisable: true, - }, - { - name: "claims already disabled", - setupParams: types.Params{ - EnableClaims: false, - ClaimEndTime: time.Now().Unix(), - }, - blockTime: time.Now(), - expectDisable: false, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Setup test case - ctx = ctx.WithBlockTime(tc.blockTime) - err := keeper.SetParams(ctx, tc.setupParams) - require.NoError(t, err) - - // Run EndBlocker - err = keeper.EndBlocker(ctx) - require.NoError(t, err) - - // Verify final state - params := keeper.GetParams(ctx) - if tc.expectDisable { - require.False(t, params.EnableClaims, "claims should be disabled") - } else { - require.Equal(t, tc.setupParams.EnableClaims, params.EnableClaims, - "claims enable state should not change") - } - }) - } -} diff --git a/x/claim/keeper/claim_count_per_block_test.go b/x/claim/keeper/claim_count_per_block_test.go deleted file mode 100644 index 9556d859..00000000 --- a/x/claim/keeper/claim_count_per_block_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package keeper_test - -import ( - "testing" - - keepertest "github.com/LumeraProtocol/lumera/testutil/keeper" - "github.com/stretchr/testify/require" -) - -func TestBlockClaimCount(t *testing.T) { - testCases := []struct { - name string - operations []string - expectedCount uint64 - }{ - { - name: "initial count is zero", - operations: []string{}, - expectedCount: 0, - }, - { - name: "single increment", - operations: []string{"increment"}, - expectedCount: 1, - }, - { - name: "multiple increments", - operations: []string{"increment", "increment", "increment"}, - expectedCount: 3, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - keeper, ctx := keepertest.ClaimKeeper(t, "") - - // Initial count should be zero. - count, err := keeper.GetBlockClaimCount(ctx) - require.NoError(t, err) - require.Equal(t, uint64(0), count, "initial count should be zero") - - // Perform operations. - for _, op := range tc.operations { - if op == "increment" { - err := keeper.IncrementBlockClaimCount(ctx) - require.NoError(t, err) - } - } - - // Check final count. - count, err = keeper.GetBlockClaimCount(ctx) - require.NoError(t, err) - require.Equal(t, tc.expectedCount, count, "unexpected final count") - }) - } -} diff --git a/x/claim/keeper/claim_record_test.go b/x/claim/keeper/claim_record_test.go deleted file mode 100644 index 7a81352f..00000000 --- a/x/claim/keeper/claim_record_test.go +++ /dev/null @@ -1,289 +0,0 @@ -package keeper_test - -import ( - "testing" - - "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - - keepertest "github.com/LumeraProtocol/lumera/testutil/keeper" - "github.com/LumeraProtocol/lumera/x/claim/keeper" - "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func TestGetClaimRecord(t *testing.T) { - testCases := []struct { - name string - setupRecord *types.ClaimRecord - queryAddress string - expectFound bool - expectErr bool - expectRecord types.ClaimRecord - }{ - { - name: "non-existent record", - setupRecord: nil, - queryAddress: "test_address", - expectFound: false, - expectErr: false, - expectRecord: types.ClaimRecord{}, - }, - { - name: "existing record", - setupRecord: &types.ClaimRecord{ - OldAddress: "test_address", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(100))), - Claimed: false, - }, - queryAddress: "test_address", - expectFound: true, - expectErr: false, - }, - { - name: "query wrong address", - setupRecord: &types.ClaimRecord{ - OldAddress: "test_address", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(100))), - Claimed: false, - }, - queryAddress: "wrong_address", - expectFound: false, - expectErr: false, - expectRecord: types.ClaimRecord{}, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - k, ctx := keepertest.ClaimKeeper(t, "") - - // Setup - if tc.setupRecord != nil { - err := k.SetClaimRecord(ctx, *tc.setupRecord) - require.NoError(t, err) - tc.expectRecord = *tc.setupRecord - } - - // Test - record, found, err := k.GetClaimRecord(ctx, tc.queryAddress) - - if tc.expectErr { - require.Error(t, err) - return - } - require.NoError(t, err) - require.Equal(t, tc.expectFound, found) - if tc.expectFound { - require.Equal(t, tc.expectRecord, record) - } - }) - } -} - -func TestSetClaimRecord(t *testing.T) { - testCases := []struct { - name string - initialRecord *types.ClaimRecord - recordToSet types.ClaimRecord - expectErr bool - }{ - { - name: "set new record", - initialRecord: nil, - recordToSet: types.ClaimRecord{ - OldAddress: "test_address", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(100))), - Claimed: false, - }, - expectErr: false, - }, - { - name: "update existing record", - initialRecord: &types.ClaimRecord{ - OldAddress: "test_address", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(100))), - Claimed: false, - }, - recordToSet: types.ClaimRecord{ - OldAddress: "test_address", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(100))), - Claimed: true, - }, - expectErr: false, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - k, ctx := keepertest.ClaimKeeper(t, "") - - // Setup - if tc.initialRecord != nil { - err := k.SetClaimRecord(ctx, *tc.initialRecord) - require.NoError(t, err) - } - - // Test - err := k.SetClaimRecord(ctx, tc.recordToSet) - if tc.expectErr { - require.Error(t, err) - return - } - require.NoError(t, err) - - // Verify - record, found, err := k.GetClaimRecord(ctx, tc.recordToSet.OldAddress) - require.NoError(t, err) - require.True(t, found) - require.Equal(t, tc.recordToSet, record) - }) - } -} - -func TestListClaimed(t *testing.T) { - testCases := []struct { - name string - setupRecords []types.ClaimRecord - vestedTerm uint32 - expectClaimed int - expectErr bool - }{ - { - name: "empty state", - setupRecords: nil, - vestedTerm: 1, - expectClaimed: 0, - expectErr: false, - }, - { - name: "no claimed records", - setupRecords: []types.ClaimRecord{ - { - OldAddress: "address1", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(100))), - Claimed: false, - VestedTier: 1, - }, - { - OldAddress: "address2", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(200))), - Claimed: false, - VestedTier: 2, - }, - }, - vestedTerm: 1, - expectClaimed: 0, - expectErr: false, - }, - { - name: "claimed records with different vested tiers", - setupRecords: []types.ClaimRecord{ - { - OldAddress: "address1", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(100))), - Claimed: true, - VestedTier: 1, - }, - { - OldAddress: "address2", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(200))), - Claimed: true, - VestedTier: 2, - }, - { - OldAddress: "address3", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(300))), - Claimed: true, - VestedTier: 1, - }, - }, - vestedTerm: 1, - expectClaimed: 2, - expectErr: false, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - k, ctx := keepertest.ClaimKeeper(t, "") - q := keeper.NewQueryServerImpl(k) - - // Setup - if tc.setupRecords != nil { - for _, record := range tc.setupRecords { - err := k.SetClaimRecord(ctx, record) - require.NoError(t, err) - } - } - - // Test - req := &types.QueryListClaimedRequest{ - VestedTerm: tc.vestedTerm, - } - resp, err := q.ListClaimed(ctx, req) - - if tc.expectErr { - require.Error(t, err) - return - } - require.NoError(t, err) - require.NotNil(t, resp) - require.Equal(t, tc.expectClaimed, len(resp.Claims)) - - // Verify all returned records are claimed and have the correct vested tier - for _, claim := range resp.Claims { - require.True(t, claim.Claimed) - require.Equal(t, tc.vestedTerm, claim.VestedTier) - } - }) - } -} - -func TestGetClaimRecordCount(t *testing.T) { - testCases := []struct { - name string - setupRecords []types.ClaimRecord - expectCount uint64 - }{ - { - name: "initial empty state", - setupRecords: nil, - expectCount: 0, - }, - { - name: "multiple records", - setupRecords: []types.ClaimRecord{ - { - OldAddress: "address1", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(100))), - Claimed: false, - }, - { - OldAddress: "address2", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(200))), - Claimed: false, - }, - }, - expectCount: 2, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - k, ctx := keepertest.ClaimKeeper(t, "") - - // Setup - if tc.setupRecords != nil { - for _, record := range tc.setupRecords { - err := k.SetClaimRecord(ctx, record) - require.NoError(t, err) - } - } - - // Test - count := k.GetClaimRecordCount(ctx) - require.Equal(t, tc.expectCount, count) - }) - } -} diff --git a/x/claim/keeper/crypto/utils_test.go b/x/claim/keeper/crypto/utils_test.go deleted file mode 100644 index de58ad41..00000000 --- a/x/claim/keeper/crypto/utils_test.go +++ /dev/null @@ -1,304 +0,0 @@ -package crypto - -import ( - "encoding/hex" - "strings" - "testing" - - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" -) - -func TestGetAddressFromPubKey(t *testing.T) { - tests := []struct { - name string - pubKey string - expectedAddress string - expectError bool - }{ - { - name: "Valid public key", - pubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - expectedAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - expectError: false, - }, - { - name: "Invalid hex string", - pubKey: "invalid", - expectedAddress: "", - expectError: true, - }, - { - name: "Empty public key", - pubKey: "", - expectedAddress: "", - expectError: true, // hex.DecodeString will fail for empty string - }, - { - name: "Odd length hex string", - pubKey: "123", - expectedAddress: "", - expectError: true, - }, - { - name: "Wrong length public key (32 bytes)", - pubKey: strings.Repeat("00", 32), - expectedAddress: "", - expectError: false, - }, - { - name: "Public key with invalid prefix (not 0x02 or 0x03)", - pubKey: "0409331fc3d23ca17d91eec40ee7711efcd56facf949d46cbfa6393d43f2747e90", - expectedAddress: "", - expectError: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - address, err := GetAddressFromPubKey(tt.pubKey) - if tt.expectError { - if err == nil { - t.Errorf("Expected an error for input '%s', but got none", tt.pubKey) - } - } else { - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if tt.expectedAddress != "" && address != tt.expectedAddress { - t.Errorf("Expected address %s, but got %s", tt.expectedAddress, address) - } - } - }) - } -} - -func TestVerifySignature(t *testing.T) { - tests := []struct { - name string - pubKey string - message string - signature string - expectValid bool - expectError bool - }{ - { - name: "Valid signature", - pubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - message: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc.038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12.lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - expectValid: true, - expectError: false, - }, - { - name: "Modified signature", - pubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - message: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc.038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12.lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - signature: "1f46b3a2129047a0d7a6bf91e2879e940ed3db06a2cafaaaabacc337141146f43e4932d357b435bbf2c48227f5c2f738df23a2ebc221dd11cb14ed4b83bd2a95c8", - expectValid: false, - expectError: false, - }, - { - name: "Invalid public key hex", - pubKey: "invalid", - message: "test", - signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - expectValid: false, - expectError: true, - }, - { - name: "Empty public key", - pubKey: "", - message: "test", - signature: "1f46b3a2129047a0d7a6bf91e2879e940ed3db06a2cafaaaabacc337141146f43e4932d357b435bbf2c48227f5c2f738df23a2ebc221dd11cb14ed4b83bd2a95c7", - expectValid: false, - expectError: true, - }, - { - name: "Invalid signature hex", - pubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - message: "test", - signature: "invalid", - expectValid: false, - expectError: true, - }, - { - name: "Empty signature", - pubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - message: "test", - signature: "", - expectValid: false, - expectError: true, - }, - { - name: "Empty message", - pubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - message: "", - signature: "1f46b3a2129047a0d7a6bf91e2879e940ed3db06a2cafaaaabacc337141146f43e4932d357b435bbf2c48227f5c2f738df23a2ebc221dd11cb14ed4b83bd2a95c7", - expectValid: false, - expectError: false, - }, - { - name: "Wrong length signature (64 bytes)", - pubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - message: "test", - signature: strings.Repeat("00", 64), - expectValid: false, - expectError: true, - }, - { - name: "Invalid public key format (wrong length)", - pubKey: strings.Repeat("00", 32), // 64 chars = 32 bytes instead of 33 - message: "test", - signature: "1f46b3a2129047a0d7a6bf91e2879e940ed3db06a2cafaaaabacc337141146f43e4932d357b435bbf2c48227f5c2f738df23a2ebc221dd11cb14ed4b83bd2a95c7", - expectValid: false, - expectError: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - isValid, err := VerifySignature(tt.pubKey, tt.message, tt.signature) - if tt.expectError { - if err == nil { - t.Errorf("Expected an error, but got none") - } - } else { - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if isValid != tt.expectValid { - t.Errorf("Expected validity %v, but got %v", tt.expectValid, isValid) - } - } - }) - } -} - -func TestGenerateKeyPair(t *testing.T) { - // Test multiple key pairs to ensure consistency - for i := 0; i < 10; i++ { - privKey, pubKey := GenerateKeyPair() - - // Test private key - if privKey == nil { - t.Fatal("Expected private key, got nil") - } - if len(privKey.Bytes()) != 32 { - t.Errorf("Expected private key length 32, got %d", len(privKey.Bytes())) - } - - // Test public key - if pubKey == nil { - t.Fatal("Expected public key, got nil") - } - if len(pubKey.Bytes()) != 33 { - t.Errorf("Expected compressed public key length 33, got %d", len(pubKey.Bytes())) - } - - // Verify public key format (should start with 0x02 or 0x03) - firstByte := pubKey.Bytes()[0] - if firstByte != 0x02 && firstByte != 0x03 { - t.Errorf("Invalid public key format: first byte should be 0x02 or 0x03, got 0x%x", firstByte) - } - - // Verify key pair relationship - derivedPub := privKey.PubKey() - if !derivedPub.Equals(pubKey) { - t.Error("Derived public key doesn't match generated public key") - } - } -} - -func TestSignMessage(t *testing.T) { - tests := []struct { - name string - message string - useNilKey bool - expectError bool - }{ - { - name: "Valid message", - message: "test message", - useNilKey: false, - expectError: false, - }, - { - name: "Empty message", - message: "", - useNilKey: false, - expectError: false, - }, - { - name: "Long message", - message: strings.Repeat("test", 1000), - useNilKey: false, - expectError: false, - }, - { - name: "Message with special characters", - message: "!@#$%^&*()_+-=[]{}|;:,.<>?", - useNilKey: false, - expectError: false, - }, - { - name: "Unicode message", - message: "Hello, 世界", - useNilKey: false, - expectError: false, - }, - { - name: "Nil private key", - message: "test message", - useNilKey: true, - expectError: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - var privKey *secp256k1.PrivKey - var pubKey *secp256k1.PubKey - - if !tt.useNilKey { - privKey, pubKey = GenerateKeyPair() - } - - // Sign the message - signature, err := SignMessage(privKey, tt.message) - if tt.expectError { - if err == nil { - t.Errorf("Expected an error, but got none") - } - return - } - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - // Verify signature format - sigBytes, err := hex.DecodeString(signature) - if err != nil { - t.Fatalf("Failed to decode signature hex: %v", err) - } - - if len(sigBytes) != 65 { - t.Errorf("Expected signature length 65, got %d", len(sigBytes)) - } - - if sigBytes[0] != 27 && sigBytes[0] != 28 { - t.Errorf("Invalid recovery byte: expected 27 or 28, got %d", sigBytes[0]) - } - - // Verify the signature using VerifySignature - pubKeyHex := hex.EncodeToString(pubKey.Bytes()) - isValid, err := VerifySignature(pubKeyHex, tt.message, signature) - if err != nil { - t.Fatalf("Signature verification failed with error: %v", err) - } - if !isValid { - t.Error("Signature verification failed") - } - }) - } -} diff --git a/x/claim/keeper/msg_server_claim_test.go b/x/claim/keeper/msg_server_claim_test.go deleted file mode 100644 index bfa8b018..00000000 --- a/x/claim/keeper/msg_server_claim_test.go +++ /dev/null @@ -1,141 +0,0 @@ -package keeper_test - -import ( - "testing" - - "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - - "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func TestMsgClaim(t *testing.T) { - k, ms, ctx := setupMsgServer(t) - - // Define valid claim record with proper coin denomination - validClaimRecord := types.ClaimRecord{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(1000000))), - Claimed: false, - } - - testCases := []struct { - name string - msg *types.MsgClaim - setup func() - expErr bool - expErrMsg string - }{ - { - name: "valid claim", - msg: &types.MsgClaim{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - NewAddress: "lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - PubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - Signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - }, - setup: func() { - sdkCtx := sdk.UnwrapSDKContext(ctx) - params := types.DefaultParams() - params.EnableClaims = true - params.MaxClaimsPerBlock = 10 - params.ClaimEndTime = sdkCtx.BlockTime().Unix() + 3600 // 1 hour from now - require.NoError(t, k.SetParams(sdkCtx, params)) - - // Set fresh claim record - require.NoError(t, k.SetClaimRecord(sdkCtx, validClaimRecord)) - - // Set fee in context - fee := sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(1000))) - ctx = sdkCtx.WithValue(types.ClaimTxFee, fee) - }, - expErr: false, - }, - { - name: "claims disabled", - msg: &types.MsgClaim{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - NewAddress: "lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - PubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - Signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - }, - setup: func() { - sdkCtx := sdk.UnwrapSDKContext(ctx) - params := types.DefaultParams() - params.EnableClaims = false - require.NoError(t, k.SetParams(sdkCtx, params)) - require.NoError(t, k.SetClaimRecord(sdkCtx, validClaimRecord)) - }, - expErr: true, - expErrMsg: types.ErrClaimDisabled.Error(), - }, - { - name: "claim period expired", - msg: &types.MsgClaim{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - NewAddress: "lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - PubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - Signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - }, - setup: func() { - sdkCtx := sdk.UnwrapSDKContext(ctx) - params := types.DefaultParams() - params.EnableClaims = true - params.ClaimEndTime = sdkCtx.BlockTime().Unix() - 3600 // 1 hour ago - require.NoError(t, k.SetParams(sdkCtx, params)) - require.NoError(t, k.SetClaimRecord(sdkCtx, validClaimRecord)) - }, - expErr: true, - expErrMsg: types.ErrClaimPeriodExpired.Error(), - }, - { - name: "already claimed", - msg: &types.MsgClaim{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - NewAddress: "lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - PubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - Signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - }, - setup: func() { - sdkCtx := sdk.UnwrapSDKContext(ctx) - params := types.DefaultParams() - params.EnableClaims = true - require.NoError(t, k.SetParams(sdkCtx, params)) - - claimedRecord := validClaimRecord - claimedRecord.Claimed = true - require.NoError(t, k.SetClaimRecord(sdkCtx, claimedRecord)) - }, - expErr: true, - expErrMsg: types.ErrClaimAlreadyClaimed.Error(), - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - if tc.setup != nil { - tc.setup() - } - - resp, err := ms.Claim(ctx, tc.msg) - - if tc.expErr { - require.Error(t, err) - require.Contains(t, err.Error(), tc.expErrMsg) - require.Nil(t, resp) - } else { - require.NoError(t, err) - require.NotNil(t, resp) - - // Check claim record was updated - sdkCtx := sdk.UnwrapSDKContext(ctx) - record, found, err := k.GetClaimRecord(sdkCtx, tc.msg.OldAddress) - require.NoError(t, err) - require.True(t, found) - require.True(t, record.Claimed) - require.NotZero(t, record.ClaimTime) - } - }) - } -} diff --git a/x/claim/keeper/msg_server_delayed_claim_test.go b/x/claim/keeper/msg_server_delayed_claim_test.go deleted file mode 100644 index 656dd7b7..00000000 --- a/x/claim/keeper/msg_server_delayed_claim_test.go +++ /dev/null @@ -1,145 +0,0 @@ -package keeper_test - -import ( - "testing" - - "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - - "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func TestMsgDelayedClaim(t *testing.T) { - k, ms, ctx := setupMsgServer(t) - - // Define valid claim record with proper coin denomination - validClaimRecord := types.ClaimRecord{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(1000000))), - Claimed: false, - } - - testCases := []struct { - name string - msg *types.MsgDelayedClaim - setup func() - expErr bool - expErrMsg string - }{ - { - name: "valid claim", - msg: &types.MsgDelayedClaim{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - NewAddress: "lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - PubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - Signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - Tier: 1, - }, - setup: func() { - sdkCtx := sdk.UnwrapSDKContext(ctx) - params := types.DefaultParams() - params.EnableClaims = true - params.MaxClaimsPerBlock = 10 - params.ClaimEndTime = sdkCtx.BlockTime().Unix() + 3600 // 1 hour from now - require.NoError(t, k.SetParams(sdkCtx, params)) - - // Set fresh claim record - require.NoError(t, k.SetClaimRecord(sdkCtx, validClaimRecord)) - - // Set fee in context - fee := sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(1000))) - ctx = sdkCtx.WithValue(types.ClaimTxFee, fee) - }, - expErr: false, - }, - { - name: "claims disabled", - msg: &types.MsgDelayedClaim{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - NewAddress: "lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - PubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - Signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - Tier: 1, - }, - setup: func() { - sdkCtx := sdk.UnwrapSDKContext(ctx) - params := types.DefaultParams() - params.EnableClaims = false - require.NoError(t, k.SetParams(sdkCtx, params)) - require.NoError(t, k.SetClaimRecord(sdkCtx, validClaimRecord)) - }, - expErr: true, - expErrMsg: types.ErrClaimDisabled.Error(), - }, - { - name: "claim period expired", - msg: &types.MsgDelayedClaim{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - NewAddress: "lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - PubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - Signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - Tier: 1, - }, - setup: func() { - sdkCtx := sdk.UnwrapSDKContext(ctx) - params := types.DefaultParams() - params.EnableClaims = true - params.ClaimEndTime = sdkCtx.BlockTime().Unix() - 3600 // 1 hour ago - require.NoError(t, k.SetParams(sdkCtx, params)) - require.NoError(t, k.SetClaimRecord(sdkCtx, validClaimRecord)) - }, - expErr: true, - expErrMsg: types.ErrClaimPeriodExpired.Error(), - }, - { - name: "already claimed", - msg: &types.MsgDelayedClaim{ - OldAddress: "Ptko7ZkiQXyT9Db45GtsewpnhnRRwpHkHBc", - NewAddress: "lumera1zvnc27832srgxa207y5hu2agy83wazfzurufyp", - PubKey: "038685010ec7ce724c1f83ba333564135feadf70eade12036546f20b95ce276a12", - Signature: "1f4926307e7d94f5290058f8836429963431b3f7fc091567f1621a510d25cbcb71240f9c4488d9cafa16c8c3457d07c263afcfe4c77e0081a4e75bb618e99e1cd3", - Tier: 1, - }, - setup: func() { - sdkCtx := sdk.UnwrapSDKContext(ctx) - params := types.DefaultParams() - params.EnableClaims = true - require.NoError(t, k.SetParams(sdkCtx, params)) - - claimedRecord := validClaimRecord - claimedRecord.Claimed = true - require.NoError(t, k.SetClaimRecord(sdkCtx, claimedRecord)) - }, - expErr: true, - expErrMsg: types.ErrClaimAlreadyClaimed.Error(), - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - if tc.setup != nil { - tc.setup() - } - - resp, err := ms.DelayedClaim(ctx, tc.msg) - - if tc.expErr { - require.Error(t, err) - require.Contains(t, err.Error(), tc.expErrMsg) - require.Nil(t, resp) - } else { - require.NoError(t, err) - require.NotNil(t, resp) - - // Check claim record was updated - sdkCtx := sdk.UnwrapSDKContext(ctx) - record, found, err := k.GetClaimRecord(sdkCtx, tc.msg.OldAddress) - require.NoError(t, err) - require.True(t, found) - require.True(t, record.Claimed) - require.NotZero(t, record.ClaimTime) - } - }) - } -} diff --git a/x/claim/keeper/msg_server_test.go b/x/claim/keeper/msg_server_test.go deleted file mode 100644 index 4ae9d33c..00000000 --- a/x/claim/keeper/msg_server_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package keeper_test - -import ( - "testing" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - - keepertest "github.com/LumeraProtocol/lumera/testutil/keeper" - "github.com/LumeraProtocol/lumera/x/claim/keeper" - "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func setupMsgServer(t testing.TB) (keeper.Keeper, types.MsgServer, sdk.Context) { - k, ctx := keepertest.ClaimKeeper(t, "") - return k, keeper.NewMsgServerImpl(k), ctx -} - -func TestMsgServer(t *testing.T) { - k, ms, ctx := setupMsgServer(t) - require.NotNil(t, ms) - require.NotNil(t, ctx) - require.NotEmpty(t, k) -} - -//Done diff --git a/x/claim/keeper/msg_update_params_test.go b/x/claim/keeper/msg_update_params_test.go deleted file mode 100644 index 9b86dbac..00000000 --- a/x/claim/keeper/msg_update_params_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package keeper_test - -import ( - "testing" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - - "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func TestMsgUpdateParams(t *testing.T) { - k, ms, ctx := setupMsgServer(t) - params := types.DefaultParams() - require.NoError(t, k.SetParams(ctx, params)) - wctx := sdk.UnwrapSDKContext(ctx) - - // default params - testCases := []struct { - name string - input *types.MsgUpdateParams - expErr bool - expErrMsg string - }{ - { - name: "invalid authority", - input: &types.MsgUpdateParams{ - Authority: "invalid", - Params: params, - }, - expErr: true, - expErrMsg: "invalid authority", - }, - { - name: "send enabled param", - input: &types.MsgUpdateParams{ - Authority: k.GetAuthority(), - Params: types.Params{}, - }, - expErr: false, - }, - { - name: "all good", - input: &types.MsgUpdateParams{ - Authority: k.GetAuthority(), - Params: params, - }, - expErr: false, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - _, err := ms.UpdateParams(wctx, tc.input) - - if tc.expErr { - require.Error(t, err) - require.Contains(t, err.Error(), tc.expErrMsg) - } else { - require.NoError(t, err) - } - }) - } -} - -//Done diff --git a/x/claim/keeper/params_test.go b/x/claim/keeper/params_test.go deleted file mode 100644 index e732e478..00000000 --- a/x/claim/keeper/params_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package keeper_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - keepertest "github.com/LumeraProtocol/lumera/testutil/keeper" - "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func TestGetParams(t *testing.T) { - k, ctx := keepertest.ClaimKeeper(t, "") - params := types.DefaultParams() - - require.NoError(t, k.SetParams(ctx, params)) - require.EqualValues(t, params, k.GetParams(ctx)) -} - -//Done diff --git a/x/claim/keeper/query_claim_record_test.go b/x/claim/keeper/query_claim_record_test.go deleted file mode 100644 index c23b001f..00000000 --- a/x/claim/keeper/query_claim_record_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package keeper_test - -import ( - "testing" - - "cosmossdk.io/math" - keepertest "github.com/LumeraProtocol/lumera/testutil/keeper" - "github.com/LumeraProtocol/lumera/x/claim/types" - "github.com/LumeraProtocol/lumera/x/claim/keeper" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -func TestClaimRecordQuery(t *testing.T) { - k, ctx := keepertest.ClaimKeeper(t, "") - q := keeper.NewQueryServerImpl(k) - - // Define a valid claim record using real Pastel network values - validRecord := types.ClaimRecord{ - OldAddress: "PtqHAEacynVd3V821NPhgxu9K4Ab6kAguHi", - Balance: sdk.NewCoins(sdk.NewCoin(types.DefaultClaimsDenom, math.NewInt(1000000))), - Claimed: false, - } - - testCases := []struct { - name string - request *types.QueryClaimRecordRequest - setup func() - expErr bool - expCode codes.Code - expRecord *types.ClaimRecord - }{ - { - name: "empty request", - request: nil, - setup: func() {}, - expErr: true, - expCode: codes.InvalidArgument, - expRecord: nil, - }, - { - name: "query non-existent record", - request: &types.QueryClaimRecordRequest{ - Address: "PtqInvalidAddressXXXXXXXXXXXXXXXXXXXX", - }, - setup: func() {}, - expErr: true, - expCode: codes.NotFound, - expRecord: nil, - }, - { - name: "query existing record", - request: &types.QueryClaimRecordRequest{ - Address: validRecord.OldAddress, - }, - setup: func() { - err := k.SetClaimRecord(ctx, validRecord) - require.NoError(t, err) - }, - expErr: false, - expRecord: &validRecord, - }, - { - name: "query claimed record", - request: &types.QueryClaimRecordRequest{ - Address: "PtqHAEacynVd3V821NPhgxu9K4Ab6kAguHi", - }, - setup: func() { - claimedRecord := validRecord - claimedRecord.Claimed = true - err := k.SetClaimRecord(ctx, claimedRecord) - require.NoError(t, err) - }, - expErr: false, - expRecord: &types.ClaimRecord{ - OldAddress: "PtqHAEacynVd3V821NPhgxu9K4Ab6kAguHi", - Balance: validRecord.Balance, - Claimed: true, - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Setup test state - tc.setup() - - // Execute query - response, err := q.ClaimRecord(ctx, tc.request) - - // Verify results - if tc.expErr { - require.Error(t, err) - statusErr, ok := status.FromError(err) - require.True(t, ok) - require.Equal(t, tc.expCode, statusErr.Code()) - require.Nil(t, response) - } else { - require.NoError(t, err) - require.NotNil(t, response) - require.Equal(t, tc.expRecord.OldAddress, response.Record.OldAddress) - require.Equal(t, tc.expRecord.Balance, response.Record.Balance) - require.Equal(t, tc.expRecord.Claimed, response.Record.Claimed) - } - }) - } -} diff --git a/x/claim/keeper/query_params_test.go b/x/claim/keeper/query_params_test.go deleted file mode 100644 index 687409c5..00000000 --- a/x/claim/keeper/query_params_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package keeper_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - keepertest "github.com/LumeraProtocol/lumera/testutil/keeper" - - "github.com/LumeraProtocol/lumera/x/claim/keeper" - "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func TestParamsQuery(t *testing.T) { - k, ctx := keepertest.ClaimKeeper(t, "") - q := keeper.NewQueryServerImpl(k) - - params := types.DefaultParams() - require.NoError(t, k.SetParams(ctx, params)) - - response, err := q.Params(ctx, &types.QueryParamsRequest{}) - require.NoError(t, err) - require.Equal(t, &types.QueryParamsResponse{Params: params}, response) -} - -//Done diff --git a/x/claim/module/genesis_test.go b/x/claim/module/genesis_test.go deleted file mode 100644 index 9b77543b..00000000 --- a/x/claim/module/genesis_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package claim_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - keepertest "github.com/LumeraProtocol/lumera/testutil/keeper" - claim "github.com/LumeraProtocol/lumera/x/claim/module" - claimtestutils "github.com/LumeraProtocol/lumera/x/claim/testutils" - "github.com/LumeraProtocol/lumera/x/claim/types" -) - -func TestGenesis(t *testing.T) { - // Get the default genesis state first - defaultGenState := types.DefaultGenesis() - - // Create test genesis state matching the default values - genesisState := types.GenesisState{ - Params: types.DefaultParams(), - // Set to 0 in tests to avoid loading external CSV totals - TotalClaimableAmount: 0, - // Will be populated during initialization - ClaimRecords: []types.ClaimRecord{}, // Empty records for test - ClaimsDenom: types.DefaultClaimsDenom, - } - - testData, err := claimtestutils.GenerateClaimingTestData() - require.NoError(t, err) - - // generate a CSV file with the test data - claimsPath, err := claimtestutils.GenerateClaimsCSVFile([]claimtestutils.ClaimCSVRecord{ - {OldAddress: testData.OldAddress, Amount: defaultGenState.TotalClaimableAmount}, - }, nil) - require.NoError(t, err) - // Ensure the file is cleaned up after the test - t.Cleanup(func() { - claimtestutils.CleanupClaimsCSVFile(claimsPath) - }) - - k, ctx := keepertest.ClaimKeeper(t, claimsPath) - claim.InitGenesis(ctx, k, genesisState) - got := claim.ExportGenesis(ctx, k) - require.NotNil(t, got) - - // Verify params - require.Equal(t, genesisState.Params, got.Params) - - // Verify the module account exists - moduleAcc := k.GetAccountKeeper().GetModuleAccount(ctx, types.ModuleName) - require.NotNil(t, moduleAcc) - require.Equal(t, types.ModuleName, moduleAcc.GetName()) - - // Verify permissions - require.Contains(t, moduleAcc.GetPermissions(), "minter") - require.Contains(t, moduleAcc.GetPermissions(), "burner") - - // Verify total claimable amount matches default genesis state - require.Equal(t, defaultGenState.TotalClaimableAmount, got.TotalClaimableAmount) -} diff --git a/x/claim/simulation/claim.go b/x/claim/simulation/claim.go index d7fd38b0..59d9d6f9 100644 --- a/x/claim/simulation/claim.go +++ b/x/claim/simulation/claim.go @@ -6,9 +6,9 @@ import ( "encoding/hex" + claimcrypto "github.com/LumeraProtocol/lumera/x/claim/keeper/crypto" "github.com/LumeraProtocol/lumera/x/claim/keeper" "github.com/LumeraProtocol/lumera/x/claim/types" - "github.com/cometbft/cometbft/crypto/secp256k1" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" @@ -34,10 +34,12 @@ func SimulateMsgClaim( } // Generate simulated keys and addresses - privKey := secp256k1.GenPrivKey() - pubKeyBytes := privKey.PubKey().Bytes() - pubKeyHex := hex.EncodeToString(pubKeyBytes) - oldAddress := sdk.AccAddress(privKey.PubKey().Address()).String() + privKey, pubKey := claimcrypto.GenerateKeyPair() + pubKeyHex := hex.EncodeToString(pubKey.Key) + oldAddress, err := claimcrypto.GetAddressFromPubKey(pubKeyHex) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgClaim, "failed to generate claim address"), nil, err + } testAmount := int64(1_000_000) // Amount to be claimed in the test case @@ -67,7 +69,7 @@ func SimulateMsgClaim( // Generate message signature message := fmt.Sprintf("%s.%s.%s", oldAddress, pubKeyHex, simAccount.Address.String()) - signature, err := privKey.Sign([]byte(message)) + signature, err := claimcrypto.SignMessage(privKey, message) if err != nil { return simtypes.NoOpMsg(types.ModuleName, TypeMsgClaim, "failed to sign message"), nil, err } @@ -76,7 +78,7 @@ func SimulateMsgClaim( OldAddress: oldAddress, NewAddress: simAccount.Address.String(), PubKey: pubKeyHex, - Signature: hex.EncodeToString(signature), + Signature: signature, } // Check if we've hit the claims per block limit diff --git a/x/claim/types/genesis_test.go b/x/claim/types/genesis_test.go deleted file mode 100644 index 2f506021..00000000 --- a/x/claim/types/genesis_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package types_test - -import ( - "fmt" - "testing" - "time" - - "github.com/LumeraProtocol/lumera/x/claim/types" - "github.com/stretchr/testify/require" -) - -func TestGenesisState_Validate(t *testing.T) { - // Setup common test values - validEndTime := time.Now().Add(time.Hour * 48).Unix() - - testCases := []struct { - name string - genState *types.GenesisState - expErr bool - }{ - { - name: "default genesis state", - genState: types.DefaultGenesis(), - expErr: false, - }, - { - name: "valid genesis state - empty records", - genState: types.NewGenesisState( - types.Params{ - EnableClaims: true, - ClaimEndTime: validEndTime, - MaxClaimsPerBlock: 50, - }, - []types.ClaimRecord{}, // Should always be empty in genesis - - types.DefaultClaimableAmountConst, // Fixed claimable amount - types.DefaultClaimsDenom, - ), - expErr: false, - }, - { - name: "invalid params - negative end time", - genState: types.NewGenesisState( - types.Params{ - EnableClaims: true, - ClaimEndTime: -1, - MaxClaimsPerBlock: 50, - }, - []types.ClaimRecord{}, - - types.DefaultClaimableAmountConst, - types.DefaultClaimsDenom, - ), - expErr: true, - }, - { - name: "invalid params - zero max claims", - genState: types.NewGenesisState( - types.Params{ - EnableClaims: true, - ClaimEndTime: validEndTime, - MaxClaimsPerBlock: 0, - }, - []types.ClaimRecord{}, - - types.DefaultClaimableAmountConst, - types.DefaultClaimsDenom, - ), - expErr: true, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - err := tc.genState.Validate() - - if tc.expErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func TestDefaultGenesis(t *testing.T) { - genState := types.DefaultGenesis() - require.NotNil(t, genState) - require.Equal(t, types.DefaultParams(), genState.Params) - require.Empty(t, genState.ClaimRecords, "Genesis claim records should be empty") - require.Equal(t, uint64(types.DefaultClaimableAmountConst), genState.TotalClaimableAmount, fmt.Sprintf("total claimable amount should be fixed at %d", types.DefaultClaimableAmountConst)) - // Validate default genesis state - require.NoError(t, genState.Validate()) -} - -func TestNewGenesisState(t *testing.T) { - params := types.DefaultParams() - genState := types.NewGenesisState( - params, - []types.ClaimRecord{}, // Should be empty in genesis - types.DefaultClaimableAmountConst, // Fixed claimable amount - types.DefaultClaimsDenom, - ) - - require.NotNil(t, genState) - require.Equal(t, params, genState.Params) - require.Empty(t, genState.ClaimRecords, "Genesis claim records should be empty") - require.Equal(t, uint64(types.DefaultClaimableAmountConst), genState.TotalClaimableAmount, fmt.Sprintf("Total claimable amount should be fixed at %d", types.DefaultClaimableAmountConst)) -} diff --git a/x/claim/types/message_delayed_claim_test.go b/x/claim/types/message_delayed_claim_test.go deleted file mode 100644 index 27493c48..00000000 --- a/x/claim/types/message_delayed_claim_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package types - -import ( - "testing" - - "github.com/LumeraProtocol/lumera/testutil/sample" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/stretchr/testify/require" -) - -func TestMsgDelayedClaim_ValidateBasic(t *testing.T) { - tests := []struct { - name string - msg MsgDelayedClaim - err error - }{ - { - name: "invalid address", - msg: MsgDelayedClaim{ - Creator: "invalid_address", - }, - err: sdkerrors.ErrInvalidAddress, - }, { - name: "valid address", - msg: MsgDelayedClaim{ - Creator: sample.AccAddress(), - Tier: 1, - }, - }, { - name: "invalid tier", - msg: MsgDelayedClaim{ - Creator: sample.AccAddress(), - Tier: 7, - }, - err: sdkerrors.ErrInvalidRequest, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := tt.msg.ValidateBasic() - if tt.err != nil { - require.ErrorIs(t, err, tt.err) - return - } - require.NoError(t, err) - }) - } -} diff --git a/x/supernode/v1/simulation/register_supernode.go b/x/supernode/v1/simulation/register_supernode.go index b8ec9aba..71c05687 100644 --- a/x/supernode/v1/simulation/register_supernode.go +++ b/x/supernode/v1/simulation/register_supernode.go @@ -42,6 +42,15 @@ func SimulateMsgRegisterSupernode( continue } + // Ensure the account isn't already associated with a different validator. + if snByAccount, foundByAccount, err := k.GetSuperNodeByAccount(ctx, simAccount.Address.String()); err == nil && foundByAccount { + if snByAccount.ValidatorAddress != valAddr.String() { + continue + } + } else if err != nil { + continue + } + // Check if supernode already exists and is not disabled supernode, superNodeExists := k.QuerySuperNode(ctx, valAddr) if superNodeExists { From 9bd3cd9feb88bce06164a6572dbe84d64e127561 Mon Sep 17 00:00:00 2001 From: Andrey Kobrin Date: Wed, 28 Jan 2026 10:41:25 -0500 Subject: [PATCH 3/5] upgrade version change to v1.12.0, changelog --- CHANGELOG.md | 15 ++++ app/app_config.go | 2 +- app/upgrades/upgrades.go | 12 +-- app/upgrades/upgrades_test.go | 12 +-- app/upgrades/{v1_10_0 => v1_12_0}/store.go | 4 +- app/upgrades/{v1_10_0 => v1_12_0}/upgrade.go | 4 +- docs/upgrade.md | 84 -------------------- 7 files changed, 32 insertions(+), 101 deletions(-) rename app/upgrades/{v1_10_0 => v1_12_0}/store.go (74%) rename app/upgrades/{v1_10_0 => v1_12_0}/upgrade.go (97%) delete mode 100644 docs/upgrade.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fc45617..d4eea4c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ --- +## 1.12.0 + +Changes included since `v1.9.1` (range: `v1.9.1..v1.12.0`). + +- Cosmos SDK: upgraded from v0.50.14 to v0.53.5, CometBFT upgraded to v0.38.20 +- enabled unordered +- migrated consensus params from `x/params` to `x/consensus` via baseapp.MigrateParams; removed `x/params` usage. +- IBC: upgraded to IBC-Go from v10.3.0 to v10.5.0 with IBC v2 readiness (Router v2, v2 packet/event handling helpers). +- Wasm: upgraded wasmd from v0.55.0-ibc2.0 to v0.61.6 and wasmvm from v3.0.0-ibc2.0 to v3.0.2. +- Module changes: removed `x/crisis`, deleted its store key and disabled crisis invariants by default. +- Client/indexer impact: legacy tx logs removed in SDK v0.53. +- Unordered transactions feature (SDK v0.52) is enabled: "fire-and-forget" tx submission model with timeout_timestamp as TTL/replay protection, useful for throughput-focused clients where strict ordering is not required. + +--- + ## 1.9.1 Changes included since `v1.9.0` (range: `v1.9.0..v1.9.1`). diff --git a/app/app_config.go b/app/app_config.go index f05f509e..3d7191ca 100644 --- a/app/app_config.go +++ b/app/app_config.go @@ -237,7 +237,7 @@ var ( ModuleAccountPermissions: moduleAccPerms, // Cosmos SDK 0.53.x new feature - unordered transactions // "Fire-and-forget" submission model with timeout_timestamp as TTL/replay protection - EnableUnorderedTransactions: false, + EnableUnorderedTransactions: true, // By default modules authority is the governance module. This is configurable with the following: // Authority: "group", // A custom module authority can be set using a module name // Authority: "cosmos1cwwv22j5ca08ggdv9c2uky355k908694z577tv", // or a specific address diff --git a/app/upgrades/upgrades.go b/app/upgrades/upgrades.go index d114b6c8..c1149467 100644 --- a/app/upgrades/upgrades.go +++ b/app/upgrades/upgrades.go @@ -15,7 +15,7 @@ import ( upgrade_v1_8_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_0" upgrade_v1_8_4 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_4" upgrade_v1_9_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_9_0" - upgrade_v1_10_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_10_0" + upgrade_v1_12_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_12_0" ) // ================================================================================================================================= @@ -30,7 +30,7 @@ import ( // | v1.8.5 | standard | none | Migrations only // | v1.9.0 | custom | none | Backfills action/supernode secondary indices // | v1.9.1 | standard | none | Migrations only -// | v1.10.0 | custom | drop crisis | Migrate consensus params from x/params to x/consensus; remove x/crisis +// | v1.12.0 | custom | drop crisis | Migrate consensus params from x/params to x/consensus; remove x/crisis // ================================================================================================================================= type UpgradeConfig struct { @@ -55,7 +55,7 @@ var upgradeNames = []string{ upgradeNameV185, upgrade_v1_9_0.UpgradeName, upgradeNameV191, - upgrade_v1_10_0.UpgradeName, + upgrade_v1_12_0.UpgradeName, } var NoUpgradeConfig = UpgradeConfig{ @@ -110,10 +110,10 @@ func SetupUpgrades(upgradeName string, params appParams.AppUpgradeParams) (Upgra return UpgradeConfig{ Handler: standardUpgradeHandler(upgradeNameV191, params), }, true - case upgrade_v1_10_0.UpgradeName: +case upgrade_v1_12_0.UpgradeName: return UpgradeConfig{ - StoreUpgrade: &upgrade_v1_10_0.StoreUpgrades, - Handler: upgrade_v1_10_0.CreateUpgradeHandler(params), + StoreUpgrade: &upgrade_v1_12_0.StoreUpgrades, + Handler: upgrade_v1_12_0.CreateUpgradeHandler(params), }, true // add future upgrades here diff --git a/app/upgrades/upgrades_test.go b/app/upgrades/upgrades_test.go index 5cba46e0..fc66c38b 100644 --- a/app/upgrades/upgrades_test.go +++ b/app/upgrades/upgrades_test.go @@ -15,7 +15,7 @@ import ( upgrade_v1_8_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_0" upgrade_v1_8_4 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_4" upgrade_v1_9_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_9_0" - upgrade_v1_10_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_10_0" + upgrade_v1_12_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_12_0" actiontypes "github.com/LumeraProtocol/lumera/x/action/v1/types" crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" ) @@ -30,7 +30,7 @@ func TestUpgradeNamesOrder(t *testing.T) { upgradeNameV185, upgrade_v1_9_0.UpgradeName, upgradeNameV191, - upgrade_v1_10_0.UpgradeName, + upgrade_v1_12_0.UpgradeName, } require.Equal(t, expected, upgradeNames, "upgradeNames should stay in ascending order") } @@ -66,8 +66,8 @@ func TestSetupUpgradesAndHandlers(t *testing.T) { "store upgrade presence mismatch for %s on %s", upgradeName, tt.chainID, ) - if upgradeName == upgrade_v1_10_0.UpgradeName && config.StoreUpgrade != nil { - require.Contains(t, config.StoreUpgrade.Deleted, crisistypes.StoreKey, "v1.10.0 should delete crisis store key") + if upgradeName == upgrade_v1_12_0.UpgradeName && config.StoreUpgrade != nil { + require.Contains(t, config.StoreUpgrade.Deleted, crisistypes.StoreKey, "v1.12.0 should delete crisis store key") } if config.Handler == nil { @@ -76,7 +76,7 @@ func TestSetupUpgradesAndHandlers(t *testing.T) { // v1.9.0 requires full keeper wiring; exercising it here would require // a full app harness. This test only verifies registration and gating. - if upgradeName == upgrade_v1_9_0.UpgradeName || upgradeName == upgrade_v1_10_0.UpgradeName { + if upgradeName == upgrade_v1_9_0.UpgradeName || upgradeName == upgrade_v1_12_0.UpgradeName { continue } @@ -119,7 +119,7 @@ func expectStoreUpgrade(upgradeName, chainID string) bool { return IsTestnet(chainID) || IsDevnet(chainID) case upgrade_v1_8_4.UpgradeName: return IsMainnet(chainID) - case upgrade_v1_10_0.UpgradeName: + case upgrade_v1_12_0.UpgradeName: return true default: return false diff --git a/app/upgrades/v1_10_0/store.go b/app/upgrades/v1_12_0/store.go similarity index 74% rename from app/upgrades/v1_10_0/store.go rename to app/upgrades/v1_12_0/store.go index b26804f9..c3927af2 100644 --- a/app/upgrades/v1_10_0/store.go +++ b/app/upgrades/v1_12_0/store.go @@ -1,11 +1,11 @@ -package v1_10_0 +package v1_12_0 import ( storetypes "cosmossdk.io/store/types" crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" ) -// StoreUpgrades defines store changes for v1.10.0. +// StoreUpgrades defines store changes for v1.12.0. var StoreUpgrades = storetypes.StoreUpgrades{ Deleted: []string{crisistypes.StoreKey}, } diff --git a/app/upgrades/v1_10_0/upgrade.go b/app/upgrades/v1_12_0/upgrade.go similarity index 97% rename from app/upgrades/v1_10_0/upgrade.go rename to app/upgrades/v1_12_0/upgrade.go index f8b36533..7091f069 100644 --- a/app/upgrades/v1_10_0/upgrade.go +++ b/app/upgrades/v1_12_0/upgrade.go @@ -1,4 +1,4 @@ -package v1_10_0 +package v1_12_0 import ( "context" @@ -15,7 +15,7 @@ import ( ) // UpgradeName is the on-chain name used for this upgrade. -const UpgradeName = "v1.10.0" +const UpgradeName = "v1.12.0" // CreateUpgradeHandler migrates consensus params from x/params to x/consensus // and then runs module migrations. diff --git a/docs/upgrade.md b/docs/upgrade.md deleted file mode 100644 index cd1920ce..00000000 --- a/docs/upgrade.md +++ /dev/null @@ -1,84 +0,0 @@ -# Benefits of upgrading Lumera from Cosmos SDK 0.50.x to 0.53.5 - -## Cosmos SDK upgrade benefits - -### App wiring modernization - -- **Declarative app wiring (depinject + core/appconfig)**: Replaces much of historical app.go wiring with declarative config (Go/YAML/JSON), improving modularity and reducing initialization boilerplate. -- **runtime/v2 AppBuilder support**: Enables hybrid setups (part declarative, part classic app.go), making it easier to evolve app composition over time. - -### Interchain readiness - -- **IBC v2 readiness**: Aligns with the IBC-Go v10 stack and its v2 features while keeping IBC v1 compatibility for existing channels. -- **Interchain feature enablement**: Paves the way for modern interchain features (ICA, IBC v2 routes, improved packet workflows) without heavy custom shims. - -### Core modules and optional features - -- **Module parity and compatibility**: Brings core modules (gov, staking, auth, bank, feegrant, evidence, circuit, etc.) to current versions, improving ecosystem alignment and upstream support. - -#### New optional modules and features - -- **x/epochs**: Standardized on-chain timers ("run logic every N period") that other modules can hook into. -- **x/protocolpool**: Separates community-pool accounting from distribution into a dedicated module account, making pool assets easier to track and manage. -- **Unordered transactions (opt-in)**: "Fire-and-forget" submission model with `timeout_timestamp` as TTL/replay protection, useful for throughput-focused clients where strict ordering is not required. - -### Parameter and consensus-params cleanup - -- **x/params deprecation**: `x/params` is deprecated as of SDK v0.53 (planned removal next release), so upgrading aligns Lumera with current ecosystem cleanup. -- **Consensus params migration**: The SDK calls out moving CometBFT consensus params from `x/params` to `x/consensus`; upgrade handlers should ensure `ConsensusParamsKeeper.Set()` is invoked appropriately. - -### Deprecations that reduce bloat - -- **x/crisis deprecation/removal**: `x/crisis` is deprecated as of SDK v0.53 (planned removal next release). Lumera removes it in the v1.10.0 upgrade, deletes its store key, and disables crisis invariants by default. - -### Testing, stability, and operations - -- **Testing and tooling maturity**: Updated test helpers, BaseApp options, and CLI utilities reduce local workarounds and make test scaffolding more consistent. -- **Performance and stability**: Accumulates patch-level fixes across the 0.5x series, improving reliability for production workloads and upgrade safety. -- **Operational consistency**: Keeps Lumera closer to current Cosmos SDK practices, making it easier to adopt upstream fixes and collaborate with the ecosystem. -- **Upgrade process enhancements (ADR-047)**: Upgrade module and cosmovisor flow support richer upgrade-plan information, enabling more structured and automatable upgrade operations. - -### Client and indexer impact - -- **Legacy tx logs removed**: SDK v0.53 no longer constructs "legacy logs" for tx query/broadcast responses, which can affect indexers or clients parsing legacy log shapes. - -## IBC upgrade benefits - -### Benefits of upgrading to IBC v2 (IBC-Go v10) - -- **Backward compatibility**: Keep IBC v1 channels while enabling IBC v2, so Lumera can upgrade without forcing counterparties to move immediately. -- **Simplified handshakes**: Reduce connection and channel setup time, lowering relayer overhead and speeding new integrations. -- **Unified routing**: Support multiple Lumera services (Cascade, Sense, Inference, NFT metadata) over a single connection, improving composability and reducing channel sprawl. -- **Payload flexibility**: Allow app-specific encodings and multi-action workflows (e.g., payment + service request in one flow) with less protocol friction. -- **Faster feature adoption**: Enable ICA, queries, and cross-chain calls without reworking the IBC stack as new apps are added. -- **Lower maintenance risk**: Trim the IBC module stack, reducing upgrade risk during the Cosmos SDK 0.53.5 transition while improving long-term scalability. - -### Benefits of upgrading to IBC-Go v10.5.0 - -- **Upstream fixes**: Pick up v10-series fixes and maintenance improvements, reducing the risk of carrying known IBC bugs. -- **Developer ergonomics**: Use newer helper APIs (including v1/v2 event parsing) to reduce custom code in Lumera. -- **Ecosystem alignment**: Stay on the latest v10 patch level for relayer compatibility and support. -- **ICA integrity hardening**: Adds extra validations for ProtoJSON-encoded ICA packets; release notes flag this as state-breaking and best rolled out via a coordinated chain upgrade. - -## Wasm upgrade benefits - -### Benefits of upgrading wasmd from 0.55 to 0.61.6 - -- **Ecosystem alignment**: Match current CosmWasm/wasmd releases commonly used alongside Cosmos SDK 0.53.5. -- **Consensus-sensitive VM upgrade**: wasmvm minor version bumps are generally consensus-breaking per wasmd compatibility notes, so this is a deliberate chain-level upgrade rather than a routine dependency bump. -- **Contract compatibility**: The contract-host interface has been stable since CosmWasm 1.0; CosmWasm 2.0 contracts remain compatible at the Wasm interface level (capabilities gated via feature flags). -- **Operational tuning hooks**: wasmd exposes knobs like `memory_cache_size` (module caching for faster instantiation) and `query_gas_limit` for performance and safety tradeoffs. -- **Security posture**: Includes fixes for consensus-critical issues (for example, non-deterministic crashes during wasm execution simulation patched in wasmvm/wasmd), strengthening chain safety. - -### Benefits of upgrading wasmvm to 3.0.2 - -- **Runtime stability**: Pick up wasmvm bug fixes and runtime hardening from the 3.x line. -- **Compatibility**: Keep contract execution compatible with modern wasm tooling and wasmd expectations. -- **Operational reliability**: Reduce risk of edge-case failures in contract execution and state sync workflows. - -## Notable changes in Lumera - -- **IBC-Go v10.5.0 alignment**: Updated IBC dependencies and test utilities to the v10 line, including v2 packet/event handling and mocks. -- **Wasm stack refresh**: Bumped wasmd/wasmvm to the current compatible versions, keeping CosmWasm integration aligned with the SDK upgrade. -- **Test harness updates**: Ported and adjusted wasm and IBC testing helpers to match newer SDK/IBC behaviors, reducing drift from upstream. -- **Crisis module removal**: The v1.10.0 upgrade drops `x/crisis`, deletes its store key, and removes invariant checks via the crisis module. From 9a9e24c5a5268ddab9350fc488bd470c2160f5ab Mon Sep 17 00:00:00 2001 From: Andrey Kobrin Date: Wed, 28 Jan 2026 10:45:39 -0500 Subject: [PATCH 4/5] fix identation --- app/upgrades/upgrades.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/upgrades/upgrades.go b/app/upgrades/upgrades.go index c1149467..3446ce01 100644 --- a/app/upgrades/upgrades.go +++ b/app/upgrades/upgrades.go @@ -110,7 +110,7 @@ func SetupUpgrades(upgradeName string, params appParams.AppUpgradeParams) (Upgra return UpgradeConfig{ Handler: standardUpgradeHandler(upgradeNameV191, params), }, true -case upgrade_v1_12_0.UpgradeName: + case upgrade_v1_12_0.UpgradeName: return UpgradeConfig{ StoreUpgrade: &upgrade_v1_12_0.StoreUpgrades, Handler: upgrade_v1_12_0.CreateUpgradeHandler(params), From 7af96ab7001ab577f627c65273a18d0c82a04a11 Mon Sep 17 00:00:00 2001 From: Andrey Kobrin Date: Wed, 28 Jan 2026 16:22:03 -0500 Subject: [PATCH 5/5] rollback upgrade version change --- CHANGELOG.md | 4 ++-- app/upgrades/upgrades.go | 13 +++++++------ app/upgrades/upgrades_test.go | 12 ++++++------ app/upgrades/{v1_12_0 => v1_10_0}/store.go | 4 ++-- app/upgrades/{v1_12_0 => v1_10_0}/upgrade.go | 4 ++-- 5 files changed, 19 insertions(+), 18 deletions(-) rename app/upgrades/{v1_12_0 => v1_10_0}/store.go (74%) rename app/upgrades/{v1_12_0 => v1_10_0}/upgrade.go (97%) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4eea4c1..fb3a6e25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,9 @@ --- -## 1.12.0 +## 1.10.0 -Changes included since `v1.9.1` (range: `v1.9.1..v1.12.0`). +Changes included since `v1.9.1` (range: `v1.9.1..v1.10.0`). - Cosmos SDK: upgraded from v0.50.14 to v0.53.5, CometBFT upgraded to v0.38.20 - enabled unordered diff --git a/app/upgrades/upgrades.go b/app/upgrades/upgrades.go index 3446ce01..135c6bc0 100644 --- a/app/upgrades/upgrades.go +++ b/app/upgrades/upgrades.go @@ -15,7 +15,7 @@ import ( upgrade_v1_8_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_0" upgrade_v1_8_4 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_4" upgrade_v1_9_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_9_0" - upgrade_v1_12_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_12_0" + upgrade_v1_10_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_10_0" ) // ================================================================================================================================= @@ -30,7 +30,7 @@ import ( // | v1.8.5 | standard | none | Migrations only // | v1.9.0 | custom | none | Backfills action/supernode secondary indices // | v1.9.1 | standard | none | Migrations only -// | v1.12.0 | custom | drop crisis | Migrate consensus params from x/params to x/consensus; remove x/crisis +// | v1.10.0 | custom | drop crisis | Migrate consensus params from x/params to x/consensus; remove x/crisis // ================================================================================================================================= type UpgradeConfig struct { @@ -46,6 +46,7 @@ const ( upgradeNameV191 = "v1.9.1" ) +// List of all known upgrade names, in chronological order. var upgradeNames = []string{ upgrade_v1_6_1.UpgradeName, upgradeNameV170, @@ -55,7 +56,7 @@ var upgradeNames = []string{ upgradeNameV185, upgrade_v1_9_0.UpgradeName, upgradeNameV191, - upgrade_v1_12_0.UpgradeName, + upgrade_v1_10_0.UpgradeName, } var NoUpgradeConfig = UpgradeConfig{ @@ -110,10 +111,10 @@ func SetupUpgrades(upgradeName string, params appParams.AppUpgradeParams) (Upgra return UpgradeConfig{ Handler: standardUpgradeHandler(upgradeNameV191, params), }, true - case upgrade_v1_12_0.UpgradeName: + case upgrade_v1_10_0.UpgradeName: return UpgradeConfig{ - StoreUpgrade: &upgrade_v1_12_0.StoreUpgrades, - Handler: upgrade_v1_12_0.CreateUpgradeHandler(params), + StoreUpgrade: &upgrade_v1_10_0.StoreUpgrades, + Handler: upgrade_v1_10_0.CreateUpgradeHandler(params), }, true // add future upgrades here diff --git a/app/upgrades/upgrades_test.go b/app/upgrades/upgrades_test.go index fc66c38b..5cba46e0 100644 --- a/app/upgrades/upgrades_test.go +++ b/app/upgrades/upgrades_test.go @@ -15,7 +15,7 @@ import ( upgrade_v1_8_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_0" upgrade_v1_8_4 "github.com/LumeraProtocol/lumera/app/upgrades/v1_8_4" upgrade_v1_9_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_9_0" - upgrade_v1_12_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_12_0" + upgrade_v1_10_0 "github.com/LumeraProtocol/lumera/app/upgrades/v1_10_0" actiontypes "github.com/LumeraProtocol/lumera/x/action/v1/types" crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" ) @@ -30,7 +30,7 @@ func TestUpgradeNamesOrder(t *testing.T) { upgradeNameV185, upgrade_v1_9_0.UpgradeName, upgradeNameV191, - upgrade_v1_12_0.UpgradeName, + upgrade_v1_10_0.UpgradeName, } require.Equal(t, expected, upgradeNames, "upgradeNames should stay in ascending order") } @@ -66,8 +66,8 @@ func TestSetupUpgradesAndHandlers(t *testing.T) { "store upgrade presence mismatch for %s on %s", upgradeName, tt.chainID, ) - if upgradeName == upgrade_v1_12_0.UpgradeName && config.StoreUpgrade != nil { - require.Contains(t, config.StoreUpgrade.Deleted, crisistypes.StoreKey, "v1.12.0 should delete crisis store key") + if upgradeName == upgrade_v1_10_0.UpgradeName && config.StoreUpgrade != nil { + require.Contains(t, config.StoreUpgrade.Deleted, crisistypes.StoreKey, "v1.10.0 should delete crisis store key") } if config.Handler == nil { @@ -76,7 +76,7 @@ func TestSetupUpgradesAndHandlers(t *testing.T) { // v1.9.0 requires full keeper wiring; exercising it here would require // a full app harness. This test only verifies registration and gating. - if upgradeName == upgrade_v1_9_0.UpgradeName || upgradeName == upgrade_v1_12_0.UpgradeName { + if upgradeName == upgrade_v1_9_0.UpgradeName || upgradeName == upgrade_v1_10_0.UpgradeName { continue } @@ -119,7 +119,7 @@ func expectStoreUpgrade(upgradeName, chainID string) bool { return IsTestnet(chainID) || IsDevnet(chainID) case upgrade_v1_8_4.UpgradeName: return IsMainnet(chainID) - case upgrade_v1_12_0.UpgradeName: + case upgrade_v1_10_0.UpgradeName: return true default: return false diff --git a/app/upgrades/v1_12_0/store.go b/app/upgrades/v1_10_0/store.go similarity index 74% rename from app/upgrades/v1_12_0/store.go rename to app/upgrades/v1_10_0/store.go index c3927af2..b26804f9 100644 --- a/app/upgrades/v1_12_0/store.go +++ b/app/upgrades/v1_10_0/store.go @@ -1,11 +1,11 @@ -package v1_12_0 +package v1_10_0 import ( storetypes "cosmossdk.io/store/types" crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" ) -// StoreUpgrades defines store changes for v1.12.0. +// StoreUpgrades defines store changes for v1.10.0. var StoreUpgrades = storetypes.StoreUpgrades{ Deleted: []string{crisistypes.StoreKey}, } diff --git a/app/upgrades/v1_12_0/upgrade.go b/app/upgrades/v1_10_0/upgrade.go similarity index 97% rename from app/upgrades/v1_12_0/upgrade.go rename to app/upgrades/v1_10_0/upgrade.go index 7091f069..f8b36533 100644 --- a/app/upgrades/v1_12_0/upgrade.go +++ b/app/upgrades/v1_10_0/upgrade.go @@ -1,4 +1,4 @@ -package v1_12_0 +package v1_10_0 import ( "context" @@ -15,7 +15,7 @@ import ( ) // UpgradeName is the on-chain name used for this upgrade. -const UpgradeName = "v1.12.0" +const UpgradeName = "v1.10.0" // CreateUpgradeHandler migrates consensus params from x/params to x/consensus // and then runs module migrations.