From fcccc2bff6341e7d86f8d806ab9eaabc53f9f469 Mon Sep 17 00:00:00 2001 From: Alexander Peters Date: Tue, 22 Nov 2022 10:54:30 +0100 Subject: [PATCH 1/8] feat: Upgrade to IBC v4.2.0 with interchain-accounts v0.2.4 (#1088) cherry-pick original #1088 except ICA part. * Upgrade to IBC v4.2.0 with interchain-accounts v0.2.4 * Fix linter issues * Test version handshake * Add more ibc e2e scenarios * Add fee middleware to wasm * Get ibc app version from middleware --- app/ante.go | 4 +- app/app.go | 121 +++++++--- app/sim_test.go | 4 +- app/test_access.go | 4 +- app/test_helpers.go | 31 ++- appplus/app.go | 90 ++++--- go.mod | 65 ++--- go.sum | 150 +++++++----- x/wasm/ibc.go | 85 ++++--- x/wasm/ibc_integration_test.go | 126 ++++++++++ x/wasm/ibc_reflect_test.go | 4 +- x/wasm/ibc_test.go | 4 +- x/wasm/ibctesting/chain.go | 228 +++++++++++------- x/wasm/ibctesting/coordinator.go | 48 +--- x/wasm/ibctesting/endpoint.go | 95 ++++++-- x/wasm/ibctesting/event_utils.go | 78 ++++-- x/wasm/ibctesting/path.go | 22 +- x/wasm/ibctesting/wasm.go | 2 +- x/wasm/keeper/handler_plugin.go | 4 +- x/wasm/keeper/handler_plugin_encoders.go | 6 +- x/wasm/keeper/handler_plugin_encoders_test.go | 6 +- x/wasm/keeper/handler_plugin_test.go | 6 +- x/wasm/keeper/ibc.go | 2 +- x/wasm/keeper/query_plugins.go | 2 +- x/wasm/keeper/query_plugins_test.go | 2 +- x/wasm/keeper/relay.go | 8 +- x/wasm/keeper/snapshotter_integration_test.go | 2 +- x/wasm/keeper/test_common.go | 60 ++--- x/wasm/keeper/wasmtesting/mock_engine.go | 53 ++++ x/wasm/keeper/wasmtesting/mock_keepers.go | 4 +- x/wasm/relay_pingpong_test.go | 14 +- x/wasm/relay_test.go | 8 +- x/wasm/types/expected_keepers.go | 6 +- x/wasmplus/keeper/test_common.go | 10 +- 34 files changed, 890 insertions(+), 464 deletions(-) create mode 100644 x/wasm/ibc_integration_test.go diff --git a/app/ante.go b/app/ante.go index 5ac4961a5a..82cb7c25e1 100644 --- a/app/ante.go +++ b/app/ante.go @@ -4,8 +4,8 @@ import ( sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" "github.com/Finschia/finschia-sdk/x/auth/ante" - ibcante "github.com/Finschia/ibc-go/v3/modules/core/ante" - "github.com/Finschia/ibc-go/v3/modules/core/keeper" + ibcante "github.com/cosmos/ibc-go/v4/modules/core/ante" + "github.com/cosmos/ibc-go/v4/modules/core/keeper" wasmkeeper "github.com/Finschia/wasmd/x/wasm/keeper" wasmTypes "github.com/Finschia/wasmd/x/wasm/types" diff --git a/app/app.go b/app/app.go index fad0978db9..b339731ceb 100644 --- a/app/app.go +++ b/app/app.go @@ -15,23 +15,26 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" - ica "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts" - icacontrollerkeeper "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/controller/keeper" - icacontrollertypes "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/controller/types" - icahost "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/host" - icahostkeeper "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/host/keeper" - icahosttypes "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/host/types" - icatypes "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/types" - transfer "github.com/Finschia/ibc-go/v3/modules/apps/transfer" - ibctransferkeeper "github.com/Finschia/ibc-go/v3/modules/apps/transfer/keeper" - ibctransfertypes "github.com/Finschia/ibc-go/v3/modules/apps/transfer/types" - ibc "github.com/Finschia/ibc-go/v3/modules/core" - ibcclient "github.com/Finschia/ibc-go/v3/modules/core/02-client" - ibcclientclient "github.com/Finschia/ibc-go/v3/modules/core/02-client/client" - ibcclienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - porttypes "github.com/Finschia/ibc-go/v3/modules/core/05-port/types" - ibchost "github.com/Finschia/ibc-go/v3/modules/core/24-host" - ibckeeper "github.com/Finschia/ibc-go/v3/modules/core/keeper" + ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" + icacontrollerkeeper "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/controller/keeper" + icacontrollertypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/controller/types" + icahost "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/host" + icahostkeeper "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/host/keeper" + icahosttypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/host/types" + icatypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/types" + ibcfee "github.com/cosmos/ibc-go/v4/modules/apps/29-fee" + ibcfeekeeper "github.com/cosmos/ibc-go/v4/modules/apps/29-fee/keeper" + ibcfeetypes "github.com/cosmos/ibc-go/v4/modules/apps/29-fee/types" + transfer "github.com/cosmos/ibc-go/v4/modules/apps/transfer" + ibctransferkeeper "github.com/cosmos/ibc-go/v4/modules/apps/transfer/keeper" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + ibc "github.com/cosmos/ibc-go/v4/modules/core" + ibcclient "github.com/cosmos/ibc-go/v4/modules/core/02-client" + ibcclientclient "github.com/cosmos/ibc-go/v4/modules/core/02-client/client" + ibcclienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + porttypes "github.com/cosmos/ibc-go/v4/modules/core/05-port/types" + ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" + ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" ocabci "github.com/Finschia/ostracon/abci/types" "github.com/Finschia/finschia-sdk/baseapp" @@ -203,6 +206,7 @@ var ( vesting.AppModuleBasic{}, wasm.AppModuleBasic{}, ica.AppModuleBasic{}, + ibcfee.AppModuleBasic{}, ) // module account permissions @@ -214,6 +218,7 @@ var ( stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + ibcfeetypes.ModuleName: nil, icatypes.ModuleName: nil, wasm.ModuleName: {authtypes.Burner}, } @@ -259,6 +264,7 @@ type WasmApp struct { ParamsKeeper paramskeeper.Keeper EvidenceKeeper evidencekeeper.Keeper IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly + IBCFeeKeeper ibcfeekeeper.Keeper ICAControllerKeeper icacontrollerkeeper.Keeper ICAHostKeeper icahostkeeper.Keeper TransferKeeper ibctransferkeeper.Keeper @@ -270,6 +276,7 @@ type WasmApp struct { ScopedICAHostKeeper capabilitykeeper.ScopedKeeper ScopedICAControllerKeeper capabilitykeeper.ScopedKeeper ScopedTransferKeeper capabilitykeeper.ScopedKeeper + ScopedIBCFeeKeeper capabilitykeeper.ScopedKeeper ScopedWasmKeeper capabilitykeeper.ScopedKeeper // make IBC modules public for test purposes @@ -313,7 +320,7 @@ func NewWasmApp( minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, - feegrant.StoreKey, authzkeeper.StoreKey, wasm.StoreKey, icahosttypes.StoreKey, icacontrollertypes.StoreKey, + feegrant.StoreKey, authzkeeper.StoreKey, wasm.StoreKey, icahosttypes.StoreKey, icacontrollertypes.StoreKey, ibcfeetypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -448,20 +455,26 @@ func NewWasmApp( AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) + // IBC Fee Module keeper + app.IBCFeeKeeper = ibcfeekeeper.NewKeeper( + appCodec, keys[ibcfeetypes.StoreKey], app.getSubspace(ibcfeetypes.ModuleName), + app.IBCKeeper.ChannelKeeper, // may be replaced with IBC middleware + app.IBCKeeper.ChannelKeeper, + &app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper, + ) + // Create Transfer Keepers app.TransferKeeper = ibctransferkeeper.NewKeeper( appCodec, keys[ibctransfertypes.StoreKey], app.getSubspace(ibctransfertypes.ModuleName), - app.IBCKeeper.ChannelKeeper, + app.IBCFeeKeeper, // ISC4 Wrapper: fee IBC middleware app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper, scopedTransferKeeper, ) - transferModule := transfer.NewAppModule(app.TransferKeeper) - transferIBCModule := transfer.NewIBCModule(app.TransferKeeper) app.ICAHostKeeper = icahostkeeper.NewKeeper( appCodec, @@ -477,14 +490,12 @@ func NewWasmApp( appCodec, keys[icacontrollertypes.StoreKey], app.getSubspace(icacontrollertypes.SubModuleName), - app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee + app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, scopedICAControllerKeeper, app.MsgServiceRouter(), ) - icaModule := ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper) - icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) // create evidence keeper with router evidenceKeeper := evidencekeeper.NewKeeper( @@ -524,19 +535,49 @@ func NewWasmApp( wasmOpts..., ) - // Create static IBC router, add app routes, then set and seal it - ibcRouter := porttypes.NewRouter() - // The gov proposal types can be individually enabled if len(enabledProposals) != 0 { govRouter.AddRoute(wasm.RouterKey, wasm.NewWasmProposalHandler(app.WasmKeeper, enabledProposals)) } - ibcRouter. - AddRoute(wasm.ModuleName, wasm.NewIBCHandler(app.WasmKeeper, app.IBCKeeper.ChannelKeeper)). - AddRoute(ibctransfertypes.ModuleName, transferIBCModule). - // AddRoute(icacontrollertypes.SubModuleName, icaControllerIBCModule). - AddRoute(icahosttypes.SubModuleName, icaHostIBCModule) - // AddRoute(intertxtypes.ModuleName, icaControllerIBCModule) + + // Create Transfer Stack + var transferStack porttypes.IBCModule + transferStack = transfer.NewIBCModule(app.TransferKeeper) + transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) + + /* + // Create Interchain Accounts Stack + // SendPacket, since it is originating from the application to core IBC: + // icaAuthModuleKeeper.SendTx -> icaController.SendPacket -> fee.SendPacket -> channel.SendPacket + + // Note: please do your research before using this in production app, this is a demo and not an officially + // supported IBC team implementation. Do your own research before using it. + var icaControllerStack porttypes.IBCModule + // You will likely want to use your own reviewed and maintained ica auth module + icaControllerStack = intertx.NewIBCModule(app.InterTxKeeper) + icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper) + icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper) + */ + + // RecvPacket, message that originates from core IBC and goes down to app, the flow is: + // channel.RecvPacket -> fee.OnRecvPacket -> icaHost.OnRecvPacket + var icaHostStack porttypes.IBCModule + icaHostStack = icahost.NewIBCModule(app.ICAHostKeeper) + icaHostStack = ibcfee.NewIBCMiddleware(icaHostStack, app.IBCFeeKeeper) + + // Create fee enabled wasm ibc Stack + var wasmStack porttypes.IBCModule + wasmStack = wasm.NewIBCHandler(app.WasmKeeper, app.IBCKeeper.ChannelKeeper, app.IBCFeeKeeper) + wasmStack = ibcfee.NewIBCMiddleware(wasmStack, app.IBCFeeKeeper) + + // Create static IBC router, add app routes, then set and seal it + ibcRouter := porttypes.NewRouter(). + AddRoute(ibctransfertypes.ModuleName, transferStack). + AddRoute(wasm.ModuleName, wasmStack). + // AddRoute(intertxtypes.ModuleName, icaControllerStack). + // AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). + AddRoute(icahosttypes.SubModuleName, icaHostStack) + app.IBCKeeper.SetRouter(ibcRouter) app.GovKeeper = govkeeper.NewKeeper( @@ -579,8 +620,10 @@ func NewWasmApp( authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), - transferModule, - icaModule, + transfer.NewAppModule(app.TransferKeeper), + ibcfee.NewAppModule(app.IBCFeeKeeper), + ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper), + // intertx.NewAppModule(appCodec, app.InterTxKeeper), crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), // always be last to make sure that it checks for all invariants and not only part of them ) @@ -609,7 +652,8 @@ func NewWasmApp( ibctransfertypes.ModuleName, ibchost.ModuleName, icatypes.ModuleName, - // intertxtypes.ModuleName, + ibcfeetypes.ModuleName, + //intertxtypes.ModuleName, wasm.ModuleName, ) @@ -634,6 +678,7 @@ func NewWasmApp( ibctransfertypes.ModuleName, ibchost.ModuleName, icatypes.ModuleName, + ibcfeetypes.ModuleName, // intertxtypes.ModuleName, wasm.ModuleName, ) @@ -666,6 +711,8 @@ func NewWasmApp( ibctransfertypes.ModuleName, ibchost.ModuleName, icatypes.ModuleName, + ibcfeetypes.ModuleName, + // intertxtypes.ModuleName, // wasm after ibc transfer wasm.ModuleName, ) @@ -698,7 +745,7 @@ func NewWasmApp( evidence.NewAppModule(app.EvidenceKeeper), wasm.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), ibc.NewAppModule(app.IBCKeeper), - transferModule, + transfer.NewAppModule(app.TransferKeeper), ) app.sm.RegisterStoreDecoders() diff --git a/app/sim_test.go b/app/sim_test.go index 7aa6522624..3d4637961e 100644 --- a/app/sim_test.go +++ b/app/sim_test.go @@ -34,8 +34,8 @@ import ( "github.com/Finschia/finschia-sdk/x/simulation" slashingtypes "github.com/Finschia/finschia-sdk/x/slashing/types" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" - ibctransfertypes "github.com/Finschia/ibc-go/v3/modules/apps/transfer/types" - ibchost "github.com/Finschia/ibc-go/v3/modules/core/24-host" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" "github.com/Finschia/ostracon/libs/log" "github.com/Finschia/wasmd/x/wasm" diff --git a/app/test_access.go b/app/test_access.go index 008f0d5a34..256b6f1c0f 100644 --- a/app/test_access.go +++ b/app/test_access.go @@ -9,8 +9,8 @@ import ( bankkeeper "github.com/Finschia/finschia-sdk/x/bank/keeper" capabilitykeeper "github.com/Finschia/finschia-sdk/x/capability/keeper" stakingkeeper "github.com/Finschia/finschia-sdk/x/staking/keeper" - ibctransferkeeper "github.com/Finschia/ibc-go/v3/modules/apps/transfer/keeper" - ibckeeper "github.com/Finschia/ibc-go/v3/modules/core/keeper" + ibctransferkeeper "github.com/cosmos/ibc-go/v4/modules/apps/transfer/keeper" + ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" "github.com/Finschia/wasmd/app/params" "github.com/Finschia/wasmd/x/wasm" diff --git a/app/test_helpers.go b/app/test_helpers.go index 9c98dd7fc0..ed1c2149d0 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -99,7 +99,7 @@ func Setup(isCheckTx bool, opts ...wasm.Option) *WasmApp { // that also act as delegators. For simplicity, each validator is bonded with a delegation // of one consensus engine unit (10^6) in the default token of the WasmApp from first genesis // account. A Nop logger is set in WasmApp. -func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, opts []wasm.Option, balances ...banktypes.Balance) *WasmApp { +func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, chainID string, opts []wasm.Option, balances ...banktypes.Balance) *WasmApp { app, genesisState := setup(t, true, 5, opts...) // set genesis accounts authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) @@ -108,7 +108,7 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs validators := make([]stakingtypes.Validator, 0, len(valSet.Validators)) delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) - bondAmt := sdk.NewInt(1000000) + bondAmt := sdk.TokensFromConsensusPower(1, sdk.DefaultPowerReduction) for _, val := range valSet.Validators { pk, err := cryptocodec.FromOcPubKeyInterface(val.PubKey) @@ -128,30 +128,30 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), MinSelfDelegation: sdk.ZeroInt(), } + validators = append(validators, validator) delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec())) - } // set validators and delegations - stakingGenesis := stakingtypes.NewGenesisState(stakingtypes.DefaultParams(), validators, delegations) - genesisState[stakingtypes.ModuleName] = app.appCodec.MustMarshalJSON(stakingGenesis) + var stakingGenesis stakingtypes.GenesisState + app.AppCodec().MustUnmarshalJSON(genesisState[stakingtypes.ModuleName], &stakingGenesis) - totalSupply := sdk.NewCoins() - for _, b := range balances { - // add genesis acc tokens and delegated tokens to total supply - totalSupply = totalSupply.Add(b.Coins.Add(sdk.NewCoin(sdk.DefaultBondDenom, bondAmt))...) - } + bondDenom := stakingGenesis.Params.BondDenom // add bonded amount to bonded pool module account balances = append(balances, banktypes.Balance{ Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), - Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)}, + Coins: sdk.Coins{sdk.NewCoin(bondDenom, bondAmt.Mul(sdk.NewInt(int64(len(valSet.Validators)))))}, }) + // set validators and delegations + stakingGenesis = *stakingtypes.NewGenesisState(stakingGenesis.Params, validators, delegations) + genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(&stakingGenesis) + // update total supply - bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, totalSupply, []banktypes.Metadata{}) - genesisState[banktypes.ModuleName] = app.appCodec.MustMarshalJSON(bankGenesis) + bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, sdk.NewCoins(), []banktypes.Metadata{}) + genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis) stateBytes, err := json.MarshalIndent(genesisState, "", " ") require.NoError(t, err) @@ -159,6 +159,7 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs // init chain will set the validator set and initialize the genesis accounts app.InitChain( abci.RequestInitChain{ + ChainId: chainID, Validators: []abci.ValidatorUpdate{}, ConsensusParams: DefaultConsensusParams, AppStateBytes: stateBytes, @@ -168,6 +169,7 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs // commit genesis changes app.Commit() app.BeginBlock(ocabci.RequestBeginBlock{Header: tmproto.Header{ + ChainID: chainID, Height: app.LastBlockHeight() + 1, AppHash: app.LastCommitID().Hash, ValidatorsHash: valSet.Hash(), @@ -391,9 +393,6 @@ func SignAndDeliver( require.Nil(t, res) } - app.EndBlock(abci.RequestEndBlock{}) - app.Commit() - return gInfo, res, err } diff --git a/appplus/app.go b/appplus/app.go index b581b0652f..6099c016c3 100644 --- a/appplus/app.go +++ b/appplus/app.go @@ -82,24 +82,27 @@ import ( upgradeclient "github.com/Finschia/finschia-sdk/x/upgrade/client" upgradekeeper "github.com/Finschia/finschia-sdk/x/upgrade/keeper" upgradetypes "github.com/Finschia/finschia-sdk/x/upgrade/types" - ica "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts" - icacontrollerkeeper "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/controller/keeper" - icacontrollertypes "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/controller/types" - icahost "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/host" - icahostkeeper "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/host/keeper" - icahosttypes "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/host/types" - icatypes "github.com/Finschia/ibc-go/v3/modules/apps/27-interchain-accounts/types" - transfer "github.com/Finschia/ibc-go/v3/modules/apps/transfer" - ibctransferkeeper "github.com/Finschia/ibc-go/v3/modules/apps/transfer/keeper" - ibctransfertypes "github.com/Finschia/ibc-go/v3/modules/apps/transfer/types" - ibc "github.com/Finschia/ibc-go/v3/modules/core" - ibcclient "github.com/Finschia/ibc-go/v3/modules/core/02-client" - ibcclientclient "github.com/Finschia/ibc-go/v3/modules/core/02-client/client" - ibcclienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - porttypes "github.com/Finschia/ibc-go/v3/modules/core/05-port/types" - ibchost "github.com/Finschia/ibc-go/v3/modules/core/24-host" - ibckeeper "github.com/Finschia/ibc-go/v3/modules/core/keeper" - ibcmock "github.com/Finschia/ibc-go/v3/testing/mock" + ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" + icacontrollerkeeper "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/controller/keeper" + icacontrollertypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/controller/types" + icahost "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/host" + icahostkeeper "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/host/keeper" + icahosttypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/host/types" + icatypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/types" + ibcfee "github.com/cosmos/ibc-go/v4/modules/apps/29-fee" + ibcfeekeeper "github.com/cosmos/ibc-go/v4/modules/apps/29-fee/keeper" + ibcfeetypes "github.com/cosmos/ibc-go/v4/modules/apps/29-fee/types" + transfer "github.com/cosmos/ibc-go/v4/modules/apps/transfer" + ibctransferkeeper "github.com/cosmos/ibc-go/v4/modules/apps/transfer/keeper" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + ibc "github.com/cosmos/ibc-go/v4/modules/core" + ibcclient "github.com/cosmos/ibc-go/v4/modules/core/02-client" + ibcclientclient "github.com/cosmos/ibc-go/v4/modules/core/02-client/client" + ibcclienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + porttypes "github.com/cosmos/ibc-go/v4/modules/core/05-port/types" + ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" + ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" + ibcmock "github.com/cosmos/ibc-go/v4/testing/mock" ocabci "github.com/Finschia/ostracon/abci/types" tmjson "github.com/Finschia/ostracon/libs/json" "github.com/Finschia/ostracon/libs/log" @@ -201,6 +204,7 @@ var ( vesting.AppModuleBasic{}, wasmplus.AppModuleBasic{}, ica.AppModuleBasic{}, + ibcfee.AppModuleBasic{}, ) // module account permissions @@ -212,6 +216,7 @@ var ( stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + ibcfeetypes.ModuleName: nil, icatypes.ModuleName: nil, wasmplustypes.ModuleName: {authtypes.Burner}, } @@ -257,6 +262,7 @@ type WasmPlusApp struct { ParamsKeeper paramskeeper.Keeper EvidenceKeeper evidencekeeper.Keeper IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly + IBCFeeKeeper ibcfeekeeper.Keeper ICAControllerKeeper icacontrollerkeeper.Keeper ICAHostKeeper icahostkeeper.Keeper TransferKeeper ibctransferkeeper.Keeper @@ -268,6 +274,7 @@ type WasmPlusApp struct { ScopedICAHostKeeper capabilitykeeper.ScopedKeeper ScopedICAControllerKeeper capabilitykeeper.ScopedKeeper ScopedTransferKeeper capabilitykeeper.ScopedKeeper + ScopedIBCFeeKeeper capabilitykeeper.ScopedKeeper ScopedWasmKeeper capabilitykeeper.ScopedKeeper // make IBC modules public for test purposes @@ -311,7 +318,7 @@ func NewWasmApp( minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, - feegrant.StoreKey, authzkeeper.StoreKey, wasmplustypes.StoreKey, icahosttypes.StoreKey, icacontrollertypes.StoreKey, + feegrant.StoreKey, authzkeeper.StoreKey, wasmplustypes.StoreKey, icahosttypes.StoreKey, icacontrollertypes.StoreKey, ibcfeetypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -446,12 +453,20 @@ func NewWasmApp( AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) + // IBC Fee Module keeper + app.IBCFeeKeeper = ibcfeekeeper.NewKeeper( + appCodec, keys[ibcfeetypes.StoreKey], app.getSubspace(ibcfeetypes.ModuleName), + app.IBCKeeper.ChannelKeeper, // may be replaced with IBC middleware + app.IBCKeeper.ChannelKeeper, + &app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper, + ) + // Create Transfer Keepers app.TransferKeeper = ibctransferkeeper.NewKeeper( appCodec, keys[ibctransfertypes.StoreKey], app.getSubspace(ibctransfertypes.ModuleName), - app.IBCKeeper.ChannelKeeper, + app.IBCFeeKeeper, // ISC4 Wrapper: fee IBC middleware app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, app.AccountKeeper, @@ -459,7 +474,7 @@ func NewWasmApp( scopedTransferKeeper, ) transferModule := transfer.NewAppModule(app.TransferKeeper) - transferIBCModule := transfer.NewIBCModule(app.TransferKeeper) + //transferIBCModule := transfer.NewIBCModule(app.TransferKeeper) app.ICAHostKeeper = icahostkeeper.NewKeeper( appCodec, @@ -475,7 +490,7 @@ func NewWasmApp( appCodec, keys[icacontrollertypes.StoreKey], app.getSubspace(icacontrollertypes.SubModuleName), - app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee + app.IBCFeeKeeper, // ISC4 Wrapper: fee IBC middleware app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, scopedICAControllerKeeper, @@ -522,17 +537,34 @@ func NewWasmApp( wasmOpts..., ) - // Create static IBC router, add app routes, then set and seal it - ibcRouter := porttypes.NewRouter() - // The gov proposal types can be individually enabled if len(enabledProposals) != 0 { govRouter.AddRoute(wasmplustypes.RouterKey, wasmpluskeeper.NewWasmProposalHandler(&app.WasmKeeper, enabledProposals)) } + + // Create Transfer Stack + var transferStack porttypes.IBCModule + transferStack = transfer.NewIBCModule(app.TransferKeeper) + transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) + // RecvPacket, message that originates from core IBC and goes down to app, the flow is: + // channel.RecvPacket -> fee.OnRecvPacket -> icaHost.OnRecvPacket + var icaHostStack porttypes.IBCModule + icaHostStack = icahost.NewIBCModule(app.ICAHostKeeper) + icaHostStack = ibcfee.NewIBCMiddleware(icaHostStack, app.IBCFeeKeeper) + + // Create fee enabled wasm ibc Stack + var wasmStack porttypes.IBCModule + wasmStack = wasm.NewIBCHandler(app.WasmKeeper, app.IBCKeeper.ChannelKeeper, app.IBCFeeKeeper) + wasmStack = ibcfee.NewIBCMiddleware(wasmStack, app.IBCFeeKeeper) + + // Create static IBC router, add app routes, then set and seal it + ibcRouter := porttypes.NewRouter() + ibcRouter. - AddRoute(wasmplustypes.ModuleName, wasm.NewIBCHandler(app.WasmKeeper, app.IBCKeeper.ChannelKeeper)). - AddRoute(ibctransfertypes.ModuleName, transferIBCModule). + AddRoute(ibctransfertypes.ModuleName, transferStack). + AddRoute(wasmplustypes.ModuleName, wasmStack). AddRoute(icahosttypes.SubModuleName, icaHostIBCModule) + app.IBCKeeper.SetRouter(ibcRouter) app.GovKeeper = govkeeper.NewKeeper( @@ -576,6 +608,7 @@ func NewWasmApp( ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), transferModule, + ibcfee.NewAppModule(app.IBCFeeKeeper), icaModule, crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), // always be last to make sure that it checks for all invariants and not only part of them ) @@ -605,6 +638,7 @@ func NewWasmApp( ibctransfertypes.ModuleName, ibchost.ModuleName, icatypes.ModuleName, + ibcfeetypes.ModuleName, wasmplustypes.ModuleName, ) @@ -629,6 +663,7 @@ func NewWasmApp( ibctransfertypes.ModuleName, ibchost.ModuleName, icatypes.ModuleName, + ibcfeetypes.ModuleName, wasmplustypes.ModuleName, ) @@ -660,6 +695,7 @@ func NewWasmApp( ibctransfertypes.ModuleName, ibchost.ModuleName, icatypes.ModuleName, + ibcfeetypes.ModuleName, // wasm after ibc transfer wasmplustypes.ModuleName, ) diff --git a/go.mod b/go.mod index 02c04c63d5..aae1b2c7cc 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,11 @@ module github.com/Finschia/wasmd go 1.20 require ( - github.com/Finschia/finschia-sdk v0.47.0-rc6 - github.com/Finschia/ibc-go/v3 v3.3.3 - github.com/Finschia/ostracon v1.0.10-0.20230417090415-bc3f5693b6a1 + github.com/Finschia/finschia-sdk v0.47.1-0.20230725074611-f8840edecbaa + github.com/Finschia/ostracon v1.1.0 github.com/Finschia/wasmvm v1.1.1-0.11.2.0.20230418093236-ce70a3856778 github.com/cosmos/iavl v0.19.4 + github.com/cosmos/ibc-go/v4 v4.3.1 github.com/dvsekhvalnov/jose2go v1.5.0 github.com/go-kit/kit v0.12.0 github.com/gogo/protobuf v1.3.3 @@ -16,20 +16,20 @@ require ( github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.15.0 + github.com/prometheus/client_golang v1.16.0 github.com/rakyll/statik v0.1.7 github.com/regen-network/cosmos-proto v0.3.1 github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa - github.com/spf13/cast v1.5.0 + github.com/spf13/cast v1.5.1 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.15.0 - github.com/stretchr/testify v1.8.2 + github.com/spf13/viper v1.16.0 + github.com/stretchr/testify v1.8.4 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/tendermint/tendermint v0.34.24 github.com/tendermint/tm-db v0.6.7 - google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f - google.golang.org/grpc v1.54.0 + google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529 + google.golang.org/grpc v1.56.2 gopkg.in/yaml.v2 v2.4.0 ) @@ -38,8 +38,8 @@ require ( github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect - github.com/VictoriaMetrics/fastcache v1.12.0 // indirect - github.com/Workiva/go-datastructures v1.0.53 // indirect + github.com/VictoriaMetrics/fastcache v1.12.1 // indirect + github.com/Workiva/go-datastructures v1.1.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect @@ -47,13 +47,14 @@ require ( github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/coinbase/rosetta-sdk-go v0.8.2 // indirect + github.com/coinbase/rosetta-sdk-go v0.8.3 // indirect + github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect - github.com/cosmos/ledger-cosmos-go v0.12.1 // indirect + github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect @@ -73,7 +74,7 @@ require ( github.com/google/orderedcode v0.0.1 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect @@ -85,31 +86,31 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/klauspost/compress v1.15.11 // indirect - github.com/lib/pq v1.10.7 // indirect + github.com/klauspost/compress v1.16.6 // indirect + github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/onsi/ginkgo v1.16.4 // indirect - github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.9.0 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/r2ishiguro/vrf v0.0.0-20180716233122-192de52975eb // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rs/cors v1.9.0 // indirect github.com/rs/zerolog v1.29.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect - github.com/spf13/afero v1.9.3 // indirect + github.com/spf13/afero v1.9.5 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect @@ -117,15 +118,17 @@ require ( github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/zondax/hid v0.9.1 // indirect - github.com/zondax/ledger-go v0.14.0 // indirect + github.com/zondax/ledger-go v0.14.1 // indirect go.etcd.io/bbolt v1.3.6 // indirect - golang.org/x/crypto v0.8.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.9.0 // indirect - golang.org/x/sys v0.7.0 // indirect - golang.org/x/term v0.7.0 // indirect - golang.org/x/text v0.9.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + golang.org/x/crypto v0.11.0 // indirect + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect + golang.org/x/net v0.12.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/term v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect + google.golang.org/genproto v0.0.0-20230525234025-438c736192d0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -134,6 +137,7 @@ require ( replace ( github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 + github.com/cosmos/ibc-go/v4 => github.com/Finschia/ibc-go/v4 v4.3.1 // Fix upstream GHSA-h395-qcrw-5vmq vulnerability. // TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 @@ -141,4 +145,5 @@ replace ( // the following version across all dependencies. github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 google.golang.org/grpc => google.golang.org/grpc v1.33.2 + ) diff --git a/go.sum b/go.sum index 8b09e11f75..8ac3dddc15 100644 --- a/go.sum +++ b/go.sum @@ -47,12 +47,12 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Finschia/finschia-sdk v0.47.0-rc6 h1:e9DOhCsaLLD3D0+d4GhqN/oGl9tLB5ncfiddFd8Ad0Y= -github.com/Finschia/finschia-sdk v0.47.0-rc6/go.mod h1:T1eSChkSMsvtvUVwRP+RNO00nbx2ZQKzAxjtpLRQopQ= -github.com/Finschia/ibc-go/v3 v3.3.3 h1:geNUwG7xU0vve1Rv8qATpAk59BL5thLuUcLvJ7xnkiM= -github.com/Finschia/ibc-go/v3 v3.3.3/go.mod h1:YC5hldLSJQDoii3W2E9J07BVdTF7fesUQcATo5zQ248= -github.com/Finschia/ostracon v1.0.10-0.20230417090415-bc3f5693b6a1 h1:sY8xWugQvQmp4p+rvfB+SKwWZLRqptVaEE7S8O+qJwk= -github.com/Finschia/ostracon v1.0.10-0.20230417090415-bc3f5693b6a1/go.mod h1:nPRoQEOOp8FFp2XQ8b1dvfHgKNxp1Zb7i1p5yrLIgG4= +github.com/Finschia/finschia-sdk v0.47.1-0.20230725074611-f8840edecbaa h1:rqmj9tGqBgJT42payCkZbFsHF1Z9KB0HJEk7JY+vN8s= +github.com/Finschia/finschia-sdk v0.47.1-0.20230725074611-f8840edecbaa/go.mod h1:7TG+PzNhHcA9txzKpFfQ1A7RUnxiaqAl4zyC5DXrD2A= +github.com/Finschia/ibc-go/v4 v4.3.1 h1:pUKry0j+1/ypCC3X1TkEzoLrS1A/low/1PE2HZL+13k= +github.com/Finschia/ibc-go/v4 v4.3.1/go.mod h1:kFZgmXXT2pt9QL7Ngx/eA7lI9JlOMGRG/oU4RTDXKcg= +github.com/Finschia/ostracon v1.1.0 h1:ruiqngsoCz1kJ3fGLJHflcvxbJrbg7QGDTruqxgLZKc= +github.com/Finschia/ostracon v1.1.0/go.mod h1:nPRoQEOOp8FFp2XQ8b1dvfHgKNxp1Zb7i1p5yrLIgG4= github.com/Finschia/wasmvm v1.1.1-0.11.2.0.20230418093236-ce70a3856778 h1:V+iocQkc3zvpgdn+nCLZ9kPM7D7u6v2Br+EkOIhvjbY= github.com/Finschia/wasmvm v1.1.1-0.11.2.0.20230418093236-ce70a3856778/go.mod h1:uCHU7ZRQ/V+WPRXr6Ak9Uu2oe2MVeO8yGZnGKU1B3NY= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -62,12 +62,12 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VictoriaMetrics/fastcache v1.12.0 h1:vnVi/y9yKDcD9akmc4NqAoqgQhJrOwUF+j9LTgn4QDE= -github.com/VictoriaMetrics/fastcache v1.12.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/Workiva/go-datastructures v1.0.53 h1:J6Y/52yX10Xc5JjXmGtWoSSxs3mZnGSaq37xZZh7Yig= -github.com/Workiva/go-datastructures v1.0.53/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= +github.com/Workiva/go-datastructures v1.1.0 h1:hu20UpgZneBhQ3ZvwiOGlqJSKIosin2Rd5wAKUHEO/k= +github.com/Workiva/go-datastructures v1.1.0/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/adlio/schema v1.3.4 h1:8K+41sfQkxfT6a79aLBxx+dBKcid6Raw2JPk5COqeqE= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -90,6 +90,7 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -111,7 +112,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -123,8 +123,10 @@ github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coinbase/rosetta-sdk-go v0.8.2 h1:+sNgMUPpntOsYLy5aRsHqBY6I0MTxZkS4JXV1Un3DKc= -github.com/coinbase/rosetta-sdk-go v0.8.2/go.mod h1:tXPR6AIW9ogsH4tYIaFOKOgfJNanCvcyl7JKLd4DToc= +github.com/coinbase/rosetta-sdk-go v0.8.3 h1:IYqd+Ser5NVh0s7p8p2Ir82iCvi75E1l0NH2H4NEr0Y= +github.com/coinbase/rosetta-sdk-go v0.8.3/go.mod h1:ChOHc+BNq7zqJDDkui0DA124GOvlAiRbdgAc1U9GMDQ= +github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= +github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71 h1:MFLTqgfJclmtaQ1SRUrWwmDX/1UBok3XWUethkJ2swQ= github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71/go.mod h1:TrHYHH4Wze7v7Hkwu1MH1W+mCPQKM+gs+PicdEV14o8= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= @@ -145,8 +147,8 @@ github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4 github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= github.com/cosmos/iavl v0.19.4 h1:t82sN+Y0WeqxDLJRSpNd8YFX5URIrT+p8n6oJbJ2Dok= github.com/cosmos/iavl v0.19.4/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= -github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w= -github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g= +github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= +github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 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.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -190,7 +192,7 @@ github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -208,6 +210,7 @@ github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -326,8 +329,8 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= @@ -405,8 +408,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c= -github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= +github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk= +github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -418,8 +421,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= @@ -438,8 +441,8 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -496,7 +499,7 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.22.1 h1:pY8O4lBfsHKZHM/6nrxkhVPUznOlIu3quZcKP/M20KI= +github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= @@ -516,8 +519,8 @@ github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0Mw github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= @@ -539,32 +542,32 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= 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.15.0 h1:5fCgGYogn0hFdhyhLbw7hEsWxufKtY9klyvdNfFlFhM= -github.com/prometheus/client_golang v1.15.0/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= 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= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= 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.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= 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= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 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.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/r2ishiguro/vrf v0.0.0-20180716233122-192de52975eb h1:3kW8n+FfBaUoqlHxCa6e90PXWpGCWWkdyTZ6F7c9m2I= github.com/r2ishiguro/vrf v0.0.0-20180716233122-192de52975eb/go.mod h1:2NzHJUkr/ERaPNQ2IUuNbB2jMTWYp2DxhcraWbzZj00= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= @@ -579,7 +582,7 @@ github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= @@ -599,7 +602,7 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa h1:YJfZp12Z3AFhSBeXOlv4BO55RMwPn2NoQeDsrdWnBtY= @@ -610,11 +613,11 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= -github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= @@ -627,8 +630,8 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= -github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= +github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -645,9 +648,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/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 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= @@ -682,8 +685,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zondax/hid v0.9.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo= github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= -github.com/zondax/ledger-go v0.14.0 h1:dlMC7aO8Wss1CxBq2I96kZ69Nh1ligzbs8UWOtq/AsA= -github.com/zondax/ledger-go v0.14.0/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= +github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c= +github.com/zondax/ledger-go v0.14.1/go.mod h1:fZ3Dqg6qcdXWSOJFKMG8GCTnD7slO/RL2feOQv8K320= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= @@ -699,11 +702,15 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= 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/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= 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-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -716,9 +723,9 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= 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= @@ -730,8 +737,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= +golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -797,8 +804,9 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= 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= @@ -882,14 +890,16 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/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-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/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.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= 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= @@ -897,8 +907,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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= @@ -920,6 +931,7 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -957,7 +969,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1032,8 +1044,12 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 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-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230525234025-438c736192d0 h1:x1vNwUhVOcsYoKyEGCZBH694SBmmBjA2EfauFVEI2+M= +google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= +google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529 h1:s5YSX+ZH5b5vS9rnpGymvIyMpLRJizowqDlOuyjXnTk= +google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1048,8 +1064,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= diff --git a/x/wasm/ibc.go b/x/wasm/ibc.go index f6c47a3059..a22ce846bc 100644 --- a/x/wasm/ibc.go +++ b/x/wasm/ibc.go @@ -6,24 +6,31 @@ import ( sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" capabilitytypes "github.com/Finschia/finschia-sdk/x/capability/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - porttypes "github.com/Finschia/ibc-go/v3/modules/core/05-port/types" - host "github.com/Finschia/ibc-go/v3/modules/core/24-host" - ibcexported "github.com/Finschia/ibc-go/v3/modules/core/exported" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v4/modules/core/05-port/types" + host "github.com/cosmos/ibc-go/v4/modules/core/24-host" + ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" wasmvmtypes "github.com/Finschia/wasmvm/types" - wasmTypes "github.com/Finschia/wasmd/x/wasm/types" + "github.com/Finschia/wasmd/x/wasm/types" ) var _ porttypes.IBCModule = IBCHandler{} +// internal interface that is implemented by ibc middleware +type appVersionGetter interface { + // GetAppVersion returns the application level version with all middleware data stripped out + GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) +} + type IBCHandler struct { - keeper wasmTypes.IBCContractKeeper - channelKeeper wasmTypes.ChannelKeeper + keeper types.IBCContractKeeper + channelKeeper types.ChannelKeeper + appVersionGetter appVersionGetter } -func NewIBCHandler(k wasmTypes.IBCContractKeeper, ck wasmTypes.ChannelKeeper) IBCHandler { - return IBCHandler{keeper: k, channelKeeper: ck} +func NewIBCHandler(k types.IBCContractKeeper, ck types.ChannelKeeper, vg appVersionGetter) IBCHandler { + return IBCHandler{keeper: k, channelKeeper: ck, appVersionGetter: vg} } // OnChanOpenInit implements the IBCModule interface @@ -36,14 +43,14 @@ func (i IBCHandler) OnChanOpenInit( chanCap *capabilitytypes.Capability, counterParty channeltypes.Counterparty, version string, -) error { +) (string, error) { // ensure port, version, capability if err := ValidateChannelParams(channelID); err != nil { - return err + return "", err } contractAddr, err := ContractFromPortID(portID) if err != nil { - return sdkerrors.Wrapf(err, "contract port id") + return "", sdkerrors.Wrapf(err, "contract port id") } msg := wasmvmtypes.IBCChannelOpenMsg{ @@ -58,15 +65,21 @@ func (i IBCHandler) OnChanOpenInit( }, }, } - _, err = i.keeper.OnOpenChannel(ctx, contractAddr, msg) + + // Allow contracts to return a version (or default to proposed version if unset) + acceptedVersion, err := i.keeper.OnOpenChannel(ctx, contractAddr, msg) if err != nil { - return err + return "", err + } + if acceptedVersion == "" { + acceptedVersion = version } + // Claim channel capability passed back by IBC module if err := i.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { - return sdkerrors.Wrap(err, "claim capability") + return "", sdkerrors.Wrap(err, "claim capability") } - return nil + return acceptedVersion, nil } // OnChanOpenTry implements the IBCModule interface @@ -113,8 +126,8 @@ func (i IBCHandler) OnChanOpenTry( // Module may have already claimed capability in OnChanOpenInit in the case of crossing hellos // (ie chainA and chainB both call ChanOpenInit before one of them calls ChanOpenTry) - // If module can already authenticate the capability then module already owns it so we don't need to claim - // Otherwise, module does not have channel capability and we must claim it from IBC + // If module can already authenticate the capability then module already owns it, so we don't need to claim + // Otherwise, module does not have channel capability, and we must claim it from IBC if !i.keeper.AuthenticateCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)) { // Only claim channel capability passed back by IBC module if we do not already own it if err := i.keeper.ClaimCapability(ctx, chanCap, host.ChannelCapabilityPath(portID, channelID)); err != nil { @@ -147,9 +160,15 @@ func (i IBCHandler) OnChanOpenAck( // OnChanOpenAck entry point) // https://github.com/cosmos/ibc-go/pull/647/files#diff-54b5be375a2333c56f2ae1b5b4dc13ac9c734561e30286505f39837ee75762c7R25 i.channelKeeper.SetChannel(ctx, portID, channelID, channelInfo) + + appVersion, ok := i.appVersionGetter.GetAppVersion(ctx, portID, channelID) + if !ok { + return sdkerrors.Wrapf(channeltypes.ErrInvalidChannelVersion, "port ID (%s) channel ID (%s)", portID, channelID) + } + msg := wasmvmtypes.IBCChannelConnectMsg{ OpenAck: &wasmvmtypes.IBCOpenAck{ - Channel: toWasmVMChannel(portID, channelID, channelInfo), + Channel: toWasmVMChannel(portID, channelID, channelInfo, appVersion), CounterpartyVersion: counterpartyVersion, }, } @@ -166,9 +185,13 @@ func (i IBCHandler) OnChanOpenConfirm(ctx sdk.Context, portID, channelID string) if !ok { return sdkerrors.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", portID, channelID) } + appVersion, ok := i.appVersionGetter.GetAppVersion(ctx, portID, channelID) + if !ok { + return sdkerrors.Wrapf(channeltypes.ErrInvalidChannelVersion, "port ID (%s) channel ID (%s)", portID, channelID) + } msg := wasmvmtypes.IBCChannelConnectMsg{ OpenConfirm: &wasmvmtypes.IBCOpenConfirm{ - Channel: toWasmVMChannel(portID, channelID, channelInfo), + Channel: toWasmVMChannel(portID, channelID, channelInfo, appVersion), }, } return i.keeper.OnConnectChannel(ctx, contractAddr, msg) @@ -184,9 +207,13 @@ func (i IBCHandler) OnChanCloseInit(ctx sdk.Context, portID, channelID string) e if !ok { return sdkerrors.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", portID, channelID) } + appVersion, ok := i.appVersionGetter.GetAppVersion(ctx, portID, channelID) + if !ok { + return sdkerrors.Wrapf(channeltypes.ErrInvalidChannelVersion, "port ID (%s) channel ID (%s)", portID, channelID) + } msg := wasmvmtypes.IBCChannelCloseMsg{ - CloseInit: &wasmvmtypes.IBCCloseInit{Channel: toWasmVMChannel(portID, channelID, channelInfo)}, + CloseInit: &wasmvmtypes.IBCCloseInit{Channel: toWasmVMChannel(portID, channelID, channelInfo, appVersion)}, } err = i.keeper.OnCloseChannel(ctx, contractAddr, msg) if err != nil { @@ -208,9 +235,13 @@ func (i IBCHandler) OnChanCloseConfirm(ctx sdk.Context, portID, channelID string if !ok { return sdkerrors.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", portID, channelID) } + appVersion, ok := i.appVersionGetter.GetAppVersion(ctx, portID, channelID) + if !ok { + return sdkerrors.Wrapf(channeltypes.ErrInvalidChannelVersion, "port ID (%s) channel ID (%s)", portID, channelID) + } msg := wasmvmtypes.IBCChannelCloseMsg{ - CloseConfirm: &wasmvmtypes.IBCCloseConfirm{Channel: toWasmVMChannel(portID, channelID, channelInfo)}, + CloseConfirm: &wasmvmtypes.IBCCloseConfirm{Channel: toWasmVMChannel(portID, channelID, channelInfo, appVersion)}, } err = i.keeper.OnCloseChannel(ctx, contractAddr, msg) if err != nil { @@ -221,12 +252,12 @@ func (i IBCHandler) OnChanCloseConfirm(ctx sdk.Context, portID, channelID string return err } -func toWasmVMChannel(portID, channelID string, channelInfo channeltypes.Channel) wasmvmtypes.IBCChannel { +func toWasmVMChannel(portID, channelID string, channelInfo channeltypes.Channel, appVersion string) wasmvmtypes.IBCChannel { return wasmvmtypes.IBCChannel{ Endpoint: wasmvmtypes.IBCEndpoint{PortID: portID, ChannelID: channelID}, CounterpartyEndpoint: wasmvmtypes.IBCEndpoint{PortID: channelInfo.Counterparty.PortId, ChannelID: channelInfo.Counterparty.ChannelId}, Order: channelInfo.Ordering.String(), - Version: channelInfo.Version, + Version: appVersion, ConnectionID: channelInfo.ConnectionHops[0], // At the moment this list must be of length 1. In the future multi-hop channels may be supported. } } @@ -239,12 +270,12 @@ func (i IBCHandler) OnRecvPacket( ) ibcexported.Acknowledgement { contractAddr, err := ContractFromPortID(packet.DestinationPort) if err != nil { - return channeltypes.NewErrorAcknowledgement(sdkerrors.Wrapf(err, "contract port id").Error()) + return channeltypes.NewErrorAcknowledgement(sdkerrors.Wrapf(err, "contract port id")) } msg := wasmvmtypes.IBCPacketReceiveMsg{Packet: newIBCPacket(packet), Relayer: relayer.String()} ack, err := i.keeper.OnRecvPacket(ctx, contractAddr, msg) if err != nil { - return channeltypes.NewErrorAcknowledgement(err.Error()) + return channeltypes.NewErrorAcknowledgement(err) } return ContractConfirmStateAck(ack) } @@ -326,7 +357,7 @@ func ValidateChannelParams(channelID string) error { return err } if channelSequence > math.MaxUint32 { - return sdkerrors.Wrapf(wasmTypes.ErrMaxIBCChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, math.MaxUint32) + return sdkerrors.Wrapf(types.ErrMaxIBCChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, math.MaxUint32) } return nil } diff --git a/x/wasm/ibc_integration_test.go b/x/wasm/ibc_integration_test.go new file mode 100644 index 0000000000..792d1a8c06 --- /dev/null +++ b/x/wasm/ibc_integration_test.go @@ -0,0 +1,126 @@ +package wasm_test + +import ( + "testing" + + wasmvm "github.com/Finschia/wasmvm" + wasmvmtypes "github.com/Finschia/wasmvm/types" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + wasmibctesting "github.com/Finschia/wasmd/x/wasm/ibctesting" + wasmkeeper "github.com/Finschia/wasmd/x/wasm/keeper" + "github.com/Finschia/wasmd/x/wasm/keeper/wasmtesting" +) + +func TestOnChanOpenInitVersion(t *testing.T) { + const startVersion = "v1" + specs := map[string]struct { + contractRsp *wasmvmtypes.IBC3ChannelOpenResponse + expVersion string + }{ + "different version": { + contractRsp: &wasmvmtypes.IBC3ChannelOpenResponse{Version: "v2"}, + expVersion: "v2", + }, + "no response": { + expVersion: startVersion, + }, + "empty result": { + contractRsp: &wasmvmtypes.IBC3ChannelOpenResponse{}, + expVersion: startVersion, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + myContract := &wasmtesting.MockIBCContractCallbacks{ + IBCChannelOpenFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error) { + return spec.contractRsp, 0, nil + }, + } + var ( + chainAOpts = []wasmkeeper.Option{ + wasmkeeper.WithWasmEngine( + wasmtesting.NewIBCContractMockWasmer(myContract)), + } + coordinator = wasmibctesting.NewCoordinator(t, 2, chainAOpts) + chainA = coordinator.GetChain(wasmibctesting.GetChainID(0)) + chainB = coordinator.GetChain(wasmibctesting.GetChainID(1)) + myContractAddr = chainA.SeedNewContractInstance() + contractInfo = chainA.App.WasmKeeper.GetContractInfo(chainA.GetContext(), myContractAddr) + ) + + path := wasmibctesting.NewPath(chainA, chainB) + coordinator.SetupConnections(path) + + path.EndpointA.ChannelConfig = &ibctesting.ChannelConfig{ + PortID: contractInfo.IBCPortID, + Version: startVersion, + Order: channeltypes.UNORDERED, + } + require.NoError(t, path.EndpointA.ChanOpenInit()) + assert.Equal(t, spec.expVersion, path.EndpointA.ChannelConfig.Version) + }) + } +} + +func TestOnChanOpenTryVersion(t *testing.T) { + const startVersion = ibctransfertypes.Version + specs := map[string]struct { + contractRsp *wasmvmtypes.IBC3ChannelOpenResponse + expVersion string + }{ + "different version": { + contractRsp: &wasmvmtypes.IBC3ChannelOpenResponse{Version: "v2"}, + expVersion: "v2", + }, + "no response": { + expVersion: startVersion, + }, + "empty result": { + contractRsp: &wasmvmtypes.IBC3ChannelOpenResponse{}, + expVersion: startVersion, + }, + } + for name, spec := range specs { + t.Run(name, func(t *testing.T) { + myContract := &wasmtesting.MockIBCContractCallbacks{ + IBCChannelOpenFn: func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error) { + return spec.contractRsp, 0, nil + }, + } + var ( + chainAOpts = []wasmkeeper.Option{ + wasmkeeper.WithWasmEngine( + wasmtesting.NewIBCContractMockWasmer(myContract)), + } + coordinator = wasmibctesting.NewCoordinator(t, 2, chainAOpts) + chainA = coordinator.GetChain(wasmibctesting.GetChainID(0)) + chainB = coordinator.GetChain(wasmibctesting.GetChainID(1)) + myContractAddr = chainA.SeedNewContractInstance() + contractInfo = chainA.ContractInfo(myContractAddr) + ) + + path := wasmibctesting.NewPath(chainA, chainB) + coordinator.SetupConnections(path) + + path.EndpointA.ChannelConfig = &ibctesting.ChannelConfig{ + PortID: contractInfo.IBCPortID, + Version: startVersion, + Order: channeltypes.UNORDERED, + } + path.EndpointB.ChannelConfig = &ibctesting.ChannelConfig{ + PortID: ibctransfertypes.PortID, + Version: ibctransfertypes.Version, + Order: channeltypes.UNORDERED, + } + + require.NoError(t, path.EndpointB.ChanOpenInit()) + require.NoError(t, path.EndpointA.ChanOpenTry()) + assert.Equal(t, spec.expVersion, path.EndpointA.ChannelConfig.Version) + }) + } +} diff --git a/x/wasm/ibc_reflect_test.go b/x/wasm/ibc_reflect_test.go index c2ab5b3cd2..c951243369 100644 --- a/x/wasm/ibc_reflect_test.go +++ b/x/wasm/ibc_reflect_test.go @@ -6,8 +6,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - ibctesting "github.com/Finschia/ibc-go/v3/testing" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" wasmvmtypes "github.com/Finschia/wasmvm/types" wasmibctesting "github.com/Finschia/wasmd/x/wasm/ibctesting" diff --git a/x/wasm/ibc_test.go b/x/wasm/ibc_test.go index 96608242ac..66ad2a2ac1 100644 --- a/x/wasm/ibc_test.go +++ b/x/wasm/ibc_test.go @@ -5,8 +5,8 @@ import ( "github.com/stretchr/testify/assert" - clienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" wasmvmtypes "github.com/Finschia/wasmvm/types" ) diff --git a/x/wasm/ibctesting/chain.go b/x/wasm/ibctesting/chain.go index f2cb4e2647..3dd9ee1b09 100644 --- a/x/wasm/ibctesting/chain.go +++ b/x/wasm/ibctesting/chain.go @@ -1,7 +1,6 @@ package ibctesting import ( - "bytes" "fmt" "testing" "time" @@ -23,14 +22,15 @@ import ( capabilitytypes "github.com/Finschia/finschia-sdk/x/capability/types" "github.com/Finschia/finschia-sdk/x/staking/teststaking" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" - clienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - commitmenttypes "github.com/Finschia/ibc-go/v3/modules/core/23-commitment/types" - host "github.com/Finschia/ibc-go/v3/modules/core/24-host" - "github.com/Finschia/ibc-go/v3/modules/core/exported" - "github.com/Finschia/ibc-go/v3/modules/core/types" - ibctmtypes "github.com/Finschia/ibc-go/v3/modules/light-clients/07-tendermint/types" - "github.com/Finschia/ibc-go/v3/testing/mock" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + commitmenttypes "github.com/cosmos/ibc-go/v4/modules/core/23-commitment/types" + host "github.com/cosmos/ibc-go/v4/modules/core/24-host" + "github.com/cosmos/ibc-go/v4/modules/core/exported" + "github.com/cosmos/ibc-go/v4/modules/core/types" + ibctmtypes "github.com/cosmos/ibc-go/v4/modules/light-clients/07-tendermint/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" + "github.com/cosmos/ibc-go/v4/testing/mock" ocabci "github.com/Finschia/ostracon/abci/types" "github.com/Finschia/ostracon/crypto/tmhash" octypes "github.com/Finschia/ostracon/types" @@ -41,6 +41,13 @@ import ( "github.com/Finschia/wasmd/x/wasm" ) +var MaxAccounts = 10 + +type SenderAccount struct { + SenderPrivKey cryptotypes.PrivKey + SenderAccount authtypes.AccountI +} + // TestChain is a testing struct that wraps a simapp with the last TM Header, the current ABCI // header and the validators of the TestChain. It also contains a field called ChainID. This // is the clientID that *other* chains use to refer to this TestChain. The SenderAccount @@ -57,15 +64,22 @@ type TestChain struct { QueryServer types.QueryServer TxConfig client.TxConfig Codec codec.BinaryCodec + Vals *octypes.ValidatorSet + NextVals *octypes.ValidatorSet - Vals *octypes.ValidatorSet - Signers []octypes.PrivValidator + // Signers is a map from validator address to the PrivValidator + // The map is converted into an array that is the same order as the validators right before signing commit + // This ensures that signers will always be in correct order even as validator powers change. + // If a test adds a new validator after chain creation, then the signer map must be updated to include + // the new PrivValidator entry. + Signers map[string]octypes.PrivValidator - SenderPrivKey cryptotypes.PrivKey - SenderAccount authtypes.AccountI + // autogenerated sender private key + SenderPrivKey cryptotypes.PrivKey + SenderAccount authtypes.AccountI + SenderAccounts []SenderAccount PendingSendPackets []channeltypes.Packet - PendingAckPackets []PacketAck } type PacketAck struct { @@ -73,37 +87,77 @@ type PacketAck struct { Ack []byte } -// NewTestChain initializes a new TestChain instance with a single validator set using a -// generated private key. It also creates a sender account to be used for delivering transactions. +// NewTestChain initializes a new test chain with a default of 4 validators +// Use this function if the tests do not need custom control over the validator set +func NewTestChain(t *testing.T, coord *Coordinator, chainID string, opts ...wasm.Option) *TestChain { + // generate validators private/public key + var ( + validatorsPerChain = 4 + validators = make([]*octypes.Validator, 0, validatorsPerChain) + signersByAddress = make(map[string]octypes.PrivValidator, validatorsPerChain) + ) + + for i := 0; i < validatorsPerChain; i++ { + privVal := mock.NewPV() + pubKey, err := privVal.GetPubKey() + require.NoError(t, err) + validators = append(validators, octypes.NewValidator(pubKey, 1)) + signersByAddress[pubKey.Address().String()] = privVal + } + + // construct validator set; + // Note that the validators are sorted by voting power + // or, if equal, by address lexical order + valSet := octypes.NewValidatorSet(validators) + + return NewTestChainWithValSet(t, coord, chainID, valSet, signersByAddress, opts...) +} + +// NewTestChainWithValSet initializes a new TestChain instance with the given validator set +// and signer array. It also initializes 10 Sender accounts with a balance of 10000000000000000000 coins of +// bond denom to use for tests. // // The first block height is committed to state in order to allow for client creations on // counterparty chains. The TestChain will return with a block height starting at 2. // // Time management is handled by the Coordinator in order to ensure synchrony between chains. // Each update of any chain increments the block header time for all chains by 5 seconds. -func NewTestChain(t *testing.T, coord *Coordinator, chainID string, opts ...wasm.Option) *TestChain { - // generate validator private/public key - privVal := mock.NewPV() - pubKey, err := privVal.GetPubKey() - require.NoError(t, err) - - // create validator set with single validator - validator := octypes.NewValidator(pubKey, 1) - valSet := octypes.NewValidatorSet([]*octypes.Validator{validator}) - signers := []octypes.PrivValidator{privVal} - - // generate genesis account - senderPrivKey := secp256k1.GenPrivKey() - acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), 0, 0) - amount, ok := sdk.NewIntFromString("10000000000000000000") - require.True(t, ok) - - balance := banktypes.Balance{ - Address: acc.GetAddress().String(), - Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, amount)), +// +// NOTE: to use a custom sender privkey and account for testing purposes, replace and modify this +// constructor function. +// +// CONTRACT: Validator array must be provided in the order expected by Tendermint. +// i.e. sorted first by power and then lexicographically by address. +func NewTestChainWithValSet(t *testing.T, coord *Coordinator, chainID string, valSet *octypes.ValidatorSet, signers map[string]octypes.PrivValidator, opts ...wasm.Option) *TestChain { + genAccs := []authtypes.GenesisAccount{} + genBals := []banktypes.Balance{} + senderAccs := []SenderAccount{} + + // generate genesis accounts + for i := 0; i < MaxAccounts; i++ { + senderPrivKey := secp256k1.GenPrivKey() + acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), uint64(i), 0) + amount, ok := sdk.NewIntFromString("10000000000000000000") + require.True(t, ok) + + // add sender account + balance := banktypes.Balance{ + Address: acc.GetAddress().String(), + Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, amount)), + } + + genAccs = append(genAccs, acc) + genBals = append(genBals, balance) + + senderAcc := SenderAccount{ + SenderAccount: acc, + SenderPrivKey: senderPrivKey, + } + + senderAccs = append(senderAccs, senderAcc) } - wasmApp := app.SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, opts, balance) + wasmApp := app.SetupWithGenesisValSet(t, valSet, genAccs, chainID, opts, genBals...) // create current header and call begin block header := tmproto.Header{ @@ -116,18 +170,20 @@ func NewTestChain(t *testing.T, coord *Coordinator, chainID string, opts ...wasm // create an account to send transactions from chain := &TestChain{ - t: t, - Coordinator: coord, - ChainID: chainID, - App: wasmApp, - CurrentHeader: header, - QueryServer: wasmApp.IBCKeeper, - TxConfig: txConfig, - Codec: wasmApp.AppCodec(), - Vals: valSet, - Signers: signers, - SenderPrivKey: senderPrivKey, - SenderAccount: acc, + t: t, + Coordinator: coord, + ChainID: chainID, + App: wasmApp, + CurrentHeader: header, + QueryServer: wasmApp.IBCKeeper, + TxConfig: txConfig, + Codec: wasmApp.AppCodec(), + Vals: valSet, + NextVals: valSet, + Signers: signers, + SenderPrivKey: senderAccs[0].SenderPrivKey, + SenderAccount: senderAccs[0].SenderAccount, + SenderAccounts: senderAccs, } coord.CommitBlock(chain) @@ -208,13 +264,24 @@ func (chain *TestChain) QueryConsensusStateProof(clientID string) ([]byte, clien // NextBlock sets the last header to the current header and increments the current header to be // at the next block height. It does not update the time as that is handled by the Coordinator. -// -// CONTRACT: this function must only be called after app.Commit() occurs +// It will call Endblock and Commit and apply the validator set changes to the next validators +// of the next block being created. This follows the Tendermint protocol of applying valset changes +// returned on block `n` to the validators of block `n+2`. +// It calls BeginBlock with the new block created before returning. func (chain *TestChain) NextBlock() { + res := chain.App.EndBlock(abci.RequestEndBlock{Height: chain.CurrentHeader.Height}) + + chain.App.Commit() + // set the last header to the current header // use nil trusted fields chain.LastHeader = chain.CurrentTMClientHeader() + // val set changes returned from previous block get applied to the next validators + // of this block. See tendermint spec for details. + chain.Vals = chain.NextVals + chain.NextVals = ibctesting.ApplyValSetChanges(chain.t, chain.Vals, res.ValidatorUpdates) + // increment the current header chain.CurrentHeader = tmproto.Header{ ChainID: chain.ChainID, @@ -224,7 +291,7 @@ func (chain *TestChain) NextBlock() { // chains. Time: chain.CurrentHeader.Time, ValidatorsHash: chain.Vals.Hash(), - NextValidatorsHash: chain.Vals.Hash(), + NextValidatorsHash: chain.NextVals.Hash(), } chain.App.BeginBlock(ocabci.RequestBeginBlock{Header: chain.CurrentHeader}) @@ -266,7 +333,7 @@ func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) (*sdk.Result, error) { return nil, err } - // SignAndDeliver calls app.Commit() + // NextBlock calls app.Commit() chain.NextBlock() // increment sequence for successful transaction execution @@ -288,11 +355,6 @@ func (chain *TestChain) captureIBCEvents(r *sdk.Result) { // Keep a queue on the chain that we can relay in tests chain.PendingSendPackets = append(chain.PendingSendPackets, toSend...) } - toAck := getAckPackets(r.Events) - if len(toAck) > 0 { - // Keep a queue on the chain that we can relay in tests - chain.PendingAckPackets = append(chain.PendingAckPackets, toAck...) - } } // GetClientState retrieves the client state for the provided clientID. The client is @@ -396,12 +458,12 @@ func (chain *TestChain) ExpireClient(amount time.Duration) { // CurrentTMClientHeader creates a TM header using the current header parameters // on the chain. The trusted fields in the header are set to nil. func (chain *TestChain) CurrentTMClientHeader() *ibctmtypes.Header { - return chain.CreateTMClientHeader(chain.ChainID, chain.CurrentHeader.Height, clienttypes.Height{}, chain.CurrentHeader.Time, chain.Vals, nil, chain.Signers) + return chain.CreateTMClientHeader(chain.ChainID, chain.CurrentHeader.Height, clienttypes.Height{}, chain.CurrentHeader.Time, chain.Vals, chain.NextVals, nil, chain.Signers) } // CreateTMClientHeader creates a TM header to update the TM client. Args are passed in to allow // caller flexibility to use params that differ from the chain. -func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, trustedHeight clienttypes.Height, timestamp time.Time, tmValSet, tmTrustedVals *octypes.ValidatorSet, signers []octypes.PrivValidator) *ibctmtypes.Header { +func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, trustedHeight clienttypes.Height, timestamp time.Time, tmValSet, nextVals, tmTrustedVals *octypes.ValidatorSet, signers map[string]octypes.PrivValidator) *ibctmtypes.Header { var ( valSet *tmproto.ValidatorSet trustedVals *tmproto.ValidatorSet @@ -409,6 +471,7 @@ func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, require.NotNil(chain.t, tmValSet) vsetHash := tmValSet.Hash() + nextValHash := nextVals.Hash() tmHeader := octypes.Header{ Version: protoversion.Consensus{Block: ocversion.BlockProtocol, App: 2}, @@ -419,18 +482,27 @@ func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, LastCommitHash: chain.App.LastCommitID().Hash, DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: vsetHash, - NextValidatorsHash: vsetHash, + NextValidatorsHash: nextValHash, ConsensusHash: tmhash.Sum([]byte("consensus_hash")), AppHash: chain.CurrentHeader.AppHash, LastResultsHash: tmhash.Sum([]byte("last_results_hash")), EvidenceHash: tmhash.Sum([]byte("evidence_hash")), ProposerAddress: tmValSet.SelectProposer([]byte{}, blockHeight, 0).Address, //nolint:staticcheck } + hhash := tmHeader.Hash() blockID := MakeBlockID(hhash, 3, tmhash.Sum([]byte("part_set"))) voteSet := octypes.NewVoteSet(chainID, blockHeight, 1, tmproto.PrecommitType, tmValSet) - commit, err := octypes.MakeCommit(blockID, blockHeight, 1, voteSet, signers, timestamp) + // MakeCommit expects a signer array in the same order as the validator array. + // Thus we iterate over the ordered validator set and construct a signer array + // from the signer map in the same order. + signerArr := make([]octypes.PrivValidator, len(tmValSet.Validators)) + for i, v := range tmValSet.Validators { + signerArr[i] = signers[v.Address.String()] + } + + commit, err := octypes.MakeCommit(blockID, blockHeight, 1, voteSet, signerArr, timestamp) require.NoError(chain.t, err) signedHeader := &tmproto.SignedHeader{ @@ -438,10 +510,8 @@ func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, Commit: commit.ToProto(), } - if tmValSet != nil { - valSet, err = tmValSet.ToProto() - require.NoError(chain.t, err) - } + valSet, err = tmValSet.ToProto() + require.NoError(chain.t, err) if tmTrustedVals != nil { trustedVals, err = tmTrustedVals.ToProto() @@ -469,29 +539,9 @@ func MakeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) octypes.Bl } } -// CreateSortedSignerArray takes two PrivValidators, and the corresponding Validator structs -// (including voting power). It returns a signer array of PrivValidators that matches the -// sorting of ValidatorSet. -// The sorting is first by .VotingPower (descending), with secondary index of .Address (ascending). -func CreateSortedSignerArray(altPrivVal, suitePrivVal octypes.PrivValidator, - altVal, suiteVal *octypes.Validator, -) []octypes.PrivValidator { - switch { - case altVal.VotingPower > suiteVal.VotingPower: - return []octypes.PrivValidator{altPrivVal, suitePrivVal} - case altVal.VotingPower < suiteVal.VotingPower: - return []octypes.PrivValidator{suitePrivVal, altPrivVal} - default: - if bytes.Compare(altVal.Address, suiteVal.Address) == -1 { - return []octypes.PrivValidator{altPrivVal, suitePrivVal} - } - return []octypes.PrivValidator{suitePrivVal, altPrivVal} - } -} - // CreatePortCapability binds and claims a capability for the given portID if it does not // already exist. This function will fail testing on any resulting error. -// NOTE: only creation of a capbility for a transfer or mock port is supported +// NOTE: only creation of a capability for a transfer or mock port is supported // Other applications must bind to the port in InitGenesis or modify this code. func (chain *TestChain) CreatePortCapability(scopedKeeper capabilitykeeper.ScopedKeeper, portID string) { // check if the portId is already binded, if not bind it @@ -506,8 +556,6 @@ func (chain *TestChain) CreatePortCapability(scopedKeeper capabilitykeeper.Scope require.NoError(chain.t, err) } - chain.App.Commit() - chain.NextBlock() } @@ -534,8 +582,6 @@ func (chain *TestChain) CreateChannelCapability(scopedKeeper capabilitykeeper.Sc require.NoError(chain.t, err) } - chain.App.Commit() - chain.NextBlock() } diff --git a/x/wasm/ibctesting/coordinator.go b/x/wasm/ibctesting/coordinator.go index 590ff59e31..7720ae399f 100644 --- a/x/wasm/ibctesting/coordinator.go +++ b/x/wasm/ibctesting/coordinator.go @@ -8,9 +8,9 @@ import ( "github.com/stretchr/testify/require" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - host "github.com/Finschia/ibc-go/v3/modules/core/24-host" - ibctesting "github.com/Finschia/ibc-go/v3/testing" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v4/modules/core/24-host" + ibctesting "github.com/cosmos/ibc-go/v4/testing" ocabci "github.com/Finschia/ostracon/abci/types" wasmkeeper "github.com/Finschia/wasmd/x/wasm/keeper" @@ -192,7 +192,6 @@ func GetChainID(index int) string { // CONTRACT: the passed in list of indexes must not contain duplicates func (coord *Coordinator) CommitBlock(chains ...*TestChain) { for _, chain := range chains { - chain.CommitBlock() chain.NextBlock() } coord.IncrementTime() @@ -202,7 +201,6 @@ func (coord *Coordinator) CommitBlock(chains ...*TestChain) { func (coord *Coordinator) CommitNBlocks(chain *TestChain, n uint64) { for i := uint64(0); i < n; i++ { chain.App.BeginBlock(ocabci.RequestBeginBlock{Header: chain.CurrentHeader}) - chain.CommitBlock() chain.NextBlock() coord.IncrementTime() } @@ -255,48 +253,27 @@ func (coord *Coordinator) ChanOpenInitOnBothChains(path *Path) error { return nil } -// from A to B +// RelayAndAckPendingPackets sends pending packages from path.EndpointA to the counterparty chain and acks func (coord *Coordinator) RelayAndAckPendingPackets(path *Path) error { // get all the packet to relay src->dest src := path.EndpointA - dest := path.EndpointB - toSend := src.Chain.PendingSendPackets - coord.t.Logf("Relay %d Packets A->B\n", len(toSend)) - - // send this to the other side - coord.IncrementTime() - coord.CommitBlock(src.Chain) - err := dest.UpdateClient() - if err != nil { - return err - } - for _, packet := range toSend { - err = dest.RecvPacket(packet) + coord.t.Logf("Relay: %d Packets A->B, %d Packets B->A\n", len(src.Chain.PendingSendPackets), len(path.EndpointB.Chain.PendingSendPackets)) + for i, v := range src.Chain.PendingSendPackets { + err := path.RelayPacket(v, nil) if err != nil { return err } + src.Chain.PendingSendPackets = append(src.Chain.PendingSendPackets[0:i], src.Chain.PendingSendPackets[i+1:]...) } - src.Chain.PendingSendPackets = nil - - // get all the acks to relay dest->src - toAck := dest.Chain.PendingAckPackets - // TODO: assert >= len(toSend)? - coord.t.Logf("Ack %d Packets B->A\n", len(toAck)) - // send the ack back from dest -> src - coord.IncrementTime() - coord.CommitBlock(dest.Chain) - err = src.UpdateClient() - if err != nil { - return err - } - for _, ack := range toAck { - err = src.AcknowledgePacket(ack.Packet, ack.Ack) + src = path.EndpointB + for i, v := range src.Chain.PendingSendPackets { + err := path.RelayPacket(v, nil) if err != nil { return err } + src.Chain.PendingSendPackets = append(src.Chain.PendingSendPackets[0:i], src.Chain.PendingSendPackets[i+1:]...) } - dest.Chain.PendingAckPackets = nil return nil } @@ -326,7 +303,6 @@ func (coord *Coordinator) TimeoutPendingPackets(path *Path) error { } } src.Chain.PendingSendPackets = nil - dest.Chain.PendingAckPackets = nil return nil } diff --git a/x/wasm/ibctesting/endpoint.go b/x/wasm/ibctesting/endpoint.go index 5097ad6200..4f7c3ec8ee 100644 --- a/x/wasm/ibctesting/endpoint.go +++ b/x/wasm/ibctesting/endpoint.go @@ -5,14 +5,15 @@ import ( "github.com/stretchr/testify/require" - clienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - connectiontypes "github.com/Finschia/ibc-go/v3/modules/core/03-connection/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - commitmenttypes "github.com/Finschia/ibc-go/v3/modules/core/23-commitment/types" - host "github.com/Finschia/ibc-go/v3/modules/core/24-host" - "github.com/Finschia/ibc-go/v3/modules/core/exported" - ibctmtypes "github.com/Finschia/ibc-go/v3/modules/light-clients/07-tendermint/types" - ibctesting "github.com/Finschia/ibc-go/v3/testing" + sdk "github.com/Finschia/finschia-sdk/types" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + connectiontypes "github.com/cosmos/ibc-go/v4/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + commitmenttypes "github.com/cosmos/ibc-go/v4/modules/core/23-commitment/types" + host "github.com/cosmos/ibc-go/v4/modules/core/24-host" + "github.com/cosmos/ibc-go/v4/modules/core/exported" + ibctmtypes "github.com/cosmos/ibc-go/v4/modules/light-clients/07-tendermint/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" ) // Endpoint is a which represents a channel endpoint and its associated @@ -50,7 +51,7 @@ func NewEndpoint( func NewDefaultEndpoint(chain *TestChain) *Endpoint { return &Endpoint{ Chain: chain, - ClientConfig: ibctesting.NewOstraconConfig(), + ClientConfig: ibctesting.NewTendermintConfig(), ConnectionConfig: ibctesting.NewConnectionConfig(), ChannelConfig: ibctesting.NewChannelConfig(), } @@ -67,7 +68,7 @@ func (endpoint *Endpoint) QueryProof(key []byte) ([]byte, clienttypes.Height) { } // QueryProofAtHeight queries proof associated with this endpoint using the proof height -// providied +// provided func (endpoint *Endpoint) QueryProofAtHeight(key []byte, height uint64) ([]byte, clienttypes.Height) { // query proof on the counterparty using the latest height of the IBC client return endpoint.Chain.QueryProofAtHeight(key, int64(height)) @@ -87,7 +88,7 @@ func (endpoint *Endpoint) CreateClient() (err error) { switch endpoint.ClientConfig.GetClientType() { case exported.Tendermint: - tmConfig, ok := endpoint.ClientConfig.(*ibctesting.OstraconConfig) + tmConfig, ok := endpoint.ClientConfig.(*ibctesting.TendermintConfig) require.True(endpoint.Chain.t, ok) height := endpoint.Counterparty.Chain.LastHeader.GetHeight().(clienttypes.Height) @@ -182,8 +183,7 @@ func (endpoint *Endpoint) ConnOpenTry() error { counterpartyClient, proofClient, proofConsensus, consensusHeight, proofInit, proofHeight := endpoint.QueryConnectionHandshakeProof() msg := connectiontypes.NewMsgConnectionOpenTry( - "", endpoint.ClientID, // does not support handshake continuation - endpoint.Counterparty.ConnectionID, endpoint.Counterparty.ClientID, + endpoint.ClientID, endpoint.Counterparty.ConnectionID, endpoint.Counterparty.ClientID, counterpartyClient, endpoint.Counterparty.Chain.GetPrefix(), []*connectiontypes.Version{ibctesting.ConnectionVersion}, endpoint.ConnectionConfig.DelayPeriod, proofInit, proofClient, proofConsensus, proofHeight, consensusHeight, @@ -282,6 +282,10 @@ func (endpoint *Endpoint) ChanOpenInit() error { endpoint.ChannelID, err = ibctesting.ParseChannelIDFromEvents(res.GetEvents()) require.NoError(endpoint.Chain.t, err) + // update version to selected app version + // NOTE: this update must be performed after SendMsgs() + endpoint.ChannelConfig.Version = endpoint.GetChannel().Version + return nil } @@ -295,7 +299,7 @@ func (endpoint *Endpoint) ChanOpenTry() error { proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) msg := channeltypes.NewMsgChannelOpenTry( - endpoint.ChannelConfig.PortID, "", // does not support handshake continuation + endpoint.ChannelConfig.PortID, endpoint.ChannelConfig.Version, endpoint.ChannelConfig.Order, []string{endpoint.ConnectionID}, endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID, endpoint.Counterparty.ChannelConfig.Version, proof, height, @@ -311,6 +315,10 @@ func (endpoint *Endpoint) ChanOpenTry() error { require.NoError(endpoint.Chain.t, err) } + // update version to selected app version + // NOTE: this update must be performed after the endpoint channelID is set + endpoint.ChannelConfig.Version = endpoint.GetChannel().Version + return nil } @@ -329,7 +337,12 @@ func (endpoint *Endpoint) ChanOpenAck() error { proof, height, endpoint.Chain.SenderAccount.GetAddress().String(), ) - return endpoint.Chain.sendMsgs(msg) + if err := endpoint.Chain.sendMsgs(msg); err != nil { + return err + } + + endpoint.ChannelConfig.Version = endpoint.GetChannel().Version + return nil } // ChanOpenConfirm will construct and execute a MsgChannelOpenConfirm on the associated endpoint. @@ -393,6 +406,17 @@ func (endpoint *Endpoint) SendPacket(packet exported.PacketI) error { // RecvPacket receives a packet on the associated endpoint. // The counterparty client is updated. func (endpoint *Endpoint) RecvPacket(packet channeltypes.Packet) error { + _, err := endpoint.RecvPacketWithResult(packet) + if err != nil { + return err + } + + return nil +} + +// RecvPacketWithResult receives a packet on the associated endpoint and the result +// of the transaction is returned. The counterparty client is updated. +func (endpoint *Endpoint) RecvPacketWithResult(packet channeltypes.Packet) (*sdk.Result, error) { // get proof of packet commitment on source packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) proof, proofHeight := endpoint.Counterparty.Chain.QueryProof(packetKey) @@ -400,11 +424,16 @@ func (endpoint *Endpoint) RecvPacket(packet channeltypes.Packet) error { recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String()) // receive on counterparty and update source client - if err := endpoint.Chain.sendMsgs(recvMsg); err != nil { - return err + res, err := endpoint.Chain.SendMsgs(recvMsg) + if err != nil { + return nil, err } - return endpoint.Counterparty.UpdateClient() + if err := endpoint.Counterparty.UpdateClient(); err != nil { + return nil, err + } + + return res, nil } // WriteAcknowledgement writes an acknowledgement on the channel associated with the endpoint. @@ -461,6 +490,36 @@ func (endpoint *Endpoint) TimeoutPacket(packet channeltypes.Packet) error { return endpoint.Chain.sendMsgs(timeoutMsg) } +// TimeoutOnClose sends a MsgTimeoutOnClose to the channel associated with the endpoint. +func (endpoint *Endpoint) TimeoutOnClose(packet channeltypes.Packet) error { + // get proof for timeout based on channel order + var packetKey []byte + + switch endpoint.ChannelConfig.Order { + case channeltypes.ORDERED: + packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) + case channeltypes.UNORDERED: + packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + default: + return fmt.Errorf("unsupported order type %s", endpoint.ChannelConfig.Order) + } + + proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey) + + channelKey := host.ChannelKey(packet.GetDestPort(), packet.GetDestChannel()) + proofClosed, _ := endpoint.Counterparty.QueryProof(channelKey) + + nextSeqRecv, found := endpoint.Counterparty.Chain.App.IBCKeeper.ChannelKeeper.GetNextSequenceRecv(endpoint.Counterparty.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID) + require.True(endpoint.Chain.t, found) + + timeoutOnCloseMsg := channeltypes.NewMsgTimeoutOnClose( + packet, nextSeqRecv, + proof, proofClosed, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String(), + ) + + return endpoint.Chain.sendMsgs(timeoutOnCloseMsg) +} + // SetChannelClosed sets a channel state to CLOSED. func (endpoint *Endpoint) SetChannelClosed() error { channel := endpoint.GetChannel() diff --git a/x/wasm/ibctesting/event_utils.go b/x/wasm/ibctesting/event_utils.go index 083368e4b0..b07805930a 100644 --- a/x/wasm/ibctesting/event_utils.go +++ b/x/wasm/ibctesting/event_utils.go @@ -1,19 +1,22 @@ package ibctesting import ( + "encoding/hex" + "fmt" "strconv" "strings" + sdk "github.com/Finschia/finschia-sdk/types" abci "github.com/tendermint/tendermint/abci/types" - clienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" ) func getSendPackets(evts []abci.Event) []channeltypes.Packet { var res []channeltypes.Packet for _, evt := range evts { - if evt.Type == "send_packet" { + if evt.Type == channeltypes.EventTypeSendPacket { packet := parsePacketFromEvent(evt) res = append(res, packet) } @@ -21,21 +24,6 @@ func getSendPackets(evts []abci.Event) []channeltypes.Packet { return res } -func getAckPackets(evts []abci.Event) []PacketAck { - var res []PacketAck - for _, evt := range evts { - if evt.Type == "write_acknowledgement" { - packet := parsePacketFromEvent(evt) - ack := PacketAck{ - Packet: packet, - Ack: []byte(getField(evt, "packet_ack")), - } - res = append(res, ack) - } - } - return res -} - // Used for various debug statements above when needed... do not remove // func showEvent(evt abci.Event) { // fmt.Printf("evt.Type: %s\n", evt.Type) @@ -46,15 +34,27 @@ func getAckPackets(evts []abci.Event) []PacketAck { func parsePacketFromEvent(evt abci.Event) channeltypes.Packet { return channeltypes.Packet{ - Sequence: getUintField(evt, "packet_sequence"), - SourcePort: getField(evt, "packet_src_port"), - SourceChannel: getField(evt, "packet_src_channel"), - DestinationPort: getField(evt, "packet_dst_port"), - DestinationChannel: getField(evt, "packet_dst_channel"), - Data: []byte(getField(evt, "packet_data")), - TimeoutHeight: parseTimeoutHeight(getField(evt, "packet_timeout_height")), - TimeoutTimestamp: getUintField(evt, "packet_timeout_timestamp"), + Sequence: getUintField(evt, channeltypes.AttributeKeySequence), + SourcePort: getField(evt, channeltypes.AttributeKeySrcPort), + SourceChannel: getField(evt, channeltypes.AttributeKeySrcChannel), + DestinationPort: getField(evt, channeltypes.AttributeKeyDstPort), + DestinationChannel: getField(evt, channeltypes.AttributeKeyDstChannel), + Data: getHexField(evt, channeltypes.AttributeKeyDataHex), + TimeoutHeight: parseTimeoutHeight(getField(evt, channeltypes.AttributeKeyTimeoutHeight)), + TimeoutTimestamp: getUintField(evt, channeltypes.AttributeKeyTimeoutTimestamp), + } +} + +func getHexField(evt abci.Event, key string) []byte { + got := getField(evt, key) + if got == "" { + return nil + } + bz, err := hex.DecodeString(got) + if err != nil { + panic(err) } + return bz } // return the value for the attribute with the given name @@ -90,3 +90,29 @@ func parseTimeoutHeight(raw string) clienttypes.Height { RevisionHeight: toUint64(chunks[1]), } } + +func ParsePortIDFromEvents(events sdk.Events) (string, error) { + for _, ev := range events { + if ev.Type == channeltypes.EventTypeChannelOpenInit || ev.Type == channeltypes.EventTypeChannelOpenTry { + for _, attr := range ev.Attributes { + if string(attr.Key) == channeltypes.AttributeKeyPortID { + return string(attr.Value), nil + } + } + } + } + return "", fmt.Errorf("port id event attribute not found") +} + +func ParseChannelVersionFromEvents(events sdk.Events) (string, error) { + for _, ev := range events { + if ev.Type == channeltypes.EventTypeChannelOpenInit || ev.Type == channeltypes.EventTypeChannelOpenTry { + for _, attr := range ev.Attributes { + if string(attr.Key) == channeltypes.AttributeVersion { + return string(attr.Value), nil + } + } + } + } + return "", fmt.Errorf("version event attribute not found") +} diff --git a/x/wasm/ibctesting/path.go b/x/wasm/ibctesting/path.go index aed139f883..b053c5a1bc 100644 --- a/x/wasm/ibctesting/path.go +++ b/x/wasm/ibctesting/path.go @@ -5,7 +5,8 @@ import ( "fmt" sdk "github.com/Finschia/finschia-sdk/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" ) // Path contains two endpoints representing two chains connected over IBC @@ -48,15 +49,21 @@ func (path *Path) RelayPacket(packet channeltypes.Packet, ack []byte) error { return err } - if err := path.EndpointB.RecvPacket(packet); err != nil { + res, err := path.EndpointB.RecvPacketWithResult(packet) + if err != nil { + return err + } + + ack, err := ibctesting.ParseAckFromEvents(res.GetEvents()) + if err != nil { return err } if err := path.EndpointA.AcknowledgePacket(packet, ack); err != nil { return err } - return nil + return nil } pc = path.EndpointB.Chain.App.IBCKeeper.ChannelKeeper.GetPacketCommitment(path.EndpointB.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) @@ -67,9 +74,16 @@ func (path *Path) RelayPacket(packet channeltypes.Packet, ack []byte) error { return err } - if err := path.EndpointA.RecvPacket(packet); err != nil { + res, err := path.EndpointA.RecvPacketWithResult(packet) + if err != nil { return err } + + ack, err := ibctesting.ParseAckFromEvents(res.GetEvents()) + if err != nil { + return err + } + if err := path.EndpointB.AcknowledgePacket(packet, ack); err != nil { return err } diff --git a/x/wasm/ibctesting/wasm.go b/x/wasm/ibctesting/wasm.go index 240d04e3ba..108408d7c2 100644 --- a/x/wasm/ibctesting/wasm.go +++ b/x/wasm/ibctesting/wasm.go @@ -13,7 +13,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" sdk "github.com/Finschia/finschia-sdk/types" - ibctesting "github.com/Finschia/ibc-go/v3/testing" + ibctesting "github.com/cosmos/ibc-go/v4/testing" "github.com/Finschia/ostracon/libs/rand" "github.com/Finschia/wasmd/x/wasm/types" diff --git a/x/wasm/keeper/handler_plugin.go b/x/wasm/keeper/handler_plugin.go index cccf06a643..0339796f2a 100644 --- a/x/wasm/keeper/handler_plugin.go +++ b/x/wasm/keeper/handler_plugin.go @@ -8,8 +8,8 @@ import ( codectypes "github.com/Finschia/finschia-sdk/codec/types" sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - host "github.com/Finschia/ibc-go/v3/modules/core/24-host" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v4/modules/core/24-host" wasmvmtypes "github.com/Finschia/wasmvm/types" "github.com/Finschia/wasmd/x/wasm/types" diff --git a/x/wasm/keeper/handler_plugin_encoders.go b/x/wasm/keeper/handler_plugin_encoders.go index 82fada009a..7521d835f7 100644 --- a/x/wasm/keeper/handler_plugin_encoders.go +++ b/x/wasm/keeper/handler_plugin_encoders.go @@ -11,9 +11,9 @@ import ( distributiontypes "github.com/Finschia/finschia-sdk/x/distribution/types" govtypes "github.com/Finschia/finschia-sdk/x/gov/types" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" - ibctransfertypes "github.com/Finschia/ibc-go/v3/modules/apps/transfer/types" - ibcclienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + ibcclienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" wasmvmtypes "github.com/Finschia/wasmvm/types" "github.com/Finschia/wasmd/x/wasm/types" diff --git a/x/wasm/keeper/handler_plugin_encoders_test.go b/x/wasm/keeper/handler_plugin_encoders_test.go index dd66948787..3b332fd690 100644 --- a/x/wasm/keeper/handler_plugin_encoders_test.go +++ b/x/wasm/keeper/handler_plugin_encoders_test.go @@ -13,9 +13,9 @@ import ( distributiontypes "github.com/Finschia/finschia-sdk/x/distribution/types" govtypes "github.com/Finschia/finschia-sdk/x/gov/types" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" - ibctransfertypes "github.com/Finschia/ibc-go/v3/modules/apps/transfer/types" - clienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" wasmvmtypes "github.com/Finschia/wasmvm/types" "github.com/Finschia/wasmd/x/wasm/keeper/wasmtesting" diff --git a/x/wasm/keeper/handler_plugin_test.go b/x/wasm/keeper/handler_plugin_test.go index 53b37e66da..ea42132706 100644 --- a/x/wasm/keeper/handler_plugin_test.go +++ b/x/wasm/keeper/handler_plugin_test.go @@ -12,9 +12,9 @@ import ( sdkerrors "github.com/Finschia/finschia-sdk/types/errors" banktypes "github.com/Finschia/finschia-sdk/x/bank/types" capabilitytypes "github.com/Finschia/finschia-sdk/x/capability/types" - clienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - ibcexported "github.com/Finschia/ibc-go/v3/modules/core/exported" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" wasmvm "github.com/Finschia/wasmvm" wasmvmtypes "github.com/Finschia/wasmvm/types" diff --git a/x/wasm/keeper/ibc.go b/x/wasm/keeper/ibc.go index 0390019d84..5a7c7943bd 100644 --- a/x/wasm/keeper/ibc.go +++ b/x/wasm/keeper/ibc.go @@ -6,7 +6,7 @@ import ( sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" capabilitytypes "github.com/Finschia/finschia-sdk/x/capability/types" - host "github.com/Finschia/ibc-go/v3/modules/core/24-host" + host "github.com/cosmos/ibc-go/v4/modules/core/24-host" "github.com/Finschia/wasmd/x/wasm/types" ) diff --git a/x/wasm/keeper/query_plugins.go b/x/wasm/keeper/query_plugins.go index 14b7922dd6..09a45454d8 100644 --- a/x/wasm/keeper/query_plugins.go +++ b/x/wasm/keeper/query_plugins.go @@ -11,7 +11,7 @@ import ( sdkerrors "github.com/Finschia/finschia-sdk/types/errors" distributiontypes "github.com/Finschia/finschia-sdk/x/distribution/types" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" wasmvmtypes "github.com/Finschia/wasmvm/types" "github.com/Finschia/wasmd/x/wasm/types" diff --git a/x/wasm/keeper/query_plugins_test.go b/x/wasm/keeper/query_plugins_test.go index d7b9a8122f..60a6905bae 100644 --- a/x/wasm/keeper/query_plugins_test.go +++ b/x/wasm/keeper/query_plugins_test.go @@ -11,7 +11,7 @@ import ( "github.com/Finschia/finschia-sdk/store" sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" wasmvmtypes "github.com/Finschia/wasmvm/types" "github.com/Finschia/wasmd/x/wasm/keeper/wasmtesting" diff --git a/x/wasm/keeper/relay.go b/x/wasm/keeper/relay.go index 233e7fa27d..c3bd329eac 100644 --- a/x/wasm/keeper/relay.go +++ b/x/wasm/keeper/relay.go @@ -24,8 +24,6 @@ func (k Keeper) OnOpenChannel( msg wasmvmtypes.IBCChannelOpenMsg, ) (string, error) { defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "ibc-open-channel") - version := "" - _, codeInfo, prefixStore, err := k.contractInstance(ctx, contractAddr) if err != nil { return "", err @@ -40,12 +38,10 @@ func (k Keeper) OnOpenChannel( if execErr != nil { return "", sdkerrors.Wrap(types.ErrExecuteFailed, execErr.Error()) } - if res != nil { - version = res.Version + return res.Version, nil } - - return version, nil + return "", nil } // OnConnectChannel calls the contract to let it know the IBC channel was established. diff --git a/x/wasm/keeper/snapshotter_integration_test.go b/x/wasm/keeper/snapshotter_integration_test.go index 6769dce749..a6a9e609aa 100644 --- a/x/wasm/keeper/snapshotter_integration_test.go +++ b/x/wasm/keeper/snapshotter_integration_test.go @@ -117,7 +117,7 @@ func newWasmExampleApp(t *testing.T) (*app.WasmApp, sdk.AccAddress) { } validator := octypes.NewValidator(pubKey, 1) valSet := octypes.NewValidatorSet([]*octypes.Validator{validator}) - wasmApp := app.SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, nil, balance) + wasmApp := app.SetupWithGenesisValSet(t, valSet, []authtypes.GenesisAccount{acc}, "testing", nil, balance) return wasmApp, senderAddr } diff --git a/x/wasm/keeper/test_common.go b/x/wasm/keeper/test_common.go index dfc929c2a1..5ab3c7ab8c 100644 --- a/x/wasm/keeper/test_common.go +++ b/x/wasm/keeper/test_common.go @@ -62,11 +62,11 @@ import ( upgradeclient "github.com/Finschia/finschia-sdk/x/upgrade/client" upgradekeeper "github.com/Finschia/finschia-sdk/x/upgrade/keeper" upgradetypes "github.com/Finschia/finschia-sdk/x/upgrade/types" - "github.com/Finschia/ibc-go/v3/modules/apps/transfer" - ibctransfertypes "github.com/Finschia/ibc-go/v3/modules/apps/transfer/types" - ibc "github.com/Finschia/ibc-go/v3/modules/core" - ibchost "github.com/Finschia/ibc-go/v3/modules/core/24-host" - ibckeeper "github.com/Finschia/ibc-go/v3/modules/core/keeper" + "github.com/cosmos/ibc-go/v4/modules/apps/transfer" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + ibc "github.com/cosmos/ibc-go/v4/modules/core" + ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" + ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" "github.com/Finschia/ostracon/crypto" "github.com/Finschia/ostracon/crypto/ed25519" "github.com/Finschia/ostracon/libs/log" @@ -173,18 +173,19 @@ func (f *TestFaucet) NewFundedRandomAccount(ctx sdk.Context, amounts ...sdk.Coin } type TestKeepers struct { - AccountKeeper authkeeper.AccountKeeper - StakingKeeper stakingkeeper.Keeper - DistKeeper distributionkeeper.Keeper - BankKeeper bankkeeper.Keeper - GovKeeper govkeeper.Keeper - ContractKeeper types.ContractOpsKeeper - WasmKeeper *Keeper - IBCKeeper *ibckeeper.Keeper - Router *baseapp.Router - EncodingConfig wasmappparams.EncodingConfig - Faucet *TestFaucet - MultiStore sdk.CommitMultiStore + AccountKeeper authkeeper.AccountKeeper + StakingKeeper stakingkeeper.Keeper + DistKeeper distributionkeeper.Keeper + BankKeeper bankkeeper.Keeper + GovKeeper govkeeper.Keeper + ContractKeeper types.ContractOpsKeeper + WasmKeeper *Keeper + IBCKeeper *ibckeeper.Keeper + Router *baseapp.Router + EncodingConfig wasmappparams.EncodingConfig + Faucet *TestFaucet + MultiStore sdk.CommitMultiStore + ScopedWasmKeeper capabilitykeeper.ScopedKeeper } // CreateDefaultTestInput common settings for CreateTestInput @@ -430,18 +431,19 @@ func createTestInput( govKeeper.SetTallyParams(ctx, govtypes.DefaultTallyParams()) keepers := TestKeepers{ - AccountKeeper: accountKeeper, - StakingKeeper: stakingKeeper, - DistKeeper: distKeeper, - ContractKeeper: contractKeeper, - WasmKeeper: &keeper, - BankKeeper: bankKeeper, - GovKeeper: govKeeper, - IBCKeeper: ibcKeeper, - Router: router, - EncodingConfig: encodingConfig, - Faucet: faucet, - MultiStore: ms, + AccountKeeper: accountKeeper, + StakingKeeper: stakingKeeper, + DistKeeper: distKeeper, + ContractKeeper: contractKeeper, + WasmKeeper: &keeper, + BankKeeper: bankKeeper, + GovKeeper: govKeeper, + IBCKeeper: ibcKeeper, + Router: router, + EncodingConfig: encodingConfig, + Faucet: faucet, + MultiStore: ms, + ScopedWasmKeeper: scopedWasmKeeper, } return ctx, keepers } diff --git a/x/wasm/keeper/wasmtesting/mock_engine.go b/x/wasm/keeper/wasmtesting/mock_engine.go index af2955c701..2bc7fd283b 100644 --- a/x/wasm/keeper/wasmtesting/mock_engine.go +++ b/x/wasm/keeper/wasmtesting/mock_engine.go @@ -347,3 +347,56 @@ func HasIBCAnalyzeFn(wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error) { func WithoutIBCAnalyzeFn(wasmvm.Checksum) (*wasmvmtypes.AnalysisReport, error) { return &wasmvmtypes.AnalysisReport{}, nil } + +var _ IBCContractCallbacks = &MockIBCContractCallbacks{} + +type MockIBCContractCallbacks struct { + IBCChannelOpenFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error) + IBCChannelConnectFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) + IBCChannelCloseFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) + IBCPacketReceiveFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketReceiveMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCReceiveResult, uint64, error) + IBCPacketAckFn func(codeID wasmvm.Checksum, env wasmvmtypes.Env, msg wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) + 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.IBCBasicResponse, uint64, error) +} + +func (m MockIBCContractCallbacks) IBCChannelOpen(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelOpenMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBC3ChannelOpenResponse, uint64, error) { + if m.IBCChannelOpenFn == nil { + panic("not expected to be called") + } + return m.IBCChannelOpenFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + +func (m MockIBCContractCallbacks) IBCChannelConnect(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelConnectMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + if m.IBCChannelConnectFn == nil { + panic("not expected to be called") + } + return m.IBCChannelConnectFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + +func (m MockIBCContractCallbacks) IBCChannelClose(codeID wasmvm.Checksum, env wasmvmtypes.Env, channel wasmvmtypes.IBCChannelCloseMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + if m.IBCChannelCloseFn == nil { + panic("not expected to be called") + } + return m.IBCChannelCloseFn(codeID, env, channel, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + +func (m MockIBCContractCallbacks) IBCPacketReceive(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketReceiveMsg, 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 { + panic("not expected to be called") + } + return m.IBCPacketReceiveFn(codeID, env, packet, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + +func (m MockIBCContractCallbacks) IBCPacketAck(codeID wasmvm.Checksum, env wasmvmtypes.Env, ack wasmvmtypes.IBCPacketAckMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + if m.IBCPacketAckFn == nil { + panic("not expected to be called") + } + return m.IBCPacketAckFn(codeID, env, ack, store, goapi, querier, gasMeter, gasLimit, deserCost) +} + +func (m MockIBCContractCallbacks) IBCPacketTimeout(codeID wasmvm.Checksum, env wasmvmtypes.Env, packet wasmvmtypes.IBCPacketTimeoutMsg, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.IBCBasicResponse, uint64, error) { + if m.IBCPacketTimeoutFn == nil { + panic("not expected to be called") + } + return m.IBCPacketTimeoutFn(codeID, env, packet, store, goapi, querier, gasMeter, gasLimit, deserCost) +} diff --git a/x/wasm/keeper/wasmtesting/mock_keepers.go b/x/wasm/keeper/wasmtesting/mock_keepers.go index 2ce5c4c7a5..8359b180c3 100644 --- a/x/wasm/keeper/wasmtesting/mock_keepers.go +++ b/x/wasm/keeper/wasmtesting/mock_keepers.go @@ -3,8 +3,8 @@ package wasmtesting import ( sdk "github.com/Finschia/finschia-sdk/types" capabilitytypes "github.com/Finschia/finschia-sdk/x/capability/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - ibcexported "github.com/Finschia/ibc-go/v3/modules/core/exported" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" "github.com/Finschia/wasmd/x/wasm/types" ) diff --git a/x/wasm/relay_pingpong_test.go b/x/wasm/relay_pingpong_test.go index 9e2d43c184..d36ca1a476 100644 --- a/x/wasm/relay_pingpong_test.go +++ b/x/wasm/relay_pingpong_test.go @@ -10,10 +10,10 @@ import ( "github.com/Finschia/finschia-sdk/store/prefix" sdk "github.com/Finschia/finschia-sdk/types" - ibctransfertypes "github.com/Finschia/ibc-go/v3/modules/apps/transfer/types" - clienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - ibctesting "github.com/Finschia/ibc-go/v3/testing" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" wasmvm "github.com/Finschia/wasmvm" wasmvmtypes "github.com/Finschia/wasmvm/types" @@ -31,7 +31,6 @@ const ( var doNotTimeout = clienttypes.NewHeight(1, 1111111) func TestPinPong(t *testing.T) { - t.Skip("check it later after enable use ibc-go v3.3.0+ in finschia-sdk") // custom IBC protocol example // scenario: given two chains, // with a contract on chain A and chain B @@ -109,11 +108,6 @@ func TestPinPong(t *testing.T) { require.Len(t, chainA.PendingSendPackets, 1) err := coordinator.RelayAndAckPendingPackets(path) require.NoError(t, err) - - // switch side - require.Len(t, chainB.PendingSendPackets, 1) - err = coordinator.RelayAndAckPendingPackets(path.Invert()) - require.NoError(t, err) } // then receive/response state is as expected diff --git a/x/wasm/relay_test.go b/x/wasm/relay_test.go index 9e2e32734b..629891fd06 100644 --- a/x/wasm/relay_test.go +++ b/x/wasm/relay_test.go @@ -11,10 +11,10 @@ import ( sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" - ibctransfertypes "github.com/Finschia/ibc-go/v3/modules/apps/transfer/types" - clienttypes "github.com/Finschia/ibc-go/v3/modules/core/02-client/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - ibctesting "github.com/Finschia/ibc-go/v3/testing" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" wasmvm "github.com/Finschia/wasmvm" wasmvmtypes "github.com/Finschia/wasmvm/types" diff --git a/x/wasm/types/expected_keepers.go b/x/wasm/types/expected_keepers.go index 658eac2781..5c09535056 100644 --- a/x/wasm/types/expected_keepers.go +++ b/x/wasm/types/expected_keepers.go @@ -8,9 +8,9 @@ import ( capabilitytypes "github.com/Finschia/finschia-sdk/x/capability/types" "github.com/Finschia/finschia-sdk/x/distribution/types" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" - connectiontypes "github.com/Finschia/ibc-go/v3/modules/core/03-connection/types" - channeltypes "github.com/Finschia/ibc-go/v3/modules/core/04-channel/types" - ibcexported "github.com/Finschia/ibc-go/v3/modules/core/exported" + connectiontypes "github.com/cosmos/ibc-go/v4/modules/core/03-connection/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" ) // BankViewKeeper defines a subset of methods implemented by the cosmos-sdk bank keeper diff --git a/x/wasmplus/keeper/test_common.go b/x/wasmplus/keeper/test_common.go index 6b6cd54b8c..030fc06c40 100644 --- a/x/wasmplus/keeper/test_common.go +++ b/x/wasmplus/keeper/test_common.go @@ -62,11 +62,11 @@ import ( upgradeclient "github.com/Finschia/finschia-sdk/x/upgrade/client" upgradekeeper "github.com/Finschia/finschia-sdk/x/upgrade/keeper" upgradetypes "github.com/Finschia/finschia-sdk/x/upgrade/types" - "github.com/Finschia/ibc-go/v3/modules/apps/transfer" - ibctransfertypes "github.com/Finschia/ibc-go/v3/modules/apps/transfer/types" - ibc "github.com/Finschia/ibc-go/v3/modules/core" - ibchost "github.com/Finschia/ibc-go/v3/modules/core/24-host" - ibckeeper "github.com/Finschia/ibc-go/v3/modules/core/keeper" + "github.com/cosmos/ibc-go/v4/modules/apps/transfer" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + ibc "github.com/cosmos/ibc-go/v4/modules/core" + ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" + ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" "github.com/Finschia/ostracon/crypto" "github.com/Finschia/ostracon/crypto/ed25519" "github.com/Finschia/ostracon/libs/log" From 4f3433e077c2dc418f5ed334fe0e4325f023a7be Mon Sep 17 00:00:00 2001 From: Alex Peters Date: Thu, 26 Jan 2023 14:49:15 +0100 Subject: [PATCH 2/8] feat: remove channel hack cherry-picking d522e54a12501a91549e7804490a9ca14a779d41 --- x/wasm/ibc.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/x/wasm/ibc.go b/x/wasm/ibc.go index a22ce846bc..faeb11eb11 100644 --- a/x/wasm/ibc.go +++ b/x/wasm/ibc.go @@ -154,12 +154,6 @@ func (i IBCHandler) OnChanOpenAck( return sdkerrors.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", portID, channelID) } channelInfo.Counterparty.ChannelId = counterpartyChannelID - // This is a bit ugly, but it is set AFTER the callback is done, yet we want to provide the contract - // access to the channel in queries. We can revisit how to better integrate with ibc-go in the future, - // but this is the best/safest we can do now. (If you remove this, you error when sending a packet during the - // OnChanOpenAck entry point) - // https://github.com/cosmos/ibc-go/pull/647/files#diff-54b5be375a2333c56f2ae1b5b4dc13ac9c734561e30286505f39837ee75762c7R25 - i.channelKeeper.SetChannel(ctx, portID, channelID, channelInfo) appVersion, ok := i.appVersionGetter.GetAppVersion(ctx, portID, channelID) if !ok { From 0d2a8f2433c9568eee49584549b786e49a8c3673 Mon Sep 17 00:00:00 2001 From: loloicci Date: Wed, 2 Aug 2023 19:55:45 +0900 Subject: [PATCH 3/8] docs: add this PR to CHANGELOG --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24412cfe98..213db1966d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased](https://github.com/Finschia/wasmd/compare/v0.1.4...HEAD) ### Features +* [\#61](https://github.com/Finschia/wasmd/pull/61) bumpup ibc-go to v4 ### Improvements @@ -24,7 +25,7 @@ * [\#46](https://github.com/Finschia/wasmd/pull/46) add admin-related events ### Improvements -* [\#43](https://github.com/Finschia/wasmd/pull/43) delete unnecessary test +* [\#43](https://github.com/Finschia/wasmd/pull/43) delete unnecessary test ### Bug Fixes * [\#35](https://github.com/Finschia/wasmd/pull/35) stop wrap twice the response of handling non-plus wasm message in plus handler From c207262f205dc48519bf554ace0110f659baf89d Mon Sep 17 00:00:00 2001 From: loloicci Date: Wed, 2 Aug 2023 19:57:50 +0900 Subject: [PATCH 4/8] chore: execute go fmt --- app/app.go | 24 +++++++++---------- app/sim_test.go | 2 +- appplus/app.go | 10 ++++---- x/wasm/ibc.go | 2 +- x/wasm/ibc_reflect_test.go | 2 +- x/wasm/ibc_test.go | 2 +- x/wasm/ibctesting/chain.go | 12 +++++----- x/wasm/ibctesting/coordinator.go | 2 +- x/wasm/ibctesting/wasm.go | 2 +- x/wasm/keeper/handler_plugin.go | 2 +- x/wasm/keeper/handler_plugin_encoders.go | 2 +- x/wasm/keeper/handler_plugin_encoders_test.go | 2 +- x/wasm/keeper/handler_plugin_test.go | 4 ++-- x/wasm/keeper/query_plugins.go | 2 +- x/wasm/keeper/query_plugins_test.go | 2 +- x/wasm/keeper/test_common.go | 8 +++---- x/wasm/relay_pingpong_test.go | 4 ++-- x/wasm/relay_test.go | 4 ++-- x/wasmplus/keeper/test_common.go | 6 ++--- 19 files changed, 47 insertions(+), 47 deletions(-) diff --git a/app/app.go b/app/app.go index b339731ceb..335c0363de 100644 --- a/app/app.go +++ b/app/app.go @@ -15,6 +15,7 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" + ocabci "github.com/Finschia/ostracon/abci/types" ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" icacontrollerkeeper "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/controller/keeper" icacontrollertypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/controller/types" @@ -35,7 +36,6 @@ import ( porttypes "github.com/cosmos/ibc-go/v4/modules/core/05-port/types" ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" - ocabci "github.com/Finschia/ostracon/abci/types" "github.com/Finschia/finschia-sdk/baseapp" "github.com/Finschia/finschia-sdk/client" @@ -546,17 +546,17 @@ func NewWasmApp( transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) /* - // Create Interchain Accounts Stack - // SendPacket, since it is originating from the application to core IBC: - // icaAuthModuleKeeper.SendTx -> icaController.SendPacket -> fee.SendPacket -> channel.SendPacket - - // Note: please do your research before using this in production app, this is a demo and not an officially - // supported IBC team implementation. Do your own research before using it. - var icaControllerStack porttypes.IBCModule - // You will likely want to use your own reviewed and maintained ica auth module - icaControllerStack = intertx.NewIBCModule(app.InterTxKeeper) - icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper) - icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper) + // Create Interchain Accounts Stack + // SendPacket, since it is originating from the application to core IBC: + // icaAuthModuleKeeper.SendTx -> icaController.SendPacket -> fee.SendPacket -> channel.SendPacket + + // Note: please do your research before using this in production app, this is a demo and not an officially + // supported IBC team implementation. Do your own research before using it. + var icaControllerStack porttypes.IBCModule + // You will likely want to use your own reviewed and maintained ica auth module + icaControllerStack = intertx.NewIBCModule(app.InterTxKeeper) + icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper) + icaControllerStack = ibcfee.NewIBCMiddleware(icaControllerStack, app.IBCFeeKeeper) */ // RecvPacket, message that originates from core IBC and goes down to app, the flow is: diff --git a/app/sim_test.go b/app/sim_test.go index 3d4637961e..ccde6c26df 100644 --- a/app/sim_test.go +++ b/app/sim_test.go @@ -34,9 +34,9 @@ import ( "github.com/Finschia/finschia-sdk/x/simulation" slashingtypes "github.com/Finschia/finschia-sdk/x/slashing/types" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" + "github.com/Finschia/ostracon/libs/log" ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" - "github.com/Finschia/ostracon/libs/log" "github.com/Finschia/wasmd/x/wasm" wasmtypes "github.com/Finschia/wasmd/x/wasm/types" diff --git a/appplus/app.go b/appplus/app.go index 6099c016c3..687486b8a9 100644 --- a/appplus/app.go +++ b/appplus/app.go @@ -82,6 +82,10 @@ import ( upgradeclient "github.com/Finschia/finschia-sdk/x/upgrade/client" upgradekeeper "github.com/Finschia/finschia-sdk/x/upgrade/keeper" upgradetypes "github.com/Finschia/finschia-sdk/x/upgrade/types" + ocabci "github.com/Finschia/ostracon/abci/types" + tmjson "github.com/Finschia/ostracon/libs/json" + "github.com/Finschia/ostracon/libs/log" + tmos "github.com/Finschia/ostracon/libs/os" ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" icacontrollerkeeper "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/controller/keeper" icacontrollertypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/controller/types" @@ -103,10 +107,6 @@ import ( ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" ibcmock "github.com/cosmos/ibc-go/v4/testing/mock" - ocabci "github.com/Finschia/ostracon/abci/types" - tmjson "github.com/Finschia/ostracon/libs/json" - "github.com/Finschia/ostracon/libs/log" - tmos "github.com/Finschia/ostracon/libs/os" wasmapp "github.com/Finschia/wasmd/app" wasmappparams "github.com/Finschia/wasmd/app/params" @@ -546,7 +546,7 @@ func NewWasmApp( var transferStack porttypes.IBCModule transferStack = transfer.NewIBCModule(app.TransferKeeper) transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) - // RecvPacket, message that originates from core IBC and goes down to app, the flow is: + // RecvPacket, message that originates from core IBC and goes down to app, the flow is: // channel.RecvPacket -> fee.OnRecvPacket -> icaHost.OnRecvPacket var icaHostStack porttypes.IBCModule icaHostStack = icahost.NewIBCModule(app.ICAHostKeeper) diff --git a/x/wasm/ibc.go b/x/wasm/ibc.go index faeb11eb11..24c1efd687 100644 --- a/x/wasm/ibc.go +++ b/x/wasm/ibc.go @@ -6,11 +6,11 @@ import ( sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" capabilitytypes "github.com/Finschia/finschia-sdk/x/capability/types" + wasmvmtypes "github.com/Finschia/wasmvm/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v4/modules/core/05-port/types" host "github.com/cosmos/ibc-go/v4/modules/core/24-host" ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" - wasmvmtypes "github.com/Finschia/wasmvm/types" "github.com/Finschia/wasmd/x/wasm/types" ) diff --git a/x/wasm/ibc_reflect_test.go b/x/wasm/ibc_reflect_test.go index c951243369..fad6765d11 100644 --- a/x/wasm/ibc_reflect_test.go +++ b/x/wasm/ibc_reflect_test.go @@ -6,9 +6,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + wasmvmtypes "github.com/Finschia/wasmvm/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" ibctesting "github.com/cosmos/ibc-go/v4/testing" - wasmvmtypes "github.com/Finschia/wasmvm/types" wasmibctesting "github.com/Finschia/wasmd/x/wasm/ibctesting" wasmkeeper "github.com/Finschia/wasmd/x/wasm/keeper" diff --git a/x/wasm/ibc_test.go b/x/wasm/ibc_test.go index 66ad2a2ac1..df8c7a2556 100644 --- a/x/wasm/ibc_test.go +++ b/x/wasm/ibc_test.go @@ -5,9 +5,9 @@ import ( "github.com/stretchr/testify/assert" + wasmvmtypes "github.com/Finschia/wasmvm/types" clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" - wasmvmtypes "github.com/Finschia/wasmvm/types" ) func TestMapToWasmVMIBCPacket(t *testing.T) { diff --git a/x/wasm/ibctesting/chain.go b/x/wasm/ibctesting/chain.go index 3dd9ee1b09..9b1709ddf5 100644 --- a/x/wasm/ibctesting/chain.go +++ b/x/wasm/ibctesting/chain.go @@ -22,6 +22,10 @@ import ( capabilitytypes "github.com/Finschia/finschia-sdk/x/capability/types" "github.com/Finschia/finschia-sdk/x/staking/teststaking" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" + ocabci "github.com/Finschia/ostracon/abci/types" + "github.com/Finschia/ostracon/crypto/tmhash" + octypes "github.com/Finschia/ostracon/types" + ocversion "github.com/Finschia/ostracon/version" clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" commitmenttypes "github.com/cosmos/ibc-go/v4/modules/core/23-commitment/types" @@ -31,10 +35,6 @@ import ( ibctmtypes "github.com/cosmos/ibc-go/v4/modules/light-clients/07-tendermint/types" ibctesting "github.com/cosmos/ibc-go/v4/testing" "github.com/cosmos/ibc-go/v4/testing/mock" - ocabci "github.com/Finschia/ostracon/abci/types" - "github.com/Finschia/ostracon/crypto/tmhash" - octypes "github.com/Finschia/ostracon/types" - ocversion "github.com/Finschia/ostracon/version" "github.com/Finschia/wasmd/app" "github.com/Finschia/wasmd/app/params" @@ -64,8 +64,8 @@ type TestChain struct { QueryServer types.QueryServer TxConfig client.TxConfig Codec codec.BinaryCodec - Vals *octypes.ValidatorSet - NextVals *octypes.ValidatorSet + Vals *octypes.ValidatorSet + NextVals *octypes.ValidatorSet // Signers is a map from validator address to the PrivValidator // The map is converted into an array that is the same order as the validators right before signing commit diff --git a/x/wasm/ibctesting/coordinator.go b/x/wasm/ibctesting/coordinator.go index 7720ae399f..1fd548f8da 100644 --- a/x/wasm/ibctesting/coordinator.go +++ b/x/wasm/ibctesting/coordinator.go @@ -8,10 +8,10 @@ import ( "github.com/stretchr/testify/require" + ocabci "github.com/Finschia/ostracon/abci/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" host "github.com/cosmos/ibc-go/v4/modules/core/24-host" ibctesting "github.com/cosmos/ibc-go/v4/testing" - ocabci "github.com/Finschia/ostracon/abci/types" wasmkeeper "github.com/Finschia/wasmd/x/wasm/keeper" ) diff --git a/x/wasm/ibctesting/wasm.go b/x/wasm/ibctesting/wasm.go index 108408d7c2..7856e5d86f 100644 --- a/x/wasm/ibctesting/wasm.go +++ b/x/wasm/ibctesting/wasm.go @@ -13,8 +13,8 @@ import ( abci "github.com/tendermint/tendermint/abci/types" sdk "github.com/Finschia/finschia-sdk/types" - ibctesting "github.com/cosmos/ibc-go/v4/testing" "github.com/Finschia/ostracon/libs/rand" + ibctesting "github.com/cosmos/ibc-go/v4/testing" "github.com/Finschia/wasmd/x/wasm/types" ) diff --git a/x/wasm/keeper/handler_plugin.go b/x/wasm/keeper/handler_plugin.go index 0339796f2a..37ef2a4572 100644 --- a/x/wasm/keeper/handler_plugin.go +++ b/x/wasm/keeper/handler_plugin.go @@ -8,9 +8,9 @@ import ( codectypes "github.com/Finschia/finschia-sdk/codec/types" sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" + wasmvmtypes "github.com/Finschia/wasmvm/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" host "github.com/cosmos/ibc-go/v4/modules/core/24-host" - wasmvmtypes "github.com/Finschia/wasmvm/types" "github.com/Finschia/wasmd/x/wasm/types" ) diff --git a/x/wasm/keeper/handler_plugin_encoders.go b/x/wasm/keeper/handler_plugin_encoders.go index 7521d835f7..bbf7088970 100644 --- a/x/wasm/keeper/handler_plugin_encoders.go +++ b/x/wasm/keeper/handler_plugin_encoders.go @@ -11,10 +11,10 @@ import ( distributiontypes "github.com/Finschia/finschia-sdk/x/distribution/types" govtypes "github.com/Finschia/finschia-sdk/x/gov/types" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" + wasmvmtypes "github.com/Finschia/wasmvm/types" ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" ibcclienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" - wasmvmtypes "github.com/Finschia/wasmvm/types" "github.com/Finschia/wasmd/x/wasm/types" ) diff --git a/x/wasm/keeper/handler_plugin_encoders_test.go b/x/wasm/keeper/handler_plugin_encoders_test.go index 3b332fd690..8191ab29eb 100644 --- a/x/wasm/keeper/handler_plugin_encoders_test.go +++ b/x/wasm/keeper/handler_plugin_encoders_test.go @@ -13,10 +13,10 @@ import ( distributiontypes "github.com/Finschia/finschia-sdk/x/distribution/types" govtypes "github.com/Finschia/finschia-sdk/x/gov/types" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" + wasmvmtypes "github.com/Finschia/wasmvm/types" ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" - wasmvmtypes "github.com/Finschia/wasmvm/types" "github.com/Finschia/wasmd/x/wasm/keeper/wasmtesting" "github.com/Finschia/wasmd/x/wasm/types" diff --git a/x/wasm/keeper/handler_plugin_test.go b/x/wasm/keeper/handler_plugin_test.go index ea42132706..5780ffc1e3 100644 --- a/x/wasm/keeper/handler_plugin_test.go +++ b/x/wasm/keeper/handler_plugin_test.go @@ -12,11 +12,11 @@ import ( sdkerrors "github.com/Finschia/finschia-sdk/types/errors" banktypes "github.com/Finschia/finschia-sdk/x/bank/types" capabilitytypes "github.com/Finschia/finschia-sdk/x/capability/types" + wasmvm "github.com/Finschia/wasmvm" + wasmvmtypes "github.com/Finschia/wasmvm/types" clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" - wasmvm "github.com/Finschia/wasmvm" - wasmvmtypes "github.com/Finschia/wasmvm/types" "github.com/Finschia/wasmd/x/wasm/keeper/wasmtesting" "github.com/Finschia/wasmd/x/wasm/types" diff --git a/x/wasm/keeper/query_plugins.go b/x/wasm/keeper/query_plugins.go index 09a45454d8..b7266a466e 100644 --- a/x/wasm/keeper/query_plugins.go +++ b/x/wasm/keeper/query_plugins.go @@ -11,8 +11,8 @@ import ( sdkerrors "github.com/Finschia/finschia-sdk/types/errors" distributiontypes "github.com/Finschia/finschia-sdk/x/distribution/types" stakingtypes "github.com/Finschia/finschia-sdk/x/staking/types" - channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" wasmvmtypes "github.com/Finschia/wasmvm/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" "github.com/Finschia/wasmd/x/wasm/types" ) diff --git a/x/wasm/keeper/query_plugins_test.go b/x/wasm/keeper/query_plugins_test.go index 60a6905bae..e793e74444 100644 --- a/x/wasm/keeper/query_plugins_test.go +++ b/x/wasm/keeper/query_plugins_test.go @@ -11,8 +11,8 @@ import ( "github.com/Finschia/finschia-sdk/store" sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" - channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" wasmvmtypes "github.com/Finschia/wasmvm/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" "github.com/Finschia/wasmd/x/wasm/keeper/wasmtesting" "github.com/Finschia/wasmd/x/wasm/types" diff --git a/x/wasm/keeper/test_common.go b/x/wasm/keeper/test_common.go index 5ab3c7ab8c..4928c9d3bb 100644 --- a/x/wasm/keeper/test_common.go +++ b/x/wasm/keeper/test_common.go @@ -62,15 +62,15 @@ import ( upgradeclient "github.com/Finschia/finschia-sdk/x/upgrade/client" upgradekeeper "github.com/Finschia/finschia-sdk/x/upgrade/keeper" upgradetypes "github.com/Finschia/finschia-sdk/x/upgrade/types" + "github.com/Finschia/ostracon/crypto" + "github.com/Finschia/ostracon/crypto/ed25519" + "github.com/Finschia/ostracon/libs/log" + "github.com/Finschia/ostracon/libs/rand" "github.com/cosmos/ibc-go/v4/modules/apps/transfer" ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" ibc "github.com/cosmos/ibc-go/v4/modules/core" ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" - "github.com/Finschia/ostracon/crypto" - "github.com/Finschia/ostracon/crypto/ed25519" - "github.com/Finschia/ostracon/libs/log" - "github.com/Finschia/ostracon/libs/rand" wasmappparams "github.com/Finschia/wasmd/app/params" "github.com/Finschia/wasmd/x/wasm/keeper/wasmtesting" diff --git a/x/wasm/relay_pingpong_test.go b/x/wasm/relay_pingpong_test.go index d36ca1a476..3cecf43023 100644 --- a/x/wasm/relay_pingpong_test.go +++ b/x/wasm/relay_pingpong_test.go @@ -10,12 +10,12 @@ import ( "github.com/Finschia/finschia-sdk/store/prefix" sdk "github.com/Finschia/finschia-sdk/types" + wasmvm "github.com/Finschia/wasmvm" + wasmvmtypes "github.com/Finschia/wasmvm/types" ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" ibctesting "github.com/cosmos/ibc-go/v4/testing" - wasmvm "github.com/Finschia/wasmvm" - wasmvmtypes "github.com/Finschia/wasmvm/types" wasmibctesting "github.com/Finschia/wasmd/x/wasm/ibctesting" wasmkeeper "github.com/Finschia/wasmd/x/wasm/keeper" diff --git a/x/wasm/relay_test.go b/x/wasm/relay_test.go index 629891fd06..e0113a2dda 100644 --- a/x/wasm/relay_test.go +++ b/x/wasm/relay_test.go @@ -11,12 +11,12 @@ import ( sdk "github.com/Finschia/finschia-sdk/types" sdkerrors "github.com/Finschia/finschia-sdk/types/errors" + wasmvm "github.com/Finschia/wasmvm" + wasmvmtypes "github.com/Finschia/wasmvm/types" ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" ibctesting "github.com/cosmos/ibc-go/v4/testing" - wasmvm "github.com/Finschia/wasmvm" - wasmvmtypes "github.com/Finschia/wasmvm/types" wasmibctesting "github.com/Finschia/wasmd/x/wasm/ibctesting" wasmkeeper "github.com/Finschia/wasmd/x/wasm/keeper" diff --git a/x/wasmplus/keeper/test_common.go b/x/wasmplus/keeper/test_common.go index 030fc06c40..5e9a5d44a2 100644 --- a/x/wasmplus/keeper/test_common.go +++ b/x/wasmplus/keeper/test_common.go @@ -62,14 +62,14 @@ import ( upgradeclient "github.com/Finschia/finschia-sdk/x/upgrade/client" upgradekeeper "github.com/Finschia/finschia-sdk/x/upgrade/keeper" upgradetypes "github.com/Finschia/finschia-sdk/x/upgrade/types" + "github.com/Finschia/ostracon/crypto" + "github.com/Finschia/ostracon/crypto/ed25519" + "github.com/Finschia/ostracon/libs/log" "github.com/cosmos/ibc-go/v4/modules/apps/transfer" ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" ibc "github.com/cosmos/ibc-go/v4/modules/core" ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" - "github.com/Finschia/ostracon/crypto" - "github.com/Finschia/ostracon/crypto/ed25519" - "github.com/Finschia/ostracon/libs/log" wasmappparams "github.com/Finschia/wasmd/app/params" wasmkeeper "github.com/Finschia/wasmd/x/wasm/keeper" From bd61258eabff27b92715ba328b219ac9c00fd254 Mon Sep 17 00:00:00 2001 From: loloicci Date: Wed, 2 Aug 2023 20:06:57 +0900 Subject: [PATCH 5/8] fix: add missed e2e ibc-fees test in cherry-pick --- tests/e2e/README.md | 3 + tests/e2e/ibc_fees_test.go | 214 ++++++++++++++++++++++++++ tests/e2e/testdata/cw20_base.wasm.gz | Bin 0 -> 105532 bytes tests/e2e/testdata/cw20_ics20.wasm.gz | Bin 0 -> 119250 bytes 4 files changed, 217 insertions(+) create mode 100644 tests/e2e/README.md create mode 100644 tests/e2e/ibc_fees_test.go create mode 100644 tests/e2e/testdata/cw20_base.wasm.gz create mode 100644 tests/e2e/testdata/cw20_ics20.wasm.gz diff --git a/tests/e2e/README.md b/tests/e2e/README.md new file mode 100644 index 0000000000..dae38fe2df --- /dev/null +++ b/tests/e2e/README.md @@ -0,0 +1,3 @@ +# End To End Testing - e2e + +Scenario tests that run against on or multiple chain instances. diff --git a/tests/e2e/ibc_fees_test.go b/tests/e2e/ibc_fees_test.go new file mode 100644 index 0000000000..200086744b --- /dev/null +++ b/tests/e2e/ibc_fees_test.go @@ -0,0 +1,214 @@ +package e2e + +import ( + "bytes" + "encoding/base64" + "fmt" + "testing" + "time" + + sdk "github.com/Finschia/finschia-sdk/types" + "github.com/Finschia/finschia-sdk/types/address" + ibcfee "github.com/cosmos/ibc-go/v4/modules/apps/29-fee/types" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/Finschia/wasmd/app" + wasmibctesting "github.com/Finschia/wasmd/x/wasm/ibctesting" + wasmtypes "github.com/Finschia/wasmd/x/wasm/types" +) + +func TestIBCFeesTransfer(t *testing.T) { + // scenario: + // given 2 chains + // with an ics-20 channel established + // when an ics-29 fee is attached to an ibc package + // then the relayer's payee is receiving the fee(s) on success + marshaler := app.MakeEncodingConfig().Marshaler + coord := wasmibctesting.NewCoordinator(t, 2) + chainA := coord.GetChain(ibctesting.GetChainID(0)) + chainB := coord.GetChain(ibctesting.GetChainID(1)) + + actorChainA := sdk.AccAddress(chainA.SenderPrivKey.PubKey().Address()) + actorChainB := sdk.AccAddress(chainB.SenderPrivKey.PubKey().Address()) + receiver := sdk.AccAddress(bytes.Repeat([]byte{1}, address.Len)) + payee := sdk.AccAddress(bytes.Repeat([]byte{2}, address.Len)) + oneToken := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1))) + + path := wasmibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig = &ibctesting.ChannelConfig{ + PortID: ibctransfertypes.PortID, + Version: string(marshaler.MustMarshalJSON(&ibcfee.Metadata{FeeVersion: ibcfee.Version, AppVersion: ibctransfertypes.Version})), + Order: channeltypes.UNORDERED, + } + path.EndpointB.ChannelConfig = &ibctesting.ChannelConfig{ + PortID: ibctransfertypes.PortID, + Version: string(marshaler.MustMarshalJSON(&ibcfee.Metadata{FeeVersion: ibcfee.Version, AppVersion: ibctransfertypes.Version})), + Order: channeltypes.UNORDERED, + } + // with an ics-20 transfer channel setup between both chains + coord.Setup(path) + require.True(t, chainA.App.IBCFeeKeeper.IsFeeEnabled(chainA.GetContext(), ibctransfertypes.PortID, path.EndpointA.ChannelID)) + // and with a payee registered on both chains + _, err := chainA.SendMsgs(ibcfee.NewMsgRegisterPayee(ibctransfertypes.PortID, path.EndpointA.ChannelID, actorChainA.String(), payee.String())) + require.NoError(t, err) + _, err = chainB.SendMsgs(ibcfee.NewMsgRegisterCounterpartyPayee(ibctransfertypes.PortID, path.EndpointB.ChannelID, actorChainB.String(), payee.String())) + require.NoError(t, err) + + // when a transfer package is sent + transferCoin := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1)) + ibcPayloadMsg := ibctransfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, transferCoin, actorChainA.String(), receiver.String(), clienttypes.Height{}, uint64(time.Now().Add(time.Minute).UnixNano())) + ibcPackageFee := ibcfee.NewFee(oneToken, oneToken, sdk.Coins{}) + feeMsg := ibcfee.NewMsgPayPacketFee(ibcPackageFee, ibctransfertypes.PortID, path.EndpointA.ChannelID, actorChainA.String(), nil) + _, err = chainA.SendMsgs(feeMsg, ibcPayloadMsg) + require.NoError(t, err) + pendingIncentivisedPackages := chainA.App.IBCFeeKeeper.GetIdentifiedPacketFeesForChannel(chainA.GetContext(), ibctransfertypes.PortID, path.EndpointA.ChannelID) + assert.Len(t, pendingIncentivisedPackages, 1) + + // and packages relayed + require.NoError(t, coord.RelayAndAckPendingPackets(path)) + + // then + expBalance := ibctransfertypes.GetTransferCoin(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, transferCoin.Denom, transferCoin.Amount) + gotBalance := chainB.Balance(receiver, expBalance.Denom) + assert.Equal(t, expBalance.String(), gotBalance.String()) + payeeBalance := chainA.AllBalances(payee) + assert.Equal(t, oneToken.Add(oneToken...).String(), payeeBalance.String()) + + // and with a payee registered for chain B to A + _, err = chainA.SendMsgs(ibcfee.NewMsgRegisterCounterpartyPayee(ibctransfertypes.PortID, path.EndpointA.ChannelID, actorChainA.String(), payee.String())) + require.NoError(t, err) + _, err = chainB.SendMsgs(ibcfee.NewMsgRegisterPayee(ibctransfertypes.PortID, path.EndpointB.ChannelID, actorChainB.String(), payee.String())) + require.NoError(t, err) + + // and transfer from B to A + ibcPayloadMsg = ibctransfertypes.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, transferCoin, actorChainB.String(), receiver.String(), clienttypes.Height{}, uint64(time.Now().Add(time.Minute).UnixNano())) + ibcPackageFee = ibcfee.NewFee(oneToken, oneToken, sdk.Coins{}) + feeMsg = ibcfee.NewMsgPayPacketFee(ibcPackageFee, ibctransfertypes.PortID, path.EndpointB.ChannelID, actorChainB.String(), nil) + _, err = chainB.SendMsgs(feeMsg, ibcPayloadMsg) + require.NoError(t, err) + pendingIncentivisedPackages = chainB.App.IBCFeeKeeper.GetIdentifiedPacketFeesForChannel(chainB.GetContext(), ibctransfertypes.PortID, path.EndpointB.ChannelID) + assert.Len(t, pendingIncentivisedPackages, 1) + + // when packages relayed + require.NoError(t, coord.RelayAndAckPendingPackets(path)) + + // then + expBalance = ibctransfertypes.GetTransferCoin(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, transferCoin.Denom, transferCoin.Amount) + gotBalance = chainA.Balance(receiver, expBalance.Denom) + assert.Equal(t, expBalance.String(), gotBalance.String()) + payeeBalance = chainB.AllBalances(payee) + assert.Equal(t, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2)).String(), payeeBalance.String()) +} + +func TestIBCFeesWasm(t *testing.T) { + // scenario: + // given 2 chains with cw20-ibc on chain A and native ics20 module on B + // and an ibc channel established + // when an ics-29 fee is attached to an ibc package + // then the relayer's payee is receiving the fee(s) on success + marshaler := app.MakeEncodingConfig().Marshaler + coord := wasmibctesting.NewCoordinator(t, 2) + chainA := coord.GetChain(ibctesting.GetChainID(0)) + chainB := coord.GetChain(ibctesting.GetChainID(1)) + actorChainA := sdk.AccAddress(chainA.SenderPrivKey.PubKey().Address()) + actorChainB := sdk.AccAddress(chainB.SenderPrivKey.PubKey().Address()) + + // setup chain A + codeID := chainA.StoreCodeFile("./testdata/cw20_base.wasm.gz").CodeID + + initMsg := []byte(fmt.Sprintf(`{"decimals": 6, "name": "test", "symbol":"ALX", "initial_balances": [{"address": %q,"amount":"100000000"}] }`, actorChainA.String())) + cw20ContractAddr := chainA.InstantiateContract(codeID, initMsg) + + initMsg = []byte(fmt.Sprintf(`{"default_timeout": 360, "gov_contract": %q, "allowlist":[{"contract":%q}]}`, actorChainA.String(), cw20ContractAddr.String())) + codeID = chainA.StoreCodeFile("./testdata/cw20_ics20.wasm.gz").CodeID + ibcContractAddr := chainA.InstantiateContract(codeID, initMsg) + ibcContractPortID := chainA.ContractInfo(ibcContractAddr).IBCPortID + + payee := sdk.AccAddress(bytes.Repeat([]byte{2}, address.Len)) + oneToken := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1))) + + path := wasmibctesting.NewPath(chainA, chainB) + path.EndpointA.ChannelConfig = &ibctesting.ChannelConfig{ + PortID: ibcContractPortID, + Version: string(marshaler.MustMarshalJSON(&ibcfee.Metadata{FeeVersion: ibcfee.Version, AppVersion: ibctransfertypes.Version})), + Order: channeltypes.UNORDERED, + } + path.EndpointB.ChannelConfig = &ibctesting.ChannelConfig{ + PortID: ibctransfertypes.PortID, + Version: string(marshaler.MustMarshalJSON(&ibcfee.Metadata{FeeVersion: ibcfee.Version, AppVersion: ibctransfertypes.Version})), + Order: channeltypes.UNORDERED, + } + // with an ics-29 fee enabled channel setup between both chains + coord.Setup(path) + require.True(t, chainA.App.IBCFeeKeeper.IsFeeEnabled(chainA.GetContext(), ibcContractPortID, path.EndpointA.ChannelID)) + require.True(t, chainB.App.IBCFeeKeeper.IsFeeEnabled(chainB.GetContext(), ibctransfertypes.PortID, path.EndpointB.ChannelID)) + // and with a payee registered for A -> B + _, err := chainA.SendMsgs(ibcfee.NewMsgRegisterPayee(ibcContractPortID, path.EndpointA.ChannelID, actorChainA.String(), payee.String())) + require.NoError(t, err) + _, err = chainB.SendMsgs(ibcfee.NewMsgRegisterCounterpartyPayee(ibctransfertypes.PortID, path.EndpointB.ChannelID, actorChainB.String(), payee.String())) + require.NoError(t, err) + + // when a transfer package is sent from ics20 contract on A to B + transfer := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf(`{"channel": %q, "remote_address": %q}`, path.EndpointA.ChannelID, actorChainB.String()))) + exec := []byte(fmt.Sprintf(`{"send":{"contract": %q, "amount": "100", "msg": %q}}`, ibcContractAddr.String(), transfer)) + execMsg := wasmtypes.MsgExecuteContract{ + Sender: actorChainA.String(), + Contract: cw20ContractAddr.String(), + Msg: exec, + } + ibcPackageFee := ibcfee.NewFee(oneToken, oneToken, sdk.Coins{}) + feeMsg := ibcfee.NewMsgPayPacketFee(ibcPackageFee, ibcContractPortID, path.EndpointA.ChannelID, actorChainA.String(), nil) + _, err = chainA.SendMsgs(feeMsg, &execMsg) + require.NoError(t, err) + pendingIncentivisedPackages := chainA.App.IBCFeeKeeper.GetIdentifiedPacketFeesForChannel(chainA.GetContext(), ibcContractPortID, path.EndpointA.ChannelID) + assert.Len(t, pendingIncentivisedPackages, 1) + + // and packages relayed + require.NoError(t, coord.RelayAndAckPendingPackets(path)) + + // then + // on chain A + gotCW20Balance, err := chainA.App.WasmKeeper.QuerySmart(chainA.GetContext(), cw20ContractAddr, []byte(fmt.Sprintf(`{"balance":{"address": %q}}`, actorChainA.String()))) + require.NoError(t, err) + assert.JSONEq(t, `{"balance":"99999900"}`, string(gotCW20Balance)) + payeeBalance := chainA.AllBalances(payee) + assert.Equal(t, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2)).String(), payeeBalance.String()) + // and on chain B + pendingIncentivisedPackages = chainA.App.IBCFeeKeeper.GetIdentifiedPacketFeesForChannel(chainA.GetContext(), ibcContractPortID, path.EndpointA.ChannelID) + assert.Len(t, pendingIncentivisedPackages, 0) + expBalance := ibctransfertypes.GetTransferCoin(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, "cw20:"+cw20ContractAddr.String(), sdk.NewInt(100)) + gotBalance := chainB.Balance(actorChainB, expBalance.Denom) + assert.Equal(t, expBalance.String(), gotBalance.String(), chainB.AllBalances(actorChainB)) + + // and with a payee registered for chain B to A + _, err = chainA.SendMsgs(ibcfee.NewMsgRegisterCounterpartyPayee(ibcContractPortID, path.EndpointA.ChannelID, actorChainA.String(), payee.String())) + require.NoError(t, err) + _, err = chainB.SendMsgs(ibcfee.NewMsgRegisterPayee(ibctransfertypes.PortID, path.EndpointB.ChannelID, actorChainB.String(), payee.String())) + require.NoError(t, err) + + // and when sent back from chain B to A + ibcPayloadMsg := ibctransfertypes.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, gotBalance, actorChainB.String(), actorChainA.String(), clienttypes.Height{}, uint64(time.Now().Add(time.Minute).UnixNano())) + ibcPackageFee = ibcfee.NewFee(oneToken, oneToken, sdk.Coins{}) + feeMsg = ibcfee.NewMsgPayPacketFee(ibcPackageFee, ibctransfertypes.PortID, path.EndpointB.ChannelID, actorChainB.String(), nil) + _, err = chainB.SendMsgs(feeMsg, ibcPayloadMsg) + require.NoError(t, err) + pendingIncentivisedPackages = chainB.App.IBCFeeKeeper.GetIdentifiedPacketFeesForChannel(chainB.GetContext(), ibctransfertypes.PortID, path.EndpointB.ChannelID) + assert.Len(t, pendingIncentivisedPackages, 1) + + // when packages relayed + require.NoError(t, coord.RelayAndAckPendingPackets(path)) + + // then + // on chain A + gotCW20Balance, err = chainA.App.WasmKeeper.QuerySmart(chainA.GetContext(), cw20ContractAddr, []byte(fmt.Sprintf(`{"balance":{"address": %q}}`, actorChainA.String()))) + require.NoError(t, err) + assert.JSONEq(t, `{"balance":"100000000"}`, string(gotCW20Balance)) + // and on chain B + payeeBalance = chainB.AllBalances(payee) + assert.Equal(t, sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2)).String(), payeeBalance.String()) +} diff --git a/tests/e2e/testdata/cw20_base.wasm.gz b/tests/e2e/testdata/cw20_base.wasm.gz new file mode 100644 index 0000000000000000000000000000000000000000..7745e80f6db3d5420a9fac311cf3b9de314fac34 GIT binary patch literal 105532 zcmV(@K-Rw>iwFq)6HQ|P17mkGFkfO}b7d}fVRLN&?7e@yUe#GAy4Tu2-*><7Ir}7s z3ypqNbJ^ zm??2mtrfi0No%gAEo$swOKo*hMU6@|TJDIJUgr5e&suA*{hl8=3AFmhgb(N4zt*p3 zJ?mM|dVU5syzMP22myO`d;|;e5p}o8P=DT)D z(e4d5-L&)iJ8!t{)|+mi^89RspHYFg-hS(i^ybHJ4pjZ^EpLCz4Y#{z#oKPa@s96% z)rRR;UVrD!J8%8rACpGL>c=~8zL9#e^ZGm9{^seMe=Hcm>!F)(`o34a>XolGP;cDDv0T0e4hqUl(t(@8bw@02U*t5vP>(b;`$%n(UUNYPzd#fTB}eg z`a4Ybct`&QDy3rdqv%N#MJkE$3CadR-U+CEs;Y&m@T8zWTA6=Rh@YbY^eok_4)v?u zYPYHH=ATBLxENAHMMCA{#Sx8@hNWZs4eCJGxLNvKB{bmCIOs4OR3iVlHf8Rl=?;pb zR~R6VSmlxKO2^VLN-j`c#p71PA(f26B%wRCWGOyKhQd%ssk%e`2K^TkJVugb;civ! z*>fz&cL&v@PkfqxkK#9dOm&jC5QgsjF&*T$-u|{-H{8DKR^Z?No!)%c%{RWCuHLC) zp6K9RDt*hXKe7{V?@^0yy?xisJAe3w8*c`FyzSPv-hTb2;2D+OaNBKfy%C@My=vcd zv%7m<6+3U<@%CGH-u$-fsgdbhZ~qbcdc-}WB|{azbtgS+Uw=KVfE%vA`SzP=y6t_sXtL)Q-7@fRQ;Lyb9Gw% zh5AeNSL#{yb@k?@W4FEK#<$&Z{m!@Ucp&^)wfv;I@ql{2dav64KDA#xfV&T$JO@#qJCL@LXCY={feSCKBczr z{5AFK>Wk`4+rOaxAN5=6^E3hfsD58PsXj*^{I=TuS@oOhg!)zW-_$>-�%=PpIwB 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ˈgGFs=P!zw{CJ+ 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 M0N}#7cTmU#05(?*h5!Hn literal 0 HcmV?d00001 diff --git a/tests/e2e/testdata/cw20_ics20.wasm.gz b/tests/e2e/testdata/cw20_ics20.wasm.gz new file mode 100644 index 0000000000000000000000000000000000000000..07517a2fb5d8f3adf35b32173f2b25763beeeb1b GIT binary patch literal 119250 zcmV(|K+(S+iwFq*6HQ|P17mkGFkfk7b22b4cVTmF0PMXBlwC)4AbP6K_ug|)_i1%Y zYJD*0UX){`@_ey^+UgKZ5QE(aTr60L4ua&Q~G8Jky2w%ca7=|hi6ctiFx9CH; zMia_L9yF196%H2!p`W zfhYg?m8MS{0hR;2tqi;-0k2~Ihd1yI-!L3aY#-qPdSeu*MyOj1YvPCTsA}Ou?5YnX zLqCr3&Qq&a<0or;Uk9H_tL#y`Rt>Q(C_RQ;Wz%I9**7! z4qKGd!JUr?z5}k1V2~r_8wG2wZ}W(bkh#+Gin(=yy2>= zXLjsHdfsszOszjq1I|pfKaZufO>-0`NHcY6=3)v$z731)@dBqhl zZ?C#y$Mx6vD!t;0Yj<3A1I(YBcKEvSC9S+tr4Om;Khp2?zo>rcivR2P_4n05^{c;f z?T+jIk1PMrU%u(>`Y!zreW(6){Vsh#zgz!?eviIe|E7Mg-o5svx2w0Qwfoe5^^!Z( zTh-0KuI^NCe5ZPcx=TIex1U$Py5n*6HT7lnfPeF!sy|VGu5Oy9i<@rxhB~Rfu5S8E z^_05lTk6~DY4y^-QU6&@?|4@ISM@Rd+xohHQva{IX`jAbQ;Co0@2T&p59@zW|ET^> zol=MN@9OUWobdA3^iBKxZ>bm5ZTg35R)1IB^!JKe!A9=UAJjK}Mc?$8{*QVZn)-GB zlm7Jo4VQncPiVORroQQ&>Iwb-=$rpUe@p$T{!jWT{g?W$@agmV2l}7&f7jpF@AKd7 z-{Bwh-|v6Gzv(yp-}XP^-{XJQ|ET}({UiRv{vZ0y|Mz!;fI`Vq{UVnw_1v=MhoAL+UfR^tSTH~oghgBy)9^IFZmaxLT2BC0;;t^Hpt88^ zPH*zOc7RXTwKXCP9;-6k-Bv|VzMyWLYWsx-7}|k9QTV005#DR8%%>I*1qgOd58Hl< zchGBuKqF|rK_3AU7CK)>&1V`QEvDOmB4|OC#Y{(KURnY$_y+;c5hDad>0OY2S!208 z(=8t>TRRPZHX>@aKr3+(uh;9g>Jc1bd09-C!LE)fljHzckbp9?ys6_=_O> zb3yhAWM4q`8D!rD*>^z3>$a|etntTpLB0*dRs}NE4HWcgredfeM=JL5YJ_K*UydS0 zZ}VFGF*aWw-FMt8Lx2t-8>M2Ia$bKCBwHC3D(~7VJ-mYYHhHc5t3+||1n6Tc!e27D zNF+X!5Zt$PYTr=ZM0`YVfe@6XL?qJ1>PrO?>7O?N>pt?f6W&ZGG|bJfm>YuH4zNHznsn44cjFgNLoD8)OZ(SUG;voq>pZoXx10hbO;=^*72fiO3CWvk)>GiCIPT&9eH zLG_dZO1c;D-1WRIP+FD17k6;ikLb8Jz-Z* z;9$bGi(Xj%ga<6|gA$X+X)xJS3Y6nOcyk>c~_E9f)k6@D(x@BNGQAEZ0pF zJUuKZ6c)6WM(af(J21Ej`y%_@w>ij$dVUk`X<~3~;fq8zptrFdaSIXzaQ=YiUfThv zkWc8}qQ~({(7eq%m%k0m@#*q=02y$ZBp;zdFg2@pKfH~mW-RZfOp9;>6>jp*mDw4V zn-SlSdljO?_4>T6dLzo)x?t^s-X!Ow2=?*_kol&L$8gz#OQ0Tyu<%FUM z`ea>yWUhr_L5UA9N0Iq?Fq~LuG*diaRBm&v*hVOZukvYnZv{BLT-%Aa`bkZI$1K1D zWVrzk_X!Uf>(g2VB3rD=7*P*S-$OMkoWVdN`Cj@1ZL9(q;$%Ln zAhuRPqiz*6j9%YBtDu475?iaFF|Sn+bLrTWjzve0tyK`)s$_^`u?phKDyT};tb*9U zAVVBmt01nd0;ff56~uPl28iASM>>*8%QpqkDIglBNx~za;K(QL$OD(gk#F{ne6u$4 z36K2S{C-B+|KDdAu*M+2SDU$prVuC@@Y6*qM>7l!Fe35Ar{Fx+N;L(^RQX4D9{gk= zYOIdr8><3{|FeK{qWyn%QT}7Cvxi3PM}5`EFV5E0$S=eFD?F-OO|{2Ac=k*+D#{9^ z*NG?n*O7*pTQh>KH}+Et?R^;MX?}KQon(WhQ>Ze5*wEKP1c0uj|2WswV*@O)svihw=t60QDbYLp*;vzc(WAxoM&1h27t!}G zW8dSm)OR$WQNKT1y$_bqd$RGUD}VG3bmrs_R>)^t03;{bhG634kBd=AmCo@4a+TKJ z8(~vp5dhTU-=t@Qg^|Smm{Q?h<|29>GA5d~@CW2oYsf?29eM{7~qFL{nPaA_$i@qigPIj&Aiw3vw)jhKODiu+-F0gfsH=fi1PT zzy7s={kpFr1a?;axInAXWS#?X;px2y2)R6T`5c+faPh1sfavl&=Gilz0HVvM%(Ex? z8Tz`Opi8Re1YM#uL+8KzhVtu^loLQJTOA<!!Ia z^8oH1le@L0O2yf`-XFETQEXMd_5j0#K6}4*nnuswQ}yH4PpV-sacD=dR%bMG7|ry( zz8Vm1K(jnf5P9@nr)9>ylhMeN%)!y`fSfu%^Qg1!(3i*SV1(hPK&*E4+BU6ljJ6y2 zGtzG2Pu^C%5Rw)Fmhb8@AQkx8*dD;2ZhNpuc?BgPbgK-ZX%z^7ZTbRoe~?$d1;vqR zmaPkDh}y_aWA?T;kc;`qNKk_YsfrYovJV|_7V#BeGvO=1bCWRUmDUSQ9u{JQh}n(P z#JObTJu+6dm@ydOD$Q=gjkoGD$U;mF5 z76#HrL+OSegi)Lj$fF3>RF+V~OvSAvrH1H5T)T@}v2z!;BIhnZc`J7`%>y$lOx;tN zzl3izO0Gq|QM7hoTK3$J22G3i~36kIf4 zqc2Ai-Rf^IVxHIeM{$wQyI|5sj{r2YrjvjkcjFY?1ee~JX@(4}Ed<5@ATV7@I7!L$ zVyX_1s)Hg$ZWt8FRzHWICi?LLY?cTW>(8iT6FA}4`xgSJ9+pYaVZl-rNK;%BK#&b7 z$pSKEo&}Wm$xx?zBgE|iJyT-}7Mqd9X6*0hidnCNBRN{3gVX+70Ft%(-y7 zBU%R;tvRE0sK^+t4g4g-hhyz!$lr0DxX52a+;V8Ee+uiKMO_(wPpRqrc7*S+g85hs z76bV@xZAHu>#e{$S5ok!mKXuMRRyVIr|YXi0=gOX%Uy) zE+P889`Qj-ajKFg>T)Kqa)#F1J+|Bxvr6QC5wghi9z+QAEr$OiL5fcc&d?=XwxcdZ zz^2iC%g!U1sv#K+^hwB{#K7%SU~TCCgiiva;~^VBcR?&R4XSz2_D>^{N60S9pOavFh)v?LZJz%L9`?r^RHwKFwAuoCex+xHr zPimnF2Y{;(zkdyeSx~1jmI1xXXEm1LQ$NDdFJSD<_^+L|qd#g#zrfMgGWwn~`g4ah zpJrCuGt8aXKIu*~Pv!fVTs=fTis?sWwPN~FhJJ`Q3C&sJP=+|>rH60-#24J(7mVY- z`mFhXzqeiw?+p;m$F&JvIf1J_7;%$7jOr6;4q$>k3KK`~LE_!yJqGjgMx0YYTak-! zllNs+e%}MxRSw7_szv30h&6x?QmFhPjUPU$+V}`0FABWlz{{a(M_j-s51Q(=t^PBL zlo)j*S{da*jh>SB2wZ~7ftSnS5>%7+GANT{J^nm8`#hSw!r(2CM;lT6M&%E@^D~L) z%2e3^Fjl903sB{J8*<<7gN|Sq5X$=q@N5*X?^kWI$Fbg^>>z4}OVAgw?ln-uD#X!I zr|?lOyb`bfgW?hc{Gl{;ioX5=`NU>5*m&^!ykfiSIfX9Au6`B~1;3{-JT7i)EUwTr zM=3fG>yeRoWF#0#wH47Q^5Bi<``Y&vg{)yn28(80dK|^}r90qJijM$H^h3q#J#X@_ zzxA1q9QnPI_dkoeVu?P{621gm8t#Z6a@9WB8K8WrKA_y^rE#Q zEt*+emHT4^A?Z^NM;@7jEm{muWowES8eVJa{TV`FvPdeG=NqU$P8Y$($+y+$j=JMrx4`fK6q(CH*EK%4;vP#s2I$KTO+9*^Uup0kaf#1$gu2ThjI=( z)3F$YF>lhG`5k9Un#V#(2dOkq$U}(113VoMs!jrx;>5#O2Ta9YyNQM=JbE|K8&1Or zpVcQBPmoT`lPH!+6giV9OZiqN5!@yW59swpBE8wq^MG1=JB338?j*`7-t!0E1zD>c zhDut9rCF!^ESGQM^=-~PYT4FK(bsk!#Xa*VlF?|`dDNid7)iu4DaJ8~%D3G?zUt#> zVYVAc{8%V1d11ZhHFU$Oghd0ydUGn%mY122Hxz?Y*#Kgundyr3nYd5@m1$RE8W z7@qg6+Nuv}EM|K5dChT$Kr;c*3=!bNrl{y@w&(+z-7@!SX5IH`tYRaUzfYIT&qu|> zwEUnp{w*x-->0eNrrRkb_VaV4f0zmFPSL z!g>o*%O>v@Ahpa((FNldE4J#V6+5jY9=*D|seX%zugx4x|mFKbPD?NRuD<-Cf+-aZOL%DgV^!|PVoc^%va3@OD` zFjNI`s^xguuCxVJX$#6|3oBAK{Y}YHDmj9et11?^!Zw1q4k{KmAagF2IhV~*6%d;% zL{&)3U}hi;a-GMyt0)Z6bLD%WDWpXvF^`U#kaaz;eD+U1`LXB%qb6h|4o}?i)xY_> zKY!rqnwo&_<;aa4cN(+=PZ!N3C z46Te#s!OdhAa6EQRS(#zsV7e7fF}T$zLfkr!WZ-}nKI66TEbu-w1An?vRcA7t(Gvi z!nySoU>W9EDG3u8cEkG*YQrLyA*Vm2ah5KlHBn@mT^r(U=w*{(!B&+_YdEjbkUlF- z{;X*-?BAp_%+hM>EVTLxN7gK@)p-O7^WTLA2?i%)RTKzr6)?>s@N&fw_;}S3n1_vH z?NQLvhifD&1od)U8UQ&00IZr+?NOX!e7gc}S4!yj^P;IZ7C_7GtD^~6fbW@46F4Lq z0ONOKh1~Nqm0E04PY>&=r-wA42!$XSsE(W*Vns4%IZ3RSbcqEp#_7 z6d-yR!pLIJ$3>t@8Z*)K2%tT^;^&md@`r>DKz#!Xjl!QKB^?xUwoh*?|DL@Ju37d- zO+{CLfV`DstIv3qRJ*pP#^of2u5+ZC^G2$F%Bw`%HDo)Z`x)B0vZkwFP7;B%l3$_~ z7ZGfEuRwbdYWfMUQnR;LTKelMCB0E8>5X0`{V}KXg_Vwe(T_w$4_QS&b%$7fJt{iy zi0gShM@0v+y}(t{#LsgJ(aCPtFl+HGR8eeS1Rm?I5kns_Hs* zRAAJ{aUu-~haj7T7k?SvpfVYF0UG^ehp0Qk+O)7XMbeHiXNV(4N`tswCDQbrv| z*%BzD^OPd@cKOh6!lWE!Eab18R4EhpaayJNqT>B}r#$g`Vht@Dq)@J#=FM*Yq{g@@ z7>*Aer&R+VpKl~&bf>rIg07Nj+?PWUoZ}q9IYu;0yRycnZ4f8PN0tAU4-C%+XM%v} ziO$4@g!TRy2c3*Kd+x^Vj6`8|CfzuE_{Xsuvzcn{l^_E4LBsr4HOFvYx2>>*z}}U> z)BeJn8F*QsBDK)JP;snPXJ#OkL<{gQ^itEgFKVN>1QV>uXdl;tHl7cEzUiI63w}U! z?gCv|yxd7utkKpE{iETH3qvgqq`<2IvFB9Ho(qgU2imYyib7M7Ae8VZoLLec#a!SL zmWmgGAro*g*m7xsufV1Q4OEK;N~W=Lt>TOr?0P`k1yx@PxweDHlnq9$*^{jGJ;sFGM9W zz`!?-d~8X;5XDY5C0Gc9_GlbPs%D8DyU%HUENZ3Si#KNgo_wI1Pxc4bjL0&sx&BE1g{)V z?_%m>fJRHDKGJQ-13M~;uq6&c7Ib@W_!1{tT zyOChZXxvUqk#G|n33o1sxQ&yFI8{U-Uo@>$AQ=QC=J5T6?GU9}!Xp)?rb@OPs0Kq> zjiM=nv_ZsB6QmSc88R()JAsH%&D#Vi3UW-sF)8jYZkYg)&}cqHjDaOaiW8y9pirp7 z=Lsqo0Y=jBex{bJuhNdFNJx`*5jwQlw6uA=FKxD#LYu_Z&;yIQr4(#f{zegQ7>CEv zZB)g{stV$j5?#qLcT_5}P`=U93*F#ROc+Fo=Wic+` z2T=PXJ|!Wr>$yERF4Ri#PZT#?<301~f64GqKq#PV@ zjKaF`^NV@%&|Q#UT=>XcaCaJZP*2`Ai&=rT`Z+Otx_wIFtrC$DaNx$;X%oURDj3j+ zoDsCAIdGn%ojLacc2L`3v{GnJ+jI#OFT7TaB8exKu+m@iwce}uxN=kkGo~4Fh)%PZ zW~{C6_~oXVfk64>f^`Qo!z+x_MT{b3lMGYaCqGg7${ET}(s(TaJ|Gk$_%Dp=0?-_r zd_mn_iE>vqKX~`Mlkl(UTdnD($qNL{!jNt@raz zShaX-2PEueCL)ud5rUzx8=x3!okC`|T_jo+5~tJ4`CCMrh;w7`7*L4)AzcqSl2PX| z2r=ZSrp=TY4-5${VCOgxS}9M^h(KUI805_ZZH!N|D91opiz@0`0NuuyT%;0egy$is z9Pk_%JZr(Ue{8bJ;Y~;2!}v%ivh_@Nz@WM)^ZH>=Gxo4f3TgoCu^@r|)Dp&c68Xim z`TNRlPYXD%mpjkQD&(0%0ZLke^2iwgnky)qz^rhYmUgrS92Xa0h#Kfnl@$SU?n^q; zz5GgBDI+{7umSb4U5E;-q-EO{42+8?hS&x$`%aW|AUooieQ9A|#&!wj?vHzTMCY8# z#w$cRkNaWzu*_e+8nUiY$dG>iDG8% zo7@LbjG8s=l-8tP-6p--Ss!M??aDcOc{&hGM@n{g%#z>R-nsb)Cfp0=z|3<-~psp924NGQ|L zO4z4l0}O>Rus%rr2#O4VFH#g@E7GbOfp5vxl;}GLJd7aHo$g^|N;+i$l;<0&x{|7{ znCqe{Z(+19YYn9?UNQ_XVQ(VTCXbg?8~e$5a5>WD7WSeCY_2wI=Bld9Rc#2Pz>jz$ ztz%mi1BqjHW!zBslgU>9TDG`D*Wv~;ODM5dK&EIyQ+5@v3O7(?g4Zp4Wo8o4FwGK0 zMyxIxWW+Ymtreq6EI#|(EF>5o!c^8=E$bm^IV{B+tEJmv{&R+A{q_E=>I~C5QS6TJ z@DUkM^5u5*0o94fE4NuY#o|k4W8Ior*n(jw&;3US}emjg<*~8@9`7tPug2iIiOx53&sz9%1J1k_021!TpwkHbSQPELoa3%X#MP>b zVT{&R#fbO@F=SH{AsFk5y3ko}I)T_t<~lCfw}}`fzAfg`EtSW90n*NJA)Qwe5EW;F z=GIivLR9X`h6sr`;aqS&`>ziU$>N3$3TfGJ@6g&216HtSEZEVR0+VJC%Ns%;HiJN- zbD-Y~l%Sc*C|K~{Qmxfyw4f<$blOjGqEhiSU+Vci+0tP$O6hY%Jo8)}$2DctLYCSeSCL z!R956rQMB1x%dj08yC=k;cSA5$@6hnmhh-02DuGvT$YM^aVjfAc`+pJjT{GXsArwv z87f8V1lM-7T_l#Rp9#BnEy8v}uR~N9*;(TgUoSnLaf&^ro^^B3XPN|;=4D=zI_j(t zu*Z8zLHvP?#oJUCUG^!v2@zuodF2K<&8@sraSJakeE4pVZUy5leSb))J>~USck^0yYg)IC+QW5X$ z($(X@zkC}Kt-%mRbx>?>(Gfi*>R>228AUvZMEI@)R@R`p1FlsbZ>Z{tX}l$f$pIWaOC#IK zhceFlmh-KQ9@@4x(P1e+SPWqLi{*5aBYzqyKyEIZ1o@4;gj$tK`?Z>KN6zJri~|mN zzwmq`gz63Nsf(B&!Q<^<`V&9OiiYr`jJECexLb(;HnEF0^QFSHhF!NsZi2yy=+>OH?hKX z*|8!&h7yCnLe6}w7&K1^Htgpx_p`|`Ck~DbV#f_)8%4|YW4C$`%fqqJj)gd~oxS@f z9iqLA{pXq&RXlcJWAa=r44#&ReR4fo&m4Ptt!Iul=><4?$rRuTd2}MVru;2#F4EeL z?!f9Aq4>VpyZdEjy}PH81J`aVD_?lwgbbTtmc^LN|>nKuG6(%3A3GMeeY(SG3%7DD}Q7~;j*wu9<|Ne$-xGW zC1vdBY7Nt46H0a&puj=h=K$?KmKDMt*Mz%Sw2v#o7gvNvGttPIx}9aMEb1hE$Sbxi zZcya|akJC7B&@j6B5npi+-P2tP0ZSuF$3!EoJO_Yq^z|!>+H)pAVErZiQ>6m0yXzZ zu+l6WN>hR9aa1+`DTdPNxHdt16ICQ56n>RaN6m+97fnduiv5T} zan}Q1Z1F-oPdWm=5QKJx`SEKLJp@1DV&C98R@^9rzztO<#m-S4zLN!=Os=k@?d)gr~jjH?Qa_o@Qpb5wy>_o@OI?$r}ivdP=r7GEsws?lP|y2?ehS9d)v z{m52bS(u0?b(*k7rak*<=4>1s zpqOM6f~9*L!dOR`_Ux<)ZL7FdQH!uYC_?^j#jE;`@K-GSGbQW$(51%tWOF`aSQtX`{B6)dCrLiLBh{1psE6qTL7Le-=c3JZ;4lM!Y1;qOSt`hk_EuTC7knC=C`+SZW76GgZVj3 z5*`q;lN16~Z7jgp`?$*JnkS=@i#0qp{FK7yX32C7z+qPl=VLL9GO z8^K3vwS#kpLm>Q? zzf9>hK29VgrD%}&qFDcg-PnNA%eWBxbPQo^z#1SFKJ(} zK}o{aHh@^oZ!18;4enPgG(UO(np(^Faik`@yZ&}StuRv48YE5vfiC9{C{=s7mumzZ z^-?oQ^nxada!itNn`dSF+;B=_N~U_YNC0uPf7Gs=hL~x}wL=!p8(<9x;!=UwC!qwt zd6eX%MYhUvj7(%(MOj-#LJL|hp<#sSZJ>}IZD1k8 zc&BxV3*~T`OL)>%@ZnGdJQNCDn)F~fKN#W?4KxW8f(zS_Zf@XRC8ReaK$atY~cMGT;15TjS#e3MV_codcvXX06>l%_096w7SfxopNLKx5s>VzsSo?~#xMB}*qH z57%yJ!8m4*9%xX@?at~UzUtZqvvt$O3hVL{KVL0<;Yz!(mRYSZv0CA%)e0q1WyA|> z!yGqkXqQ>8&@YbR{Pe5Ngj%uJgf@IQ$`4a66-oZ+D|uhe>v@m=<-9a^8E%fpk2C%l zC7)$seaujDRV+Xo2rpTyxFBDGNNr)(r6Oe}o1!8VNvN-~!Jp4n^*vjS>nUekcVgcg zQ$SqkgGB1WU1qJRBB2Kk9U?y*Fw06YMi=k0yU7T0UKEwcA-ntM61HkDWI;RoKA^dC zco=wPY1l4DfvEj$<<+E-o*5WXzWt}=*Yi=g5)N^kj74<$pfJaL#xOn9D*(BF`I^)ycX?FU(JnnzmP-8 z&*OEj3A6H|%&M1SsTO14VzU`ENn^EsNPO&RZC1X5@+l;VnAW(IS@{ae_sohTaSi!e z5GS(UYFEA*n2Wty`HD&4M|Q16YH-$CqH3+hw`(mH`W8l&QJDTnwO}K_EwvJq#7>WJ z@hhg#NUTmCJIhy*t-yCT4w!l@4ziHfqp2Esx|C{)EE^zGmY6~4taOQ4mf`^>#H3R` z++@y5S7=wdOdr!4E?hc5sLx7Mdhw>r%2@Notc+nUgqQ`rE7U#S?qHY7YAJpz8QHKh zGPg3aC7YrM*qniFac^P@3diSz{5<354F>_$ikb8#DFy^+#MLkL|7bq{#v}{mC zAOO6)l28RRpfyHmE1R*uW#^##ua5O~9w=65UXZscZn?L`xzDZez>YNZUT;$dUY%GlySKs&HNmpwdhk zmsCYG zsVxKEf+NhYVG;~Yu7ieUBAlO^_kUK8diR;I97~QkvzrnW5uxCCbZm4wk(rIO326YTg8Kt zF`Nxr-^b^p{Ct3)H)-b^K3~bt2l+W`JB!ac4jVXGqr}TAopH$38Hai(@l>V#+~85b#aTnobB@a-bD^@LWp&Mn*%-mi#<)t7`~VUTr&0N_oFJ) zlRd7>2e;r(!Vck}b-qLf(RoDpyv@U!R7WIfIh`n{Swdfz?`0p=CuD#oPN&vw^HiFD zn&uxKaLb#hap_vlMv+5t<=b&QUg~rZ zE7}|A9McqA#wg>J~aLp(m zkW(I{1D*f_CH7=g&f-`A0Dr-^TEb$_rH)g|{L?xyjSI|_zB%A5a1J=b%-!s{qry*r z{*UjB%pqx*{MtPvP1!@zRCP$2l9rWoNSd-|b%utZ-7|KL6?Ctb=VA>JC&44W(DI>E zLU=Cn8N7>OsB6#PMfILT=yI;KB6nrTT?x4>bCehDpPQz=yqb?apcsITGEMnOC&H)) zH+6P|sk1$9p9pAk4LCmOSJRReec`@biDeFtF*-wK#2=k#nF(kbla0z^}B6I>5zv{p*@`DnUKy+B%?iVnDp2bwZ44 z1v6^O)QF~EU>65);a^;c3GP2&t1;!1*wYH(DUo6-Gbk0}OYn(j&S5u8z9}C_ZXu<0 zHH`PCEQQx#M2=a}9Wx6yMNEl3@T8J_q$*ma{|F>gKABaNDPPw!G_54*y|QWc zm4%}rEJ<^!d{x>s`&FrqF28VxJ?~QkJ(OR(!yY0|g?egJrZzpdwkq*HGPsV3{W`P% zOe{4njD{-IegNY=FA^+$7*JU9OBTTLPf&#or%_gZzOq3x8d#Y?JqT zJOFW3YJqrv9f*~S0%6+#AO@W|-lvh)%9OX!l0R<>J!fY+41c(fmO;!g1ZOr3L>&mZ zPzMJAn>OA$OY1QP6~l|7;yq?O&Yh9*mAS3g>Jzi%L#Uuyc7{+bOZyY;m_<^SqxE^Fr0|*gjC>KK z&`S=14+IfZC^`Cecc8LtQG9$1T`buW2x3?^ItuEsotA_8Y;n}jZA!{H-+b=vq%HTL zzEw5+=-X)(rfRr#h7Gss4S$soN5oc1$+@4Q04aT!U@;SaTEX{cZ||8Y>EiI&PM?eX zmUtoj<}2JPoX`J~P=JAObx_mAK%M&yZ@`Cd)*0?Q_nT)7bfeXfv^Z3PyZm>(L()9M zA!#n51I@)cFqJjYK^2$dGpN92G+Qv1ZSahz@89hgPVVSkXE1|peYe*Im|7HDZ)4&d ztSfJqbNIvS#bf~Gt;u#wrwQ7PRo-w}Jm)X)ebKZ^6RN^RQ3O+gp^|Y$C&%{*yB0LUXsU`*F0p;T(Dog*=u?RNgtd{1R8(5~=(+tu2IJMV z3>JX7pv;!zt%bfpIW+&vWedF=5)A^QO(<^*Fi^6L$Fo6x>EU4GAa$CSD77(26ER3D zRaZNzZc~&~vf%LrTJXK4zW1#^{ur6=^g&NaWlHKkB}J{(mECUTPKFZ4SK7D6h%Vpr z4w@UE)U3ku!*{d4>65Y=!w=u_4q_9Z)YahW@`o%(KFR305+k?fB_$hpq)R*#n}ZNN zcP3r{=*2|TMdS`lR8^5JK&ng=7qXo)NBsGHpX$C(Rllbx$4d3Ejx6T6H6Ot2=eoQt zd(E7=uFia}pCtke4H-pq$*7Z&*4_0yB*F~ZDZe~h*?4@zq=O_v$2s3%;u zS;V3?Ql6(dqZFj+5~yM6V|hUqB9+WPmj2?+%~LU*NjQJSEOD&-VVF0%K^nkY6S1^| z%7XoYSDDd()QY8!O-tA~*rm@=Bsg5m(nhlUGBZ&ZF!iCQEerxj0o)Kj0~4_0X;5eG zX{b93^yxYaw2)kE%==`nc|ZBxuRQYC@BN2A|McIJ>xoaDtruUqcc9Kj8*|ubSbpOj zw6^B5(NJ8+H8vWSe>#_qhUFibFVm%s4u#8y>>z~#1!g#&;S3)vl8dKcthrlNT!AY)QQ&Y){sTenq@FqHI?-D9rH+!vSmh{UG*?g@od#Yktc z_k_YhI-#(wB-BLWbk}+56OqZ(cfxgg_MQeASjvm)lvg{?kv)}_%RHL*G{}HU2d1={ zV1cE)%KNUw``%#E3CgA+ovIWd=;-aoz4aauo}zW7+b!#)LIyDLfd-ZqgNha%Ff1(w zt`8L5loK-r?`P{Mae=aKHeroGoWity={(uPt;pG`@J!Ek%sG6gBrP5KIm61&$@SL7 zQ%%5FE!nVnGq-Ui2-lYo5)7lH!ystQgCL>A4+0Jy)hkHw$TMa8*StbAw`|5RvzoDvTCbw%&O2#f~fDT`uOcuAwiwE{8W8bML(HU&dm8Q?;y`yzgcCb(=YsFI-UM>`UkDG zO(z@iY)a@*dpn+rmfw^tztPdo)0WIbwE?6!AZJt%i_!k)clyeIF&S#3 zMKaWKa%Q#8<2|#qT!Ik{f{*gy|ArgsM+*hTbqgLmK@Sp9Df4?txi{xwV?pYS{rqA1 zT$OKy7wh0l%vnY?VxCFL6QF2ZIFo=>iYyiL7tfnHH|mo)H?hG-b28_4+;q8kd4@T2 z|2fotB~EM7K~VlBpia{r-cJkP(*O1K@m;_%>q#{exE3qz(&CYi^RF8 zh2H+lL|FVO9u4#tRfGk@G*2{0*c%NJQZ$G}Wiao5dZpq0)iE1H^rx{>UAC-%m`~Z_@}o5Aq=VgB2RE8}yVK=kG#N0rEsN(Prq$BWgpB!X!!<)g+@np;v$!BT2UjD+ms7;W-4;{1;1D9ev)dq|i2 zkXTdKS`bUup-Ycbei~IeTtJsKpavBH=UHOeY^5wcfndqRV8F-dm4UFA|6Xd5~eaK4%?rbGGFGL7;6`IU#7P0%=Q+ z(0U!TcR{s>fnHSGJuJDJ^w~tNPu4loWq5ij&TFRE38B}Mz4SV^)!$BtgyA`cxhYq1 zqxmFnAVbXZ0b}gH!NIimxqAQ^JAss(MkeGwGF_Oh`VPHMz!>P({PfOy4eoI1Jv8(l z)dwar0}~-xM(&72hTg+D9?j78Xr5M$+ql94oi6ukQ+0^PeQNyaq7n+f>k#jR^w9Bh zF3^;vs@@i@pEINb9bJMB(L+t{%3>iuC!G{JPr(KJoFUWk*Ob{_wqXA10P|P-_^R-0 z`K$e7lLyqEPBdBU-;Noqp@&CkTYNzIt0ikS-qVM#(IfQ?)~YzI4AzPul7s+qh@P9l z`hKnay`|)WE+cWx;&Kcw-5j{HTDmFky3?-f__P|~T}ZiCs7NrCVd{OND)Qzk&c4}U zt%-sMXp|{4c>dF5CemIg+444m;7Q;GylcVZ(Ve(v5n*~uLpiE0<)X;dk z=?nuvV5UT>(rQdj`jxv$5fM z&OFVhE}H}poX7xk8c7~bUJUih4HVeH=BT zFd|h0j5I167iSS+ZPL3GL&kAWeo{ooZtcWHav5ekr|P7BJcvl8{zSck(0mjfgGQQr zZlw)N%A9qAUj8EHQz_|uUCmvRtF)9G%nDVi)G%pcE|{H=4{-D>)%)xHQAt%xtBXV1 zyq^KoJ?c%<(bfe8InjD!`7@M4*qkShD~});h%xcKl|9KJMy`93R^?M**z&FWl;;B%xDYPk2Ic5=Db4DgzbEQW0mU zBw~{2Y*Z?TLN^SbHlW5hzkZHqltNCY%2!O6ANhc@)C_jop$|9#9iV32?cR@0mv_1M z`E`(@lSpNIM97jkBq=ll6QsV3oV?EBJ$!w&YGpXn$2J`Ltj~N5}eRwHLm{E#AhXxxLf6^ou>w{`lpHj)7J1I=SmJ7t~fR) zQl?XKDe)n02FGI@+GbT*lHZS+3~g9qBlC+c;~NL2{5gV;v$F9aK|nawrgNW9b_K0d zRaz&m14mZfq+@3yK28H4@;=$>0qt}C1Z9|uSi6i^yNn#|l9otGyNp=7jEr^})wE0e zj zBxzP6>u~N8haQ;*ns1aNGo1zoI;iQCNVG-Vusrw?y+-zQ2KZb)kN^WmI<$5Tot`Q+>TH^nHRMLX`cvRe7zQ6wkcz*1x|2#zqVk6T zKj?-n>WI1#X$iaK-`Jt7rZLnNa$a1yqzIJ2Y9So4(B#)%3mS0YIn^{B zMu15cf#is<;l}B=`$nt7QKYr>6QJIf?egKfj(ho?K7Us}iFa>UJc}6o|Fm(wsCG<4MWzq+lvGD;oIyYcLd)GHRev(JIo@ zH7XD+X1k$lR6t{*_=z`)WH;%wJ8}G*paHK&-hq8=AVB?wzQ#fJa!&$0L=^kd=wTl? z-4WT19&V8^w{Td6HOJDxx!D712DbBJRT~ zVqq0cl2jF|h)#o5G_eQGAA432GpitJ0{kLcBCCihRx#?Zio&pp#uO1u536YPvWi4l z#n^N&tB9A#D&mS&ybu~zVMV4Qk;%Oqna=W2SytZn6IuBaS$T%C@<|0sw{PNa zf^{6{2#V!)bm~a(Bl?u#C$9`Xyd9-;kOQ)O;D_dMK28B{xVIGd_4s4JsNtu(oy}tO zJ<72|)-8+Sa(q9jC~6X|?}Va-jHi|iIcRY$8I#6VndCaaGWHWnZql+EaUkms-x|>I z-hj@0(?%7bII?>%)n3c#k7v$TF_U|o&Dd3r8S9mlX2s*6M>0}p57=ZGWTZa#uDX$W z%DsQ)U3DY%{a~aX@M}gY?+ty-Ge#-pz~#drB)cac4`9xH_c2F1pZ$*Mo_$l;u}S$H znvKM1#X9Bl=afAFhL756^YPsnYJ6Bv^Rc~}Q?^X%cGK?-ys|Ng#pxeGGtcocd<2b? z=Xs$cXyot`@w?19ac-z~;+(X5P*;c09M!Dw-J{teK1?X->O-10XdTo&C(ecC;LL#U zVWMXM?;H052@TpK=T!ObWAI?8I&zMYhrFSDY|fE$R8y$JT1|51oKuxKbM7{6&YZhT z+jQvrwRkq@%(;EozXLFE5$&lH2ZtOUcaUH)En#B*C+WbNdvxtQu|s;RenQZDAG*m4 zIj`g>?kkw|K%_PK92zW;ZS@bMN_|4fo?|)m;DoA9Jvcz`o^+32TMtca_4o5=bIKv% z2aVO*!DjobraxQrq6; zofej3)|6Tf)Z{dSElw|(*M>K+!|R-8hXV$Z)7b7Z#ctE+Uv6zDFV6|(j)|Nf@f?A5 z!0ii;Goj=Zk>@^4W(;hiiHG|rOVgAkevjc^fF66gcT&x@WX@4djrtKkT-PJIssotH zBpwt((DCb6@Y{?O6__mvXcqJmw?@${asO zW7f3i_dKDPGtSz+Vr{d!N-90iMo=z(NOlI+;3r@I!V`hEYREXroZLW&qaJ1E96((= z2T;`yV4x(!t13qw5#xFoOqULyQ#E*>AZU5+JXJfo@T44FxSwd@330_Sfgh;NGWY~3 zS#ZrC+1GjtAb>wRp|(PI*;|Jas$9j0vdJ1_igNGjb6tN|A^TKjV1;0)2!FW~%m@hlBF6UB(}f z)9+bw2;QY?K0iDraVPCHCI$mvL&KZATXE4HZmxytNN%~yJN{O^j$C)_mJ>C>XSdu_ z3%TXEdTySN>U5(9B3X3V$!^Q}p%kYkwfAh@bGdV?e<6bVdiGpiF1|lJc&p~Qyl|^O ztEdwlWk!@>$|uQdNe)xwdZcd^-`UTKQ0KDOm+vjou)*6&PeETr4}`uu?s@ ztl0@iuO-!EfTB3zBi`A6%{M^7A1AvY0TmnUFXCW{yXKwXPW5@BKS~u!@Ik_xd%mhw zqjnf%&c3fIP-YZYyk}6SmxPxWOEO5_k?wd*e8;AZXw?|)9PV zy_S*KOj886>vS;7=++pz(-=dzNfwQ!%8bIqp8Je>^zQ@hvjK5HPBxWEjjQHe%9eq)3udbJn$Lr!6>#$fsoT%ecK3>zP=thK zc_Fd95LsR*EH7l1hu;CqOOWM-!tyk_`-~CNb_JoKlf=-;ypr)W<)UPvI1Rz4=NEj+2)@7-d`JZ_ zooiBW9xBjFl6q%bs>!K}eWhA3N2-N&sn)Qg+!POl9p%uDGLJWDpp{hn9gHTKXY-LH zuiz7(Fn;-el`w$8-iL}GN;p;9*BmfH+@2#-g(D@BIxRr z7qqBh`mu1BJ?Cbiun;m2|dA&663RiKacaH20udm0OL{c z5%opkv^}@Ookvh2o)(zA--aV4HV~;{*Swo{BBfgmTC*w=MwAxkAR+9h ztDT5-gtgP`l*LCeKN`VD>_qIaCP5xtp4t?fSy+%qEy%eA+0Jf`eZi4y%^f+;pYlBg z5$DVnd8bx8;AdNJOv8{fd zva=hkB?r8s0xxjE^BKJ0M*v>8FL;H7$YO{v+6kiF6w~=LRB4MzGie89!D_sRAx5;- zeJ%ft7IZk+2s8McBTrjMD@2$k2#EILhwN7`EdMuAmsC4md}=XX*P55tWiGG#AC%j* z7UXsr`M&;@_*`}1pr+Nytj6emEi~hXr;YKr(O{r(a!0V$4$KJBz~C@;TAb!4%uE9Ckm-^x|+3=?dfV|C`JoG9YFVAO(1f7qKp1$F8XCeP${yugbau=BxsmVZ$NM+ zw)kXKlN~~lieFC;(L?RgTxyT!QhPF&+GPSz0Oz?q^uM_yD$$Fi|FD<-TfNdgFb90O zGKWut`A@zMmNJ=xK!b_UV6#6BCWZ!ETlKk2gX2tto8hO4X9ExoZf6?2kZL3v ze9WamL`Ox27cv=M!eqFa$#6`_Fmx6P`%oj(AVyafsiW#fR@IH?=nJeZ;0k0-fD66( zmfmW@p2(}&OI|1El9z{AsB6!W)t=)8)snD}TGDrbIY99XAo=r|(t0M??`!k@CVY@Ns#y>v?=? z4@G3RXvOupS!pZ-)0mcA>8r1N?IZC8nJy`6Tj61S|MZnFe(cX5|BL&-O(!Y(EWYo> z(lMW;h>Oc*h#pG@2-PRtCh$9b;0k93hIHryWB^;p|7ZmmTl)5s@4o%N9s9tipT(UG z2F~grY6EBaFg}tK9~sW_5qmhV1rZOWE_5A4U4ckD89o%6-BIYX@~cEpdZHYWokA4g zkx!S0K5B#aF+QZc`=d6LAt>*%H+EAJ>9n{j>7I`|yOIu9wO|N<*(XGcd?AHhP2P9b^i+*Mz_W~Ul0#y`VJaBsmCzgs1Z+qGF>mXc$1s`+*`>4TEs{YXbn z##vxBDNJb$NVkrv#X|;YuBXj+{jCeZO$(YHZy2dOarB-%aXx$EeB+7pYo0itH;$ku zj<=nZUqXND2*YGT<9&9tS@pmdyTvFDzC`?xf*`B?DRCL{;PXl*aGF&fS%@9{W2{EN z(kJ}%+gho;Y(8qX&AoN?Bw4y^asu(eF?ishD2TX~25g`5z$Z8h87Mt$@MuaHhK7(w zJ8-&mHNsmO33SX%7WA#`>5rdLWxiA<`-M*4&!Mcy>8aX>rP`{5UZlj`b4sX1N<4pm zPl=S202qK44*=l&`^eGy;+!$v;&ZAiv`F12?l)-JDri|8Cq3{!&xa1i&rnRl={5KCg0qmDgSsb_ZVmdElCI z`mo)mmw$oM9tI$pD1GA()kW$4e|2CGk{8tZ>HiMn>Z}(Q9;)n`>!46dKCv;cb`kn^ z8@!(op_g|bI?i#K`2k;6+tS<7TTYU^t3dZaWFM3iVo%z@X`+^DwJ6h;7`&qX-(lY;UyOgtQE~!Nq>0DZ@8Ow?2j-)?Ph^s#-I+z38M#b=zZ*^!d_C1 zg)B$FWw;yq81NP`(v$$jnlSVto65PVk)Eb}Zpxp3z}GUCEfA~<+gL;@GyufsrRIyN z%r`CBx<_r@BTn7x?9;+|`lwemIWc3KT(}nYESPHSuGkusMm$+K0~gNVbm81+31Rb# z9i5GB@dnQ`I@&_iA@{NEfhRGz|I#qhvVSPc{#qJ4w;H$c=`$U-#Xk3HJp{|u@FI_r z-O8>YW*G;RVMb(CrSDdTNpb_8b!VX!tSU}+w)kU<*;wAo#w>qKKm0#2-=3%9u24By zMp%H9RBVW)}V0-9URxN0gr-gmG)_J{JfYWVJ(AmX^JWmeb{49~w-5)|rt46s)f^@QGko`w>1ukF>KaK)o;#cNHe>N$w_ z${A91*@gnxPFBEFRZ(N34vbwv02>7hexq7?K9Hz^b>{BPo}nD7YRsvM z!RRqBL&@`#)$=FZ=TBG9pR&)>^X4a)uTX^c{^poUV?2|VoDrhGAeZ|T=W}p>$I$b!66D(7!k6pURf`uP-y8h5m!zJ zDI#D#AdQJsjmccC(CsD}Avc zNeati1U1O3ip%(T*Q7;R)G_IJBt1dmz-7s#zfvg;)z%+=P{>he_Q9x=`o`z9 zM!eNX9t755X`mX%O+q+ncy|>gGok$$iOiJ%w6ns@K`qEF75U&Xydq#v7&dm8T%G@< z&B)CD3y#c*+Q@9@k$KMR#n>sY2W5zZ?YLe~=&c3@-Qi|nx;+C^)RF4Dj^GOG<1W(2 zY7KVJBGP%i`E9;R(DQZQA}F^uIUzr{$ZuKX*Ft?87S~M&*SOfwD4K%nS;fdcYBugz zG#sWU`&F&)vudkb5<+)ZPn7!nOlC@L7V(TY)jK1e>75Zz^$yL+-WlOe zk)&rd5y%O;%6Ap!V8l5C5mW;q2f*A%1M!ZaJ`m!$oKuS(5ir)B5z%KhA`O`WJR(hZMD&lzh*bH_e5cQ1ylM&Lb{&Z$mhy8;`7Mj} zMC2s15MMIa5gc?bB>IURI6TTMD|D+FX$sK9YK7*cMnVe*gI*c6L~4jF)QN?m?03 zD{BsAjMpdwcjp_*pw?3>BfsnS%E*6F$~aM@jO|Prr!6ci!a!k}y24VQzLbnkUrPRn z2YtL}%*Xn2gKlliyZy$TMfBe&UYwekro|~w@3EPOtE8AFT&Cy=pD{@>op2ge!N#$0 zbc1`k`ItBi-1SG%@r>t6X<7!u)1)*e3*m5aT!zH7>Q74AAx*AnO50CctufQxZ9elg zjGyKGZY|Qo3rV0270KpW&AIOe?aJkyYIW(Qf2R3_uH0ms+AGTjv+A{E(|TLzB&^x| zB2uzuXM@+$c}uGNg&X0cUE90?x@*0;dQUbX+yqm0p>$rxRj zRM7;VKaJrnoWj~^D>Jnpr?yHh=(HaU(%rH*m#6vyV_~hJ3oxce8Nk>6puQHruapbja+%;z|w8O%*yD1pX5t5RCi;gE6M7T+@G z(gvsvrZ%SBY%NN^`r`96cbAx^x%(r}(hQyPZD)Mb85q`jXEb&upjSbyGeO_Z_>`K- zx1I6PP1VyGpE~19XMFCA?{>y_I^#Q?37pROZfBm?JYi;K_iM&z8K#*Dy&?;Ji(5QoS=@ie{wvsTewiE-L{*(DAe()I?7)(mM&1G3hzq+GWl z#yw6r8$~B(Y}_ViG0%UCf(&s}!~{oTkJz9_v!7y%$tb=~IJt%JNf*NNsQrl<15-jt zc?ps+hNSC2(w*)DiDF2)b0IOQo>JbRN?Vd8f-~$B`F%&IL*7hROT`>;k_eBZZ~{qi z*a_WK%;Aeq#oT^v!0DZ63pXX+Zd6H`1BwZrH%W7_-XERxE-hjTmdD%t)=slXF2h&? zxGOp-$}%1_8!dvQYzZMxrT(msba?Q`g+eGc8U&jAG;;qIkPUeYJ+b8fW`-)bQ?4Rm7( zX`tuJ0e$a>|7CMP|L3kgXK#XJcuJY10!Jk(urtJ&XC@r+GGQX{jw+LdMw1OSglTB> zChwp*w|A5Genp9^G`#ym)T9p3XAi*`wO3&k2QUpY6}lS>ZS(HItxm}neHcjtjjM#R zS>YG^6(zGuR^!dv6$KQWq)^HBAcKsT@D@$Yc5_mwe3f~Wd?j()FSl>O`k>Lo0QfthTYd721=0BbGTyWzNq=Q%r>Tr0Nuyz!8V8eA@J;I092&zJ}K$+LP*1O9%+L3xfhaJt%ND5$?eXZf#H}cw1__Yb!Lpg5S_F zevI6d3Bsx5!CIeJr$t84V#6}dOKo_yX;`C&A^&;Pc&oQfnnKlhV__KT1`sIGv*7ak2HIr`PqBru8Ar*;cV?iOt|zYyh{ZrOKUe^!XgRpAt)0 z9++*^E8uD+UD=7zJ1Go{Ct8=G|oUg{Gi*$?Gb+^uLzUo-N#!p+1#>=c$ zQScRv*3a-2&BE2GGj*BioU}}5{>iJVN%)(}(4s%zEUe)cSRoK(niBsEQ;{?;6-kpz z9Vs1V*VV^W`z84MuxhUm;$A65&XFR^r3leD7g-}khNZ}e6j>`pmPwI}j;kXP@-vel zM)+9fqYft%4ooL}of1KckfSWSLDJ)S?GR)cN@Seo_~u5`QYf3Gk8km)QW3PzP#q7E zFy2X6LBfHCuIAWDo)R_hcbi>M zYj~LUl$eL{z4)}jPdWKwAe&gu*07o^9RkCYD^($O6FFLPWfl4{XIw6{nH+tZbDO-2B$H!p zU>>Q_JZ5t2@G-so`e#M`Q!;1P!JO&vahd?@tBg>8kgnV7*l!i_ftR;?D_!+P2cy%>*kq1dtxV>4X z?PgL3`OL_%P9QaOsfGwI*8^M;&e{mtdKtFo_nWhI`={^hjhxxLD&t@UGa#b~VM{PTZ&7hjQQP12}^|_m^ zG}APi8SsMvJ>X8#h@O&jq4dfYb;V zou?GX_Ok6+Tol{+s9I40q?R77{()+`@ytUZ(gV$<8QA_W13lNy_3zzgRM!4;-GMo4 zAfHf|+PN-o7MbhH&h;T9p@Y5>nsj_CqK%GUlhHw?C|kuaoevE>mOQD?R;$5MTOD*% zHo@^?kr*IIqRu8GRM^HX~L8}wA%Gd4ZYUO@uW(jH$8O?AOK)R zPZa}GyP(0E(dLoShEblYrivE5cMQD>zI>`^fH}I0qDoWaVBF$*7jro-j87Ib6t|TD zK1Hj&f2C~JSYDn}l;53oAsz$vb)oi35s)Ou=y0De@M0~mQfpbS_6u!ytY})wrxTDd z`6W4Q$)RQSxYg~ma6W%_mU&_lv zC#*9S!(q^usw!V<-Pef6;DRb4df+&p1Yp!0M#-zikE*PCL#h8!r9p&{o>QVivdz02 zU8n%)0mW)hP2&Nw!nu;BM)4tTjn;arATKUnj<1RsrRpqemSTed!*tRS$zriob`%pM8*ht*hAA3YaajVmQB=xh3EF z`PDr2GUID~P-QR0-_O*1t1;qrKyq!BM?W-jxgyhqvTa@gUV zhu9Yyvtv$bkW3V(R|8>jZAz$aplfRY^%YYk=BOyM)2OmydaF~+3#{3RcCaSN4_fim zDn`ZG(ZX3c+T-kau#(~rifF=vw#r8_214P;mQ;K>^H)!~}PYQB8VxXv`CpUC<0JH}teo{}NH zeA;;2*jsWAUp{I4Wtx0zFXhV<#t#Sc>lNNR)z5oxNB$MjYS4bX9N407#Z1wdNKB(6 z?Q-~8u|;13KLxIRX>`t=$LmIBElP=!bx<6iffeJ2TrqynJdRH~3H?^~wmn#RGyRsK zA$Bej4YBV~7pt}a6~Uv&$eTIr%&rers_{Zo3Py(colF>38Kn*(xzm`TqC!yw03Fo+ zxJRKQ;z?YdiW>h?(WjOPgIgh_QwZs-lo}IKH>t==q{xsI8IdCANRj1IB(+_TDQv{u zLC5dWqc-P`>mwlkI0WC4jb8{WZ;Dq$Dt@2hRmV(gS#+E-6D9wQcDP2SKuPTL;(R$U znqD4uG%Dyq$Suuz8l-jk@IJ+jALPan3KR{t?@ntOX(Ut;+$V1)MGi(153XuEBZ*&S zwkLnk2jFx*(E1c1+j`EoJ}tb%%=>LZ;)hh3@7^^ZK={QWyO!Bo7Y?AfFz|#9sKzLx z$|$1|>+}!SSo(v`qFKvbG;8&+bVlVS!{W4|^t6}Pv0GQ>Ns8wlkq^5`+>$In@h~@YY_Ll66Vr3u)`vDluVi~_* zh8p+^vt^$Y>Xg~18G}bF?snYaZV$^aprkHVlhyM7vG?{tb{*G!;OqPK-kbN{%$>mi z7<`br?{X*)MIwR{3K&4N3U5k7O0m6$6qdtO=?}R|f6zl!N>s7D%*GNSnYJMt*}w^G z!wxNtEhL0(Qig1l10}RPlCc|j!=#W}Ru)NUFSf#}zzJ)OILIy>)9XFI-#Oj4-+T}N z^_f(t66W51_x9~RefoU$`Iz)-N?SA)(^I;p+7y)x>yamyO}SC^WjZK7sN=^z!XRaU za=RnM23Cy&MdR6)M|o2fPPDC4(fO@(Yegr@WAx2XdQA2nz*^UBv2fKt#aWuxpX$e6d<_-I7^P0^%C~vdoraP95 z>gCiI!P&}7>#8rUr|p>zKhq8QC(f3nvr@z56ZQ6(AL2eP9kY&Ry0lD~iX`=!1}J5G z2oB5Hh`z`f{L?CWCe;aDv_{ANiMpp{T6686p=^_UqM}zfpnG33uZcnBJBg-b?Wj}I z$n|ubbOVACb^4#sS1n_2DOIk?WkeT`X#%n+JpML9~|Eu5l)&$Xx%!iLN<70Gw!E+WnW$cof}o?buD6yEE>_*0Aa3TfTiGX{p8o@!=ZVRQEOkjC|K+WM`EQ@~Qcvy)BysA@ z7uW3UF!N-ujrKoyHV{a7|NrV2?Up!`<1u#oJD)|giKnlbr@Kg5d;Jf7?+fjR2dR?R zFMZKJh^Z8KFpbFTn)W|VUcI057KHXsCz75Pz(78KHCLPcIo`1A?a*Q6gB^Nb>%nS^ zLv}McXWrzDllELqL&FKROk|%Jc9xRi!0gPQN;WxlH*0R87UjZD+;cl^pXNa`Pui!q zJZU$p!n8LW_qMhW>w&6ShZP7-C0m9c#>eit2B-(;9B(duT=D&*dQAKgwH<$0O?r>< zETt(wTY&H+EmWUPL3RG^AAI=>&wugCmyj{oX?;$u4dqMF8ssWCFI;?aZL9)qZk^>D zIx`X$bw(czL70)&prrz+XF2MVqJDcYyuDBDbwk1WP9RKe^DA!AOr^y}#8pc+`kTOE`KX&yj2Y6aKr5sJPR5I`Y)Qgh!Y6d?f+=&E@oq$8%kfDT+u z3zr*cT#BIaKJ{9`AUqf&)5v2RtYqsfWYr{&ar;wxVdQWR%6j^XUpQS=`2}C?T0b6>ni(S%0M=07drYPnb=tF^&_%8w zA2XvIse{)-C-!FStaqVq1uM#9W<>e0+E5zA_GUL`pyGe5_ zsOQ1q&`{5Jx%99&gxaZ_oQpO_gMmK}r7m**+b%JQB9J(>5`6V1jfpMaftaiB=j-18 z_RG0vUbs^kDZFt@8R;wE_EqaNtM<#E2^^stJfSGB{?spi`A>v%yqT2imoDl=mu`J0 z-}3c4|Cu{ozwpK_*YCo&ef=gP-Ewph1D}ZZ-9P`#+O4c}6Onou_h37(>ET>6?g<#o+`iVm17>zP*Q)pW^qu_9d#r>fov<#Z7+Sq(%Gs-^@>SXWoD0s)m>+J;3u zO3J^RR$ZV#f-01~MdsZ$f=CgMom7GwZlxAfD1m-e z?*sDB zbbeVKW)kM;sMCj^)PT{$t$TfcSkfv%mub(hMzL`&=#;*lHXOqS$IF+`6T}8hjtX|NW2#$KVRZum@bV;>RcfB;xJnplz)KtuB?t z@grpcBU`%6vCuo4CH-eKO-H7wu;8KKP~ff2MXB8rbvBy&>vdj@T^tH^B-h0bH8 z5Cw8ejq{+xvPauH4gSxI&=L360?PD$Q?~yCyZ>%R7K%YD%TTn#cfpj!s>!~rg zO(6XQo_}vL+f%ze;^+re=g#8jby()$=Ch1dYBkqNd3_>1K;71W(YY0&{X9+3?8#a3 zOseg=04RjB8#w`Z$~s9JgsUl@26$Sf26`dBQwMpKL3>G}yL+SqpX@dVe9?wgwOhL)v8Pq zS=z}FUnaf{vdBW@xRS+gH)%@RRi`ZVi4Mz40_zJTDrp0zopoj6+o4Q+p>G%d?V_h| z6jmm_4c8Lu%F4tS%(%f6U*+`rw?ditHWY0?2E**a%EY77WaGQOOgw*PmX%EXHggTa z;bBmnmcOOSPma7pbio(h29%679v?+obYkej$C#n#&qe#gPv`@d69&wiq@w9wk_L_m z)4e2??j;H7UJ{HjH7Kq#eifE0H0q78y`BF4lukrCzhv~|f1gUhZ?fvwQ4Kglm$%#7 z;ij{KNL$VXD8*e3=(lV2IA0yFGydqobiq`>uX8q^!E7>_O|({TeL@Ke9T`}16mNg* zaO-=ulKi7gi@~Ru-eU93x3JHC zW39C9*h*WNm9`tKv`BfGFD1kB)*iuTTkWX5w&NqD%wD^LhBVr1cihTeyW@83wcFp^ zo4459Je#UzsH2vlLM=mTwHkm^4b-@K?>j+cdeF#q87H@}n3mq~)QQ?F}q;-yaKAN!C-jWAap+*mh#5X zYR4=02SenzH8~D;za48b+;wxVWPf=uqju$)UbA|1|LlAFc&D+CtEn7bpx!>7se_m; zu#NK_o2;r|a#e_JP!FuY}UriRv}F|^t`+Z;55SZ;CPA01BVp6coIxmv-uvi0845Vp4Umf`D@ z`t`oqdbOL^numdD-Z)*1TY`%%EWz2hCAb*31m`^y$~QOmmuBpzy|^FQi}Pg!)}R>p ztA2OKi{O$)C9%?p+eJ7mMisyS~^mz`Z87i z5Ax%6rZg^u2 z2#+0*GH)V^LjGQN%(q!o+YY8BlR6;)vu$ru)z5Tjbb6v|mMSAUARW#C2Vs{`LUQy* zaO)PC=sp?W!F0`4I~Wpb1}+a&8p2r2Qnj4it2miS!I@8t9|i%+(CIZlwBsMz0)$T;X9+`qZpk`n&ON?J7z+e#vOqsZu9l4M=@EvopBZM=Zk1u zdHh3;aXn~*sV9)lV>>=sfYfos^#G0Av~hk#(WLI6arU6D;^-#w1)^mJbppA@mHs$- zHnB+*qZ4wuebf0AnEMTcEXJeWDss-s1prI3OFrSYi_0dprP{) zuRsY(^OSn}fP6?WkI4i0R{2R4NvmdcWag<(QddtVoz69T#ny6LSj5?|h%;dkcZ^NC zZ#6G;CpA%p3F{CuFEvvvGsGU< z!)d80wNTlu-uBB7AV$`jL93+V-fxu|r!_HG>Mt$NosT z>u_{N{**r@^Bi49!`{((-!R(133B;}tmTiUy0QYMN2|h9nghux zR|Pz0R2>%TB-DnZihBlFcsAa^R8KN>>~(!mSiynhSYjVi4EQu9S?UGCq0&(J3g913 ziy|FXmxjODw7N*eG8 zMhfv|f`g~tWtR_`*ik^$uq#vzH`i?4OxxgziaiBP)ySIyg4BZ~xk7G{NwFZ0shdo^ zRpBebQdh+yXllKNV)94tbDhVndl_e@5D7dNw63tbmj(oUFgk!w} zeN6s{u=cq8j;iYrTgva3zYuJ?Fc&SdYNRh9v9zzk^lrJ-l=Z?% z+m^e0xKl1QY58y#2@*dpsQwHt95L%e_H?xMgh;2` zt8GVXw}-Dlrl|+gxU;erxt`_q)4ZPH_2UW(8R%TKtNf)zC*0g1ac8HRFcjkmo<`l{ zb~Ug(^=x|_dC8qF28cLjU;Y3l{J0=%Uqep?fS}~r`2J7H@`v%xK zK89q_Z6;7v&yhAWX~rXZKlTi-771o91|KMqh}U5pNam>ZKS?rVQZ9RDG?UA-o|d&i z%ec;SvVa|YrfvDLVId9dp%ZvKTqwvqm{ArpU?t`t&viyKPzUAa(GUf0e%&H97Ncv( za*I;k+*+b;{lf$gpM*nPfvZy@?i|;>cRJOG!V{@IEzB*A3{`V5RO!pb*b`@=F6Fe@ zh}=47&$P#$`A2X`?og_zC&DwGv1hbez1$pmq8|8XNKKyQGtZ@CGUBQ9ppX=(n4|`H z{5TI|PNcAX$?eT#Ssk$o<}fQpr;^69Q!p0-DeH07JW6$_}PiWLQhbObNS$n+~C-@*p+izB+vsAh_hmj?8!({iCi&OE$c( zc&-AYfd8lt>lE&o-aoN{KF5};QOg;&T#H&>V9WKW2_gZ*``>MI0!~I-yU*f)8iM4hwM$526_}f(w z7$I@p(Qj(n$PZK?iMBZhE!#5c2CPfATsh|R<>!nDb>(v)T25)+Nvj6u@i2;Sp`LO&(xm2%r2D-&8E#~I zPKO&=iGbdqcz<(KS-X6ir-}X`vMHRHlt0|>*#RTuJRV5){e>rFLh{zxpbJ}yHz=*Y zIl)VA^?zp4>#r;^+nE36obC@e!|hUIc~PZc-qq#bZ*)x>oc<;QcK6998+;0$D>v&?I^`@%46FJb3WU#b`B!4eN8L5vUFUh@itBh5yDn zwa2PEk8q^TeKR`eV~@};2hv7%lqC8grN6`b>61SboSopagn%;H|K{w3tY

T_oD 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

{>NVz3P?ishb_(Z}E?_9TsF2I>%fFrsFc(R0iK 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%0A*f(aN@$z#YMg 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 z Date: Wed, 2 Aug 2023 20:08:02 +0900 Subject: [PATCH 6/8] chore: make format --- app/app.go | 2 +- appplus/app.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/app.go b/app/app.go index 335c0363de..e6e196569f 100644 --- a/app/app.go +++ b/app/app.go @@ -653,7 +653,7 @@ func NewWasmApp( ibchost.ModuleName, icatypes.ModuleName, ibcfeetypes.ModuleName, - //intertxtypes.ModuleName, + // intertxtypes.ModuleName, wasm.ModuleName, ) diff --git a/appplus/app.go b/appplus/app.go index 687486b8a9..833793849d 100644 --- a/appplus/app.go +++ b/appplus/app.go @@ -474,7 +474,7 @@ func NewWasmApp( scopedTransferKeeper, ) transferModule := transfer.NewAppModule(app.TransferKeeper) - //transferIBCModule := transfer.NewIBCModule(app.TransferKeeper) + // transferIBCModule := transfer.NewIBCModule(app.TransferKeeper) app.ICAHostKeeper = icahostkeeper.NewKeeper( appCodec, From c15813534dc0c01e77d865c5bbdac9c11eb6ab56 Mon Sep 17 00:00:00 2001 From: loloicci Date: Wed, 2 Aug 2023 20:26:23 +0900 Subject: [PATCH 7/8] fix: fix missed duplicating changes for app/app.go to appplus/app.go --- appplus/app.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/appplus/app.go b/appplus/app.go index 833793849d..b473f24a81 100644 --- a/appplus/app.go +++ b/appplus/app.go @@ -473,8 +473,6 @@ func NewWasmApp( app.BankKeeper, scopedTransferKeeper, ) - transferModule := transfer.NewAppModule(app.TransferKeeper) - // transferIBCModule := transfer.NewIBCModule(app.TransferKeeper) app.ICAHostKeeper = icahostkeeper.NewKeeper( appCodec, @@ -486,6 +484,7 @@ func NewWasmApp( scopedICAHostKeeper, app.MsgServiceRouter(), ) + app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper( appCodec, keys[icacontrollertypes.StoreKey], @@ -496,8 +495,6 @@ func NewWasmApp( scopedICAControllerKeeper, app.MsgServiceRouter(), ) - icaModule := ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper) - icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) // create evidence keeper with router evidenceKeeper := evidencekeeper.NewKeeper( @@ -563,7 +560,7 @@ func NewWasmApp( ibcRouter. AddRoute(ibctransfertypes.ModuleName, transferStack). AddRoute(wasmplustypes.ModuleName, wasmStack). - AddRoute(icahosttypes.SubModuleName, icaHostIBCModule) + AddRoute(icahosttypes.SubModuleName, icaHostStack) app.IBCKeeper.SetRouter(ibcRouter) @@ -607,9 +604,9 @@ func NewWasmApp( authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), - transferModule, + transfer.NewAppModule(app.TransferKeeper), ibcfee.NewAppModule(app.IBCFeeKeeper), - icaModule, + ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper), crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), // always be last to make sure that it checks for all invariants and not only part of them ) @@ -728,7 +725,7 @@ func NewWasmApp( evidence.NewAppModule(app.EvidenceKeeper), wasmplus.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), ibc.NewAppModule(app.IBCKeeper), - transferModule, + transfer.NewAppModule(app.TransferKeeper), ) app.sm.RegisterStoreDecoders() From 3494e8b9ddb1c72b12921353d10dd0558bd86501 Mon Sep 17 00:00:00 2001 From: loloicci Date: Thu, 3 Aug 2023 11:11:16 +0900 Subject: [PATCH 8/8] build: upgrade finschia-sdk to v0.48.0-rc1 --- go.mod | 14 +++++++------- go.sum | 38 +++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/go.mod b/go.mod index aae1b2c7cc..de862264c7 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/Finschia/wasmd go 1.20 require ( - github.com/Finschia/finschia-sdk v0.47.1-0.20230725074611-f8840edecbaa - github.com/Finschia/ostracon v1.1.0 + github.com/Finschia/finschia-sdk v0.48.0-rc1 + github.com/Finschia/ostracon v1.1.1 github.com/Finschia/wasmvm v1.1.1-0.11.2.0.20230418093236-ce70a3856778 github.com/cosmos/iavl v0.19.4 github.com/cosmos/ibc-go/v4 v4.3.1 @@ -29,7 +29,7 @@ require ( github.com/tendermint/tendermint v0.34.24 github.com/tendermint/tm-db v0.6.7 google.golang.org/genproto/googleapis/api v0.0.0-20230629202037-9506855d4529 - google.golang.org/grpc v1.56.2 + google.golang.org/grpc v1.57.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -38,6 +38,7 @@ require ( github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/Finschia/r2ishiguro_vrf v0.1.2 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/Workiva/go-datastructures v1.1.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect @@ -50,7 +51,6 @@ require ( github.com/coinbase/rosetta-sdk-go v0.8.3 // indirect github.com/coinbase/rosetta-sdk-go/types v1.0.0 // indirect github.com/confio/ics23/go v0.9.0 // indirect - github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71 // indirect github.com/cosmos/btcutil v1.0.5 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gorocksdb v1.2.0 // indirect @@ -86,7 +86,7 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/klauspost/compress v1.16.6 // indirect + github.com/klauspost/compress v1.16.7 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -98,6 +98,7 @@ require ( github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce // indirect github.com/onsi/ginkgo v1.16.4 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect @@ -105,7 +106,6 @@ require ( github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect - github.com/r2ishiguro/vrf v0.0.0-20180716233122-192de52975eb // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rs/cors v1.9.0 // indirect github.com/rs/zerolog v1.29.1 // indirect @@ -121,7 +121,7 @@ require ( github.com/zondax/ledger-go v0.14.1 // indirect go.etcd.io/bbolt v1.3.6 // indirect golang.org/x/crypto v0.11.0 // indirect - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect + golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect golang.org/x/net v0.12.0 // indirect golang.org/x/sys v0.10.0 // indirect golang.org/x/term v0.10.0 // indirect diff --git a/go.sum b/go.sum index 8ac3dddc15..bea2f3569c 100644 --- a/go.sum +++ b/go.sum @@ -41,22 +41,24 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMb github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Finschia/finschia-sdk v0.47.1-0.20230725074611-f8840edecbaa h1:rqmj9tGqBgJT42payCkZbFsHF1Z9KB0HJEk7JY+vN8s= -github.com/Finschia/finschia-sdk v0.47.1-0.20230725074611-f8840edecbaa/go.mod h1:7TG+PzNhHcA9txzKpFfQ1A7RUnxiaqAl4zyC5DXrD2A= +github.com/Finschia/finschia-sdk v0.48.0-rc1 h1:kTN42yD/ThbR7+TUxcL1LoOg/1XJDP4YLPke+Foiers= +github.com/Finschia/finschia-sdk v0.48.0-rc1/go.mod h1:3mRSwNMCoGkerQ5vOQSjPAaFv3o50o2zGxvp0Otiueo= github.com/Finschia/ibc-go/v4 v4.3.1 h1:pUKry0j+1/ypCC3X1TkEzoLrS1A/low/1PE2HZL+13k= github.com/Finschia/ibc-go/v4 v4.3.1/go.mod h1:kFZgmXXT2pt9QL7Ngx/eA7lI9JlOMGRG/oU4RTDXKcg= -github.com/Finschia/ostracon v1.1.0 h1:ruiqngsoCz1kJ3fGLJHflcvxbJrbg7QGDTruqxgLZKc= -github.com/Finschia/ostracon v1.1.0/go.mod h1:nPRoQEOOp8FFp2XQ8b1dvfHgKNxp1Zb7i1p5yrLIgG4= +github.com/Finschia/ostracon v1.1.1 h1:Hdj2Xe9YSlD0hXbacIXUfOL6NfkF/lxg6AB8OnKvwgM= +github.com/Finschia/ostracon v1.1.1/go.mod h1:Ub1TWTN2+PfdCFo8ckdc4PxkfPmh2qQ8mmey+gLK5fw= +github.com/Finschia/r2ishiguro_vrf v0.1.2 h1:lDBz6NQMx1pw5I3End6xFmXpM//7KcmTr3Ka983e7v8= +github.com/Finschia/r2ishiguro_vrf v0.1.2/go.mod h1:OHRtvzcJnfIrcJ0bvPNktJozRFAyZFuv56E9R3/qB+Y= github.com/Finschia/wasmvm v1.1.1-0.11.2.0.20230418093236-ce70a3856778 h1:V+iocQkc3zvpgdn+nCLZ9kPM7D7u6v2Br+EkOIhvjbY= github.com/Finschia/wasmvm v1.1.1-0.11.2.0.20230418093236-ce70a3856778/go.mod h1:uCHU7ZRQ/V+WPRXr6Ak9Uu2oe2MVeO8yGZnGKU1B3NY= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= -github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -127,8 +129,6 @@ github.com/coinbase/rosetta-sdk-go v0.8.3 h1:IYqd+Ser5NVh0s7p8p2Ir82iCvi75E1l0NH github.com/coinbase/rosetta-sdk-go v0.8.3/go.mod h1:ChOHc+BNq7zqJDDkui0DA124GOvlAiRbdgAc1U9GMDQ= github.com/coinbase/rosetta-sdk-go/types v1.0.0 h1:jpVIwLcPoOeCR6o1tU+Xv7r5bMONNbHU7MuEHboiFuA= github.com/coinbase/rosetta-sdk-go/types v1.0.0/go.mod h1:eq7W2TMRH22GTW0N0beDnN931DW0/WOI1R2sdHNHG4c= -github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71 h1:MFLTqgfJclmtaQ1SRUrWwmDX/1UBok3XWUethkJ2swQ= -github.com/coniks-sys/coniks-go v0.0.0-20180722014011-11acf4819b71/go.mod h1:TrHYHH4Wze7v7Hkwu1MH1W+mCPQKM+gs+PicdEV14o8= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= @@ -408,8 +408,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk= -github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -448,7 +448,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw= +github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= @@ -487,6 +487,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA 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/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce h1:/pEpMk55wH0X+E5zedGEMOdLuWmV8P4+4W3+LZaM6kg= +github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= @@ -502,7 +504,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= @@ -568,8 +570,6 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/r2ishiguro/vrf v0.0.0-20180716233122-192de52975eb h1:3kW8n+FfBaUoqlHxCa6e90PXWpGCWWkdyTZ6F7c9m2I= -github.com/r2ishiguro/vrf v0.0.0-20180716233122-192de52975eb/go.mod h1:2NzHJUkr/ERaPNQ2IUuNbB2jMTWYp2DxhcraWbzZj00= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -737,8 +737,8 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -761,7 +761,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -969,12 +969,12 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= +golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.12.0 h1:xKuo6hzt+gMav00meVPUlXwSdoEJP46BR+wdxQEFK2o= +gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=