From ad0c311d1e31667d33892eb5e0e647c25bd573a4 Mon Sep 17 00:00:00 2001 From: Nicolas Lara Date: Fri, 23 Dec 2022 18:40:58 +0100 Subject: [PATCH 01/30] Upgrade IBC to v4.2.0 (#3838) * initial changes to migrate to ibc v4 * added checksum to proposal * begin and end block are now being called inside nextBlock * added changelog * linked pr on changelog * remove local replace * using error acks from osmoutils * osmoutils tagged * go sum * added checksum --- CHANGELOG.md | 15 +- app/ante.go | 4 +- app/keepers/keepers.go | 24 +- app/keepers/modules.go | 8 +- app/modules.go | 12 +- app/upgrades/v12/upgrades.go | 4 +- app/upgrades/v13/upgrades.go | 2 +- app/upgrades/v5/upgrades.go | 2 +- app/upgrades/v9/constants.go | 2 +- app/upgrades/v9/msg_filter_ante.go | 2 +- app/upgrades/v9/msg_filter_ante_test.go | 2 +- app/upgrades/v9/upgrades.go | 8 +- go.mod | 12 +- go.sum | 20 +- go.work.sum | 55 ++ osmoutils/ibc.go | 20 +- tests/ibc-hooks/ibc_middleware_test.go | 896 ++++++++++++++++++++++++ wasmbinding/test/custom_query_test.go | 3 + wasmbinding/test/store_run_test.go | 3 + x/ibc-hooks/hooks.go | 8 +- x/ibc-hooks/ibc_module.go | 20 +- x/ibc-hooks/ics4_middleware.go | 34 +- x/ibc-hooks/testutils/testing_hooks.go | 4 +- x/ibc-hooks/wasm_hook.go | 18 +- x/ibc-rate-limit/ibc_middleware_test.go | 6 +- x/ibc-rate-limit/ibc_module.go | 20 +- x/ibc-rate-limit/ics4_wrapper.go | 11 +- x/ibc-rate-limit/rate_limit.go | 6 +- x/ibc-rate-limit/testutil/chain.go | 9 +- x/ibc-rate-limit/testutil/wasm.go | 8 +- 30 files changed, 1112 insertions(+), 126 deletions(-) create mode 100644 tests/ibc-hooks/ibc_middleware_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 02d07de0017..df83ddd6249 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,8 +42,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -### Misc Improvements +* IBC features + * Upgrade to IBC v4.2.0 +* Cosmwasm + * Upgrade to wasmd v0.30.x +### Features +* [#2387](https://github.com/osmosis-labs/osmosis/pull/3838) Upgrade to IBC v4.2.0, and as a requirement for it wasmd to 0.30.0 +* [#3609](https://github.com/osmosis-labs/osmosis/pull/3609) Add Downtime-detection module. +* [#2788](https://github.com/osmosis-labs/osmosis/pull/2788) Add logarithm base 2 implementation. * [#3677](https://github.com/osmosis-labs/osmosis/pull/3677) Add methods for cloning and mutative multiplication on osmomath.BigDec. * [#3676](https://github.com/osmosis-labs/osmosis/pull/3676) implement `PowerInteger` function on `osmomath.BigDec` * [#3678](https://github.com/osmosis-labs/osmosis/pull/3678) implement mutative `PowerIntegerMut` function on `osmomath.BigDec`. @@ -84,12 +91,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#3611](https://github.com/osmosis-labs/osmosis/pull/3611),[#3647](https://github.com/osmosis-labs/osmosis/pull/3647) Introduce osmocli, to automate thousands of lines of CLI boilerplate * [#3634](https://github.com/osmosis-labs/osmosis/pull/3634) (Makefile) Ensure correct golang version in make build and make install. (Thank you @jhernandezb ) -<<<<<<< HEAD -* [#3712](https://github.com/osmosis-labs/osmosis/pull/3712) replace `osmomath.BigDec` `Power` with `PowerInteger` - -======= +* [#3712](https://github.com/osmosis-labs/osmosis/pull/3712) replace `osmomath.BigDec` `Power` with `PowerInteger` * [#3711](https://github.com/osmosis-labs/osmosis/pull/3711) Use Dec instead of Int for additive `ErrTolerace` in `osmoutils`. ->>>>>>> 5ab7ebf6 (refactor(osmoutils): use Dec for additive tolerance instead of Int (#3711)) ## v13.0.0 diff --git a/app/ante.go b/app/ante.go index 5d8964104c8..7d5338bb82c 100644 --- a/app/ante.go +++ b/app/ante.go @@ -3,8 +3,8 @@ package app import ( wasm "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" - ibcante "github.com/cosmos/ibc-go/v3/modules/core/ante" - ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper" + ibcante "github.com/cosmos/ibc-go/v4/modules/core/ante" + ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" servertypes "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index a21aa893a41..3579fcc9a84 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -38,19 +38,19 @@ import ( ibcratelimit "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit" ibcratelimittypes "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types" - icahost "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/host" - icahostkeeper "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/host/keeper" - icahosttypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/host/types" - ibctransferkeeper "github.com/cosmos/ibc-go/v3/modules/apps/transfer/keeper" - ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - ibcclient "github.com/cosmos/ibc-go/v3/modules/core/02-client" - ibcclienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" - porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" - ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host" - ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper" + 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" + ibctransferkeeper "github.com/cosmos/ibc-go/v4/modules/apps/transfer/keeper" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + ibcclient "github.com/cosmos/ibc-go/v4/modules/core/02-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" // IBC Transfer: Defines the "transfer" IBC port - transfer "github.com/cosmos/ibc-go/v3/modules/apps/transfer" + transfer "github.com/cosmos/ibc-go/v4/modules/apps/transfer" _ "github.com/osmosis-labs/osmosis/v13/client/docs/statik" owasm "github.com/osmosis-labs/osmosis/v13/wasmbinding" @@ -349,7 +349,7 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.Ics20WasmHooks.ContractKeeper = appKeepers.ContractKeeper // wire up x/wasm to IBC - ibcRouter.AddRoute(wasm.ModuleName, wasm.NewIBCHandler(appKeepers.WasmKeeper, appKeepers.IBCKeeper.ChannelKeeper)) + ibcRouter.AddRoute(wasm.ModuleName, wasm.NewIBCHandler(appKeepers.WasmKeeper, appKeepers.IBCKeeper.ChannelKeeper, appKeepers.IBCKeeper.ChannelKeeper)) appKeepers.IBCKeeper.SetRouter(ibcRouter) // register the proposal types diff --git a/app/keepers/modules.go b/app/keepers/modules.go index de9643c0f20..444b7e09196 100644 --- a/app/keepers/modules.go +++ b/app/keepers/modules.go @@ -3,9 +3,9 @@ package keepers import ( "github.com/CosmWasm/wasmd/x/wasm" wasmclient "github.com/CosmWasm/wasmd/x/wasm/client" - transfer "github.com/cosmos/ibc-go/v3/modules/apps/transfer" - ibc "github.com/cosmos/ibc-go/v3/modules/core" - ibcclientclient "github.com/cosmos/ibc-go/v3/modules/core/02-client/client" + transfer "github.com/cosmos/ibc-go/v4/modules/apps/transfer" + ibc "github.com/cosmos/ibc-go/v4/modules/core" + ibcclientclient "github.com/cosmos/ibc-go/v4/modules/core/02-client/client" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" @@ -25,7 +25,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking" "github.com/cosmos/cosmos-sdk/x/upgrade" upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client" - ica "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts" + ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" _ "github.com/osmosis-labs/osmosis/v13/client/docs/statik" "github.com/osmosis-labs/osmosis/v13/x/epochs" diff --git a/app/modules.go b/app/modules.go index ffe86946713..a15823ee59b 100644 --- a/app/modules.go +++ b/app/modules.go @@ -5,13 +5,13 @@ import ( "github.com/cosmos/cosmos-sdk/client" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - ibc "github.com/cosmos/ibc-go/v3/modules/core" - ibchost "github.com/cosmos/ibc-go/v3/modules/core/24-host" - ibckeeper "github.com/cosmos/ibc-go/v3/modules/core/keeper" + 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" - ica "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts" - icatypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/types" + ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" + icatypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/types" ibc_hooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks" diff --git a/app/upgrades/v12/upgrades.go b/app/upgrades/v12/upgrades.go index 37679efe698..45f8e20e8ec 100644 --- a/app/upgrades/v12/upgrades.go +++ b/app/upgrades/v12/upgrades.go @@ -8,8 +8,8 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - icahosttypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/host/types" - ibctransfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" + icahosttypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/host/types" + ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types" superfluidtypes "github.com/osmosis-labs/osmosis/v13/x/superfluid/types" diff --git a/app/upgrades/v13/upgrades.go b/app/upgrades/v13/upgrades.go index 8fe71a4c518..8642f0d7025 100644 --- a/app/upgrades/v13/upgrades.go +++ b/app/upgrades/v13/upgrades.go @@ -11,7 +11,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" + transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" "github.com/osmosis-labs/osmosis/v13/app/keepers" "github.com/osmosis-labs/osmosis/v13/app/upgrades" diff --git a/app/upgrades/v5/upgrades.go b/app/upgrades/v5/upgrades.go index 8fb22147740..cce699f08d8 100644 --- a/app/upgrades/v5/upgrades.go +++ b/app/upgrades/v5/upgrades.go @@ -1,7 +1,7 @@ package v5 import ( - ibcconnectiontypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" + ibcconnectiontypes "github.com/cosmos/ibc-go/v4/modules/core/03-connection/types" // bech32ibctypes "github.com/osmosis-labs/bech32-ibc/x/bech32ibc/types" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/app/upgrades/v9/constants.go b/app/upgrades/v9/constants.go index 922fb7936a4..0228f3288cf 100644 --- a/app/upgrades/v9/constants.go +++ b/app/upgrades/v9/constants.go @@ -5,7 +5,7 @@ import ( store "github.com/cosmos/cosmos-sdk/store/types" - icahosttypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/host/types" + icahosttypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/host/types" tokenfactorytypes "github.com/osmosis-labs/osmosis/v13/x/tokenfactory/types" ) diff --git a/app/upgrades/v9/msg_filter_ante.go b/app/upgrades/v9/msg_filter_ante.go index b6035b35976..0d803d20b56 100644 --- a/app/upgrades/v9/msg_filter_ante.go +++ b/app/upgrades/v9/msg_filter_ante.go @@ -4,7 +4,7 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - ibcchanneltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + ibcchanneltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" ) // MsgFilterDecorator defines an AnteHandler decorator for the v9 upgrade that diff --git a/app/upgrades/v9/msg_filter_ante_test.go b/app/upgrades/v9/msg_filter_ante_test.go index 531887f1cc1..e66522c3873 100644 --- a/app/upgrades/v9/msg_filter_ante_test.go +++ b/app/upgrades/v9/msg_filter_ante_test.go @@ -7,7 +7,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/stretchr/testify/require" - ibcchanneltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + ibcchanneltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" "github.com/osmosis-labs/osmosis/v13/app" v8 "github.com/osmosis-labs/osmosis/v13/app/upgrades/v8" diff --git a/app/upgrades/v9/upgrades.go b/app/upgrades/v9/upgrades.go index 6fe0dc15613..377012e3ee6 100644 --- a/app/upgrades/v9/upgrades.go +++ b/app/upgrades/v9/upgrades.go @@ -12,10 +12,10 @@ import ( gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types" - ica "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts" - icacontrollertypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/controller/types" - icahosttypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/host/types" - icatypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/types" + ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" + icacontrollertypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/controller/types" + 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" "github.com/osmosis-labs/osmosis/v13/app/keepers" "github.com/osmosis-labs/osmosis/v13/app/upgrades" diff --git a/go.mod b/go.mod index 5c367df20bf..85aeeef9583 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,11 @@ module github.com/osmosis-labs/osmosis/v13 go 1.18 require ( - github.com/CosmWasm/wasmd v0.29.2-osmo-v13 + github.com/CosmWasm/wasmd v0.30.0 github.com/cosmos/cosmos-proto v1.0.0-alpha8 github.com/cosmos/cosmos-sdk v0.46.7 github.com/cosmos/go-bip39 v1.0.0 - github.com/cosmos/ibc-go/v3 v3.4.0 + github.com/cosmos/ibc-go/v4 v4.2.0 github.com/gogo/protobuf v1.3.3 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.2 @@ -18,7 +18,7 @@ require ( github.com/ory/dockertest/v3 v3.9.1 github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 github.com/osmosis-labs/osmosis/osmomath v0.0.2 - github.com/osmosis-labs/osmosis/osmoutils v0.0.1 + github.com/osmosis-labs/osmosis/osmoutils v0.0.2-ibc-work github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/spf13/cast v1.5.0 @@ -40,10 +40,11 @@ require ( github.com/Abirdcfly/dupword v0.0.7 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/alingse/asasalint v0.0.11 // indirect - github.com/cosmos/gogoproto v1.4.2 // indirect + github.com/cosmos/gogoproto v1.4.3 // indirect github.com/cosmos/iavl v0.19.4 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect github.com/felixge/httpsnoop v1.0.1 // indirect github.com/google/btree v1.1.2 // indirect github.com/kkHAIKE/contextcheck v1.1.3 // indirect @@ -297,7 +298,8 @@ require ( replace ( // osmosis-patched wasmd - github.com/CosmWasm/wasmd => github.com/osmosis-labs/wasmd v0.29.2-osmo-v13 + // ToDo: replace the commit hash with v0.30.0-osmo-v14 once the version is tagged + github.com/CosmWasm/wasmd => github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30 // dragonberry github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 // Our cosmos-sdk branch is: https://github.com/osmosis-labs/cosmos-sdk, current branch: v13.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/8757a61551aa1ea993c85a523e18094ab555b1d7 diff --git a/go.sum b/go.sum index cf321861ac9..1551200e993 100644 --- a/go.sum +++ b/go.sum @@ -221,15 +221,15 @@ github.com/cosmos/cosmos-sdk/ics23/go v0.8.0/go.mod h1:2a4dBq88TUoqoWAU5eu0lGvpF github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= -github.com/cosmos/gogoproto v1.4.2 h1:UeGRcmFW41l0G0MiefWhkPEVEwvu78SZsHBvI78dAYw= -github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= +github.com/cosmos/gogoproto v1.4.3 h1:RP3yyVREh9snv/lsOvmsAPQt8f44LgL281X0IOIhhcI= +github.com/cosmos/gogoproto v1.4.3/go.mod h1:0hLIG5TR7IvV1fme1HCFKjfzW9X2x0Mo+RooWXCnOWU= github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= 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/ibc-go/v3 v3.4.0 h1:ha3cqEG36pqMWqA1D+kxDWBTZXpeFMd/aZIQF7I0xro= -github.com/cosmos/ibc-go/v3 v3.4.0/go.mod h1:VwB/vWu4ysT5DN2aF78d17LYmx3omSAdq6gpKvM7XRA= -github.com/cosmos/interchain-accounts v0.1.0 h1:QmuwNsf1Hxl3P5GSGt7Z+JeuHPiZw4Z34R/038P5T6s= +github.com/cosmos/ibc-go/v4 v4.2.0 h1:Fx/kKq/uvawrAxk6ZrQ6sEIgffLRU5Cs/AUnvpPBrHI= +github.com/cosmos/ibc-go/v4 v4.2.0/go.mod h1:57qWScDtfCx3FOMLYmBIKPbOLE6xiVhrgxHAQmbWYXM= +github.com/cosmos/interchain-accounts v0.2.4 h1:7UrroFQsCRSp17980mk6anx4YteveIJVkU+a0wlsHQI= github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4= github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY= github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI= @@ -277,6 +277,8 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8 github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.19+incompatible h1:lzEmjivyNHFHMNAFLXORMBXyGIhw/UP4DvJwvyKYq64= github.com/docker/docker v20.10.19+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= @@ -853,10 +855,10 @@ github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:Ylmch github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI= github.com/osmosis-labs/osmosis/osmomath v0.0.2 h1:8vTobkYfoRTCJCie+jE7gzXvqUUfoPI4NSvTskoci50= github.com/osmosis-labs/osmosis/osmomath v0.0.2/go.mod h1:IpoXO7lvmfsBFfQzaqovs541hpqtrnM+GJSZDi/TZtc= -github.com/osmosis-labs/osmosis/osmoutils v0.0.1 h1:iANKdKa6cCgX1NJAldzfedwUPmeaKNrMu/atBCWtGg8= -github.com/osmosis-labs/osmosis/osmoutils v0.0.1/go.mod h1:T7CCZKYhKWASnv5mRE8u3m0gst3NZ/sU16Brjmv4UPw= -github.com/osmosis-labs/wasmd v0.29.2-osmo-v13 h1:HvxAks1ctB3nBx1cXqcmfA0g0BKe7Og77OA2j2rxaJk= -github.com/osmosis-labs/wasmd v0.29.2-osmo-v13/go.mod h1:UlLBU5vuHncwQUM9W8lw+2mEptEMFxxfVWupZ6sXtn4= +github.com/osmosis-labs/osmosis/osmoutils v0.0.2-ibc-work h1:/cMOafE/0qNdNcqQsMBFAh/SGi8zdFVmWo6j2R/MQ0I= +github.com/osmosis-labs/osmosis/osmoutils v0.0.2-ibc-work/go.mod h1:T7CCZKYhKWASnv5mRE8u3m0gst3NZ/sU16Brjmv4UPw= +github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30 h1:6uMi7HhPSwvKKU7j5NqljseFTEz4I7qHr+IPnnn42Ck= +github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30/go.mod h1:5fDYJyMXBq6u2iuHqqOTYiZ5NitIOeIW5k7qEXqbwJE= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= diff --git a/go.work.sum b/go.work.sum index cc948aa93a8..ba20f67a17f 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,4 +1,59 @@ +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/osmosis-labs/wasmd v0.29.2-osmo-v13/go.mod h1:UlLBU5vuHncwQUM9W8lw+2mEptEMFxxfVWupZ6sXtn4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= diff --git a/osmoutils/ibc.go b/osmoutils/ibc.go index 67f5864463c..84f08b85bc9 100644 --- a/osmoutils/ibc.go +++ b/osmoutils/ibc.go @@ -3,11 +3,25 @@ package osmoutils import ( "encoding/json" - transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" + transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" ) +// NewStringErrorAcknowledgement returns a new instance of Acknowledgement using an Acknowledgement_Error +// type in the Response field. These errors differ from the IBC errors in that we use custom error strings. +// NOTE: Acknowledgements are written into state and thus, changes made to error strings included in packet acknowledgements +// risk an app hash divergence when nodes in a network are running different patch versions of software. +func NewStringErrorAcknowledgement(err string) channeltypes.Acknowledgement { + // ToDo: Do we want to do this or do we want to use the IBC errors and emit the string? + + return channeltypes.Acknowledgement{ + Response: &channeltypes.Acknowledgement_Error{ + Error: err, + }, + } +} + // MustExtractDenomFromPacketOnRecv takes a packet with a valid ICS20 token data in the Data field and returns the // denom as represented in the local chain. // If the data cannot be unmarshalled this function will panic diff --git a/tests/ibc-hooks/ibc_middleware_test.go b/tests/ibc-hooks/ibc_middleware_test.go new file mode 100644 index 00000000000..7ca0743a499 --- /dev/null +++ b/tests/ibc-hooks/ibc_middleware_test.go @@ -0,0 +1,896 @@ +package ibc_hooks_test + +import ( + "encoding/json" + "fmt" + "testing" + + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + + "github.com/osmosis-labs/osmosis/v13/x/gamm/pool-models/balancer" + gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types" + ibchooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks" + minttypes "github.com/osmosis-labs/osmosis/v13/x/mint/types" + + "github.com/osmosis-labs/osmosis/osmoutils" + + "github.com/osmosis-labs/osmosis/v13/app/apptesting" + + "github.com/stretchr/testify/suite" + + sdk "github.com/cosmos/cosmos-sdk/types" + + transfertypes "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" + + osmosisibctesting "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/testutil" + + "github.com/osmosis-labs/osmosis/v13/tests/ibc-hooks/testutils" +) + +type HooksTestSuite struct { + apptesting.KeeperTestHelper + + coordinator *ibctesting.Coordinator + + chainA *osmosisibctesting.TestChain + chainB *osmosisibctesting.TestChain + + path *ibctesting.Path +} + +func (suite *HooksTestSuite) SetupTest() { + suite.Setup() + ibctesting.DefaultTestingAppInit = osmosisibctesting.SetupTestingApp + suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) + suite.chainA = &osmosisibctesting.TestChain{ + TestChain: suite.coordinator.GetChain(ibctesting.GetChainID(1)), + } + suite.chainB = &osmosisibctesting.TestChain{ + TestChain: suite.coordinator.GetChain(ibctesting.GetChainID(2)), + } + err := suite.chainA.MoveEpochsToTheFuture() + suite.Require().NoError(err) + err = suite.chainB.MoveEpochsToTheFuture() + suite.Require().NoError(err) + suite.path = NewTransferPath(suite.chainA, suite.chainB) + suite.coordinator.Setup(suite.path) +} + +func TestIBCHooksTestSuite(t *testing.T) { + suite.Run(t, new(HooksTestSuite)) +} + +// ToDo: Move this to osmosistesting to avoid repetition +func NewTransferPath(chainA, chainB *osmosisibctesting.TestChain) *ibctesting.Path { + path := ibctesting.NewPath(chainA.TestChain, chainB.TestChain) + path.EndpointA.ChannelConfig.PortID = ibctesting.TransferPort + path.EndpointB.ChannelConfig.PortID = ibctesting.TransferPort + path.EndpointA.ChannelConfig.Version = transfertypes.Version + path.EndpointB.ChannelConfig.Version = transfertypes.Version + + return path +} + +func (suite *HooksTestSuite) TestOnRecvPacketHooks() { + var ( + trace transfertypes.DenomTrace + amount sdk.Int + receiver string + status testutils.Status + ) + + testCases := []struct { + msg string + malleate func(*testutils.Status) + expPass bool + }{ + {"override", func(status *testutils.Status) { + suite.chainB.GetOsmosisApp().TransferStack. + ICS4Middleware.Hooks = testutils.TestRecvOverrideHooks{Status: status} + }, true}, + {"before and after", func(status *testutils.Status) { + suite.chainB.GetOsmosisApp().TransferStack. + ICS4Middleware.Hooks = testutils.TestRecvBeforeAfterHooks{Status: status} + }, true}, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.msg, func() { + suite.SetupTest() // reset + + path := NewTransferPath(suite.chainA, suite.chainB) + suite.coordinator.Setup(path) + receiver = suite.chainB.SenderAccount.GetAddress().String() // must be explicitly changed in malleate + status = testutils.Status{} + + amount = sdk.NewInt(100) // must be explicitly changed in malleate + seq := uint64(1) + + trace = transfertypes.ParseDenomTrace(sdk.DefaultBondDenom) + + // send coin from chainA to chainB + transferMsg := transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, sdk.NewCoin(trace.IBCDenom(), amount), suite.chainA.SenderAccount.GetAddress().String(), receiver, clienttypes.NewHeight(1, 110), 0) + _, err := suite.chainA.SendMsgs(transferMsg) + suite.Require().NoError(err) // message committed + + tc.malleate(&status) + + data := transfertypes.NewFungibleTokenPacketData(trace.GetFullDenomPath(), amount.String(), suite.chainA.SenderAccount.GetAddress().String(), receiver) + packet := channeltypes.NewPacket(data.GetBytes(), seq, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(1, 100), 0) + + ack := suite.chainB.GetOsmosisApp().TransferStack. + OnRecvPacket(suite.chainB.GetContext(), packet, suite.chainA.SenderAccount.GetAddress()) + + if tc.expPass { + suite.Require().True(ack.Success()) + } else { + suite.Require().False(ack.Success()) + } + + if _, ok := suite.chainB.GetOsmosisApp().TransferStack. + ICS4Middleware.Hooks.(testutils.TestRecvOverrideHooks); ok { + suite.Require().True(status.OverrideRan) + suite.Require().False(status.BeforeRan) + suite.Require().False(status.AfterRan) + } + + if _, ok := suite.chainB.GetOsmosisApp().TransferStack. + ICS4Middleware.Hooks.(testutils.TestRecvBeforeAfterHooks); ok { + suite.Require().False(status.OverrideRan) + suite.Require().True(status.BeforeRan) + suite.Require().True(status.AfterRan) + } + }) + } +} + +func (suite *HooksTestSuite) makeMockPacket(receiver, memo string, prevSequence uint64) channeltypes.Packet { + packetData := transfertypes.FungibleTokenPacketData{ + Denom: sdk.DefaultBondDenom, + Amount: "1", + Sender: suite.chainB.SenderAccount.GetAddress().String(), + Receiver: receiver, + Memo: memo, + } + + return channeltypes.NewPacket( + packetData.GetBytes(), + prevSequence+1, + suite.path.EndpointB.ChannelConfig.PortID, + suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, + suite.path.EndpointA.ChannelID, + clienttypes.NewHeight(0, 100), + 0, + ) +} + +func (suite *HooksTestSuite) receivePacket(receiver, memo string) []byte { + return suite.receivePacketWithSequence(receiver, memo, 0) +} + +func (suite *HooksTestSuite) receivePacketWithSequence(receiver, memo string, prevSequence uint64) []byte { + channelCap := suite.chainB.GetChannelCapability( + suite.path.EndpointB.ChannelConfig.PortID, + suite.path.EndpointB.ChannelID) + + packet := suite.makeMockPacket(receiver, memo, prevSequence) + + err := suite.chainB.GetOsmosisApp().HooksICS4Wrapper.SendPacket( + suite.chainB.GetContext(), channelCap, packet) + suite.Require().NoError(err, "IBC send failed. Expected success. %s", err) + + // Update both clients + err = suite.path.EndpointB.UpdateClient() + suite.Require().NoError(err) + err = suite.path.EndpointA.UpdateClient() + suite.Require().NoError(err) + + // recv in chain a + res, err := suite.path.EndpointA.RecvPacketWithResult(packet) + + // get the ack from the chain a's response + ack, err := ibctesting.ParseAckFromEvents(res.GetEvents()) + suite.Require().NoError(err) + + // manually send the acknowledgement to chain b + err = suite.path.EndpointA.AcknowledgePacket(packet, ack) + suite.Require().NoError(err) + return ack +} + +func (suite *HooksTestSuite) TestRecvTransferWithMetadata() { + // Setup contract + suite.chainA.StoreContractCode(&suite.Suite, "./bytecode/echo.wasm") + addr := suite.chainA.InstantiateContract(&suite.Suite, "{}", 1) + + ackBytes := suite.receivePacket(addr.String(), fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": {"echo": {"msg": "test"} } } }`, addr)) + ackStr := string(ackBytes) + fmt.Println(ackStr) + var ack map[string]string // This can't be unmarshalled to Acknowledgement because it's fetched from the events + err := json.Unmarshal(ackBytes, &ack) + suite.Require().NoError(err) + suite.Require().NotContains(ack, "error") + suite.Require().Equal(ack["result"], "eyJjb250cmFjdF9yZXN1bHQiOiJkR2hwY3lCemFHOTFiR1FnWldOb2J3PT0iLCJpYmNfYWNrIjoiZXlKeVpYTjFiSFFpT2lKQlVUMDlJbjA9In0=") +} + +// After successfully executing a wasm call, the contract should have the funds sent via IBC +func (suite *HooksTestSuite) TestFundsAreTransferredToTheContract() { + // Setup contract + suite.chainA.StoreContractCode(&suite.Suite, "./bytecode/echo.wasm") + addr := suite.chainA.InstantiateContract(&suite.Suite, "{}", 1) + + // Check that the contract has no funds + localDenom := osmoutils.MustExtractDenomFromPacketOnRecv(suite.makeMockPacket("", "", 0)) + balance := suite.chainA.GetOsmosisApp().BankKeeper.GetBalance(suite.chainA.GetContext(), addr, localDenom) + suite.Require().Equal(sdk.NewInt(0), balance.Amount) + + // Execute the contract via IBC + ackBytes := suite.receivePacket(addr.String(), fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": {"echo": {"msg": "test"} } } }`, addr)) + ackStr := string(ackBytes) + fmt.Println(ackStr) + var ack map[string]string // This can't be unmarshalled to Acknowledgement because it's fetched from the events + err := json.Unmarshal(ackBytes, &ack) + suite.Require().NoError(err) + suite.Require().NotContains(ack, "error") + suite.Require().Equal(ack["result"], "eyJjb250cmFjdF9yZXN1bHQiOiJkR2hwY3lCemFHOTFiR1FnWldOb2J3PT0iLCJpYmNfYWNrIjoiZXlKeVpYTjFiSFFpT2lKQlVUMDlJbjA9In0=") + + // Check that the token has now been transferred to the contract + balance = suite.chainA.GetOsmosisApp().BankKeeper.GetBalance(suite.chainA.GetContext(), addr, localDenom) + suite.Require().Equal(sdk.NewInt(1), balance.Amount) +} + +// If the wasm call wails, the contract acknowledgement should be an error and the funds returned +func (suite *HooksTestSuite) TestFundsAreReturnedOnFailedContractExec() { + // Setup contract + suite.chainA.StoreContractCode(&suite.Suite, "./bytecode/echo.wasm") + addr := suite.chainA.InstantiateContract(&suite.Suite, "{}", 1) + + // Check that the contract has no funds + localDenom := osmoutils.MustExtractDenomFromPacketOnRecv(suite.makeMockPacket("", "", 0)) + balance := suite.chainA.GetOsmosisApp().BankKeeper.GetBalance(suite.chainA.GetContext(), addr, localDenom) + suite.Require().Equal(sdk.NewInt(0), balance.Amount) + + // Execute the contract via IBC with a message that the contract will reject + ackBytes := suite.receivePacket(addr.String(), fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": {"not_echo": {"msg": "test"} } } }`, addr)) + ackStr := string(ackBytes) + fmt.Println(ackStr) + var ack map[string]string // This can't be unmarshalled to Acknowledgement because it's fetched from the events + err := json.Unmarshal(ackBytes, &ack) + suite.Require().NoError(err) + suite.Require().Contains(ack, "error") + + // Check that the token has now been transferred to the contract + balance = suite.chainA.GetOsmosisApp().BankKeeper.GetBalance(suite.chainA.GetContext(), addr, localDenom) + fmt.Println(balance) + suite.Require().Equal(sdk.NewInt(0), balance.Amount) +} + +func (suite *HooksTestSuite) TestPacketsThatShouldBeSkipped() { + var sequence uint64 + receiver := suite.chainB.SenderAccount.GetAddress().String() + + testCases := []struct { + memo string + expPassthrough bool + }{ + {"", true}, + {"{01]", true}, // bad json + {"{}", true}, + {`{"something": ""}`, true}, + {`{"wasm": "test"}`, false}, + {`{"wasm": []`, true}, // invalid top level JSON + {`{"wasm": {}`, true}, // invalid top level JSON + {`{"wasm": []}`, false}, + {`{"wasm": {}}`, false}, + {`{"wasm": {"contract": "something"}}`, false}, + {`{"wasm": {"contract": "osmo1clpqr4nrk4khgkxj78fcwwh6dl3uw4epasmvnj"}}`, false}, + {`{"wasm": {"msg": "something"}}`, false}, + // invalid receiver + {`{"wasm": {"contract": "osmo1clpqr4nrk4khgkxj78fcwwh6dl3uw4epasmvnj", "msg": {}}}`, false}, + // msg not an object + {fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": 1}}`, receiver), false}, + } + + for _, tc := range testCases { + ackBytes := suite.receivePacketWithSequence(receiver, tc.memo, sequence) + ackStr := string(ackBytes) + fmt.Println(ackStr) + var ack map[string]string // This can't be unmarshalled to Acknowledgement because it's fetched from the events + err := json.Unmarshal(ackBytes, &ack) + suite.Require().NoError(err) + if tc.expPassthrough { + suite.Require().Equal("AQ==", ack["result"], tc.memo) + } else { + suite.Require().Contains(ackStr, "error", tc.memo) + } + sequence += 1 + } +} + +// After successfully executing a wasm call, the contract should have the funds sent via IBC +func (suite *HooksTestSuite) TestFundTracking() { + // Setup contract + suite.chainA.StoreContractCode(&suite.Suite, "./bytecode/counter.wasm") + addr := suite.chainA.InstantiateContract(&suite.Suite, `{"count": 0}`, 1) + + // Check that the contract has no funds + localDenom := osmoutils.MustExtractDenomFromPacketOnRecv(suite.makeMockPacket("", "", 0)) + balance := suite.chainA.GetOsmosisApp().BankKeeper.GetBalance(suite.chainA.GetContext(), addr, localDenom) + suite.Require().Equal(sdk.NewInt(0), balance.Amount) + + // Execute the contract via IBC + suite.receivePacket( + addr.String(), + fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": {"increment": {} } } }`, addr)) + + state := suite.chainA.QueryContract( + &suite.Suite, addr, + []byte(fmt.Sprintf(`{"get_count": {"addr": "%s"}}`, ibchooks.WasmHookModuleAccountAddr))) + suite.Require().Equal(`{"count":0}`, state) + + state = suite.chainA.QueryContract( + &suite.Suite, addr, + []byte(fmt.Sprintf(`{"get_total_funds": {"addr": "%s"}}`, ibchooks.WasmHookModuleAccountAddr))) + suite.Require().Equal(`{"total_funds":[{"denom":"ibc/C053D637CCA2A2BA030E2C5EE1B28A16F71CCB0E45E8BE52766DC1B241B77878","amount":"1"}]}`, state) + + suite.receivePacketWithSequence( + addr.String(), + fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": {"increment": {} } } }`, addr), 1) + + state = suite.chainA.QueryContract( + &suite.Suite, addr, + []byte(fmt.Sprintf(`{"get_count": {"addr": "%s"}}`, ibchooks.WasmHookModuleAccountAddr))) + suite.Require().Equal(`{"count":1}`, state) + + state = suite.chainA.QueryContract( + &suite.Suite, addr, + []byte(fmt.Sprintf(`{"get_total_funds": {"addr": "%s"}}`, ibchooks.WasmHookModuleAccountAddr))) + suite.Require().Equal(`{"total_funds":[{"denom":"ibc/C053D637CCA2A2BA030E2C5EE1B28A16F71CCB0E45E8BE52766DC1B241B77878","amount":"2"}]}`, state) + + // Check that the token has now been transferred to the contract + balance = suite.chainA.GetOsmosisApp().BankKeeper.GetBalance(suite.chainA.GetContext(), addr, localDenom) + suite.Require().Equal(sdk.NewInt(2), balance.Amount) +} + +// custom MsgTransfer constructor that supports Memo +func NewMsgTransfer( + token sdk.Coin, sender, receiver string, memo string, +) *transfertypes.MsgTransfer { + return &transfertypes.MsgTransfer{ + SourcePort: "transfer", + SourceChannel: "channel-0", + Token: token, + Sender: sender, + Receiver: receiver, + TimeoutHeight: clienttypes.NewHeight(0, 100), + TimeoutTimestamp: 0, + Memo: memo, + } +} + +type Direction int64 + +const ( + AtoB Direction = iota + BtoA +) + +func (suite *HooksTestSuite) GetEndpoints(direction Direction) (sender *ibctesting.Endpoint, receiver *ibctesting.Endpoint) { + switch direction { + case AtoB: + sender = suite.path.EndpointA + receiver = suite.path.EndpointB + case BtoA: + sender = suite.path.EndpointB + receiver = suite.path.EndpointA + } + return sender, receiver +} + +func (suite *HooksTestSuite) RelayPacket(packet channeltypes.Packet, direction Direction) (*sdk.Result, []byte) { + sender, receiver := suite.GetEndpoints(direction) + + err := receiver.UpdateClient() + suite.Require().NoError(err) + + // receiver Receives + receiveResult, err := receiver.RecvPacketWithResult(packet) + suite.Require().NoError(err) + + ack, err := ibctesting.ParseAckFromEvents(receiveResult.GetEvents()) + suite.Require().NoError(err) + + // sender Acknowledges + err = sender.AcknowledgePacket(packet, ack) + suite.Require().NoError(err) + + err = sender.UpdateClient() + suite.Require().NoError(err) + err = receiver.UpdateClient() + suite.Require().NoError(err) + + return receiveResult, ack +} + +func (suite *HooksTestSuite) FullSend(msg sdk.Msg, direction Direction) (*sdk.Result, *sdk.Result, string, error) { + var sender *osmosisibctesting.TestChain + switch direction { + case AtoB: + sender = suite.chainA + case BtoA: + sender = suite.chainB + } + sendResult, err := sender.SendMsgsNoCheck(msg) + suite.Require().NoError(err) + + packet, err := ibctesting.ParsePacketFromEvents(sendResult.GetEvents()) + suite.Require().NoError(err) + + receiveResult, ack := suite.RelayPacket(packet, direction) + + return sendResult, receiveResult, string(ack), err +} + +func (suite *HooksTestSuite) TestAcks() { + suite.chainA.StoreContractCode(&suite.Suite, "./bytecode/counter.wasm") + addr := suite.chainA.InstantiateContract(&suite.Suite, `{"count": 0}`, 1) + + // Generate swap instructions for the contract + callbackMemo := fmt.Sprintf(`{"ibc_callback":"%s"}`, addr) + // Send IBC transfer with the memo with crosschain-swap instructions + transferMsg := NewMsgTransfer(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000)), suite.chainA.SenderAccount.GetAddress().String(), addr.String(), callbackMemo) + suite.FullSend(transferMsg, AtoB) + + // The test contract will increment the counter for itself every time it receives an ack + state := suite.chainA.QueryContract( + &suite.Suite, addr, + []byte(fmt.Sprintf(`{"get_count": {"addr": "%s"}}`, addr))) + suite.Require().Equal(`{"count":1}`, state) + + suite.FullSend(transferMsg, AtoB) + state = suite.chainA.QueryContract( + &suite.Suite, addr, + []byte(fmt.Sprintf(`{"get_count": {"addr": "%s"}}`, addr))) + suite.Require().Equal(`{"count":2}`, state) + +} + +func (suite *HooksTestSuite) TestSendWithoutMemo() { + // Sending a packet without memo to ensure that the ibc_callback middleware doesn't interfere with a regular send + transferMsg := NewMsgTransfer(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000)), suite.chainA.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), "") + _, _, ack, err := suite.FullSend(transferMsg, AtoB) + suite.Require().NoError(err) + suite.Require().Contains(ack, "result") +} + +type Chain int64 + +const ( + ChainA Chain = iota + ChainB +) + +// This is a copy of the SetupGammPoolsWithBondDenomMultiplier from the test helpers, but using chainA instead of the default +func (suite *HooksTestSuite) SetupPools(chainName Chain, multipliers []sdk.Dec) []gammtypes.CFMMPoolI { + chain := suite.GetChain(chainName) + acc1 := chain.SenderAccount.GetAddress() + bondDenom := chain.GetOsmosisApp().StakingKeeper.BondDenom(chain.GetContext()) + + pools := []gammtypes.CFMMPoolI{} + for index, multiplier := range multipliers { + token := fmt.Sprintf("token%d", index) + uosmoAmount := gammtypes.InitPoolSharesSupply.ToDec().Mul(multiplier).RoundInt() + + var ( + defaultFutureGovernor = "" + + // pool assets + defaultFooAsset = balancer.PoolAsset{ + Weight: sdk.NewInt(100), + Token: sdk.NewCoin(bondDenom, uosmoAmount), + } + defaultBarAsset = balancer.PoolAsset{ + Weight: sdk.NewInt(100), + Token: sdk.NewCoin(token, sdk.NewInt(10000)), + } + + poolAssets = []balancer.PoolAsset{defaultFooAsset, defaultBarAsset} + ) + + poolParams := balancer.PoolParams{ + SwapFee: sdk.NewDecWithPrec(1, 2), + ExitFee: sdk.NewDecWithPrec(1, 2), + } + msg := balancer.NewMsgCreateBalancerPool(acc1, poolParams, poolAssets, defaultFutureGovernor) + + poolId, err := chain.GetOsmosisApp().SwapRouterKeeper.CreatePool(chain.GetContext(), msg) + suite.Require().NoError(err) + + pool, err := chain.GetOsmosisApp().GAMMKeeper.GetPoolAndPoke(chain.GetContext(), poolId) + suite.Require().NoError(err) + + pools = append(pools, pool) + } + + return pools +} + +func (suite *HooksTestSuite) SetupCrosschainSwaps(chainName Chain, withAckTracking bool) (sdk.AccAddress, sdk.AccAddress) { + chain := suite.GetChain(chainName) + owner := chain.SenderAccount.GetAddress() + + // Fund the account with some uosmo and some stake + bankKeeper := chain.GetOsmosisApp().BankKeeper + i, ok := sdk.NewIntFromString("20000000000000000000000") + suite.Require().True(ok) + amounts := sdk.NewCoins(sdk.NewCoin("uosmo", i), sdk.NewCoin("stake", i), sdk.NewCoin("token0", i), sdk.NewCoin("token1", i)) + err := bankKeeper.MintCoins(chain.GetContext(), minttypes.ModuleName, amounts) + suite.Require().NoError(err) + err = bankKeeper.SendCoinsFromModuleToAccount(chain.GetContext(), minttypes.ModuleName, owner, amounts) + suite.Require().NoError(err) + + suite.SetupPools(chainName, []sdk.Dec{sdk.NewDec(20), sdk.NewDec(20)}) + + // Setup contract + chain.StoreContractCode(&suite.Suite, "./bytecode/swaprouter.wasm") + swaprouterAddr := chain.InstantiateContract(&suite.Suite, + fmt.Sprintf(`{"owner": "%s"}`, owner), 1) + chain.StoreContractCode(&suite.Suite, "./bytecode/crosschain_swaps.wasm") + trackAcks := "false" + if withAckTracking { + trackAcks = "true" + } + // Configuring two prefixes for the same channel here. This is so that we can test bad acks when the receiver can't handle the receiving addr + channels := `[["osmo", "channel-0"],["juno", "channel-0"]]` + crosschainAddr := chain.InstantiateContract(&suite.Suite, + fmt.Sprintf(`{"swap_contract": "%s", "track_ibc_sends": %s, "channels": %s}`, swaprouterAddr, trackAcks, channels), 2) + + osmosisApp := chain.GetOsmosisApp() + contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisApp.WasmKeeper) + + ctx := chain.GetContext() + + // ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins + msg := `{"set_route":{"input_denom":"token0","output_denom":"token1","pool_route":[{"pool_id":"1","token_out_denom":"stake"},{"pool_id":"2","token_out_denom":"token1"}]}}` + _, err = contractKeeper.Execute(ctx, swaprouterAddr, owner, []byte(msg), sdk.NewCoins()) + suite.Require().NoError(err) + + // Move forward one block + chain.NextBlock() + chain.Coordinator.IncrementTime() + + // Update both clients + err = suite.path.EndpointA.UpdateClient() + suite.Require().NoError(err) + err = suite.path.EndpointB.UpdateClient() + suite.Require().NoError(err) + + return swaprouterAddr, crosschainAddr +} + +func (suite *HooksTestSuite) TestCrosschainSwaps() { + owner := suite.chainA.SenderAccount.GetAddress() + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + osmosisApp := suite.chainA.GetOsmosisApp() + contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisApp.WasmKeeper) + + balanceSender := osmosisApp.BankKeeper.GetBalance(suite.chainA.GetContext(), owner, "token0") + + ctx := suite.chainA.GetContext() + + msg := fmt.Sprintf(`{"osmosis_swap":{"input_coin":{"denom":"token0","amount":"1000"},"output_denom":"token1","slippage":{"max_slippage_percentage":"20"},"receiver":"%s"}}`, + suite.chainB.SenderAccount.GetAddress(), + ) + res, err := contractKeeper.Execute(ctx, crosschainAddr, owner, []byte(msg), sdk.NewCoins(sdk.NewCoin("token0", sdk.NewInt(1000)))) + suite.Require().NoError(err) + suite.Require().Contains(string(res), "Sent") + suite.Require().Contains(string(res), "token1") + suite.Require().Contains(string(res), fmt.Sprintf("to channel-0/%s", suite.chainB.SenderAccount.GetAddress())) + + balanceSender2 := osmosisApp.BankKeeper.GetBalance(suite.chainA.GetContext(), owner, "token0") + suite.Require().Equal(int64(1000), balanceSender.Amount.Sub(balanceSender2.Amount).Int64()) +} + +// Crosschain swaps should successfully work with and without ack tracking. Only BadAcks depend on ack tracking. +func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCWithoutAckTracking() { + suite.CrosschainSwapsViaIBCTest(false) +} +func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCWithAckTracking() { + suite.CrosschainSwapsViaIBCTest(true) +} + +func (suite *HooksTestSuite) CrosschainSwapsViaIBCTest(withAckTracking bool) { + initializer := suite.chainB.SenderAccount.GetAddress() + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, withAckTracking) + // Send some token0 tokens to B so that there are ibc tokens to send to A and crosschain-swap + transferMsg := NewMsgTransfer(sdk.NewCoin("token0", sdk.NewInt(2000)), suite.chainA.SenderAccount.GetAddress().String(), initializer.String(), "") + suite.FullSend(transferMsg, AtoB) + + // Calculate the names of the tokens when swapped via IBC + denomTrace0 := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", "channel-0", "token0")) + token0IBC := denomTrace0.IBCDenom() + denomTrace1 := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", "channel-0", "token1")) + token1IBC := denomTrace1.IBCDenom() + + osmosisAppB := suite.chainB.GetOsmosisApp() + balanceToken0 := osmosisAppB.BankKeeper.GetBalance(suite.chainB.GetContext(), initializer, token0IBC) + receiver := initializer + balanceToken1 := osmosisAppB.BankKeeper.GetBalance(suite.chainB.GetContext(), receiver, token1IBC) + + suite.Require().Equal(int64(0), balanceToken1.Amount.Int64()) + + // Generate swap instructions for the contract + swapMsg := fmt.Sprintf(`{"osmosis_swap":{"input_coin":{"denom":"token0","amount":"1000"},"output_denom":"token1","slippage":{"max_slippage_percentage":"20"},"receiver":"%s"}}`, + receiver, + ) + // Generate full memo + msg := fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": %s } }`, crosschainAddr, swapMsg) + // Send IBC transfer with the memo with crosschain-swap instructions + transferMsg = NewMsgTransfer(sdk.NewCoin(token0IBC, sdk.NewInt(1000)), suite.chainB.SenderAccount.GetAddress().String(), crosschainAddr.String(), msg) + _, receiveResult, _, err := suite.FullSend(transferMsg, BtoA) + + // We use the receive result here because the receive adds another packet to be sent back + suite.Require().NoError(err) + suite.Require().NotNil(receiveResult) + + // "Relay the packet" by executing the receive on chain B + packet, err := ibctesting.ParsePacketFromEvents(receiveResult.GetEvents()) + suite.Require().NoError(err) + suite.RelayPacket(packet, AtoB) + + balanceToken0After := osmosisAppB.BankKeeper.GetBalance(suite.chainB.GetContext(), initializer, token0IBC) + suite.Require().Equal(int64(1000), balanceToken0.Amount.Sub(balanceToken0After.Amount).Int64()) + + balanceToken1After := osmosisAppB.BankKeeper.GetBalance(suite.chainB.GetContext(), receiver, token1IBC) + suite.Require().Greater(balanceToken1After.Amount.Int64(), int64(0)) +} + +// This is a copy of the above to test bad acks. Lots of repetition here could be abstracted, but keeping as-is for +// now to avoid complexity +// The main difference between this test and the above one is that the receiver specified in the memo does not +// exist on chain B +func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCBadAck() { + initializer := suite.chainB.SenderAccount.GetAddress() + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + // Send some token0 tokens to B so that there are ibc tokens to send to A and crosschain-swap + transferMsg := NewMsgTransfer(sdk.NewCoin("token0", sdk.NewInt(2000)), suite.chainA.SenderAccount.GetAddress().String(), initializer.String(), "") + suite.FullSend(transferMsg, AtoB) + + // Calculate the names of the tokens when swapped via IBC + denomTrace0 := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", "channel-0", "token0")) + token0IBC := denomTrace0.IBCDenom() + + osmosisAppB := suite.chainB.GetOsmosisApp() + balanceToken0 := osmosisAppB.BankKeeper.GetBalance(suite.chainB.GetContext(), initializer, token0IBC) + receiver := "juno1ka8v934kgrw6679fs9cuu0kesyl0ljjy4tmycx" // Will not exist on chainB + + // Generate swap instructions for the contract. This will send correctly on chainA, but fail to be received on chainB + recoverAddr := suite.chainA.SenderAccounts[8].SenderAccount.GetAddress() + swapMsg := fmt.Sprintf(`{"osmosis_swap":{"input_coin":{"denom":"token0","amount":"1000"},"output_denom":"token1","slippage":{"max_slippage_percentage":"20"},"receiver":"%s","failed_delivery": {"recovery_addr": "%s"}}}`, + receiver, // Note that this is the chain A account, which does not exist on chain B + recoverAddr, + ) + // Generate full memo + msg := fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": %s } }`, crosschainAddr, swapMsg) + // Send IBC transfer with the memo with crosschain-swap instructions + transferMsg = NewMsgTransfer(sdk.NewCoin(token0IBC, sdk.NewInt(1000)), suite.chainB.SenderAccount.GetAddress().String(), crosschainAddr.String(), msg) + _, receiveResult, _, err := suite.FullSend(transferMsg, BtoA) + + // We use the receive result here because the receive adds another packet to be sent back + suite.Require().NoError(err) + suite.Require().NotNil(receiveResult) + + // "Relay the packet" by executing the receive on chain B + packet, err := ibctesting.ParsePacketFromEvents(receiveResult.GetEvents()) + suite.Require().NoError(err) + _, ack2 := suite.RelayPacket(packet, AtoB) + fmt.Println(string(ack2)) + + balanceToken0After := osmosisAppB.BankKeeper.GetBalance(suite.chainB.GetContext(), initializer, token0IBC) + suite.Require().Equal(int64(1000), balanceToken0.Amount.Sub(balanceToken0After.Amount).Int64()) + + // The balance is stuck in the contract + osmosisAppA := suite.chainA.GetOsmosisApp() + balanceContract := osmosisAppA.BankKeeper.GetBalance(suite.chainA.GetContext(), crosschainAddr, "token1") + suite.Require().Greater(balanceContract.Amount.Int64(), int64(0)) + + // check that the contract knows this + state := suite.chainA.QueryContract( + &suite.Suite, crosschainAddr, + []byte(fmt.Sprintf(`{"recoverable": {"addr": "%s"}}`, recoverAddr))) + suite.Require().Contains(state, "token1") + suite.Require().Contains(state, `"sequence":2`) + + // Recover the stuck amount + recoverMsg := `{"recover": {}}` + contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisAppA.WasmKeeper) + _, err = contractKeeper.Execute(suite.chainA.GetContext(), crosschainAddr, recoverAddr, []byte(recoverMsg), sdk.NewCoins()) + suite.Require().NoError(err) + + balanceRecovery := osmosisAppA.BankKeeper.GetBalance(suite.chainA.GetContext(), recoverAddr, "token1") + suite.Require().Greater(balanceRecovery.Amount.Int64(), int64(0)) +} + +func (suite *HooksTestSuite) TestBadCrosschainSwapsNextMemoMessages() { + initializer := suite.chainB.SenderAccount.GetAddress() + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + // Send some token0 tokens to B so that there are ibc tokens to send to A and crosschain-swap + transferMsg := NewMsgTransfer(sdk.NewCoin("token0", sdk.NewInt(20000)), suite.chainA.SenderAccount.GetAddress().String(), initializer.String(), "") + suite.FullSend(transferMsg, AtoB) + + // Calculate the names of the tokens when swapped via IBC + denomTrace0 := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", "channel-0", "token0")) + token0IBC := denomTrace0.IBCDenom() + + recoverAddr := suite.chainA.SenderAccounts[8].SenderAccount.GetAddress() + receiver := initializer + + innerMsg := fmt.Sprintf(`{"osmosis_swap":{"input_coin":{"denom":"token0","amount":"1000"},"output_denom":"token1","slippage":{"max_slippage_percentage":"20"},"receiver":"%s","failed_delivery": {"recovery_addr": "%s"},"next_memo":%%s}}`, + receiver, // Note that this is the chain A account, which does not exist on chain B + recoverAddr) + + testCases := []struct { + memo string + expPass bool + }{ + {fmt.Sprintf(innerMsg, `1`), false}, + {fmt.Sprintf(innerMsg, `""`), false}, + {fmt.Sprintf(innerMsg, `null`), true}, + {fmt.Sprintf(innerMsg, `"{\"ibc_callback\": \"something\"}"`), false}, + {fmt.Sprintf(innerMsg, `"{\"myKey\": \"myValue\"}"`), true}, + {fmt.Sprintf(innerMsg, `"{}""`), true}, + } + + for _, tc := range testCases { + // Generate swap instructions for the contract. This will send correctly on chainA, but fail to be received on chainB + // Generate full memo + msg := fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": %s } }`, crosschainAddr, tc.memo) + // Send IBC transfer with the memo with crosschain-swap instructions + transferMsg = NewMsgTransfer(sdk.NewCoin(token0IBC, sdk.NewInt(1000)), suite.chainB.SenderAccount.GetAddress().String(), crosschainAddr.String(), msg) + _, _, ack, _ := suite.FullSend(transferMsg, BtoA) + if tc.expPass { + fmt.Println(ack) + suite.Require().Contains(ack, "result", tc.memo) + } else { + suite.Require().Contains(ack, "error", tc.memo) + } + } +} + +func (suite *HooksTestSuite) CreateIBCPoolOnChainB() { + chain := suite.GetChain(ChainB) + acc1 := chain.SenderAccount.GetAddress() + bondDenom := chain.GetOsmosisApp().StakingKeeper.BondDenom(chain.GetContext()) + + multiplier := sdk.NewDec(20) + denomTrace1 := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", "channel-0", "token1")) + token1IBC := denomTrace1.IBCDenom() + + uosmoAmount := gammtypes.InitPoolSharesSupply.ToDec().Mul(multiplier).RoundInt() + + defaultFutureGovernor := "" + + // pool assets + defaultFooAsset := balancer.PoolAsset{ + Weight: sdk.NewInt(100), + Token: sdk.NewCoin(bondDenom, uosmoAmount), + } + defaultBarAsset := balancer.PoolAsset{ + Weight: sdk.NewInt(100), + Token: sdk.NewCoin(token1IBC, sdk.NewInt(10000)), + } + + poolAssets := []balancer.PoolAsset{defaultFooAsset, defaultBarAsset} + + poolParams := balancer.PoolParams{ + SwapFee: sdk.NewDecWithPrec(1, 2), + ExitFee: sdk.NewDecWithPrec(1, 2), + } + msg := balancer.NewMsgCreateBalancerPool(acc1, poolParams, poolAssets, defaultFutureGovernor) + + poolId, err := chain.GetOsmosisApp().SwapRouterKeeper.CreatePool(chain.GetContext(), msg) + suite.Require().NoError(err) + + _, err = chain.GetOsmosisApp().GAMMKeeper.GetPoolAndPoke(chain.GetContext(), poolId) + suite.Require().NoError(err) + +} + +func (suite *HooksTestSuite) SetupIBCRouteOnChainB(swaprouterAddr, owner sdk.AccAddress) { + chain := suite.GetChain(ChainB) + denomTrace1 := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", "channel-0", "token1")) + token1IBC := denomTrace1.IBCDenom() + + msg := fmt.Sprintf(`{"set_route":{"input_denom":"%s","output_denom":"token0","pool_route":[{"pool_id":"3","token_out_denom":"stake"},{"pool_id":"1","token_out_denom":"token0"}]}}`, + token1IBC) + osmosisApp := chain.GetOsmosisApp() + contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisApp.WasmKeeper) + _, err := contractKeeper.Execute(chain.GetContext(), swaprouterAddr, owner, []byte(msg), sdk.NewCoins()) + suite.Require().NoError(err) + + // Move forward one block + chain.NextBlock() + chain.Coordinator.IncrementTime() + + // Update both clients + err = suite.path.EndpointA.UpdateClient() + suite.Require().NoError(err) + err = suite.path.EndpointB.UpdateClient() + suite.Require().NoError(err) + +} + +func (suite *HooksTestSuite) TestCrosschainForwardWithMemo() { + initializer := suite.chainB.SenderAccount.GetAddress() + receiver := suite.chainA.SenderAccount.GetAddress() + + _, crosschainAddrA := suite.SetupCrosschainSwaps(ChainA, true) + swapRouterAddrB, crosschainAddrB := suite.SetupCrosschainSwaps(ChainB, true) + // Send some token0 and token1 tokens to B so that there are ibc token0 to send to A and crosschain-swap, and token1 to create the pool + transferMsg := NewMsgTransfer(sdk.NewCoin("token0", sdk.NewInt(500000)), suite.chainA.SenderAccount.GetAddress().String(), initializer.String(), "") + suite.FullSend(transferMsg, AtoB) + transferMsg1 := NewMsgTransfer(sdk.NewCoin("token1", sdk.NewInt(500000)), suite.chainA.SenderAccount.GetAddress().String(), initializer.String(), "") + suite.FullSend(transferMsg1, AtoB) + suite.CreateIBCPoolOnChainB() + suite.SetupIBCRouteOnChainB(swapRouterAddrB, suite.chainB.SenderAccount.GetAddress()) + + // Calculate the names of the tokens when swapped via IBC + denomTrace0 := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", "channel-0", "token0")) + token0IBC := denomTrace0.IBCDenom() + denomTrace1 := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", "channel-0", "token1")) + token1IBC := denomTrace1.IBCDenom() + + balanceToken0IBCBefore := suite.chainA.GetOsmosisApp().BankKeeper.GetBalance(suite.chainA.GetContext(), receiver, token0IBC) + fmt.Println("receiver now has: ", balanceToken0IBCBefore) + suite.Require().Equal(int64(0), balanceToken0IBCBefore.Amount.Int64()) + + //suite.Require().Equal(int64(0), balanceToken1.Amount.Int64()) + + // Generate swap instructions for the contract + nextMemo := fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": {"osmosis_swap":{"input_coin":{"denom":"%s","amount":"800"},"output_denom":"token0","slippage":{"max_slippage_percentage":"20"},"receiver":"%s"}}}}`, + crosschainAddrB, + token1IBC, + receiver, + ) + swapMsg := fmt.Sprintf(`{"osmosis_swap":{"input_coin":{"denom":"token0","amount":"1000"},"output_denom":"token1","slippage":{"max_slippage_percentage":"20"},"receiver":"%s", "next_memo": %#v}}`, + crosschainAddrB, + nextMemo, + ) + fmt.Println(swapMsg) + // Generate full memo + msg := fmt.Sprintf(`{"wasm": {"contract": "%s", "msg": %s } }`, crosschainAddrA, swapMsg) + // Send IBC transfer with the memo with crosschain-swap instructions + transferMsg = NewMsgTransfer(sdk.NewCoin(token0IBC, sdk.NewInt(1000)), suite.chainB.SenderAccount.GetAddress().String(), crosschainAddrA.String(), msg) + _, receiveResult, _, err := suite.FullSend(transferMsg, BtoA) + + // We use the receive result here because the receive adds another packet to be sent back + suite.Require().NoError(err) + suite.Require().NotNil(receiveResult) + + // "Relay the packet" by executing the receive on chain B + packet, err := ibctesting.ParsePacketFromEvents(receiveResult.GetEvents()) + suite.Require().NoError(err) + relayResult, _ := suite.RelayPacket(packet, AtoB) + + // Now that chain B has processed it, it should be sending a message to chain A. Relay the response + packet2, err := ibctesting.ParsePacketFromEvents(relayResult.GetEvents()) + suite.Require().NoError(err) + suite.RelayPacket(packet2, BtoA) + + balanceToken0IBCAfter := suite.chainA.GetOsmosisApp().BankKeeper.GetBalance(suite.chainA.GetContext(), receiver, token0IBC) + fmt.Println("receiver now has: ", balanceToken0IBCAfter) + suite.Require().Greater(balanceToken0IBCAfter.Amount.Int64(), int64(0)) +} + +func (suite *HooksTestSuite) GetChain(name Chain) *osmosisibctesting.TestChain { + if name == ChainA { + return suite.chainA + } else { + return suite.chainB + } +} diff --git a/wasmbinding/test/custom_query_test.go b/wasmbinding/test/custom_query_test.go index 639889f03cb..cb015fc9edd 100644 --- a/wasmbinding/test/custom_query_test.go +++ b/wasmbinding/test/custom_query_test.go @@ -1,6 +1,7 @@ package wasmbinding import ( + "crypto/sha256" "encoding/json" "fmt" "os" @@ -305,6 +306,8 @@ func storeReflectCode(t *testing.T, ctx sdk.Context, osmosis *app.OsmosisApp, ad src := wasmtypes.StoreCodeProposalFixture(func(p *wasmtypes.StoreCodeProposal) { p.RunAs = addr.String() p.WASMByteCode = wasmCode + checksum := sha256.Sum256(wasmCode) + p.CodeHash = checksum[:] }) // when stored diff --git a/wasmbinding/test/store_run_test.go b/wasmbinding/test/store_run_test.go index 6f276149818..8fca6baf600 100644 --- a/wasmbinding/test/store_run_test.go +++ b/wasmbinding/test/store_run_test.go @@ -1,6 +1,7 @@ package wasmbinding import ( + "crypto/sha256" "encoding/json" "os" "testing" @@ -41,6 +42,8 @@ func storeCodeViaProposal(t *testing.T, ctx sdk.Context, osmosis *app.OsmosisApp src := types.StoreCodeProposalFixture(func(p *types.StoreCodeProposal) { p.RunAs = addr.String() p.WASMByteCode = wasmCode + checksum := sha256.Sum256(wasmCode) + p.CodeHash = checksum[:] }) // when stored diff --git a/x/ibc-hooks/hooks.go b/x/ibc-hooks/hooks.go index 14557cd1dcd..49081b2cac4 100644 --- a/x/ibc-hooks/hooks.go +++ b/x/ibc-hooks/hooks.go @@ -6,20 +6,20 @@ import ( capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" // ibc-go - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - ibcexported "github.com/cosmos/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" ) type Hooks interface{} type OnChanOpenInitOverrideHooks interface { - OnChanOpenInitOverride(im IBCMiddleware, ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) error + OnChanOpenInitOverride(im IBCMiddleware, ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) (string, error) } type OnChanOpenInitBeforeHooks interface { OnChanOpenInitBeforeHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) } type OnChanOpenInitAfterHooks interface { - OnChanOpenInitAfterHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string, err error) + OnChanOpenInitAfterHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string, finalVersion string, err error) } // OnChanOpenTry Hooks diff --git a/x/ibc-hooks/ibc_module.go b/x/ibc-hooks/ibc_module.go index b7646274a02..50430eb08dd 100644 --- a/x/ibc-hooks/ibc_module.go +++ b/x/ibc-hooks/ibc_module.go @@ -6,9 +6,9 @@ import ( capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" // ibc-go - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" - ibcexported "github.com/cosmos/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" + ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" ) var _ porttypes.Middleware = &IBCMiddleware{} @@ -35,7 +35,7 @@ func (im IBCMiddleware) OnChanOpenInit( channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string, -) error { +) (string, error) { if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenInitOverrideHooks); ok { return hook.OnChanOpenInitOverride(im, ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) } @@ -44,12 +44,12 @@ func (im IBCMiddleware) OnChanOpenInit( hook.OnChanOpenInitBeforeHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) } - err := im.App.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) + finalVersion, err := im.App.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenInitAfterHooks); ok { - hook.OnChanOpenInitAfterHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version, err) + hook.OnChanOpenInitAfterHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version, finalVersion, err) } - return err + return version, err } // OnChanOpenTry implements the IBCMiddleware interface @@ -252,6 +252,6 @@ func (im IBCMiddleware) WriteAcknowledgement( return im.ICS4Middleware.WriteAcknowledgement(ctx, chanCap, packet, ack) } -//func (im IBCMiddleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { -// return im.ICS4Middleware.GetAppVersion(ctx, portID, channelID) -//} +func (im IBCMiddleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { + return im.ICS4Middleware.GetAppVersion(ctx, portID, channelID) +} diff --git a/x/ibc-hooks/ics4_middleware.go b/x/ibc-hooks/ics4_middleware.go index 6ec2b54b2d4..5aeeeca3239 100644 --- a/x/ibc-hooks/ics4_middleware.go +++ b/x/ibc-hooks/ics4_middleware.go @@ -6,8 +6,8 @@ import ( capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" // ibc-go - porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" - ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" + porttypes "github.com/cosmos/ibc-go/v4/modules/core/05-port/types" + ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" ) var _ porttypes.ICS4Wrapper = &ICS4Middleware{} @@ -60,18 +60,18 @@ func (i ICS4Middleware) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilit return err } -//func (i ICS4Middleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { -// if hook, ok := i.Hooks.(GetAppVersionOverrideHooks); ok { -// return hook.GetAppVersionOverride(i, ctx, portID, channelID) -// } -// -// if hook, ok := i.Hooks.(GetAppVersionBeforeHooks); ok { -// hook.GetAppVersionBeforeHook(ctx, portID, channelID) -// } -// version, err := (*i.channel).GetAppVersion(ctx, portID, channelID) -// if hook, ok := i.Hooks.(GetAppVersionAfterHooks); ok { -// hook.GetAppVersionAfterHook(ctx, portID, channelID, version, err) -// } -// -// return version, err -//} +func (i ICS4Middleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { + if hook, ok := i.Hooks.(GetAppVersionOverrideHooks); ok { + return hook.GetAppVersionOverride(i, ctx, portID, channelID) + } + + if hook, ok := i.Hooks.(GetAppVersionBeforeHooks); ok { + hook.GetAppVersionBeforeHook(ctx, portID, channelID) + } + version, err := i.channel.GetAppVersion(ctx, portID, channelID) + if hook, ok := i.Hooks.(GetAppVersionAfterHooks); ok { + hook.GetAppVersionAfterHook(ctx, portID, channelID, version, err) + } + + return version, err +} diff --git a/x/ibc-hooks/testutils/testing_hooks.go b/x/ibc-hooks/testutils/testing_hooks.go index 3b9671c03fc..cf94cadceaf 100644 --- a/x/ibc-hooks/testutils/testing_hooks.go +++ b/x/ibc-hooks/testutils/testing_hooks.go @@ -5,8 +5,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" // ibc-go - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - ibcexported "github.com/cosmos/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" ibchooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks" ) diff --git a/x/ibc-hooks/wasm_hook.go b/x/ibc-hooks/wasm_hook.go index 05a4b53584f..245c0b4cd17 100644 --- a/x/ibc-hooks/wasm_hook.go +++ b/x/ibc-hooks/wasm_hook.go @@ -10,9 +10,9 @@ import ( wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" sdk "github.com/cosmos/cosmos-sdk/types" - transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" + transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks/types" ) @@ -47,10 +47,10 @@ func (h WasmHooks) OnRecvPacketOverride(im IBCMiddleware, ctx sdk.Context, packe return im.App.OnRecvPacket(ctx, packet, relayer) } if err != nil { - return channeltypes.NewErrorAcknowledgement(err.Error()) + return osmoutils.NewStringErrorAcknowledgement(err.Error()) } if msgBytes == nil || contractAddr == nil { // This should never happen - return channeltypes.NewErrorAcknowledgement("error in wasmhook message validation") + return osmoutils.NewStringErrorAcknowledgement("error in wasmhook message validation") } // The funds sent on this packet need to be transferred to the wasm hooks module address/ @@ -62,7 +62,7 @@ func (h WasmHooks) OnRecvPacketOverride(im IBCMiddleware, ctx sdk.Context, packe data.Receiver = WasmHookModuleAccountAddr.String() bz, err := json.Marshal(data) if err != nil { - return channeltypes.NewErrorAcknowledgement(fmt.Sprintf("cannot marshal the ICS20 packet: %s", err.Error())) + return osmoutils.NewStringErrorAcknowledgement(fmt.Sprintf("cannot marshal the ICS20 packet: %s", err.Error())) } packet.Data = bz @@ -76,7 +76,7 @@ func (h WasmHooks) OnRecvPacketOverride(im IBCMiddleware, ctx sdk.Context, packe if !ok { // This should never happen, as it should've been caught in the underlaying call to OnRecvPacket, // but returning here for completeness - return channeltypes.NewErrorAcknowledgement("Invalid packet data: Amount is not an int") + return osmoutils.NewStringErrorAcknowledgement("Invalid packet data: Amount is not an int") } // The packet's denom is the denom in the sender chain. This needs to be converted to the local denom. @@ -91,13 +91,13 @@ func (h WasmHooks) OnRecvPacketOverride(im IBCMiddleware, ctx sdk.Context, packe } response, err := h.execWasmMsg(ctx, &execMsg) if err != nil { - return channeltypes.NewErrorAcknowledgement(err.Error()) + return osmoutils.NewStringErrorAcknowledgement(err.Error()) } fullAck := ContractAck{ContractResult: response.Data, IbcAck: ack.Acknowledgement()} bz, err = json.Marshal(fullAck) if err != nil { - return channeltypes.NewErrorAcknowledgement(fmt.Sprintf(types.ErrBadResponse, err.Error())) + return osmoutils.NewStringErrorAcknowledgement(fmt.Sprintf(types.ErrBadResponse, err.Error())) } return channeltypes.NewResultAcknowledgement(bz) diff --git a/x/ibc-rate-limit/ibc_middleware_test.go b/x/ibc-rate-limit/ibc_middleware_test.go index 9ec7e207db2..47e57ac74b6 100644 --- a/x/ibc-rate-limit/ibc_middleware_test.go +++ b/x/ibc-rate-limit/ibc_middleware_test.go @@ -12,9 +12,9 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" sdk "github.com/cosmos/cosmos-sdk/types" - transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" - ibctesting "github.com/cosmos/ibc-go/v3/testing" + transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" "github.com/stretchr/testify/suite" "github.com/osmosis-labs/osmosis/v13/app/apptesting" diff --git a/x/ibc-rate-limit/ibc_module.go b/x/ibc-rate-limit/ibc_module.go index 29174e8a17a..e9ee1577fa8 100644 --- a/x/ibc-rate-limit/ibc_module.go +++ b/x/ibc-rate-limit/ibc_module.go @@ -9,10 +9,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" - "github.com/cosmos/ibc-go/v3/modules/core/exported" + transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/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" + "github.com/cosmos/ibc-go/v4/modules/core/exported" "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types" ) @@ -38,7 +38,7 @@ func (im *IBCModule) OnChanOpenInit(ctx sdk.Context, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string, -) error { +) (string, error) { return im.app.OnChanOpenInit( ctx, order, @@ -125,7 +125,7 @@ func (im *IBCModule) OnRecvPacket( relayer sdk.AccAddress, ) exported.Acknowledgement { if err := ValidateReceiverAddress(packet); err != nil { - return channeltypes.NewErrorAcknowledgement(err.Error()) + return osmoutils.NewStringErrorAcknowledgement(err.Error()) } contract := im.ics4Middleware.GetParams(ctx) @@ -137,10 +137,10 @@ func (im *IBCModule) OnRecvPacket( err := CheckAndUpdateRateLimits(ctx, im.ics4Middleware.ContractKeeper, "recv_packet", contract, packet) if err != nil { if strings.Contains(err.Error(), "rate limit exceeded") { - return channeltypes.NewErrorAcknowledgement(types.ErrRateLimitExceeded.Error()) + return osmoutils.NewStringErrorAcknowledgement(types.ErrRateLimitExceeded.Error()) } fullError := sdkerrors.Wrap(types.ErrContractError, err.Error()) - return channeltypes.NewErrorAcknowledgement(fullError.Error()) + return osmoutils.NewStringErrorAcknowledgement(fullError.Error()) } // if this returns an Acknowledgement that isn't successful, all state changes are discarded @@ -232,3 +232,7 @@ func (im *IBCModule) WriteAcknowledgement( ) error { return im.ics4Middleware.WriteAcknowledgement(ctx, chanCap, packet, ack) } + +func (im *IBCModule) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { + return im.ics4Middleware.GetAppVersion(ctx, portID, channelID) +} diff --git a/x/ibc-rate-limit/ics4_wrapper.go b/x/ibc-rate-limit/ics4_wrapper.go index ad53bea30ec..52c9bd33a9e 100644 --- a/x/ibc-rate-limit/ics4_wrapper.go +++ b/x/ibc-rate-limit/ics4_wrapper.go @@ -8,9 +8,9 @@ import ( bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" - channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" - porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" - "github.com/cosmos/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" + "github.com/cosmos/ibc-go/v4/modules/core/exported" ) var ( @@ -26,6 +26,11 @@ type ICS4Wrapper struct { paramSpace paramtypes.Subspace } +func (i *ICS4Wrapper) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { + //TODO implement me + panic("implement me") +} + func NewICS4Middleware( channel porttypes.ICS4Wrapper, accountKeeper *authkeeper.AccountKeeper, contractKeeper *wasmkeeper.PermissionedKeeper, diff --git a/x/ibc-rate-limit/rate_limit.go b/x/ibc-rate-limit/rate_limit.go index 6dfd2ec9713..7568bc078af 100644 --- a/x/ibc-rate-limit/rate_limit.go +++ b/x/ibc-rate-limit/rate_limit.go @@ -6,9 +6,9 @@ import ( wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" - "github.com/cosmos/ibc-go/v3/modules/core/exported" + transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + "github.com/cosmos/ibc-go/v4/modules/core/exported" "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types" ) diff --git a/x/ibc-rate-limit/testutil/chain.go b/x/ibc-rate-limit/testutil/chain.go index fa00ec47955..11691dc4058 100644 --- a/x/ibc-rate-limit/testutil/chain.go +++ b/x/ibc-rate-limit/testutil/chain.go @@ -8,9 +8,8 @@ import ( "github.com/cosmos/cosmos-sdk/client" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" - ibctesting "github.com/cosmos/ibc-go/v3/testing" - "github.com/cosmos/ibc-go/v3/testing/simapp/helpers" - abci "github.com/tendermint/tendermint/abci/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" + "github.com/cosmos/ibc-go/v4/testing/simapp/helpers" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/osmosis-labs/osmosis/v13/app" @@ -76,12 +75,8 @@ func SignAndDeliver( ) // Simulate a sending a transaction and committing a block - app.BeginBlock(abci.RequestBeginBlock{Header: header}) gInfo, res, err := app.Deliver(txCfg.TxEncoder(), tx) - app.EndBlock(abci.RequestEndBlock{}) - app.Commit() - return gInfo, res, err } diff --git a/x/ibc-rate-limit/testutil/wasm.go b/x/ibc-rate-limit/testutil/wasm.go index b764bfa4544..a11133baec6 100644 --- a/x/ibc-rate-limit/testutil/wasm.go +++ b/x/ibc-rate-limit/testutil/wasm.go @@ -1,6 +1,7 @@ package osmosisibctesting import ( + "crypto/sha256" "fmt" "io/ioutil" @@ -10,9 +11,10 @@ import ( wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" - "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types" + transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" "github.com/stretchr/testify/suite" + + "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types" ) func (chain *TestChain) StoreContractCode(suite *suite.Suite, path string) { @@ -26,6 +28,8 @@ func (chain *TestChain) StoreContractCode(suite *suite.Suite, path string) { src := wasmtypes.StoreCodeProposalFixture(func(p *wasmtypes.StoreCodeProposal) { p.RunAs = addr.String() p.WASMByteCode = wasmCode + checksum := sha256.Sum256(wasmCode) + p.CodeHash = checksum[:] }) // when stored From e8c3c6cbe242f9681f8dde53c2426b57a4176232 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 22 Dec 2022 16:18:16 -0500 Subject: [PATCH 02/30] feat(x/twap): modify cli to add geometric option (#3812) * feat(x/twap): geometric twap code gen query boilerplate * revert cli change * query gen * wire up API * test * fix * fixes * cli * lint * refactor via flag * refactor * refactor * fixes * lint * add arithmetic twap alias --- x/twap/client/cli/query.go | 110 +++++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 22 deletions(-) diff --git a/x/twap/client/cli/query.go b/x/twap/client/cli/query.go index 4baa6ff70c2..1eec7eda4ea 100644 --- a/x/twap/client/cli/query.go +++ b/x/twap/client/cli/query.go @@ -1,6 +1,7 @@ package twapcli import ( + "context" "fmt" "strings" "time" @@ -18,21 +19,23 @@ import ( // GetQueryCmd returns the cli query commands for this module. func GetQueryCmd() *cobra.Command { cmd := osmocli.QueryIndexCmd(types.ModuleName) - cmd.AddCommand(GetQueryTwapCommand()) + cmd.AddCommand(GetQueryArithmeticCommand()) + cmd.AddCommand(GetQueryGeometricCommand()) return cmd } -// GetQueryTwapCommand returns multiplier of an asset by denom. -func GetQueryTwapCommand() *cobra.Command { +// GetQueryArithmeticCommand returns an arithmetic twap query command. +func GetQueryArithmeticCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "twap [poolid] [base denom] [start time] [end time]", - Short: "Query twap", - Long: osmocli.FormatLongDescDirect(`Query twap for pool. Start time must be unix time. End time can be unix time or duration. + Use: "arithmetic [poolid] [base denom] [start time] [end time]", + Short: "Query arithmetic twap", + Aliases: []string{"twap"}, + Long: osmocli.FormatLongDescDirect(`Query arithmetic twap for pool. Start time must be unix time. End time can be unix time or duration. Example: -{{.CommandPrefix}} twap 1 uosmo 1667088000 24h -{{.CommandPrefix}} twap 1 uosmo 1667088000 1667174400 +{{.CommandPrefix}} arithmetic 1 uosmo 1667088000 24h +{{.CommandPrefix}} arithmetic 1 uosmo 1667088000 1667174400 `, types.ModuleName), Args: cobra.ExactArgs(4), RunE: func(cmd *cobra.Command, args []string) error { @@ -41,37 +44,76 @@ Example: if err != nil { return err } - clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { return err } + quoteDenom, err := getQuoteDenomFromLiquidity(cmd.Context(), clientCtx, poolId, baseDenom) + if err != nil { + return err + } + queryClient := queryproto.NewQueryClient(clientCtx) - gammClient := gammtypes.NewQueryClient(clientCtx) - liquidity, err := gammClient.TotalPoolLiquidity(cmd.Context(), &gammtypes.QueryTotalPoolLiquidityRequest{PoolId: poolId}) + res, err := queryClient.ArithmeticTwap(cmd.Context(), &queryproto.ArithmeticTwapRequest{ + PoolId: poolId, + BaseAsset: baseDenom, + QuoteAsset: quoteDenom, + StartTime: startTime, + EndTime: &endTime, + }) + + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetQueryGeometricCommand returns a geometric twap query command. +func GetQueryGeometricCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "geometric [poolid] [base denom] [start time] [end time]", + Short: "Query geometric twap", + Long: osmocli.FormatLongDescDirect(`Query geometric twap for pool. Start time must be unix time. End time can be unix time or duration. + +Example: +{{.CommandPrefix}} geometric 1 uosmo 1667088000 24h +{{.CommandPrefix}} geometric 1 uosmo 1667088000 1667174400 +`, types.ModuleName), + Args: cobra.ExactArgs(4), + RunE: func(cmd *cobra.Command, args []string) error { + // boilerplate parse fields + poolId, baseDenom, startTime, endTime, err := twapQueryParseArgs(args) + if err != nil { + return err + } + clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { return err } - if len(liquidity.Liquidity) != 2 { - return fmt.Errorf("pool %d has %d assets of liquidity, CLI support only exists for 2 assets right now.", poolId, len(liquidity.Liquidity)) + quoteDenom, err := getQuoteDenomFromLiquidity(cmd.Context(), clientCtx, poolId, baseDenom) + if err != nil { + return err } - quoteDenom := "" - if liquidity.Liquidity[0].Denom == baseDenom { - quoteDenom = liquidity.Liquidity[1].Denom - } else if liquidity.Liquidity[1].Denom == baseDenom { - quoteDenom = liquidity.Liquidity[0].Denom - } else { - return fmt.Errorf("pool %d doesn't have provided baseDenom %s, has %s and %s", - poolId, baseDenom, liquidity.Liquidity[0], liquidity.Liquidity[1]) + queryClient := queryproto.NewQueryClient(clientCtx) + if err != nil { + return err } - res, err := queryClient.ArithmeticTwap(cmd.Context(), &queryproto.ArithmeticTwapRequest{ + res, err := queryClient.GeometricTwap(cmd.Context(), &queryproto.GeometricTwapRequest{ PoolId: poolId, BaseAsset: baseDenom, QuoteAsset: quoteDenom, StartTime: startTime, EndTime: &endTime, }) + if err != nil { return err } @@ -85,6 +127,30 @@ Example: return cmd } +// getQuoteDenomFromLiquidity gets the quote liquidity denom from the pool. In addition, validates that base denom +// exists in the pool. Fails if not. +func getQuoteDenomFromLiquidity(ctx context.Context, clientCtx client.Context, poolId uint64, baseDenom string) (string, error) { + gammClient := gammtypes.NewQueryClient(clientCtx) + liquidity, err := gammClient.TotalPoolLiquidity(ctx, &gammtypes.QueryTotalPoolLiquidityRequest{PoolId: poolId}) + if err != nil { + return "", err + } + if len(liquidity.Liquidity) != 2 { + return "", fmt.Errorf("pool %d has %d assets of liquidity, CLI support only exists for 2 assets right now.", poolId, len(liquidity.Liquidity)) + } + + quoteDenom := "" + if liquidity.Liquidity[0].Denom == baseDenom { + quoteDenom = liquidity.Liquidity[1].Denom + } else if liquidity.Liquidity[1].Denom == baseDenom { + quoteDenom = liquidity.Liquidity[0].Denom + } else { + return "", fmt.Errorf("pool %d doesn't have provided baseDenom %s, has %s and %s", + poolId, baseDenom, liquidity.Liquidity[0], liquidity.Liquidity[1]) + } + return quoteDenom, nil +} + func twapQueryParseArgs(args []string) (poolId uint64, baseDenom string, startTime time.Time, endTime time.Time, err error) { // boilerplate parse fields // From a2fc2c8d691574f764115676b0d4785e2beb9891 Mon Sep 17 00:00:00 2001 From: Nicolas Lara Date: Fri, 23 Dec 2022 19:29:17 +0100 Subject: [PATCH 03/30] Make wasm hooks importable (#3850) * moved ibc-hooks to its own go.mod * updated ibc hooks version * go sum * add ics23 patch into x/ibc-hooks * Fix wasm import version conflict * Update x/ibc-hooks to osmoutils v0.0.2 * Update versions Co-authored-by: Dev Ojha --- app/app.go | 2 +- app/keepers/keepers.go | 2 +- app/keepers/modules.go | 2 +- app/modules.go | 3 +- app/upgrades/v13/upgrade_test.go | 2 +- app/upgrades/v14/constants.go | 24 + go.mod | 3 +- go.sum | 6 +- go.work | 1 + go.work.sum | 485 ++++++++- tests/ibc-hooks/ibc_middleware_test.go | 2 +- x/ibc-hooks/go.mod | 145 +++ x/ibc-hooks/go.sum | 1295 ++++++++++++++++++++++++ x/ibc-hooks/keeper/keeper.go | 53 + x/ibc-hooks/testutils/testing_hooks.go | 2 +- x/ibc-hooks/wasm_hook.go | 4 +- 16 files changed, 2019 insertions(+), 12 deletions(-) create mode 100644 app/upgrades/v14/constants.go create mode 100644 x/ibc-hooks/go.mod create mode 100644 x/ibc-hooks/go.sum create mode 100644 x/ibc-hooks/keeper/keeper.go diff --git a/app/app.go b/app/app.go index 2f7ce2ed6f7..e34065c31d7 100644 --- a/app/app.go +++ b/app/app.go @@ -53,7 +53,7 @@ import ( v8 "github.com/osmosis-labs/osmosis/v13/app/upgrades/v8" v9 "github.com/osmosis-labs/osmosis/v13/app/upgrades/v9" _ "github.com/osmosis-labs/osmosis/v13/client/docs/statik" - ibc_hooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks" + ibc_hooks "github.com/osmosis-labs/osmosis/x/ibc-hooks" ) const appName = "OsmosisApp" diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 3579fcc9a84..595a7a308af 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -34,9 +34,9 @@ import ( upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - ibchooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks" ibcratelimit "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit" ibcratelimittypes "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types" + ibchooks "github.com/osmosis-labs/osmosis/x/ibc-hooks" 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" diff --git a/app/keepers/modules.go b/app/keepers/modules.go index 444b7e09196..2b91ec88a7e 100644 --- a/app/keepers/modules.go +++ b/app/keepers/modules.go @@ -30,7 +30,6 @@ import ( _ "github.com/osmosis-labs/osmosis/v13/client/docs/statik" "github.com/osmosis-labs/osmosis/v13/x/epochs" "github.com/osmosis-labs/osmosis/v13/x/gamm" - ibc_hooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks" ibc_rate_limit "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit" "github.com/osmosis-labs/osmosis/v13/x/incentives" "github.com/osmosis-labs/osmosis/v13/x/lockup" @@ -42,6 +41,7 @@ import ( "github.com/osmosis-labs/osmosis/v13/x/tokenfactory" "github.com/osmosis-labs/osmosis/v13/x/twap/twapmodule" "github.com/osmosis-labs/osmosis/v13/x/txfees" + ibc_hooks "github.com/osmosis-labs/osmosis/x/ibc-hooks" ) // AppModuleBasics returns ModuleBasics for the module BasicManager. diff --git a/app/modules.go b/app/modules.go index a15823ee59b..7974a215c9d 100644 --- a/app/modules.go +++ b/app/modules.go @@ -5,6 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + 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" @@ -13,7 +14,7 @@ import ( ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" icatypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/types" - ibc_hooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks" + ibc_hooks "github.com/osmosis-labs/osmosis/x/ibc-hooks" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" diff --git a/app/upgrades/v13/upgrade_test.go b/app/upgrades/v13/upgrade_test.go index 137566eb6e7..d16e5d35f24 100644 --- a/app/upgrades/v13/upgrade_test.go +++ b/app/upgrades/v13/upgrade_test.go @@ -12,7 +12,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/osmosis-labs/osmosis/v13/app/apptesting" - ibc_hooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks" + ibc_hooks "github.com/osmosis-labs/osmosis/x/ibc-hooks" ) type UpgradeTestSuite struct { diff --git a/app/upgrades/v14/constants.go b/app/upgrades/v14/constants.go new file mode 100644 index 00000000000..ac64426faef --- /dev/null +++ b/app/upgrades/v14/constants.go @@ -0,0 +1,24 @@ +package v14 + +import ( + store "github.com/cosmos/cosmos-sdk/store/types" + ibchookstypes "github.com/osmosis-labs/osmosis/x/ibc-hooks/types" + + "github.com/osmosis-labs/osmosis/v13/app/upgrades" + downtimetypes "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" + protorevtypes "github.com/osmosis-labs/osmosis/v13/x/protorev/types" + swaproutertypes "github.com/osmosis-labs/osmosis/v13/x/swaprouter/types" + valsetpreftypes "github.com/osmosis-labs/osmosis/v13/x/valset-pref/types" +) + +// UpgradeName defines the on-chain upgrade name for the Osmosis v14 upgrade. +const UpgradeName = "v14" + +var Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, + CreateUpgradeHandler: CreateUpgradeHandler, + StoreUpgrades: store.StoreUpgrades{ + Added: []string{valsetpreftypes.StoreKey, protorevtypes.StoreKey, swaproutertypes.StoreKey, downtimetypes.StoreKey, ibchookstypes.StoreKey}, + Deleted: []string{}, + }, +} diff --git a/go.mod b/go.mod index 85aeeef9583..3de01815702 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,8 @@ require ( github.com/ory/dockertest/v3 v3.9.1 github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 github.com/osmosis-labs/osmosis/osmomath v0.0.2 - github.com/osmosis-labs/osmosis/osmoutils v0.0.2-ibc-work + github.com/osmosis-labs/osmosis/osmoutils v0.0.2 + github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.4 github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/spf13/cast v1.5.0 diff --git a/go.sum b/go.sum index 1551200e993..b60788f1091 100644 --- a/go.sum +++ b/go.sum @@ -855,8 +855,10 @@ github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:Ylmch github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI= github.com/osmosis-labs/osmosis/osmomath v0.0.2 h1:8vTobkYfoRTCJCie+jE7gzXvqUUfoPI4NSvTskoci50= github.com/osmosis-labs/osmosis/osmomath v0.0.2/go.mod h1:IpoXO7lvmfsBFfQzaqovs541hpqtrnM+GJSZDi/TZtc= -github.com/osmosis-labs/osmosis/osmoutils v0.0.2-ibc-work h1:/cMOafE/0qNdNcqQsMBFAh/SGi8zdFVmWo6j2R/MQ0I= -github.com/osmosis-labs/osmosis/osmoutils v0.0.2-ibc-work/go.mod h1:T7CCZKYhKWASnv5mRE8u3m0gst3NZ/sU16Brjmv4UPw= +github.com/osmosis-labs/osmosis/osmoutils v0.0.2 h1:oFsKFhmVOQHzqRfezFAkg/BlsUEwPhQK5n13a3uC6xc= +github.com/osmosis-labs/osmosis/osmoutils v0.0.2/go.mod h1:T7CCZKYhKWASnv5mRE8u3m0gst3NZ/sU16Brjmv4UPw= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.4 h1:Ny0GQ40agzVesBpZ/AG8Bi7Hn3ZN+qGEJOX272Bck+Q= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.4/go.mod h1:JleJ+kfjhlUpYnk7VfNrpHd+P7A5Lq5VhuAxGV7FbJM= github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30 h1:6uMi7HhPSwvKKU7j5NqljseFTEz4I7qHr+IPnnn42Ck= github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30/go.mod h1:5fDYJyMXBq6u2iuHqqOTYiZ5NitIOeIW5k7qEXqbwJE= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= diff --git a/go.work b/go.work index b4ddea0fe2f..d0323029630 100644 --- a/go.work +++ b/go.work @@ -2,4 +2,5 @@ go 1.18 use ./osmomath use ./osmoutils +use ./x/ibc-hooks use . diff --git a/go.work.sum b/go.work.sum index ba20f67a17f..b5ad2dc796a 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,3 +1,19 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= @@ -9,6 +25,15 @@ cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3Ee cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= @@ -20,10 +45,13 @@ cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7X cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/firestore v1.8.0/go.mod h1:r3KB8cAdRIe8znzoPWLw8S6gpDVd9treohhn8b09424= cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= @@ -46,17 +74,472 @@ cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3s cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/adlio/schema v1.1.13/go.mod h1:L5Z7tw+7lRK1Fnpi/LT/ooCP1elkXn0krMWBQHUhEDE= +github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.11/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= +github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/bufbuild/buf v1.9.0/go.mod h1:1Q+rMHiMVcfgScEF/GOldxmu4o9TrQ2sQQh58K6MscE= +github.com/bufbuild/connect-go v1.0.0/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I= +github.com/bufbuild/protocompile v0.1.0/go.mod h1:ix/MMMdsT3fzxfw91dvbfzKW3fRRnuPCP47kpAm5m/4= +github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0= +github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= +github.com/cosmos/interchain-accounts v0.2.4/go.mod h1:jeiJEb0zg609G0oCrCG0r6Guhb7YbA1uFiwww/1YgZE= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= +github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/api v1.15.3/go.mod h1:/g/qgcoBcEXALCNZgRRisyTW0nY86++L0KbeAMXYCeY= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hashicorp/serf v0.9.8/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= +github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/informalsystems/tm-load-test v1.0.0/go.mod h1:WVaSKaQdfZK3v0C74EMzn7//+3aeCZF8wkIKBz2/M74= +github.com/jdxcode/netrc v0.0.0-20210204082910-926c7f70242a/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw= +github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= +github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= +github.com/jhump/protoreflect v1.12.1-0.20220721211354-060cc04fc18b/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI= +github.com/jhump/protoreflect v1.13.1-0.20220928232736-101791cb1b4c/go.mod h1:JytZfP5d0r8pVNLZvai7U/MCuTWITgrI4tTg7puQFKI= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/osmosis-labs/wasmd v0.29.2-osmo-v13/go.mod h1:UlLBU5vuHncwQUM9W8lw+2mEptEMFxxfVWupZ6sXtn4= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/buildkit v0.10.4/go.mod h1:Yajz9vt1Zw5q9Pp4pdb3TCSUXJBIroIQGQ3TTs/sLug= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q= +github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY= +github.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g= +github.com/nats-io/nats.go v1.12.1/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= +github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= +github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= +github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI= +github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= +github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.8.0/go.mod h1:TmKwZAo97S4Fy4sfMH/HX/cQP5D+ijra2NyLpNNmttY= +github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw= +github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= +github.com/tendermint/tendermint v0.34.14/go.mod h1:FrwVm3TvsVicI9Z7FlucHV6Znfd5KBc/Lpp69cCwtk0= +github.com/tendermint/tendermint v0.34.21/go.mod h1:XDvfg6U7grcFTDx7VkzxnhazQ/bspGJAn4DZ6DcLLjQ= +github.com/tendermint/tendermint v0.34.23/go.mod h1:rXVrl4OYzmIa1I91av3iLv2HS0fGSiucyW9J4aMTpKI= +github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= +github.com/tendermint/tm-db v0.6.6/go.mod h1:wP8d49A85B7/erz/r4YbKssKw6ylsO/hKtFk7E1aWZI= +github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/vektra/mockery/v2 v2.14.0/go.mod h1:bnD1T8tExSgPD1ripLkDbr60JA9VtQeu12P3wgLZd7M= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/client/v2 v2.305.5/go.mod h1:zQjKllfqfBVyVStbt4FaosoX2iYd8fV/GRy/PbowgP4= +go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.36.3/go.mod h1:Dts42MGkzZne2yCru741+bFiTMWkIj/LLRizad7b9tw= +go.opentelemetry.io/otel v1.11.0/go.mod h1:H2KtuEphyMvlhZ+F7tg9GRhAOe60moNx61Ex+WmiKkk= +go.opentelemetry.io/otel/metric v0.32.3/go.mod h1:pgiGmKohxHyTPHGOff+vrtIH39/R9fiO/WoenUQ3kcc= +go.opentelemetry.io/otel/trace v1.11.0/go.mod h1:nyYjis9jy0gytE9LXGU+/m1sHTKbRY0fX0hulNNDP1U= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220726230323-06994584191e/go.mod h1:AaygXjzTFtRAg2ttMY5RMuhpJ3cNnI0XpyFJD1iQRSM= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220727055044-e65921a090b8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211101144312-62acf1d99145/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/tests/ibc-hooks/ibc_middleware_test.go b/tests/ibc-hooks/ibc_middleware_test.go index 7ca0743a499..9f316700bb8 100644 --- a/tests/ibc-hooks/ibc_middleware_test.go +++ b/tests/ibc-hooks/ibc_middleware_test.go @@ -9,8 +9,8 @@ import ( "github.com/osmosis-labs/osmosis/v13/x/gamm/pool-models/balancer" gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types" - ibchooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks" minttypes "github.com/osmosis-labs/osmosis/v13/x/mint/types" + ibchooks "github.com/osmosis-labs/osmosis/x/ibc-hooks" "github.com/osmosis-labs/osmosis/osmoutils" diff --git a/x/ibc-hooks/go.mod b/x/ibc-hooks/go.mod new file mode 100644 index 00000000000..65f3b7a9918 --- /dev/null +++ b/x/ibc-hooks/go.mod @@ -0,0 +1,145 @@ +module github.com/osmosis-labs/osmosis/x/ibc-hooks + +go 1.18 + +require ( + github.com/CosmWasm/wasmd v0.29.2 + github.com/cosmos/cosmos-sdk v0.46.7 + github.com/cosmos/ibc-go/v4 v4.2.0 + github.com/gorilla/mux v1.8.0 + github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/osmosis-labs/osmosis/osmoutils v0.0.2 + github.com/spf13/cobra v1.6.1 + github.com/tendermint/tendermint v0.34.24 +) + +require ( + filippo.io/edwards25519 v1.0.0-beta.2 // indirect + 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/CosmWasm/wasmvm v1.1.1 // indirect + github.com/Workiva/go-datastructures v1.0.53 // indirect + github.com/armon/go-metrics v0.4.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/btcsuite/btcd v0.22.1 // indirect + github.com/cenkalti/backoff/v4 v4.1.1 // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect + github.com/confio/ics23/go v0.7.0 // indirect + github.com/cosmos/btcutil v1.0.4 // indirect + github.com/cosmos/cosmos-proto v1.0.0-alpha8 // indirect + github.com/cosmos/go-bip39 v1.0.0 // indirect + github.com/cosmos/gogoproto v1.4.3 // indirect + github.com/cosmos/gorocksdb v1.2.0 // indirect + github.com/cosmos/iavl v0.19.4 // indirect + github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect + github.com/cosmos/ledger-go v0.9.2 // indirect + github.com/creachadair/taskgroup v0.3.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 + github.com/dgraph-io/badger/v3 v3.2103.2 // indirect + github.com/dgraph-io/ristretto v0.1.0 // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect + github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac // indirect + github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gogo/gateway v1.1.0 // indirect + github.com/gogo/protobuf v1.3.3 // indirect + github.com/golang/glog v1.0.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/btree v1.1.2 // indirect + github.com/google/flatbuffers v1.12.1 // indirect + github.com/google/gofuzz v1.2.0 // indirect + 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/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 + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect + github.com/improbable-eng/grpc-web v0.15.0 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/klauspost/compress v1.15.11 // indirect + github.com/lib/pq v1.10.6 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // 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/opencontainers/go-digest v1.0.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.5 // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect + github.com/rakyll/statik v0.1.7 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/regen-network/cosmos-proto v0.3.1 // indirect + github.com/rs/cors v1.8.2 // indirect + github.com/rs/zerolog v1.27.0 // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/spf13/afero v1.9.2 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.14.0 // indirect + github.com/stretchr/testify v1.8.1 // indirect + github.com/subosito/gotenv v1.4.1 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + github.com/tendermint/btcd v0.1.1 // indirect + github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b // indirect + github.com/zondax/hid v0.9.0 // indirect + go.etcd.io/bbolt v1.3.6 // indirect + go.opencensus.io v0.23.0 // indirect + golang.org/x/crypto v0.1.0 // indirect + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect + golang.org/x/net v0.1.0 // indirect + golang.org/x/sys v0.1.0 // indirect + golang.org/x/term v0.1.0 // indirect + golang.org/x/text v0.4.0 // indirect + google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e // indirect + google.golang.org/grpc v1.50.1 // indirect + google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + nhooyr.io/websocket v1.8.6 // indirect +) + +replace ( + // osmosis-patched wasmd + github.com/CosmWasm/wasmd => github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30 + // dragonberry + github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 + // Our cosmos-sdk branch is: https://github.com/osmosis-labs/cosmos-sdk, current branch: v13.x. Direct commit link: https://github.com/osmosis-labs/cosmos-sdk/commit/8757a61551aa1ea993c85a523e18094ab555b1d7 + // tag: https://github.com/osmosis-labs/cosmos-sdk/releases/tag/sdk-v13.0.0-rc2 + github.com/cosmos/cosmos-sdk => github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20221118211718-545aed73e94e + // use cosmos-compatible protobufs + github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 +) diff --git a/x/ibc-hooks/go.sum b/x/ibc-hooks/go.sum new file mode 100644 index 00000000000..31a1070a25b --- /dev/null +++ b/x/ibc-hooks/go.sum @@ -0,0 +1,1295 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.0.0-beta.2 h1:/BZRNzm8N4K4eWfK28dL4yescorxtO7YG1yun8fy+pI= +filippo.io/edwards25519 v1.0.0-beta.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +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/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +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/CosmWasm/wasmvm v1.1.1 h1:0xtdrmmsP9fibe+x42WcMkp5aQ738BICgcH3FNVLzm4= +github.com/CosmWasm/wasmvm v1.1.1/go.mod h1:ei0xpvomwSdONsxDuONzV7bL1jSET1M8brEx0FCXc+A= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +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/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= +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/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= +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/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6/go.mod h1:eSYp2T6f0apnuW8TzhV3f6Aff2SE8Dwio++U4ha4yEM= +github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +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= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.4.0 h1:yCQqn7dwca4ITXb+CbubHmedzaQYHhNhrEXLYUeEe8Q= +github.com/armon/go-metrics v0.4.0/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +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/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= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= +github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +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 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +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.7.0 h1:lmTO/JEpCvZgpbkOITL95rA80CPKb5CtMzLaqF2mCNg= +github.com/coinbase/rosetta-sdk-go v0.7.0/go.mod h1:7nD3oBPIiHqhRprqvMgPoGxe/nyq3yftRmpsy29coWE= +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= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44= +github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU= +github.com/cosmos/cosmos-proto v1.0.0-alpha8 h1:d3pCRuMYYvGA5bM0ZbbjKn+AoQD4A7dyNG2wzwWalUw= +github.com/cosmos/cosmos-proto v1.0.0-alpha8/go.mod h1:6/p+Bc4O8JKeZqe0VqUGTX31eoYqemTT4C1hLCWsO7I= +github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 h1:iKclrn3YEOwk4jQHT2ulgzuXyxmzmPczUalMwW4XH9k= +github.com/cosmos/cosmos-sdk/ics23/go v0.8.0/go.mod h1:2a4dBq88TUoqoWAU5eu0lGvpFP3wWDPgdHPargtyw30= +github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= +github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= +github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/gogoproto v1.4.3 h1:RP3yyVREh9snv/lsOvmsAPQt8f44LgL281X0IOIhhcI= +github.com/cosmos/gogoproto v1.4.3/go.mod h1:0hLIG5TR7IvV1fme1HCFKjfzW9X2x0Mo+RooWXCnOWU= +github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= +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/ibc-go/v4 v4.2.0 h1:Fx/kKq/uvawrAxk6ZrQ6sEIgffLRU5Cs/AUnvpPBrHI= +github.com/cosmos/ibc-go/v4 v4.2.0/go.mod h1:57qWScDtfCx3FOMLYmBIKPbOLE6xiVhrgxHAQmbWYXM= +github.com/cosmos/interchain-accounts v0.2.4 h1:7UrroFQsCRSp17980mk6anx4YteveIJVkU+a0wlsHQI= +github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4= +github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY= +github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI= +github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI= +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= +github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM= +github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= +github.com/dgraph-io/badger/v3 v3.2103.2 h1:dpyM5eCJAtQCBcMCZcT4UBZchuTJgCywerHHgmxfxM8= +github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M= +github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= +github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac h1:opbrjaN/L8gg6Xh5D04Tem+8xVcz6ajZlGCs49mQgyg= +github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= +github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +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/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= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +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.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +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= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= +github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= +github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= +github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +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-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= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= +github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= +github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 h1:uUjLpLt6bVvZ72SQc/B4dXcPBw4Vgd7soowdRl52qEM= +github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87/go.mod h1:XGsKKeXxeRr95aEOgipvluMPlgjr7dGlk9ZTWOjcUcg= +github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= +github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jhump/protoreflect v1.12.1-0.20220721211354-060cc04fc18b h1:izTof8BKh/nE1wrKOrloNA5q4odOarjf+Xpe+4qow98= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +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/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= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +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/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +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.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= +github.com/lib/pq v1.10.6/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= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +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 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/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.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +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= +github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= +github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +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/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +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 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +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/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= +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= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= +github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20221118211718-545aed73e94e h1:A3byMZpvq21iI7yWJUNdHw0nf8jVAbVUsWY9twnXSXE= +github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20221118211718-545aed73e94e/go.mod h1:rud0OaBIuq3+qOqtwT4SR7Q7iSzRp7w41fjninTjfnQ= +github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20221223175211-9d2007cbaad6 h1:/Ea4oM6/hQLusuQfex0slJg+Gc8UYq7XVOchBNQg9g4= +github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20221223175211-9d2007cbaad6/go.mod h1:T7CCZKYhKWASnv5mRE8u3m0gst3NZ/sU16Brjmv4UPw= +github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30 h1:6uMi7HhPSwvKKU7j5NqljseFTEz4I7qHr+IPnnn42Ck= +github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30/go.mod h1:5fDYJyMXBq6u2iuHqqOTYiZ5NitIOeIW5k7qEXqbwJE= +github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +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 v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +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= +github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +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.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +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/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +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.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +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.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +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= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= +github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +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/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= +github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= +github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= +github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= +github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +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/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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +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.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +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/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.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +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.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU= +github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +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= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +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 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= +github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= +github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= +github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= +github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= +github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tendermint/tendermint v0.34.24 h1:879MKKJWYYPJEMMKME+DWUTY4V9f/FBpnZDI82ky+4k= +github.com/tendermint/tendermint v0.34.24/go.mod h1:rXVrl4OYzmIa1I91av3iLv2HS0fGSiucyW9J4aMTpKI= +github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b h1:Y3ZPG6gdDCAV2sdGkD759ji/09GzaNu1X3qKTmZIbTo= +github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b/go.mod h1:ADqbS9NOSnBRK9R2RtYC61CdsHmVMD/yXAzcMuPexbU= +github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= +github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/sjson v1.1.4/go.mod h1:wXpKXu8CtDjKAZ+3DrKY5ROCorDFahq8l0tey/Lx1fg= +github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI= +github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= +github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +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= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +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/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +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= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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-20200820211705-5c72a883971a/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.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +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= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +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/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-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +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.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +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-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +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= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/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.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +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= +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.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +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= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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-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= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +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.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= +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= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +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= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +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-20221024183307-1bc688fe9f3e h1:S9GbmC1iCgvbLyAokVCwiO6tVIrU9Y7c5oMx1V/ki/Y= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +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.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk= +google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/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= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/x/ibc-hooks/keeper/keeper.go b/x/ibc-hooks/keeper/keeper.go new file mode 100644 index 00000000000..5aa2965bcbd --- /dev/null +++ b/x/ibc-hooks/keeper/keeper.go @@ -0,0 +1,53 @@ +package keeper + +import ( + "fmt" + + "github.com/tendermint/tendermint/libs/log" + + "github.com/osmosis-labs/osmosis/x/ibc-hooks/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type ( + Keeper struct { + storeKey sdk.StoreKey + } +) + +// NewKeeper returns a new instance of the x/ibchooks keeper +func NewKeeper( + storeKey sdk.StoreKey, +) Keeper { + return Keeper{ + storeKey: storeKey, + } +} + +// Logger returns a logger for the x/tokenfactory module +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +func GetPacketKey(channel string, packetSequence uint64) []byte { + return []byte(fmt.Sprintf("%s::%d", channel, packetSequence)) +} + +// StorePacketCallback stores which contract will be listening for the ack or timeout of a packet +func (k Keeper) StorePacketCallback(ctx sdk.Context, channel string, packetSequence uint64, contract string) { + store := ctx.KVStore(k.storeKey) + store.Set(GetPacketKey(channel, packetSequence), []byte(contract)) +} + +// GetPacketCallback returns the bech32 addr of the contract that is expecting a callback from a packet +func (k Keeper) GetPacketCallback(ctx sdk.Context, channel string, packetSequence uint64) string { + store := ctx.KVStore(k.storeKey) + return string(store.Get(GetPacketKey(channel, packetSequence))) +} + +// DeletePacketCallback deletes the callback from storage once it has been processed +func (k Keeper) DeletePacketCallback(ctx sdk.Context, channel string, packetSequence uint64) { + store := ctx.KVStore(k.storeKey) + store.Delete(GetPacketKey(channel, packetSequence)) +} diff --git a/x/ibc-hooks/testutils/testing_hooks.go b/x/ibc-hooks/testutils/testing_hooks.go index cf94cadceaf..cce68c627f2 100644 --- a/x/ibc-hooks/testutils/testing_hooks.go +++ b/x/ibc-hooks/testutils/testing_hooks.go @@ -8,7 +8,7 @@ import ( channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" - ibchooks "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks" + ibchooks "github.com/osmosis-labs/osmosis/x/ibc-hooks" ) var ( diff --git a/x/ibc-hooks/wasm_hook.go b/x/ibc-hooks/wasm_hook.go index 245c0b4cd17..5d0f172295b 100644 --- a/x/ibc-hooks/wasm_hook.go +++ b/x/ibc-hooks/wasm_hook.go @@ -4,6 +4,8 @@ import ( "encoding/json" "fmt" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/osmosis-labs/osmosis/osmoutils" @@ -14,7 +16,7 @@ import ( channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" - "github.com/osmosis-labs/osmosis/v13/x/ibc-hooks/types" + "github.com/osmosis-labs/osmosis/x/ibc-hooks/types" ) type ContractAck struct { From 129cbcbbadfde2292ccca98f626fd03a10114244 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 23 Dec 2022 15:35:01 -0500 Subject: [PATCH 04/30] refactor(x/twap): handle spot price error case in the context of geometric twap (#3845) * refactor(x/twap): handle spot price error case * supporting test cases * table-driven log tests --- osmomath/sigfig_round_test.go | 7 + .../pool-models/balancer/pool_suite_test.go | 16 ++ x/twap/logic.go | 38 ++- x/twap/logic_test.go | 225 +++++++++++++++++- 4 files changed, 280 insertions(+), 6 deletions(-) diff --git a/osmomath/sigfig_round_test.go b/osmomath/sigfig_round_test.go index 71cbb96ac6f..eca712b0096 100644 --- a/osmomath/sigfig_round_test.go +++ b/osmomath/sigfig_round_test.go @@ -70,6 +70,13 @@ func TestSigFigRound(t *testing.T) { tenToSigFig: sdk.NewInt(100), expectedResult: sdk.MustNewDecFromStr("0.087"), }, + + { + name: "minimum decimal is still kept", + decimal: sdk.NewDecWithPrec(1, 18), + tenToSigFig: sdk.NewInt(10), + expectedResult: sdk.NewDecWithPrec(1, 18), + }, } for i, tc := range testCases { diff --git a/x/gamm/pool-models/balancer/pool_suite_test.go b/x/gamm/pool-models/balancer/pool_suite_test.go index 54484c78e11..8cddfa5acf6 100644 --- a/x/gamm/pool-models/balancer/pool_suite_test.go +++ b/x/gamm/pool-models/balancer/pool_suite_test.go @@ -766,6 +766,22 @@ func (suite *KeeperTestSuite) TestBalancerSpotPriceBounds() { quoteDenomWeight: sdk.NewInt(100), expectError: true, }, + { + name: "internal error due to spot price precision being too small, resulting in 0 spot price", + quoteDenomPoolInput: sdk.NewCoin(baseDenom, sdk.OneInt()), + quoteDenomWeight: sdk.NewInt(100), + baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.NewDec(10).PowerMut(19).TruncateInt().Sub(sdk.NewInt(2))), + baseDenomWeight: sdk.NewInt(100), + expectError: true, + }, + { + name: "at min spot price", + quoteDenomPoolInput: sdk.NewCoin(baseDenom, sdk.OneInt()), + quoteDenomWeight: sdk.NewInt(100), + baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.NewDec(10).PowerMut(18).TruncateInt()), + baseDenomWeight: sdk.NewInt(100), + expectedOutput: sdk.OneDec().Quo(sdk.NewDec(10).PowerMut(18)), + }, } for _, tc := range tests { diff --git a/x/twap/logic.go b/x/twap/logic.go index 2f4a471111d..c7e279e812e 100644 --- a/x/twap/logic.go +++ b/x/twap/logic.go @@ -190,6 +190,20 @@ func recordWithUpdatedAccumulators(record types.TwapRecord, newTime time.Time) t p1NewAccum := types.SpotPriceMulDuration(record.P1LastSpotPrice, timeDelta) newRecord.P1ArithmeticTwapAccumulator = newRecord.P1ArithmeticTwapAccumulator.Add(p1NewAccum) + // If the last spot price is zero, then the logarithm is undefined. + // As a result, we cannot update the geometric accumulator. + // We set the last error time to be the new time, and return the record. + if record.P0LastSpotPrice.IsZero() { + newRecord.LastErrorTime = newTime + return newRecord + } + + // logP0SpotPrice = log_{2}{P_0} + logP0SpotPrice := twapLog(record.P0LastSpotPrice) + // p0NewGeomAccum = log_{2}{P_0} * timeDelta + p0NewGeomAccum := types.SpotPriceMulDuration(logP0SpotPrice, timeDelta) + newRecord.GeometricTwapAccumulator = newRecord.GeometricTwapAccumulator.Add(p0NewGeomAccum) + return newRecord } @@ -243,11 +257,25 @@ func computeArithmeticTwap(startRecord types.TwapRecord, endRecord types.TwapRec } return endRecord.P1LastSpotPrice, err } - var accumDiff sdk.Dec - if quoteAsset == startRecord.Asset0Denom { - accumDiff = endRecord.P0ArithmeticTwapAccumulator.Sub(startRecord.P0ArithmeticTwapAccumulator) - } else { - accumDiff = endRecord.P1ArithmeticTwapAccumulator.Sub(startRecord.P1ArithmeticTwapAccumulator) + + return strategy.computeTwap(startRecord, endRecord, quoteAsset), err +} + +// twapLog returns the logarithm of the given spot price, base 2. +// Panics if zero is given. +func twapLog(price sdk.Dec) sdk.Dec { + if price.IsZero() { + panic("twap: cannot take logarithm of zero") + } + + return osmomath.BigDecFromSDKDec(price).LogBase2().SDKDec() +} + +// twapPow exponentiates 2 to the given exponent. +func twapPow(exponent sdk.Dec) sdk.Dec { + exp2 := osmomath.Exp2(osmomath.BigDecFromSDKDec(exponent.Abs())) + if exponent.IsNegative() { + return osmomath.OneDec().Quo(exp2).SDKDec() } return types.AccumDiffDivDuration(accumDiff, timeDelta), err } diff --git a/x/twap/logic_test.go b/x/twap/logic_test.go index 7ea6f6a98c9..0d347e8b6e0 100644 --- a/x/twap/logic_test.go +++ b/x/twap/logic_test.go @@ -9,6 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + "github.com/osmosis-labs/osmosis/osmomath" "github.com/osmosis-labs/osmosis/osmoutils" "github.com/osmosis-labs/osmosis/osmoutils/osmoassert" gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types" @@ -260,7 +261,27 @@ func TestRecordWithUpdatedAccumulators(t *testing.T) { "same time, accumulator should not change": { record: defaultRecord, newTime: time.Unix(1, 0), - expRecord: newExpRecord(oneDec, twoDec), + expRecord: newExpRecord(oneDec, twoDec, pointFiveDec), + }, + "sp0 - zero spot price - accum0 unchanged, accum1 updated, geom accum unchanged, last err time set": { + record: withPrice0Set(defaultRecord, sdk.ZeroDec()), + newTime: defaultRecord.Time.Add(time.Second), + expRecord: withLastErrTime(newExpRecord(oneDec, twoDec.Add(sdk.NewDecWithPrec(1, 1).Mul(OneSec)), pointFiveDec), defaultRecord.Time.Add(time.Second)), + }, + "sp1 - zero spot price - accum0 updated, accum1 unchanged, geom accum updated correctly": { + record: withPrice1Set(defaultRecord, sdk.ZeroDec()), + newTime: defaultRecord.Time.Add(time.Second), + expRecord: newExpRecord(tenSecAccum.Add(oneDec), twoDec, pointFiveDec.Add(geometricTenSecAccum)), + }, + "both sp - zero spot price - accum0 unchange, accum1 unchanged, geom accum unchanged": { + record: withPrice1Set(withPrice0Set(defaultRecord, sdk.ZeroDec()), sdk.ZeroDec()), + newTime: defaultRecord.Time.Add(time.Second), + expRecord: withLastErrTime(newExpRecord(oneDec, twoDec, pointFiveDec), defaultRecord.Time.Add(time.Second)), + }, + "spot price of one - geom accumulator 0": { + record: withPrice1Set(withPrice0Set(defaultRecord, sdk.OneDec()), sdk.OneDec()), + newTime: defaultRecord.Time.Add(time.Second), + expRecord: newExpRecord(oneDec.Add(OneSec), twoDec.Add(OneSec), pointFiveDec), }, } @@ -1424,3 +1445,205 @@ func (s *TestSuite) TestAfterCreatePool() { }) } } + +// This tests the behavior of computeArithmeticTwap, around error returning +// when there has been an intermediate spot price error. +func (s *TestSuite) TestComputeArithmeticTwapWithSpotPriceError() { + newOneSidedRecordWErrorTime := func(time time.Time, accum sdk.Dec, useP0 bool, errTime time.Time) types.TwapRecord { + record := newOneSidedRecord(time, accum, useP0) + record.LastErrorTime = errTime + return record + } + + arithStrategy := &twap.ArithmeticTwapStrategy{ + TwapKeeper: *s.App.TwapKeeper, + } + + tests := map[string]computeTwapTestCase{ + // should error, since end time may have been used to interpolate this value + "errAtEndTime from end record": { + startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newOneSidedRecordWErrorTime(tPlusOne, OneSec, true, tPlusOne), + quoteAsset: denom0, + expTwap: sdk.OneDec(), + expErr: true, + }, + // should error, since start time may have been used to interpolate this value + "err at StartTime exactly from end record": { + startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newOneSidedRecordWErrorTime(tPlusOne, OneSec, true, baseTime), + quoteAsset: denom0, + expTwap: sdk.OneDec(), + expErr: true, + }, + // should error, since start record is erroneous + "err at StartTime exactly from start record": { + startRecord: newOneSidedRecordWErrorTime(baseTime, sdk.ZeroDec(), true, baseTime), + endRecord: newOneSidedRecord(tPlusOne, OneSec, true), + quoteAsset: denom0, + expTwap: sdk.OneDec(), + expErr: true, + }, + "err before StartTime": { + startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newOneSidedRecordWErrorTime(tPlusOne, OneSec, true, tMinOne), + quoteAsset: denom0, + expTwap: sdk.OneDec(), + expErr: false, + }, + // Should not happen, but if it did would error + "err after EndTime": { + startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newOneSidedRecordWErrorTime(tPlusOne, OneSec.MulInt64(2), true, baseTime.Add(20*time.Second)), + quoteAsset: denom0, + expTwap: sdk.OneDec().MulInt64(2), + expErr: true, + }, + } + for name, test := range tests { + s.Run(name, func() { + actualTwap, err := twap.ComputeTwap(test.startRecord, test.endRecord, test.quoteAsset, arithStrategy) + s.Require().Equal(test.expTwap, actualTwap) + osmoassert.ConditionalError(s.T(), test.expErr, err) + }) + } +} + +// TestTwapLog_CorrectBase tests that the base of 2 is used for the twap log function. +// log_2{16} = 4 +func (s *TestSuite) TestTwapLog_CorrectBase() { + logOf := sdk.NewDec(16) + expectedValue := sdk.NewDec(4) + + result := twap.TwapLog(logOf) + + s.Require().Equal(expectedValue, result) +} + +func (s *TestSuite) TestTwapLog() { + smallestAdditiveTolerance := osmomath.ErrTolerance{ + AdditiveTolerance: sdk.SmallestDec(), + } + + testcases := []struct { + name string + price sdk.Dec + expected sdk.Dec + expectPanic bool + }{ + { + "max spot price", + gammtypes.MaxSpotPrice, + // log_2{2^128 - 1} = 128 + sdk.MustNewDecFromStr("127.999999999999999999"), + false, + }, + { + "zero price - panic", + sdk.ZeroDec(), + sdk.Dec{}, + true, + }, + { + "smallest dec", + sdk.SmallestDec(), + // https://www.wolframalpha.com/input?i=log+base+2+of+%2810%5E-18%29+with+20+digits + sdk.MustNewDecFromStr("59.794705707972522262").Neg(), + false, + }, + } + + for _, tc := range testcases { + s.Run(tc.name, func() { + osmoassert.ConditionalPanic(s.T(), tc.expectPanic, func() { + result := twap.TwapLog(tc.price) + + smallestAdditiveTolerance.CompareBigDec( + osmomath.BigDecFromSDKDec(tc.expected), + osmomath.BigDecFromSDKDec(result), + ) + }) + }) + } +} + +// TestTwapPow_CorrectBase tests that the base of 2 is used for the twap power function. +// 2^3 = 8 +func (s *TestSuite) TestTwapPow_CorrectBase() { + exponentValue := osmomath.NewBigDec(3) + expectedValue := sdk.NewDec(8) + + result := twap.TwapPow(exponentValue.SDKDec()) + + s.Require().Equal(expectedValue, result) +} + +// TestTwapPow_NegativeExponent tests that twap pow can handle a negative exponent +// 2^-1 = 0.5 +func (s *TestSuite) TestTwapPow_NegativeExponent() { + expectedResult := sdk.MustNewDecFromStr("0.5") + result := twap.TwapPow(oneDec.Neg()) + s.Require().Equal(expectedResult, result) +} + +func testCaseFromDeltas(s *TestSuite, startAccum, accumDiff sdk.Dec, timeDelta time.Duration, expectedTwap sdk.Dec) computeTwapTestCase { + return computeTwapTestCase{ + newOneSidedRecord(baseTime, startAccum, true), + newOneSidedRecord(baseTime.Add(timeDelta), startAccum.Add(accumDiff), true), + []twap.TwapStrategy{ + &twap.ArithmeticTwapStrategy{ + TwapKeeper: *s.App.TwapKeeper, + }, + }, + denom0, + expectedTwap, + false, + false, + } +} + +func testCaseFromDeltasAsset1(s *TestSuite, startAccum, accumDiff sdk.Dec, timeDelta time.Duration, expectedTwap sdk.Dec) computeTwapTestCase { + return computeTwapTestCase{ + newOneSidedRecord(baseTime, startAccum, false), + newOneSidedRecord(baseTime.Add(timeDelta), startAccum.Add(accumDiff), false), + []twap.TwapStrategy{ + &twap.ArithmeticTwapStrategy{ + TwapKeeper: *s.App.TwapKeeper, + }, + }, + denom1, + expectedTwap, + false, + false, + } +} + +func geometricTestCaseFromDeltas0(s *TestSuite, startAccum, accumDiff sdk.Dec, timeDelta time.Duration, expectedTwap sdk.Dec) computeTwapTestCase { + return computeTwapTestCase{ + newOneSidedGeometricRecord(baseTime, startAccum), + newOneSidedGeometricRecord(baseTime.Add(timeDelta), startAccum.Add(accumDiff)), + []twap.TwapStrategy{ + &twap.GeometricTwapStrategy{ + TwapKeeper: *s.App.TwapKeeper, + }, + }, + denom0, + expectedTwap, + false, + false, + } +} + +func geometricTestCaseFromDeltas1(s *TestSuite, startAccum, accumDiff sdk.Dec, timeDelta time.Duration, expectedTwap sdk.Dec) computeTwapTestCase { + return geometricTestCaseFromDeltas0(s, startAccum, accumDiff, timeDelta, sdk.OneDec().Quo(expectedTwap)) +} + +func testThreeAssetCaseFromDeltas(startAccum, accumDiff sdk.Dec, timeDelta time.Duration, expectedTwap sdk.Dec) computeThreeAssetArithmeticTwapTestCase { + return computeThreeAssetArithmeticTwapTestCase{ + newThreeAssetOneSidedRecord(baseTime, startAccum, true), + newThreeAssetOneSidedRecord(baseTime.Add(timeDelta), startAccum.Add(accumDiff), true), + []string{denom0, denom0, denom1}, + []sdk.Dec{expectedTwap, expectedTwap, expectedTwap}, + false, + } +} From 8196036b46ca18c5caedfde325a224f4c1210690 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 23 Dec 2022 16:07:38 -0500 Subject: [PATCH 05/30] test(x/twap): add randomized geometric twap test on a balancer pool (#3844) * test(x/twap): add randomized test with a balancer pool * comments * multiplicative tolerance, fewer retries and larger initial supply range --- x/twap/api_test.go | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/x/twap/api_test.go b/x/twap/api_test.go index 5807f8aa4e5..b77f8243327 100644 --- a/x/twap/api_test.go +++ b/x/twap/api_test.go @@ -3,10 +3,14 @@ package twap_test import ( "errors" "fmt" + "math/rand" "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/osmosis-labs/osmosis/osmomath" + sdkrand "github.com/osmosis-labs/osmosis/v13/simulation/simtypes/random" + "github.com/osmosis-labs/osmosis/v13/x/gamm/pool-models/balancer" "github.com/osmosis-labs/osmosis/v13/x/twap" "github.com/osmosis-labs/osmosis/v13/x/twap/types" ) @@ -811,3 +815,75 @@ func (s *TestSuite) TestGetArithmeticTwapToNow_ThreeAsset() { }) } } + +// TestGeometricTwapToNow_BalancerPool_Randomized the goal of this test case is to validate +// that no internal panics occur when computing geometric twap. It also sanity checks +// that geometric twap is roughly close to spot price. +func (s *TestSuite) TestGeometricTwapToNow_BalancerPool_Randomized() { + seed := int64(1) + r := rand.New(rand.NewSource(seed)) + retries := 200 + + type randTestCase struct { + elapsedTimeMs int + weightA sdk.Int + tokenASupply sdk.Int + weightB sdk.Int + tokenBSupply sdk.Int + } + + maxUint64 := ^uint(0) + + for i := 0; i < retries; i++ { + elapsedTimeMs := sdkrand.RandIntBetween(r, 1, int(maxUint64>>1)) + weightA := sdk.NewInt(int64(sdkrand.RandIntBetween(r, 1, 1000))) + tokenASupply := sdk.NewInt(int64(sdkrand.RandIntBetween(r, 10_000, 1_000_000_000_000_000_000))) + + tokenBSupply := sdk.NewInt(int64(sdkrand.RandIntBetween(r, 10_000, 1_000_000_000_000_000_000))) + weightB := sdk.NewInt(int64(sdkrand.RandIntBetween(r, 1, 1000))) + + s.Run(fmt.Sprintf("elapsedTimeMs=%d, weightA=%d, tokenASupply=%d, weightB=%d, tokenBSupply=%d", elapsedTimeMs, weightA, tokenASupply, weightB, tokenBSupply), func() { + s.SetupTest() + + ctx := s.Ctx + app := s.App + + assets := []balancer.PoolAsset{ + { + Token: sdk.NewCoin(denom0, tokenASupply), + Weight: weightA, + }, + { + Token: sdk.NewCoin(denom1, tokenBSupply), + Weight: weightB, + }, + } + + s.PrepareCustomBalancerPool(assets, balancer.PoolParams{ + SwapFee: sdk.ZeroDec(), + ExitFee: sdk.ZeroDec(), + }) + + // We add 1ms to avoid always landing on the same block time + // In that case, the most recent spot price would be used + // instead of interpolation. + oldTime := ctx.BlockTime().Add(1 * time.Millisecond) + newTime := oldTime.Add(time.Duration(elapsedTimeMs)) + + ctx = ctx.WithBlockTime(newTime) + + spotPrice, err := app.GAMMKeeper.CalculateSpotPrice(ctx, 1, denom1, denom0) + s.Require().NoError(err) + + twap, err := app.TwapKeeper.GetGeometricTwapToNow(ctx, 1, denom0, denom1, oldTime) + s.Require().NoError(err) + + osmomath.ErrTolerance{ + MultiplicativeTolerance: sdk.SmallestDec(), + }.CompareBigDec( + osmomath.BigDecFromSDKDec(spotPrice), + osmomath.BigDecFromSDKDec(twap), + ) + }) + } +} From c7c022215dae85cd8fe821c9ce2abcf4aa624287 Mon Sep 17 00:00:00 2001 From: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Date: Sat, 24 Dec 2022 05:08:52 +0700 Subject: [PATCH 06/30] Basic geometric twap e2e test (#3835) * feat(x/twap): geometric twap code gen query boilerplate * revert cli change * query gen * wire up API * test * fix * fixes * add geometric queries * create pool.json * add test * resolve conflict * fix: swap uosmo in * fix problem with wallet creation * updates * simplify and add comments * Update tests/e2e/e2e_test.go * Update tests/e2e/e2e_test.go * Update tests/e2e/configurer/chain/queries.go Co-authored-by: Adam Tucker * Update tests/e2e/configurer/chain/queries.go Co-authored-by: Adam Tucker * Update tests/e2e/e2e_test.go Co-authored-by: Adam Tucker * Update tests/e2e/e2e_test.go Co-authored-by: Adam Tucker * Update tests/e2e/e2e_test.go Co-authored-by: Adam Tucker * Update tests/e2e/e2e_test.go Co-authored-by: Adam Tucker Co-authored-by: Roman Co-authored-by: Roman Co-authored-by: Adam Tucker --- tests/e2e/configurer/chain/queries.go | 43 +++++++++++- tests/e2e/e2e_test.go | 97 ++++++++++++++++++++++++++- tests/e2e/scripts/geometricPool.json | 7 ++ 3 files changed, 142 insertions(+), 5 deletions(-) create mode 100644 tests/e2e/scripts/geometricPool.json diff --git a/tests/e2e/configurer/chain/queries.go b/tests/e2e/configurer/chain/queries.go index 1b53ca5a31f..5a7bc1f2123 100644 --- a/tests/e2e/configurer/chain/queries.go +++ b/tests/e2e/configurer/chain/queries.go @@ -187,7 +187,6 @@ func (n *NodeConfig) QueryArithmeticTwapToNow(poolId uint64, baseAsset, quoteAss return sdk.Dec{}, err } - // nolint: staticcheck var response twapqueryproto.ArithmeticTwapToNowResponse err = util.Cdc.UnmarshalJSON(bz, &response) require.NoError(n.t, err) // this error should not happen @@ -209,13 +208,53 @@ func (n *NodeConfig) QueryArithmeticTwap(poolId uint64, baseAsset, quoteAsset st return sdk.Dec{}, err } - // nolint: staticcheck var response twapqueryproto.ArithmeticTwapResponse err = util.Cdc.UnmarshalJSON(bz, &response) require.NoError(n.t, err) // this error should not happen return response.ArithmeticTwap, nil } +func (n *NodeConfig) QueryGeometricTwapToNow(poolId uint64, baseAsset, quoteAsset string, startTime time.Time) (sdk.Dec, error) { + path := "osmosis/twap/v1beta1/GeometricTwapToNow" + + bz, err := n.QueryGRPCGateway( + path, + "pool_id", strconv.FormatInt(int64(poolId), 10), + "base_asset", baseAsset, + "quote_asset", quoteAsset, + "start_time", startTime.Format(time.RFC3339Nano), + ) + if err != nil { + return sdk.Dec{}, err + } + + var response twapqueryproto.GeometricTwapToNowResponse + err = util.Cdc.UnmarshalJSON(bz, &response) + require.NoError(n.t, err) + return response.GeometricTwap, nil +} + +func (n *NodeConfig) QueryGeometricTwap(poolId uint64, baseAsset, quoteAsset string, startTime time.Time, endTime time.Time) (sdk.Dec, error) { + path := "osmosis/twap/v1beta1/GeometricTwap" + + bz, err := n.QueryGRPCGateway( + path, + "pool_id", strconv.FormatInt(int64(poolId), 10), + "base_asset", baseAsset, + "quote_asset", quoteAsset, + "start_time", startTime.Format(time.RFC3339Nano), + "end_time", endTime.Format(time.RFC3339Nano), + ) + if err != nil { + return sdk.Dec{}, err + } + + var response twapqueryproto.GeometricTwapResponse + err = util.Cdc.UnmarshalJSON(bz, &response) + require.NoError(n.t, err) + return response.GeometricTwap, nil +} + // QueryHashFromBlock gets block hash at a specific height. Otherwise, error. func (n *NodeConfig) QueryHashFromBlock(height int64) (string, error) { block, err := n.rpcClient.Block(context.Background(), &height) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index bf59468d30a..1561a1ece7b 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -263,16 +263,16 @@ func (s *IntegrationTestSuite) TestAddToExistingLock() { chainA.LockAndAddToExistingLock(sdk.NewInt(1000000000000000000), fmt.Sprintf("gamm/pool/%d", poolId), lockupWalletAddr, lockupWalletSuperfluidAddr) } -// TestTWAP tests TWAP by creating a pool, performing a swap. +// TestArithmeticTWAP tests TWAP by creating a pool, performing a swap. // These two operations should create TWAP records. // Then, we wait until the epoch for the records to be pruned. // The records are guranteed to be pruned at the next epoch // because twap keep time = epoch time / 4 and we use a timer // to wait for at least the twap keep time. -func (s *IntegrationTestSuite) TestTWAP() { +func (s *IntegrationTestSuite) TestArithmeticTWAP() { const ( poolFile = "nativeDenomThreeAssetPool.json" - walletName = "swap-exact-amount-in-wallet" + walletName = "arithmetic-twap-wallet" denomA = "stake" denomB = "uion" @@ -570,3 +570,94 @@ func (s *IntegrationTestSuite) TestExpeditedProposals() { s.T().Logf("expeditedVotingPeriodDuration within two seconds of expected time: %v", timeDelta) close(totalTimeChan) } + +// TestGeometricTWAP tests geometric twap. +// It does the following: creates a pool, queries twap, performs a swap , and queries twap again. +// Twap is expected to change after the swap. +// The pool is created with 1_000_000 uosmo and 2_000_000 stake and equal weights. +// Assuming base asset is uosmo, the initial twap is 2 +// Upon swapping 1_000_000 uosmo for stake, supply changes, making uosmo less expensive. +// As a result of the swap, twap changes to 0.5. +func (s *IntegrationTestSuite) TestGeometricTWAP() { + const ( + // This pool contains 1_000_000 uosmo and 2_000_000 stake. + // Equals weights. + poolFile = "geometricPool.json" + walletName = "geometric-twap-wallet" + + denomA = "uosmo" // 1_000_000 uosmo + denomB = "stake" // 2_000_000 stake + + minAmountOut = "1" + + epochIdentifier = "day" + ) + + chainA := s.configurer.GetChainConfig(0) + chainANode, err := chainA.GetDefaultNode() + s.NoError(err) + + // Triggers the creation of TWAP records. + poolId := chainANode.CreatePool(poolFile, initialization.ValidatorWalletName) + swapWalletAddr := chainANode.CreateWallet(walletName) + + // We add 5 ms to avoid landing directly on block time in twap. If block time + // is provided as start time, the latest spot price is used. Otherwise + // interpolation is done. + timeBeforeSwapPlus5ms := chainANode.QueryLatestBlockTime().Add(5 * time.Millisecond) + // Wait for the next height so that the requested twap + // start time (timeBeforeSwap) is not equal to the block time. + chainA.WaitForNumHeights(1) + + s.T().Log("querying for the first geometric TWAP to now (before swap)") + // Assume base = uosmo, quote = stake + // At pool creation time, the twap should be: + // quote assset supply / base asset supply = 2_000_000 / 1_000_000 = 2 + initialTwapBOverA, err := chainANode.QueryGeometricTwapToNow(poolId, denomA, denomB, timeBeforeSwapPlus5ms) + s.Require().NoError(err) + s.Require().Equal(sdk.NewDec(2), initialTwapBOverA) + + // Assume base = stake, quote = uosmo + // At pool creation time, the twap should be: + // quote assset supply / base asset supply = 1_000_000 / 2_000_000 = 0.5 + initialTwapAOverB, err := chainANode.QueryGeometricTwapToNow(poolId, denomB, denomA, timeBeforeSwapPlus5ms) + s.Require().NoError(err) + s.Require().Equal(sdk.NewDecWithPrec(5, 1), initialTwapAOverB) + + coinAIn := fmt.Sprintf("1000000%s", denomA) + chainANode.BankSend(coinAIn, chainA.NodeConfigs[0].PublicAddress, swapWalletAddr) + + s.T().Logf("performing swap of %s for %s", coinAIn, denomB) + + // stake out = stake supply * (1 - (uosmo supply before / uosmo supply after)^(uosmo weight / stake weight)) + // = 2_000_000 * (1 - (1_000_000 / 2_000_000)^1) + // = 2_000_000 * 0.5 + // = 1_000_000 + chainANode.SwapExactAmountIn(coinAIn, minAmountOut, fmt.Sprintf("%d", poolId), denomB, swapWalletAddr) + + // New supply post swap: + // stake = 2_000_000 - 1_000_000 - 1_000_000 + // uosmo = 1_000_000 + 1_000_000 = 2_000_000 + + timeAfterSwap := chainANode.QueryLatestBlockTime() + chainA.WaitForNumHeights(1) + timeAfterSwapPlus1Height := chainANode.QueryLatestBlockTime() + + s.T().Log("querying for the TWAP from after swap to now") + afterSwapTwapBOverA, err := chainANode.QueryGeometricTwap(poolId, denomA, denomB, timeAfterSwap, timeAfterSwapPlus1Height) + s.Require().NoError(err) + + // We swap uosmo so uosmo's supply will increase and stake will decrease. + // The the price after will be smaller than the previous one. + s.Require().True(initialTwapBOverA.GT(afterSwapTwapBOverA)) + + // Assume base = uosmo, quote = stake + // At pool creation, we had: + // quote assset supply / base asset supply = 2_000_000 / 1_000_000 = 2 + // Next, we swapped 1_000_000 uosmo for stake. + // Now, we roughly have + // uatom = 1_000_000 + // uosmo = 2_000_000 + // quote assset supply / base asset supply = 1_000_000 / 2_000_000 = 0.5 + osmoassert.DecApproxEq(s.T(), sdk.NewDecWithPrec(5, 1), afterSwapTwapBOverA, sdk.NewDecWithPrec(1, 2)) +} diff --git a/tests/e2e/scripts/geometricPool.json b/tests/e2e/scripts/geometricPool.json new file mode 100644 index 00000000000..8c60b25e5cf --- /dev/null +++ b/tests/e2e/scripts/geometricPool.json @@ -0,0 +1,7 @@ +{ + "weights": "1uosmo,1stake", + "initial-deposit": "1000000uosmo,2000000stake", + "swap-fee": "0", + "exit-fee": "0", + "future-governor": "" +} From 1afb23ebc178512df9ba32bb2f344a6912e0dc43 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 23 Dec 2022 18:30:06 -0500 Subject: [PATCH 07/30] feat(x/twap): whitelist GeometricTwap and GeometricTwapToNow (#3852) * feat(x/twap): GeometricTwap and GeometricTwapToNow queries added to Stargate whitelist * update docs --- CHANGELOG.md | 23 ++++------------------- wasmbinding/stargate_whitelist.go | 2 ++ x/twap/README.md | 7 ++++++- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df83ddd6249..4e09c10781c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,25 +54,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#3677](https://github.com/osmosis-labs/osmosis/pull/3677) Add methods for cloning and mutative multiplication on osmomath.BigDec. * [#3676](https://github.com/osmosis-labs/osmosis/pull/3676) implement `PowerInteger` function on `osmomath.BigDec` * [#3678](https://github.com/osmosis-labs/osmosis/pull/3678) implement mutative `PowerIntegerMut` function on `osmomath.BigDec`. - -### Features - -### Bug fixes - -## v13.1.2 - -### Bug fixes - -* Fix state export -* Update swagger files for v13 - -## v13.1.1 - -* Add a check in the makefile for using go v1.18 - -## v13.1.0 - -* Correctly apply DragonBerry IBC patch +* [#3708](https://github.com/osmosis-labs/osmosis/pull/3708) `Exp2` function to compute 2^decimal. +* [#3693](https://github.com/osmosis-labs/osmosis/pull/3693) Add `EstimateSwapExactAmountOut` query to stargate whitelist +* [#3731](https://github.com/osmosis-labs/osmosis/pull/3731) BigDec Power functions with decimal exponent. +* [#3847](https://github.com/osmosis-labs/osmosis/pull/3847) GeometricTwap and GeometricTwapToNow queries added to Stargate whitelist. ### API breaks diff --git a/wasmbinding/stargate_whitelist.go b/wasmbinding/stargate_whitelist.go index e3fd3fae74e..b7217e50527 100644 --- a/wasmbinding/stargate_whitelist.go +++ b/wasmbinding/stargate_whitelist.go @@ -123,6 +123,8 @@ func init() { // twap setWhitelistedQuery("/osmosis.twap.v1beta1.Query/ArithmeticTwap", &twapquerytypes.ArithmeticTwapResponse{}) setWhitelistedQuery("/osmosis.twap.v1beta1.Query/ArithmeticTwapToNow", &twapquerytypes.ArithmeticTwapToNowResponse{}) + setWhitelistedQuery("/osmosis.twap.v1beta1.Query/GeometricTwap", &twapquerytypes.GeometricTwapResponse{}) + setWhitelistedQuery("/osmosis.twap.v1beta1.Query/GeometricTwapToNow", &twapquerytypes.GeometricTwapToNowResponse{}) setWhitelistedQuery("/osmosis.twap.v1beta1.Query/Params", &twapquerytypes.ParamsResponse{}) } diff --git a/x/twap/README.md b/x/twap/README.md index aaae5be05f4..1a00a8369e3 100644 --- a/x/twap/README.md +++ b/x/twap/README.md @@ -30,7 +30,8 @@ Given these interpolated accumulation values, we can compute the TWAP as before. ## Module API -The primary intended API is `GetArithmeticTwap`, which is documented below, and has a similar cosmwasm binding. +The primary intended APIs are `GetArithmeticTwap` and `GetGeometricTwap`, which are documented below, +and have a similar cosmwasm binding. ```go // GetArithmeticTwap returns an arithmetic time weighted average price. @@ -68,6 +69,10 @@ func (k Keeper) GetArithmeticTwap(ctx sdk.Context, There are convenience methods for `GetArithmeticTwapToNow` which sets `endTime = ctx.BlockTime()`, and has minor gas reduction. For users who need TWAPs outside the 48 hours stored in the state machine, you can get the latest accumulation store record from `GetBeginBlockAccumulatorRecord`. +Geometric TWAP has comparable methods with the same parameters. Namely, `GetGeometricTwap` and `GetGeometricTwapToNow`. +The semantics of these methods are the same with the arithmetic version. The only difference is the low-level +computation of the TWAP, which is done via the geometric mean. + ## Code layout **api.go** is the main file you should look at as a user of this module. From c12bfa3abf8ee7d0a85555554faf11c723a94242 Mon Sep 17 00:00:00 2001 From: Roman Date: Sat, 24 Dec 2022 18:51:43 -0500 Subject: [PATCH 08/30] fix(scripts): proto gen for osmoutils (#3854) * fix(scripts): proto gen for osmoutils * Update scripts/protocgen.sh --- osmoutils/sumtree/tree.pb.go | 40 ++++++++++++++++++------------------ scripts/protocgen.sh | 1 + 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/osmoutils/sumtree/tree.pb.go b/osmoutils/sumtree/tree.pb.go index df4790f1cfa..4f007610f28 100644 --- a/osmoutils/sumtree/tree.pb.go +++ b/osmoutils/sumtree/tree.pb.go @@ -169,26 +169,26 @@ func init() { } var fileDescriptor_31a1c5f55b935f78 = []byte{ - // 304 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x91, 0x41, 0x4b, 0xc3, 0x30, - 0x1c, 0xc5, 0x1b, 0xdd, 0x44, 0xe3, 0x4e, 0x65, 0xc2, 0x18, 0x92, 0x95, 0x1e, 0xa4, 0x97, 0x25, - 0xd6, 0x21, 0xec, 0x28, 0xf3, 0x24, 0x88, 0x42, 0x8f, 0xde, 0xd2, 0x34, 0xeb, 0x82, 0x6d, 0x33, - 0x9b, 0x74, 0xe8, 0xb7, 0xf0, 0x63, 0xed, 0xb8, 0xa3, 0x78, 0x18, 0xd2, 0x7e, 0x11, 0x69, 0x5a, - 0xa7, 0x82, 0xe0, 0x29, 0xff, 0x97, 0xfc, 0x78, 0xef, 0x91, 0x3f, 0x74, 0xa5, 0x4a, 0xa5, 0x12, - 0x8a, 0xa8, 0x22, 0xd5, 0x39, 0xe7, 0x64, 0xe5, 0x87, 0x5c, 0x53, 0x9f, 0xd4, 0x02, 0x2f, 0x73, - 0xa9, 0xa5, 0x7d, 0xd2, 0x32, 0x58, 0x69, 0x99, 0x73, 0xdc, 0x12, 0xc3, 0x7e, 0x2c, 0x63, 0x69, - 0x08, 0x52, 0x4f, 0x0d, 0x3c, 0x44, 0xcc, 0xd0, 0x24, 0xa4, 0xea, 0xdb, 0x8c, 0x49, 0x91, 0x35, - 0xef, 0xee, 0x15, 0xec, 0xdc, 0xc9, 0x88, 0xdb, 0x53, 0x78, 0xc8, 0x16, 0x22, 0x89, 0x72, 0x9e, - 0x0d, 0x80, 0xb3, 0xef, 0x1d, 0x5f, 0x9c, 0xe2, 0x3f, 0x73, 0xf0, 0x75, 0x8d, 0x05, 0x3b, 0xda, - 0x7d, 0x82, 0x5d, 0x73, 0x65, 0xf7, 0x61, 0x57, 0x64, 0x11, 0x7f, 0x1e, 0x00, 0x07, 0x78, 0xbd, - 0xa0, 0x11, 0x76, 0x00, 0x7b, 0x94, 0xb1, 0x22, 0x2d, 0x12, 0xaa, 0x85, 0xcc, 0x06, 0x7b, 0x0e, - 0xf0, 0x8e, 0x66, 0x78, 0xbd, 0x1d, 0x59, 0xef, 0xdb, 0xd1, 0x59, 0x2c, 0xf4, 0xa2, 0x08, 0x31, - 0x93, 0x29, 0x69, 0x9b, 0x36, 0xc7, 0x58, 0x45, 0x8f, 0x44, 0xbf, 0x2c, 0xb9, 0xc2, 0x37, 0x99, - 0x0e, 0x7e, 0x79, 0xb8, 0x53, 0xd8, 0xb9, 0xe5, 0x74, 0x6e, 0x9f, 0xc3, 0x4e, 0xc2, 0xe9, 0xdc, - 0x04, 0xfe, 0x57, 0xd8, 0x90, 0xb3, 0xfb, 0x75, 0x89, 0xc0, 0xa6, 0x44, 0xe0, 0xa3, 0x44, 0xe0, - 0xb5, 0x42, 0xd6, 0xa6, 0x42, 0xd6, 0x5b, 0x85, 0xac, 0x87, 0xcb, 0x1f, 0x4d, 0x5a, 0x9f, 0x71, - 0x42, 0x43, 0xf5, 0x25, 0xc8, 0xca, 0x9f, 0x98, 0xb9, 0xd0, 0x22, 0xd9, 0xed, 0x27, 0x3c, 0x30, - 0xdf, 0x38, 0xf9, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x09, 0x06, 0x72, 0xc1, 0xb9, 0x01, 0x00, 0x00, + // 302 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x91, 0xb1, 0x4e, 0xeb, 0x30, + 0x18, 0x85, 0xe3, 0x7b, 0x53, 0x04, 0xa6, 0x53, 0x54, 0xa4, 0xa8, 0x42, 0x6e, 0x94, 0x01, 0x65, + 0xa9, 0x4d, 0x60, 0xe9, 0x88, 0xca, 0x84, 0x40, 0x0c, 0x19, 0xd9, 0x1c, 0xc7, 0x4d, 0x2d, 0x92, + 0xb8, 0xc4, 0x0e, 0x82, 0xb7, 0xe0, 0xb1, 0x3a, 0x76, 0x44, 0x0c, 0x15, 0x4a, 0x5e, 0x04, 0xc5, + 0x09, 0x05, 0x24, 0x24, 0xa6, 0xdf, 0xc7, 0xfe, 0x74, 0xce, 0x91, 0x7f, 0xe8, 0x4b, 0x95, 0x4b, + 0x25, 0x14, 0x51, 0x55, 0xae, 0x4b, 0xce, 0xc9, 0x63, 0x18, 0x73, 0x4d, 0x43, 0xd2, 0x0a, 0xbc, + 0x2a, 0xa5, 0x96, 0xce, 0x51, 0xcf, 0x60, 0xa5, 0x65, 0xc9, 0x71, 0x4f, 0x8c, 0x47, 0xa9, 0x4c, + 0xa5, 0x21, 0x48, 0x7b, 0xea, 0xe0, 0x31, 0x62, 0x86, 0x26, 0x31, 0x55, 0x5f, 0x66, 0x4c, 0x8a, + 0xa2, 0x7b, 0xf7, 0x2f, 0xa0, 0x7d, 0x2b, 0x13, 0xee, 0xcc, 0xe0, 0x3e, 0x5b, 0x8a, 0x2c, 0x29, + 0x79, 0xe1, 0x02, 0xef, 0x7f, 0x70, 0x78, 0x76, 0x8c, 0x7f, 0xcd, 0xc1, 0x97, 0x2d, 0x16, 0xed, + 0x68, 0xff, 0x01, 0x0e, 0xcc, 0x95, 0x33, 0x82, 0x03, 0x51, 0x24, 0xfc, 0xc9, 0x05, 0x1e, 0x08, + 0x86, 0x51, 0x27, 0x9c, 0x08, 0x0e, 0x29, 0x63, 0x55, 0x5e, 0x65, 0x54, 0x0b, 0x59, 0xb8, 0xff, + 0x3c, 0x10, 0x1c, 0xcc, 0xf1, 0x7a, 0x3b, 0xb1, 0xde, 0xb6, 0x93, 0x93, 0x54, 0xe8, 0x65, 0x15, + 0x63, 0x26, 0x73, 0xd2, 0x37, 0xed, 0xc6, 0x54, 0x25, 0xf7, 0x44, 0x3f, 0xaf, 0xb8, 0xc2, 0x57, + 0x85, 0x8e, 0x7e, 0x78, 0xf8, 0x33, 0x68, 0xdf, 0x70, 0xba, 0x70, 0x4e, 0xa1, 0x9d, 0x71, 0xba, + 0x30, 0x81, 0x7f, 0x15, 0x36, 0xe4, 0xfc, 0x7a, 0x5d, 0x23, 0xb0, 0xa9, 0x11, 0x78, 0xaf, 0x11, + 0x78, 0x69, 0x90, 0xb5, 0x69, 0x90, 0xf5, 0xda, 0x20, 0xeb, 0x2e, 0xfc, 0xd6, 0xa4, 0xf7, 0x99, + 0x66, 0x34, 0x56, 0x9f, 0xc2, 0xcc, 0x4a, 0x8b, 0x6c, 0xb7, 0x9b, 0x78, 0xcf, 0x7c, 0xe1, 0xf9, + 0x47, 0x00, 0x00, 0x00, 0xff, 0xff, 0x30, 0x34, 0x4b, 0x32, 0xb5, 0x01, 0x00, 0x00, } func (m *Node) Marshal() (dAtA []byte, err error) { diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index 9b17c63409e..c566d8b24a4 100755 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -25,6 +25,7 @@ cd .. # # Note: Proto files are suffixed with the current binary version. cp -r github.com/osmosis-labs/osmosis/v13/* ./ +cp -r github.com/osmosis-labs/osmosis/osmoutils ./osmoutils rm -rf github.com go mod tidy -compat=1.18 From 168ccdaa47ff528ab76113f42886059687bbcf91 Mon Sep 17 00:00:00 2001 From: Roman Date: Tue, 27 Dec 2022 13:48:18 -0500 Subject: [PATCH 09/30] fix(scripts): proto gen osmoutils path (#3859) --- scripts/protocgen.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/protocgen.sh b/scripts/protocgen.sh index c566d8b24a4..00f593bc924 100755 --- a/scripts/protocgen.sh +++ b/scripts/protocgen.sh @@ -25,7 +25,7 @@ cd .. # # Note: Proto files are suffixed with the current binary version. cp -r github.com/osmosis-labs/osmosis/v13/* ./ -cp -r github.com/osmosis-labs/osmosis/osmoutils ./osmoutils +cp -r github.com/osmosis-labs/osmosis/osmoutils ./ rm -rf github.com go mod tidy -compat=1.18 From de76db0fc544ea269e39c7d5d7068296ea57f962 Mon Sep 17 00:00:00 2001 From: Nicolas Lara Date: Thu, 29 Dec 2022 13:53:13 +0100 Subject: [PATCH 10/30] added packet timeouts to wasm hooks (#3862) --- tests/ibc-hooks/bytecode/counter.wasm | Bin 0 -> 161000 bytes tests/ibc-hooks/ibc_middleware_test.go | 34 ++++ .../contracts/counter/src/contract.rs | 65 ++++++-- .../testutils/contracts/counter/src/msg.rs | 12 ++ x/ibc-hooks/wasm_hook.go | 155 ++++++++++++++++++ 5 files changed, 251 insertions(+), 15 deletions(-) create mode 100644 tests/ibc-hooks/bytecode/counter.wasm diff --git a/tests/ibc-hooks/bytecode/counter.wasm b/tests/ibc-hooks/bytecode/counter.wasm new file mode 100644 index 0000000000000000000000000000000000000000..2e4d8b7ccf9ac9a23319f62773985642af2ec5b8 GIT binary patch literal 161000 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 bf&~ba$#}Ix7j(p#2!Dib`6$Aj9ijgNj(1gD literal 0 HcmV?d00001 diff --git a/tests/ibc-hooks/ibc_middleware_test.go b/tests/ibc-hooks/ibc_middleware_test.go index 9f316700bb8..35bd95ffd30 100644 --- a/tests/ibc-hooks/ibc_middleware_test.go +++ b/tests/ibc-hooks/ibc_middleware_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "testing" + "time" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" @@ -460,6 +461,39 @@ func (suite *HooksTestSuite) TestAcks() { } +func (suite *HooksTestSuite) TestTimeouts() { + suite.chainA.StoreContractCode(&suite.Suite, "./bytecode/counter.wasm") + addr := suite.chainA.InstantiateContract(&suite.Suite, `{"count": 0}`, 1) + + // Generate swap instructions for the contract + callbackMemo := fmt.Sprintf(`{"ibc_callback":"%s"}`, addr) + // Send IBC transfer with the memo with crosschain-swap instructions + transferMsg := NewMsgTransfer(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000)), suite.chainA.SenderAccount.GetAddress().String(), addr.String(), callbackMemo) + transferMsg.TimeoutTimestamp = uint64(suite.coordinator.CurrentTime.Add(time.Minute).UnixNano()) + sendResult, err := suite.chainA.SendMsgsNoCheck(transferMsg) + suite.Require().NoError(err) + + packet, err := ibctesting.ParsePacketFromEvents(sendResult.GetEvents()) + suite.Require().NoError(err) + + // Move chainB forward one block + suite.chainB.NextBlock() + // One month later + suite.coordinator.IncrementTimeBy(time.Hour) + err = suite.path.EndpointA.UpdateClient() + suite.Require().NoError(err) + + err = suite.path.EndpointA.TimeoutPacket(packet) + suite.Require().NoError(err) + + // The test contract will increment the counter for itself by 10 when a packet times out + state := suite.chainA.QueryContract( + &suite.Suite, addr, + []byte(fmt.Sprintf(`{"get_count": {"addr": "%s"}}`, addr))) + suite.Require().Equal(`{"count":10}`, state) + +} + func (suite *HooksTestSuite) TestSendWithoutMemo() { // Sending a packet without memo to ensure that the ibc_callback middleware doesn't interfere with a regular send transferMsg := NewMsgTransfer(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1000)), suite.chainA.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), "") diff --git a/x/ibc-hooks/testutils/contracts/counter/src/contract.rs b/x/ibc-hooks/testutils/contracts/counter/src/contract.rs index be67b59302b..3a36bfe97cd 100644 --- a/x/ibc-hooks/testutils/contracts/counter/src/contract.rs +++ b/x/ibc-hooks/testutils/contracts/counter/src/contract.rs @@ -76,25 +76,60 @@ pub mod execute { } pub fn reset(deps: DepsMut, info: MessageInfo, count: i32) -> Result { - COUNTERS.update( - deps.storage, - info.sender.clone(), - |state| -> Result<_, ContractError> { - match state { - None => Err(ContractError::Unauthorized {}), - Some(state) if state.owner != info.sender.clone() => { - Err(ContractError::Unauthorized {}) - } - _ => Ok(Counter { - count, - total_funds: vec![], - owner: info.sender.clone(), - }), - } + utils::update_counter(deps, info.sender, &|_counter| count, &|_counter| vec![])?; + Ok(Response::new().add_attribute("action", "reset")) + } +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result { + match msg { + SudoMsg::ReceiveAck { + channel: _, + sequence: _, + ack: _, + success, + } => sudo::receive_ack(deps, env.contract.address, success), + SudoMsg::IBCTimeout { + channel: _, + sequence: _, + } => sudo::ibc_timeout(deps, env.contract.address), + } +} + +pub mod sudo { + use cosmwasm_std::Addr; + + use super::*; + + pub fn receive_ack( + deps: DepsMut, + contract: Addr, + _success: bool, + ) -> Result { + utils::update_counter( + deps, + contract, + &|counter| match counter { + None => 1, + Some(counter) => counter.count + 1, }, )?; Ok(Response::new().add_attribute("action", "reset")) } + + pub(crate) fn ibc_timeout(deps: DepsMut, contract: Addr) -> Result { + utils::update_counter( + deps, + contract, + &|counter| match counter { + None => 10, + Some(counter) => counter.count + 10, + }, + &|_counter| vec![], + )?; + Ok(Response::new().add_attribute("action", "timeout")) + } } pub fn naive_add_coins(lhs: &Vec, rhs: &Vec) -> Vec { diff --git a/x/ibc-hooks/testutils/contracts/counter/src/msg.rs b/x/ibc-hooks/testutils/contracts/counter/src/msg.rs index 6c29fdf2508..db85e9ad4e5 100644 --- a/x/ibc-hooks/testutils/contracts/counter/src/msg.rs +++ b/x/ibc-hooks/testutils/contracts/counter/src/msg.rs @@ -32,3 +32,15 @@ pub struct GetCountResponse { pub struct GetTotalFundsResponse { pub total_funds: Vec, } + +#[cw_serde] +pub enum SudoMsg { + ReceiveAck { + channel: String, + sequence: u64, + ack: String, + success: bool, + }, + #[serde(rename = "ibc_timeout")] + IBCTimeout { channel: String, sequence: u64 }, +} diff --git a/x/ibc-hooks/wasm_hook.go b/x/ibc-hooks/wasm_hook.go index 5d0f172295b..58da6336a0c 100644 --- a/x/ibc-hooks/wasm_hook.go +++ b/x/ibc-hooks/wasm_hook.go @@ -12,6 +12,7 @@ import ( wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" transfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" channeltypes "github.com/cosmos/ibc-go/v4/modules/core/04-channel/types" ibcexported "github.com/cosmos/ibc-go/v4/modules/core/exported" @@ -204,3 +205,157 @@ func ValidateAndParseMemo(memo string, receiver string) (isWasmRouted bool, cont return isWasmRouted, contractAddr, msgBytes, nil } + +func (h WasmHooks) SendPacketOverride(i ICS4Middleware, ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI) error { + concretePacket, ok := packet.(channeltypes.Packet) + if !ok { + return i.channel.SendPacket(ctx, chanCap, packet) // continue + } + + isIcs20, data := isIcs20Packet(concretePacket) + if !isIcs20 { + return i.channel.SendPacket(ctx, chanCap, packet) // continue + } + + isCallbackRouted, metadata := jsonStringHasKey(data.GetMemo(), types.IBCCallbackKey) + if !isCallbackRouted { + return i.channel.SendPacket(ctx, chanCap, packet) // continue + } + + // We remove the callback metadata from the memo as it has already been processed. + + // If the only available key in the memo is the callback, we should remove the memo + // from the data completely so the packet is sent without it. + // This way receiver chains that are on old versions of IBC will be able to process the packet + + callbackRaw := metadata[types.IBCCallbackKey] // This will be used later. + delete(metadata, types.IBCCallbackKey) + bzMetadata, err := json.Marshal(metadata) + if err != nil { + return sdkerrors.Wrap(err, "Send packet with callback error") + } + stringMetadata := string(bzMetadata) + if stringMetadata == "{}" { + data.Memo = "" + } else { + data.Memo = stringMetadata + } + dataBytes, err := json.Marshal(data) + if err != nil { + return sdkerrors.Wrap(err, "Send packet with callback error") + } + + packetWithoutCallbackMemo := channeltypes.Packet{ + Sequence: concretePacket.Sequence, + SourcePort: concretePacket.SourcePort, + SourceChannel: concretePacket.SourceChannel, + DestinationPort: concretePacket.DestinationPort, + DestinationChannel: concretePacket.DestinationChannel, + Data: dataBytes, + TimeoutTimestamp: concretePacket.TimeoutTimestamp, + TimeoutHeight: concretePacket.TimeoutHeight, + } + + err = i.channel.SendPacket(ctx, chanCap, packetWithoutCallbackMemo) + if err != nil { + return err + } + + // Make sure the callback contract is a string and a valid bech32 addr. If it isn't, ignore this packet + contract, ok := callbackRaw.(string) + if !ok { + return nil + } + _, err = sdk.AccAddressFromBech32(contract) + if err != nil { + return nil + } + + h.ibcHooksKeeper.StorePacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence(), contract) + return nil +} + +func (h WasmHooks) OnAcknowledgementPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error { + err := im.App.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) + if err != nil { + return err + } + + if !h.ProperlyConfigured() { + // Not configured. Return from the underlying implementation + return nil + } + + contract := h.ibcHooksKeeper.GetPacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) + if contract == "" { + // No callback configured + return nil + } + + contractAddr, err := sdk.AccAddressFromBech32(contract) + if err != nil { + return sdkerrors.Wrap(err, "Ack callback error") // The callback configured is not a bech32. Error out + } + + success := "false" + if !osmoutils.IsAckError(acknowledgement) { + success = "true" + } + + // Notify the sender that the ack has been received + ackAsJson, err := json.Marshal(acknowledgement) + if err != nil { + // If the ack is not a json object, error + return err + } + + sudoMsg := []byte(fmt.Sprintf( + `{"receive_ack": {"channel": "%s", "sequence": %d, "ack": %s, "success": %s}}`, + packet.SourceChannel, packet.Sequence, ackAsJson, success)) + _, err = h.ContractKeeper.Sudo(ctx, contractAddr, sudoMsg) + if err != nil { + // error processing the callback + // ToDo: Open Question: Should we also delete the callback here? + return sdkerrors.Wrap(err, "Ack callback error") + } + h.ibcHooksKeeper.DeletePacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) + return nil +} + +func (h WasmHooks) OnTimeoutPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error { + err := im.App.OnTimeoutPacket(ctx, packet, relayer) + if err != nil { + return err + } + + if !h.ProperlyConfigured() { + // Not configured. Return from the underlying implementation + return nil + } + + contract := h.ibcHooksKeeper.GetPacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) + if contract == "" { + // No callback configured + return nil + } + + contractAddr, err := sdk.AccAddressFromBech32(contract) + if err != nil { + return sdkerrors.Wrap(err, "Timeout callback error") // The callback configured is not a bech32. Error out + } + + sudoMsg := []byte(fmt.Sprintf( + `{"ibc_timeout": {"channel": "%s", "sequence": %d}}`, + packet.SourceChannel, packet.Sequence)) + _, err = h.ContractKeeper.Sudo(ctx, contractAddr, sudoMsg) + if err != nil { + // error processing the callback. This could be because the contract doesn't implement the message type to + // process the callback. Retrying this will not help, so we delete the callback from storage. + // Since the packet has timed out, we don't expect any other responses that may trigger the callback. + h.ibcHooksKeeper.DeletePacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) + return sdkerrors.Wrap(err, "Timeout callback error") + } + // + h.ibcHooksKeeper.DeletePacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) + return nil +} From 8f88f7d70e231aad8ee904a42b5f8abb9a9100d1 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 30 Dec 2022 13:55:36 -0600 Subject: [PATCH 11/30] add negative to cli (#3888) --- osmoutils/osmocli/parsers.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osmoutils/osmocli/parsers.go b/osmoutils/osmocli/parsers.go index e8da7f14c57..1b051c6ac7c 100644 --- a/osmoutils/osmocli/parsers.go +++ b/osmoutils/osmocli/parsers.go @@ -166,6 +166,14 @@ func parseFieldFromDirectlySetFlag(fVal reflect.Value, fType reflect.StructField } func ParseFieldFromArg(fVal reflect.Value, fType reflect.StructField, arg string) error { + // We cant pass in a negative number due to the way pflags works... + // This is an (extraordinarily ridiculous) workaround that checks if a negative int is encapsulated in square brackets, + // and if so, trims the square brackets + if strings.HasPrefix(arg, "[") && strings.HasSuffix(arg, "]") && arg[1] == '-' { + arg = strings.TrimPrefix(arg, "[") + arg = strings.TrimSuffix(arg, "]") + } + switch fType.Type.Kind() { // SetUint allows anyof type u8, u16, u32, u64, and uint case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: From f4c7d479adc6e546b191124cf9edded056aa4d49 Mon Sep 17 00:00:00 2001 From: Nicolas Lara Date: Mon, 2 Jan 2023 23:47:30 +0100 Subject: [PATCH 12/30] Making osmoutils compile on chains that don't use our SDK fork (#3899) * making osmoutils compile on chains that don't use osmosis' fork of the cosmos sdk * updated imports for e2e tests * go fumpt * updated version everywhere * added changelog entry --- CHANGELOG.md | 3 ++- app/app.go | 15 +++++++++++++++ go.mod | 4 ++-- go.sum | 8 ++++---- go.work.sum | 1 + osmoutils/module_account.go | 10 +++++++++- x/ibc-hooks/go.mod | 2 +- x/ibc-hooks/go.sum | 4 ++-- 8 files changed, 36 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e09c10781c..7bb251f6663 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,7 +58,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#3693](https://github.com/osmosis-labs/osmosis/pull/3693) Add `EstimateSwapExactAmountOut` query to stargate whitelist * [#3731](https://github.com/osmosis-labs/osmosis/pull/3731) BigDec Power functions with decimal exponent. * [#3847](https://github.com/osmosis-labs/osmosis/pull/3847) GeometricTwap and GeometricTwapToNow queries added to Stargate whitelist. - +* [#3899](https://github.com/osmosis-labs/osmosis/pull/3899) Fixed osmoutils so its importable by chains that don't use the osmosis CosmosSDK fork + ### API breaks * [#3763](https://github.com/osmosis-labs/osmosis/pull/3763) Move binary search and error tolerance code from `osmoutils` into `osmomath` diff --git a/app/app.go b/app/app.go index e34065c31d7..9c059c0da56 100644 --- a/app/app.go +++ b/app/app.go @@ -6,8 +6,12 @@ import ( "net/http" "os" "path/filepath" + "reflect" "strings" + vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + "github.com/osmosis-labs/osmosis/osmoutils" + "github.com/CosmWasm/wasmd/x/wasm" "github.com/gorilla/mux" "github.com/rakyll/statik/fs" @@ -143,6 +147,16 @@ func init() { DefaultNodeHome = filepath.Join(userHomeDir, ".osmosisd") } +// initReusablePackageInjections injects data available within osmosis into the reusable packages. +// This is done to ensure they can be built without depending on at compilation time and thus imported by other chains +// This should always be called before any other function to avoid inconsistent data +func initReusablePackageInjections() { + // Inject ClawbackVestingAccount account type into osmoutils + osmoutils.OsmoUtilsExtraAccountTypes = map[reflect.Type]struct{}{ + reflect.TypeOf(&vestingtypes.ClawbackVestingAccount{}): {}, + } +} + // NewOsmosisApp returns a reference to an initialized Osmosis. func NewOsmosisApp( logger log.Logger, @@ -157,6 +171,7 @@ func NewOsmosisApp( wasmOpts []wasm.Option, baseAppOptions ...func(*baseapp.BaseApp), ) *OsmosisApp { + initReusablePackageInjections() // This should run before anything else to make sure the variables are properly initialized encodingConfig := GetEncodingConfig() appCodec := encodingConfig.Marshaler cdc := encodingConfig.Amino diff --git a/go.mod b/go.mod index 3de01815702..12a10ba8151 100644 --- a/go.mod +++ b/go.mod @@ -18,8 +18,8 @@ require ( github.com/ory/dockertest/v3 v3.9.1 github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 github.com/osmosis-labs/osmosis/osmomath v0.0.2 - github.com/osmosis-labs/osmosis/osmoutils v0.0.2 - github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.4 + github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230101095308-fa4e70e17dbf + github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230101095308-fa4e70e17dbf github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/spf13/cast v1.5.0 diff --git a/go.sum b/go.sum index b60788f1091..001887aebaf 100644 --- a/go.sum +++ b/go.sum @@ -855,10 +855,10 @@ github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3 h1:Ylmch github.com/osmosis-labs/go-mutesting v0.0.0-20221208041716-b43bcd97b3b3/go.mod h1:lV6KnqXYD/ayTe7310MHtM3I2q8Z6bBfMAi+bhwPYtI= github.com/osmosis-labs/osmosis/osmomath v0.0.2 h1:8vTobkYfoRTCJCie+jE7gzXvqUUfoPI4NSvTskoci50= github.com/osmosis-labs/osmosis/osmomath v0.0.2/go.mod h1:IpoXO7lvmfsBFfQzaqovs541hpqtrnM+GJSZDi/TZtc= -github.com/osmosis-labs/osmosis/osmoutils v0.0.2 h1:oFsKFhmVOQHzqRfezFAkg/BlsUEwPhQK5n13a3uC6xc= -github.com/osmosis-labs/osmosis/osmoutils v0.0.2/go.mod h1:T7CCZKYhKWASnv5mRE8u3m0gst3NZ/sU16Brjmv4UPw= -github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.4 h1:Ny0GQ40agzVesBpZ/AG8Bi7Hn3ZN+qGEJOX272Bck+Q= -github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.4/go.mod h1:JleJ+kfjhlUpYnk7VfNrpHd+P7A5Lq5VhuAxGV7FbJM= +github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230101095308-fa4e70e17dbf h1:FZOlrTSaf/YWokt3+tSSZpcu6zu3dXLhsvhJWkHeBxU= +github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230101095308-fa4e70e17dbf/go.mod h1:T7CCZKYhKWASnv5mRE8u3m0gst3NZ/sU16Brjmv4UPw= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230101095308-fa4e70e17dbf h1:qcDUVsM6BNuGJ3dfGs3onOPzR0donLgXznqv60HRk+8= +github.com/osmosis-labs/osmosis/x/ibc-hooks v0.0.0-20230101095308-fa4e70e17dbf/go.mod h1:5zNisZDypMTW32EABSuWI/EacHC48590PpSO9QwFzCg= github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30 h1:6uMi7HhPSwvKKU7j5NqljseFTEz4I7qHr+IPnnn42Ck= github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30/go.mod h1:5fDYJyMXBq6u2iuHqqOTYiZ5NitIOeIW5k7qEXqbwJE= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= diff --git a/go.work.sum b/go.work.sum index b5ad2dc796a..160f89cd4bd 100644 --- a/go.work.sum +++ b/go.work.sum @@ -260,6 +260,7 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= +github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI= github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= diff --git a/osmoutils/module_account.go b/osmoutils/module_account.go index 20c57704cb5..4b87582bd6f 100644 --- a/osmoutils/module_account.go +++ b/osmoutils/module_account.go @@ -10,6 +10,11 @@ import ( vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" ) +// OsmoUtilsExtraAccountTypes is a map of extra account types that can be overridden. +// This is defined as a global variable so it can be modified in the chain's app.go and used here without +// having to import the chain. Specifically, this is used for compatibility with Osmosis' Cosmos SDK fork +var OsmoUtilsExtraAccountTypes map[reflect.Type]struct{} + type AccountKeeper interface { NewAccount(sdk.Context, authtypes.AccountI) authtypes.AccountI @@ -48,8 +53,11 @@ func CanCreateModuleAccountAtAddr(ctx sdk.Context, ak AccountKeeper, addr sdk.Ac reflect.TypeOf(&vestingtypes.BaseVestingAccount{}): {}, reflect.TypeOf(&vestingtypes.PeriodicVestingAccount{}): {}, reflect.TypeOf(&vestingtypes.PermanentLockedAccount{}): {}, - reflect.TypeOf(&vestingtypes.ClawbackVestingAccount{}): {}, } + for extraAccountType := range OsmoUtilsExtraAccountTypes { + overrideAccountTypes[extraAccountType] = struct{}{} + } + if _, clear := overrideAccountTypes[reflect.TypeOf(existingAcct)]; clear { return nil } diff --git a/x/ibc-hooks/go.mod b/x/ibc-hooks/go.mod index 65f3b7a9918..e4808eac863 100644 --- a/x/ibc-hooks/go.mod +++ b/x/ibc-hooks/go.mod @@ -8,7 +8,7 @@ require ( github.com/cosmos/ibc-go/v4 v4.2.0 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/osmosis-labs/osmosis/osmoutils v0.0.2 + github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230101095308-fa4e70e17dbf github.com/spf13/cobra v1.6.1 github.com/tendermint/tendermint v0.34.24 ) diff --git a/x/ibc-hooks/go.sum b/x/ibc-hooks/go.sum index 31a1070a25b..c260c6fdaa8 100644 --- a/x/ibc-hooks/go.sum +++ b/x/ibc-hooks/go.sum @@ -620,8 +620,8 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20221118211718-545aed73e94e h1:A3byMZpvq21iI7yWJUNdHw0nf8jVAbVUsWY9twnXSXE= github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20221118211718-545aed73e94e/go.mod h1:rud0OaBIuq3+qOqtwT4SR7Q7iSzRp7w41fjninTjfnQ= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20221223175211-9d2007cbaad6 h1:/Ea4oM6/hQLusuQfex0slJg+Gc8UYq7XVOchBNQg9g4= -github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20221223175211-9d2007cbaad6/go.mod h1:T7CCZKYhKWASnv5mRE8u3m0gst3NZ/sU16Brjmv4UPw= +github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230101095308-fa4e70e17dbf h1:FZOlrTSaf/YWokt3+tSSZpcu6zu3dXLhsvhJWkHeBxU= +github.com/osmosis-labs/osmosis/osmoutils v0.0.0-20230101095308-fa4e70e17dbf/go.mod h1:T7CCZKYhKWASnv5mRE8u3m0gst3NZ/sU16Brjmv4UPw= github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30 h1:6uMi7HhPSwvKKU7j5NqljseFTEz4I7qHr+IPnnn42Ck= github.com/osmosis-labs/wasmd v0.29.2-0.20221222131554-7c8ea36a6e30/go.mod h1:5fDYJyMXBq6u2iuHqqOTYiZ5NitIOeIW5k7qEXqbwJE= github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE= From 19e4a9d12fd9a8d0b2d99d975e133c8cdfa22066 Mon Sep 17 00:00:00 2001 From: Supanat Date: Wed, 4 Jan 2023 21:39:51 +0700 Subject: [PATCH 13/30] remove deprecation from arithmetic & geometric twap to now query (#3917) --- proto/osmosis/twap/v1beta1/query.proto | 8 +- x/twap/client/queryproto/query.pb.go | 114 +++++++++++++++---------- 2 files changed, 76 insertions(+), 46 deletions(-) diff --git a/proto/osmosis/twap/v1beta1/query.proto b/proto/osmosis/twap/v1beta1/query.proto index 95374ece07c..c04939956ee 100644 --- a/proto/osmosis/twap/v1beta1/query.proto +++ b/proto/osmosis/twap/v1beta1/query.proto @@ -23,9 +23,15 @@ service Query { } rpc ArithmeticTwapToNow(ArithmeticTwapToNowRequest) returns (ArithmeticTwapToNowResponse) { - option deprecated = true; option (google.api.http).get = "/osmosis/twap/v1beta1/ArithmeticTwapToNow"; } + rpc GeometricTwap(GeometricTwapRequest) returns (GeometricTwapResponse) { + option (google.api.http).get = "/osmosis/twap/v1beta1/GeometricTwap"; + } + rpc GeometricTwapToNow(GeometricTwapToNowRequest) + returns (GeometricTwapToNowResponse) { + option (google.api.http).get = "/osmosis/twap/v1beta1/GeometricTwapToNow"; + } } message ArithmeticTwapRequest { diff --git a/x/twap/client/queryproto/query.pb.go b/x/twap/client/queryproto/query.pb.go index 5856b31e1df..7452d378c6e 100644 --- a/x/twap/client/queryproto/query.pb.go +++ b/x/twap/client/queryproto/query.pb.go @@ -349,50 +349,57 @@ func init() { func init() { proto.RegisterFile("osmosis/twap/v1beta1/query.proto", fileDescriptor_141a22dba58615af) } var fileDescriptor_141a22dba58615af = []byte{ - // 676 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x95, 0x4f, 0x4f, 0xd4, 0x4e, - 0x18, 0xc7, 0x77, 0x16, 0x58, 0x7e, 0x3b, 0xe4, 0x07, 0x71, 0x44, 0xc4, 0x02, 0xed, 0xa6, 0x12, - 0x82, 0x02, 0xad, 0x0b, 0x9e, 0x88, 0x17, 0x36, 0x1e, 0x34, 0x31, 0x46, 0x1b, 0x62, 0x8c, 0x97, - 0xcd, 0x6c, 0x77, 0x2c, 0x8d, 0xdb, 0x4e, 0xb7, 0x33, 0x0b, 0xee, 0xd5, 0x93, 0x89, 0x17, 0x12, - 0x4f, 0x5e, 0x7c, 0x0d, 0xbe, 0x0c, 0x6e, 0x62, 0xbc, 0x18, 0x0f, 0xd5, 0x80, 0xaf, 0x80, 0x57, - 0x60, 0xe6, 0x4f, 0x57, 0xd8, 0x34, 0x88, 0x27, 0xe3, 0xa9, 0x3b, 0xcf, 0xf3, 0x7d, 0xbe, 0xcf, - 0x67, 0x9e, 0x4e, 0x67, 0x61, 0x8d, 0xb2, 0x88, 0xb2, 0x90, 0xb9, 0x7c, 0x0f, 0x27, 0xee, 0x6e, - 0xbd, 0x45, 0x38, 0xae, 0xbb, 0xdd, 0x1e, 0x49, 0xfb, 0x4e, 0x92, 0x52, 0x4e, 0xd1, 0xb4, 0x56, - 0x38, 0x42, 0xe1, 0x68, 0x85, 0x31, 0x1d, 0xd0, 0x80, 0x4a, 0x81, 0x2b, 0x7e, 0x29, 0xad, 0xb1, - 0x54, 0xe8, 0x26, 0x16, 0xcd, 0x94, 0xf8, 0x34, 0x6d, 0x6b, 0x9d, 0x5d, 0xa8, 0x0b, 0x48, 0x4c, - 0x44, 0x23, 0xa5, 0x31, 0x7d, 0x29, 0x72, 0x5b, 0x98, 0x91, 0x81, 0xc4, 0xa7, 0x61, 0xac, 0xf3, - 0x37, 0x4f, 0xe7, 0x25, 0xf0, 0x40, 0x95, 0xe0, 0x20, 0x8c, 0x31, 0x0f, 0x69, 0xae, 0x9d, 0x0f, - 0x28, 0x0d, 0x3a, 0xc4, 0xc5, 0x49, 0xe8, 0xe2, 0x38, 0xa6, 0x5c, 0x26, 0xf3, 0x4e, 0xd7, 0x74, - 0x56, 0xae, 0x5a, 0xbd, 0xe7, 0x2e, 0x8e, 0xfb, 0x79, 0x4a, 0x35, 0x69, 0xaa, 0x9d, 0xaa, 0x85, - 0x4e, 0x59, 0xc3, 0x55, 0x3c, 0x8c, 0x08, 0xe3, 0x38, 0x4a, 0x94, 0xc0, 0x7e, 0x5f, 0x86, 0x57, - 0xb6, 0xd2, 0x90, 0xef, 0x44, 0x84, 0x87, 0xfe, 0xf6, 0x1e, 0x4e, 0x3c, 0xd2, 0xed, 0x11, 0xc6, - 0xd1, 0x55, 0x38, 0x9e, 0x50, 0xda, 0x69, 0x86, 0xed, 0x59, 0x50, 0x03, 0xcb, 0xa3, 0x5e, 0x45, - 0x2c, 0xef, 0xb7, 0xd1, 0x02, 0x84, 0x62, 0x3b, 0x4d, 0xcc, 0x18, 0xe1, 0xb3, 0xe5, 0x1a, 0x58, - 0xae, 0x7a, 0x55, 0x11, 0xd9, 0x12, 0x01, 0x64, 0xc1, 0x89, 0x6e, 0x8f, 0xf2, 0x3c, 0x3f, 0x22, - 0xf3, 0x50, 0x86, 0x94, 0xe0, 0x29, 0x84, 0x8c, 0xe3, 0x94, 0x37, 0x05, 0xcb, 0xec, 0x68, 0x0d, - 0x2c, 0x4f, 0xac, 0x1b, 0x8e, 0x02, 0x75, 0x72, 0x50, 0x67, 0x3b, 0x07, 0x6d, 0x2c, 0x1c, 0x64, - 0x56, 0xe9, 0x24, 0xb3, 0x2e, 0xf5, 0x71, 0xd4, 0xd9, 0xb4, 0x7f, 0xd5, 0xda, 0xfb, 0xdf, 0x2c, - 0xe0, 0x55, 0x65, 0x40, 0xc8, 0x91, 0x07, 0xff, 0x23, 0x71, 0x5b, 0xf9, 0x8e, 0xfd, 0xd6, 0x77, - 0xee, 0x20, 0xb3, 0xc0, 0x49, 0x66, 0x4d, 0x29, 0xdf, 0xbc, 0x52, 0xb9, 0x8e, 0x93, 0xb8, 0x2d, - 0xa4, 0xf6, 0x1b, 0x00, 0x67, 0x86, 0x07, 0xc4, 0x12, 0x1a, 0x33, 0x82, 0xba, 0x70, 0x0a, 0x0f, - 0x32, 0x4d, 0x71, 0x4a, 0xe4, 0xa4, 0xaa, 0x8d, 0x7b, 0x82, 0xf8, 0x6b, 0x66, 0x2d, 0x05, 0x21, - 0xdf, 0xe9, 0xb5, 0x1c, 0x9f, 0x46, 0xfa, 0xb5, 0xe8, 0xc7, 0x1a, 0x6b, 0xbf, 0x70, 0x79, 0x3f, - 0x21, 0xcc, 0xb9, 0x4b, 0xfc, 0x93, 0xcc, 0x9a, 0x51, 0x0c, 0x43, 0x76, 0xb6, 0x37, 0x89, 0xcf, - 0xb4, 0xb6, 0x3f, 0x02, 0x68, 0x9c, 0xa5, 0xd9, 0xa6, 0x0f, 0xe9, 0xde, 0xbf, 0xfb, 0xce, 0xec, - 0x7d, 0x00, 0xe7, 0x0a, 0x77, 0xf4, 0xf7, 0x86, 0x3c, 0x05, 0xff, 0x7f, 0x84, 0x53, 0x1c, 0x31, - 0x3d, 0x56, 0xfb, 0x01, 0x9c, 0xcc, 0x03, 0x9a, 0x6a, 0x13, 0x56, 0x12, 0x19, 0x91, 0x30, 0x13, - 0xeb, 0xf3, 0x4e, 0xd1, 0x05, 0xe4, 0xa8, 0xaa, 0xc6, 0xa8, 0x40, 0xf5, 0x74, 0xc5, 0xfa, 0xa7, - 0x11, 0x38, 0xf6, 0x58, 0x5c, 0x05, 0xa8, 0x0f, 0x2b, 0x4a, 0x81, 0xae, 0x9f, 0x57, 0xaf, 0x31, - 0x8c, 0xc5, 0xf3, 0x45, 0x0a, 0xcd, 0x5e, 0x7c, 0xf5, 0xf9, 0xc7, 0xdb, 0xb2, 0x89, 0xe6, 0xdd, - 0xc2, 0xfb, 0x4b, 0x37, 0x7c, 0x07, 0xe0, 0xe4, 0xd9, 0xb1, 0xa3, 0x95, 0x62, 0xfb, 0xc2, 0xdb, - 0xc1, 0x58, 0xbd, 0x98, 0x58, 0x33, 0xad, 0x4a, 0xa6, 0x25, 0xb4, 0x58, 0xcc, 0x34, 0x04, 0xf2, - 0x01, 0xc0, 0xcb, 0x05, 0x47, 0x02, 0xdd, 0xba, 0x48, 0xcf, 0xd3, 0xdf, 0x83, 0x51, 0xff, 0x83, - 0x0a, 0x8d, 0x7a, 0x5b, 0xa2, 0xae, 0xa0, 0x1b, 0x17, 0x41, 0x95, 0xa5, 0xaf, 0xcb, 0xa0, 0xf1, - 0xe4, 0xe0, 0xc8, 0x04, 0x87, 0x47, 0x26, 0xf8, 0x7e, 0x64, 0x82, 0xfd, 0x63, 0xb3, 0x74, 0x78, - 0x6c, 0x96, 0xbe, 0x1c, 0x9b, 0xa5, 0x67, 0x77, 0x4e, 0x1d, 0x4f, 0xed, 0xb8, 0xd6, 0xc1, 0x2d, - 0x36, 0xb0, 0xdf, 0xad, 0x6f, 0xb8, 0x2f, 0x55, 0x13, 0xbf, 0x13, 0x92, 0x98, 0xab, 0xff, 0x09, - 0xf5, 0x51, 0x55, 0xe4, 0x63, 0xe3, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, 0x99, 0x01, 0xcf, 0x37, - 0x02, 0x07, 0x00, 0x00, + // 799 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x96, 0x41, 0x4f, 0x1b, 0x47, + 0x14, 0xc7, 0x3d, 0x2e, 0x98, 0x7a, 0x10, 0x46, 0x9d, 0x02, 0x85, 0x05, 0x76, 0xad, 0x85, 0x22, + 0x17, 0xc3, 0x2e, 0x86, 0x1b, 0xea, 0x05, 0xab, 0x12, 0xad, 0x54, 0x55, 0xed, 0x0a, 0x55, 0x55, + 0x2f, 0xd6, 0xd8, 0x9e, 0x2e, 0xab, 0x7a, 0x77, 0xd6, 0xbb, 0x63, 0x88, 0xaf, 0xb9, 0xe4, 0x90, + 0x1c, 0x50, 0xa2, 0x1c, 0x72, 0x48, 0xee, 0x39, 0xe4, 0x7b, 0x70, 0x4a, 0x90, 0x72, 0x89, 0x72, + 0x70, 0x22, 0xc8, 0x27, 0xe0, 0x13, 0x44, 0x3b, 0x33, 0xeb, 0x78, 0x9d, 0x15, 0x31, 0x27, 0x84, + 0x94, 0x93, 0x99, 0xf7, 0xfe, 0xef, 0xbd, 0xdf, 0xbc, 0xd9, 0x37, 0x03, 0x2c, 0xd2, 0xd0, 0xa5, + 0xa1, 0x13, 0x9a, 0xec, 0x18, 0xfb, 0xe6, 0x51, 0xa5, 0x4e, 0x18, 0xae, 0x98, 0xed, 0x0e, 0x09, + 0xba, 0x86, 0x1f, 0x50, 0x46, 0xd1, 0x8c, 0x54, 0x18, 0x91, 0xc2, 0x90, 0x0a, 0x65, 0xc6, 0xa6, + 0x36, 0xe5, 0x02, 0x33, 0xfa, 0x4b, 0x68, 0x95, 0xb5, 0xd4, 0x6c, 0xd1, 0xa2, 0x16, 0x90, 0x06, + 0x0d, 0x9a, 0x52, 0xa7, 0xa7, 0xea, 0x6c, 0xe2, 0x91, 0xa8, 0x90, 0xd0, 0xa8, 0x0d, 0x2e, 0x32, + 0xeb, 0x38, 0x24, 0x7d, 0x49, 0x83, 0x3a, 0x9e, 0xf4, 0xaf, 0x0f, 0xfa, 0x39, 0x70, 0x5f, 0xe5, + 0x63, 0xdb, 0xf1, 0x30, 0x73, 0x68, 0xac, 0x5d, 0xb2, 0x29, 0xb5, 0x5b, 0xc4, 0xc4, 0xbe, 0x63, + 0x62, 0xcf, 0xa3, 0x8c, 0x3b, 0xe3, 0x4a, 0x0b, 0xd2, 0xcb, 0x57, 0xf5, 0xce, 0x7f, 0x26, 0xf6, + 0xba, 0xb1, 0x4b, 0x14, 0xa9, 0x89, 0x9d, 0x8a, 0x85, 0x74, 0x69, 0xc3, 0x51, 0xcc, 0x71, 0x49, + 0xc8, 0xb0, 0xeb, 0x0b, 0x81, 0xfe, 0x2c, 0x0b, 0x67, 0xf7, 0x02, 0x87, 0x1d, 0xba, 0x84, 0x39, + 0x8d, 0x83, 0x63, 0xec, 0x5b, 0xa4, 0xdd, 0x21, 0x21, 0x43, 0x3f, 0xc0, 0x09, 0x9f, 0xd2, 0x56, + 0xcd, 0x69, 0xce, 0x83, 0x22, 0x28, 0x8d, 0x59, 0xb9, 0x68, 0xf9, 0x5b, 0x13, 0x2d, 0x43, 0x18, + 0x6d, 0xa7, 0x86, 0xc3, 0x90, 0xb0, 0xf9, 0x6c, 0x11, 0x94, 0xf2, 0x56, 0x3e, 0xb2, 0xec, 0x45, + 0x06, 0xa4, 0xc1, 0xc9, 0x76, 0x87, 0xb2, 0xd8, 0xff, 0x0d, 0xf7, 0x43, 0x6e, 0x12, 0x82, 0x7f, + 0x20, 0x0c, 0x19, 0x0e, 0x58, 0x2d, 0x62, 0x99, 0x1f, 0x2b, 0x82, 0xd2, 0xe4, 0xb6, 0x62, 0x08, + 0x50, 0x23, 0x06, 0x35, 0x0e, 0x62, 0xd0, 0xea, 0xf2, 0x69, 0x4f, 0xcb, 0x5c, 0xf6, 0xb4, 0xef, + 0xba, 0xd8, 0x6d, 0xed, 0xea, 0x9f, 0x62, 0xf5, 0x93, 0x77, 0x1a, 0xb0, 0xf2, 0xdc, 0x10, 0xc9, + 0x91, 0x05, 0xbf, 0x25, 0x5e, 0x53, 0xe4, 0x1d, 0xff, 0x62, 0xde, 0xc5, 0xd3, 0x9e, 0x06, 0x2e, + 0x7b, 0xda, 0xb4, 0xc8, 0x1b, 0x47, 0x8a, 0xac, 0x13, 0xc4, 0x6b, 0x46, 0x52, 0xfd, 0x3e, 0x80, + 0x73, 0xc3, 0x0d, 0x0a, 0x7d, 0xea, 0x85, 0x04, 0xb5, 0xe1, 0x34, 0xee, 0x7b, 0x6a, 0xd1, 0x57, + 0xc2, 0x3b, 0x95, 0xaf, 0xfe, 0x1a, 0x11, 0xbf, 0xed, 0x69, 0x6b, 0xb6, 0xc3, 0x0e, 0x3b, 0x75, + 0xa3, 0x41, 0x5d, 0x79, 0x2c, 0xf2, 0x67, 0x33, 0x6c, 0xfe, 0x6f, 0xb2, 0xae, 0x4f, 0x42, 0xe3, + 0x17, 0xd2, 0xb8, 0xec, 0x69, 0x73, 0x82, 0x61, 0x28, 0x9d, 0x6e, 0x15, 0x70, 0xa2, 0xb4, 0xfe, + 0x0a, 0x40, 0x25, 0x49, 0x73, 0x40, 0xff, 0xa0, 0xc7, 0xb7, 0xf7, 0xcc, 0xf4, 0x13, 0x00, 0x17, + 0x53, 0x77, 0x74, 0x73, 0x4d, 0x7e, 0x9a, 0x85, 0x33, 0xfb, 0x84, 0xba, 0x84, 0x05, 0x5f, 0x47, + 0x22, 0x65, 0x24, 0xee, 0x01, 0x38, 0x3b, 0xd4, 0x1f, 0x79, 0x58, 0x1e, 0x2c, 0xd8, 0xb1, 0x63, + 0xf0, 0xac, 0xf6, 0xaf, 0x7d, 0x56, 0xb3, 0x82, 0x20, 0x99, 0x4d, 0xb7, 0xa6, 0xec, 0xc1, 0xba, + 0xfa, 0x4b, 0x00, 0x17, 0x12, 0x24, 0xb7, 0x7d, 0x1a, 0x1e, 0x00, 0xa8, 0xa4, 0x6d, 0xe8, 0x86, + 0xfa, 0x3b, 0x0d, 0xa7, 0xfe, 0xc4, 0x01, 0x76, 0x43, 0xd9, 0x52, 0xfd, 0x77, 0x58, 0x88, 0x0d, + 0x12, 0x69, 0x17, 0xe6, 0x7c, 0x6e, 0xe1, 0x28, 0x93, 0xdb, 0x4b, 0x46, 0xda, 0x53, 0x6c, 0x88, + 0xa8, 0xea, 0x58, 0x04, 0x6a, 0xc9, 0x88, 0xed, 0x87, 0x39, 0x38, 0xfe, 0x57, 0xf4, 0x28, 0xa2, + 0x2e, 0xcc, 0x09, 0x05, 0x5a, 0xb9, 0x2a, 0x5e, 0x62, 0x28, 0xab, 0x57, 0x8b, 0x04, 0x9a, 0xbe, + 0x7a, 0xf7, 0xf5, 0x87, 0x47, 0x59, 0x15, 0x2d, 0x99, 0xa9, 0x2f, 0xb9, 0x2c, 0xf8, 0x04, 0xc0, + 0x42, 0xf2, 0x02, 0x42, 0xe5, 0xf4, 0xf4, 0xa9, 0xef, 0xa4, 0xb2, 0x31, 0x9a, 0x58, 0x32, 0x6d, + 0x70, 0xa6, 0x35, 0xb4, 0x9a, 0xce, 0x34, 0x04, 0xf2, 0x02, 0xc0, 0xef, 0x53, 0x2e, 0x47, 0xb4, + 0x35, 0x4a, 0xcd, 0xc1, 0x59, 0x50, 0x2a, 0xd7, 0x88, 0x90, 0xa8, 0x15, 0x8e, 0x5a, 0x46, 0x3f, + 0x8d, 0x82, 0x2a, 0xb8, 0x1e, 0x03, 0x38, 0x95, 0xf8, 0x7c, 0xd1, 0x7a, 0x7a, 0xdd, 0xb4, 0xeb, + 0x55, 0x29, 0x8f, 0xa4, 0x95, 0x74, 0x65, 0x4e, 0xf7, 0x23, 0x5a, 0x49, 0xa7, 0x4b, 0x52, 0x3c, + 0x07, 0x10, 0x7d, 0x3e, 0x56, 0xc8, 0x1c, 0xa1, 0x60, 0xa2, 0x8b, 0x5b, 0xa3, 0x07, 0x48, 0xcc, + 0x2d, 0x8e, 0xb9, 0x8e, 0x4a, 0x23, 0x60, 0xf2, 0xc8, 0xea, 0xdf, 0xa7, 0xe7, 0x2a, 0x38, 0x3b, + 0x57, 0xc1, 0xfb, 0x73, 0x15, 0x9c, 0x5c, 0xa8, 0x99, 0xb3, 0x0b, 0x35, 0xf3, 0xe6, 0x42, 0xcd, + 0xfc, 0xfb, 0xf3, 0xc0, 0x74, 0xcb, 0x6c, 0x9b, 0x2d, 0x5c, 0x0f, 0xfb, 0xa9, 0x8f, 0x2a, 0x3b, + 0xe6, 0x1d, 0x51, 0xa0, 0xd1, 0x72, 0x88, 0xc7, 0xc4, 0xbf, 0x9c, 0xe2, 0x46, 0xca, 0xf1, 0x9f, + 0x9d, 0x8f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x83, 0xed, 0xb2, 0x07, 0x4d, 0x0b, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -438,7 +445,6 @@ func (c *queryClient) ArithmeticTwap(ctx context.Context, in *ArithmeticTwapRequ return out, nil } -// Deprecated: Do not use. func (c *queryClient) ArithmeticTwapToNow(ctx context.Context, in *ArithmeticTwapToNowRequest, opts ...grpc.CallOption) (*ArithmeticTwapToNowResponse, error) { out := new(ArithmeticTwapToNowResponse) err := c.cc.Invoke(ctx, "/osmosis.twap.v1beta1.Query/ArithmeticTwapToNow", in, out, opts...) @@ -448,6 +454,24 @@ func (c *queryClient) ArithmeticTwapToNow(ctx context.Context, in *ArithmeticTwa return out, nil } +func (c *queryClient) GeometricTwap(ctx context.Context, in *GeometricTwapRequest, opts ...grpc.CallOption) (*GeometricTwapResponse, error) { + out := new(GeometricTwapResponse) + err := c.cc.Invoke(ctx, "/osmosis.twap.v1beta1.Query/GeometricTwap", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) GeometricTwapToNow(ctx context.Context, in *GeometricTwapToNowRequest, opts ...grpc.CallOption) (*GeometricTwapToNowResponse, error) { + out := new(GeometricTwapToNowResponse) + err := c.cc.Invoke(ctx, "/osmosis.twap.v1beta1.Query/GeometricTwapToNow", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { Params(context.Context, *ParamsRequest) (*ParamsResponse, error) From 952b2d7aefce2c27037e423c2b9cf7db93ba0847 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Mon, 5 Dec 2022 19:22:02 -0600 Subject: [PATCH 14/30] Add types & boilerplate for the Downtime detector module (#3609) Sub-component of #3603 Adds types for the thin module intended for downtime detection - Add downtime detection module types No tests added - Does this pull request introduce a new feature or user-facing behavior changes? somewhat - Is a relevant changelog entry added to the `Unreleased` section in `CHANGELOG.md`? yes - How is the feature or change documented? In its spec --- CHANGELOG.md | 2 - .../downtime-detector/v1beta1/genesis.proto | 40 + .../downtime-detector/v1beta1/query.proto | 49 + x/downtime-detector/README.md | 30 + .../client/queryproto/query.pb.go | 978 ++++++++++++++++++ .../client/queryproto/query.pb.gw.go | 236 +++++ .../downtimedetector_module/module.go | 119 +++ x/downtime-detector/keeper.go | 52 + x/downtime-detector/types/constants.go | 9 + x/downtime-detector/types/genesis.go | 9 + x/downtime-detector/types/genesis.pb.go | 798 ++++++++++++++ x/ibc-rate-limit/testutil/wasm.go | 4 +- 12 files changed, 2322 insertions(+), 4 deletions(-) create mode 100644 proto/osmosis/downtime-detector/v1beta1/genesis.proto create mode 100644 proto/osmosis/downtime-detector/v1beta1/query.proto create mode 100644 x/downtime-detector/README.md create mode 100644 x/downtime-detector/client/queryproto/query.pb.go create mode 100644 x/downtime-detector/client/queryproto/query.pb.gw.go create mode 100644 x/downtime-detector/downtimedetector_module/module.go create mode 100644 x/downtime-detector/keeper.go create mode 100644 x/downtime-detector/types/constants.go create mode 100644 x/downtime-detector/types/genesis.go create mode 100644 x/downtime-detector/types/genesis.pb.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bb251f6663..21f67d49480 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,8 +47,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Cosmwasm * Upgrade to wasmd v0.30.x -### Features -* [#2387](https://github.com/osmosis-labs/osmosis/pull/3838) Upgrade to IBC v4.2.0, and as a requirement for it wasmd to 0.30.0 * [#3609](https://github.com/osmosis-labs/osmosis/pull/3609) Add Downtime-detection module. * [#2788](https://github.com/osmosis-labs/osmosis/pull/2788) Add logarithm base 2 implementation. * [#3677](https://github.com/osmosis-labs/osmosis/pull/3677) Add methods for cloning and mutative multiplication on osmomath.BigDec. diff --git a/proto/osmosis/downtime-detector/v1beta1/genesis.proto b/proto/osmosis/downtime-detector/v1beta1/genesis.proto new file mode 100644 index 00000000000..a1ce25eedce --- /dev/null +++ b/proto/osmosis/downtime-detector/v1beta1/genesis.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package osmosis.downtimedetector.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "cosmos_proto/cosmos.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types"; + +// Params holds parameters for the downtime-detector module +message Params {} + +message GenesisDowntimeEntry { + google.protobuf.Duration downtime_duration = 1 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true, + (gogoproto.moretags) = "yaml:\"downtime_duration\"" + ]; + google.protobuf.Timestamp last_downtime = 2 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true, + (gogoproto.moretags) = "yaml:\"last_downtime\"" + ]; +} + +// GenesisState defines the twap module's genesis state. +message GenesisState { + repeated GenesisDowntimeEntry downtimes = 1 [ (gogoproto.nullable) = false ]; + + google.protobuf.Timestamp last_block_time = 2 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true, + (gogoproto.moretags) = "yaml:\"last_block_time\"" + ]; + + // params is the container of twap parameters. + Params params = 3 [ (gogoproto.nullable) = false ]; +} diff --git a/proto/osmosis/downtime-detector/v1beta1/query.proto b/proto/osmosis/downtime-detector/v1beta1/query.proto new file mode 100644 index 00000000000..97c07b26930 --- /dev/null +++ b/proto/osmosis/downtime-detector/v1beta1/query.proto @@ -0,0 +1,49 @@ +syntax = "proto3"; +package osmosis.downtimedetector.v1beta1; + +import "gogoproto/gogo.proto"; +import "osmosis/downtime-detector/v1beta1/genesis.proto"; + +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "google/api/annotations.proto"; +import "google/protobuf/any.proto"; +import "cosmos_proto/cosmos.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto"; + +service Query { + rpc Params(ParamsRequest) returns (ParamsResponse) { + option (google.api.http).get = "/osmosis/downtime-detector/v1beta1/Params"; + } + rpc RecoveredSinceDowntimeOfLength(RecoveredSinceDowntimeOfLengthRequest) + returns (RecoveredSinceDowntimeOfLengthResponse) { + option (google.api.http).get = + "/osmosis/downtime-detector/v1beta1/RecoveredSinceDowntimeOfLength"; + } +} + +// Query for has it been at least $RECOVERY_DURATION units of time, +// since the chain has been down for $DOWNTIME_DURATION. +// Note: $DOWNTIME_DURATION must be in set {SPECIFY_SET} +message RecoveredSinceDowntimeOfLengthRequest { + google.protobuf.Duration downtime = 1 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true, + (gogoproto.moretags) = "yaml:\"downtime_duration\"" + ]; + google.protobuf.Duration recovery = 2 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true, + (gogoproto.moretags) = "yaml:\"recovery_duration\"" + ]; +} + +message RecoveredSinceDowntimeOfLengthResponse { + bool succesfully_recovered = 1; +} + +message ParamsRequest {} +message ParamsResponse { Params params = 1 [ (gogoproto.nullable) = false ]; } diff --git a/x/downtime-detector/README.md b/x/downtime-detector/README.md new file mode 100644 index 00000000000..938354186de --- /dev/null +++ b/x/downtime-detector/README.md @@ -0,0 +1,30 @@ +# Downtime-detector + +For several use cases, we need a module that can detect when the chain is recovering from downtime. We want to be able to efficiently know "Has it been $RECOVERY_PERIOD minutes since the chain has been down for $DOWNTIME_PERIOD", and expose this as a query to contracts. + +So for instance, you'd want to know if it has been at least 10 minutes, since the chain was down for > 30 minutes. Since you assume in such an event that it may take ~10 minutes for price oracles to be arb'd to correct. +Suggested Design + +Theres a couple designs, such as: + +* Iterating over block times from the last N blocks (with a heuristic filter based on average block time) + * Implies bounds on recovery time + * Linear iteration if heuristic is met + * Requires encoding expected block time +* Restricting downtime period, and storing a state entry for last time a downtime of length $D occurred + +Because this will be in important txs for contracts, we need to go with the approach that has minimal query compute, which is the latter. So we explain that in more depth. + +We restrict the $DOWNTIME_PERIOD options that you can query, to be: 30seconds, 1 min, 2 min, 3 min, 4 min, 5 min, 10 min, 20 min, 30 min, 40 min, 50 min, 1 hr, 1.5hr, 2 hr, 2.5 hr, 3 hr, 4 hr, 5 hr, 6 hr, 9hr, 12hr, 18hr, 24hr, 36hr, 48hr. + +In the downtime detector module, we store state entries for: + +* Last blocks timestamp +* For each period, last time there was downtime + +Then in every begin block: + +* Store last blocks timestamp +* if time since last block timestamp >= 30 seconds, iterate through all $DOWNTIME_PERIODS less than the downtime, and in each add a state entry for the current block time + +Then our query for has it been $RECOVERY_PERIOD since $DOWNTIME_PERIOD, simply reads the state entry for that $DOWNTIME_PERIOD, and then checks if time difference between now and that block is > RECOVERY_PERIOD. \ No newline at end of file diff --git a/x/downtime-detector/client/queryproto/query.pb.go b/x/downtime-detector/client/queryproto/query.pb.go new file mode 100644 index 00000000000..a31ccb14e87 --- /dev/null +++ b/x/downtime-detector/client/queryproto/query.pb.go @@ -0,0 +1,978 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: osmosis/downtime-detector/v1beta1/query.proto + +package queryproto + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "github.com/gogo/protobuf/types" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + types1 "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Query for has it been at least $RECOVERY_DURATION units of time, +// since the chain has been down for $DOWNTIME_DURATION. +// Note: $DOWNTIME_DURATION must be in set {SPECIFY_SET} +type RecoveredSinceDowntimeOfLengthRequest struct { + Downtime time.Duration `protobuf:"bytes,1,opt,name=downtime,proto3,stdduration" json:"downtime" yaml:"downtime_duration"` + Recovery time.Duration `protobuf:"bytes,2,opt,name=recovery,proto3,stdduration" json:"recovery" yaml:"recovery_duration"` +} + +func (m *RecoveredSinceDowntimeOfLengthRequest) Reset() { *m = RecoveredSinceDowntimeOfLengthRequest{} } +func (m *RecoveredSinceDowntimeOfLengthRequest) String() string { return proto.CompactTextString(m) } +func (*RecoveredSinceDowntimeOfLengthRequest) ProtoMessage() {} +func (*RecoveredSinceDowntimeOfLengthRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_b748b3d07fa8b8cb, []int{0} +} +func (m *RecoveredSinceDowntimeOfLengthRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RecoveredSinceDowntimeOfLengthRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RecoveredSinceDowntimeOfLengthRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RecoveredSinceDowntimeOfLengthRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_RecoveredSinceDowntimeOfLengthRequest.Merge(m, src) +} +func (m *RecoveredSinceDowntimeOfLengthRequest) XXX_Size() int { + return m.Size() +} +func (m *RecoveredSinceDowntimeOfLengthRequest) XXX_DiscardUnknown() { + xxx_messageInfo_RecoveredSinceDowntimeOfLengthRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_RecoveredSinceDowntimeOfLengthRequest proto.InternalMessageInfo + +func (m *RecoveredSinceDowntimeOfLengthRequest) GetDowntime() time.Duration { + if m != nil { + return m.Downtime + } + return 0 +} + +func (m *RecoveredSinceDowntimeOfLengthRequest) GetRecovery() time.Duration { + if m != nil { + return m.Recovery + } + return 0 +} + +type RecoveredSinceDowntimeOfLengthResponse struct { + SuccesfullyRecovered bool `protobuf:"varint,1,opt,name=succesfully_recovered,json=succesfullyRecovered,proto3" json:"succesfully_recovered,omitempty"` +} + +func (m *RecoveredSinceDowntimeOfLengthResponse) Reset() { + *m = RecoveredSinceDowntimeOfLengthResponse{} +} +func (m *RecoveredSinceDowntimeOfLengthResponse) String() string { return proto.CompactTextString(m) } +func (*RecoveredSinceDowntimeOfLengthResponse) ProtoMessage() {} +func (*RecoveredSinceDowntimeOfLengthResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b748b3d07fa8b8cb, []int{1} +} +func (m *RecoveredSinceDowntimeOfLengthResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RecoveredSinceDowntimeOfLengthResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RecoveredSinceDowntimeOfLengthResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RecoveredSinceDowntimeOfLengthResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_RecoveredSinceDowntimeOfLengthResponse.Merge(m, src) +} +func (m *RecoveredSinceDowntimeOfLengthResponse) XXX_Size() int { + return m.Size() +} +func (m *RecoveredSinceDowntimeOfLengthResponse) XXX_DiscardUnknown() { + xxx_messageInfo_RecoveredSinceDowntimeOfLengthResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_RecoveredSinceDowntimeOfLengthResponse proto.InternalMessageInfo + +func (m *RecoveredSinceDowntimeOfLengthResponse) GetSuccesfullyRecovered() bool { + if m != nil { + return m.SuccesfullyRecovered + } + return false +} + +type ParamsRequest struct { +} + +func (m *ParamsRequest) Reset() { *m = ParamsRequest{} } +func (m *ParamsRequest) String() string { return proto.CompactTextString(m) } +func (*ParamsRequest) ProtoMessage() {} +func (*ParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_b748b3d07fa8b8cb, []int{2} +} +func (m *ParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ParamsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_ParamsRequest.Merge(m, src) +} +func (m *ParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *ParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_ParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_ParamsRequest proto.InternalMessageInfo + +type ParamsResponse struct { + Params types1.Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *ParamsResponse) Reset() { *m = ParamsResponse{} } +func (m *ParamsResponse) String() string { return proto.CompactTextString(m) } +func (*ParamsResponse) ProtoMessage() {} +func (*ParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b748b3d07fa8b8cb, []int{3} +} +func (m *ParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_ParamsResponse.Merge(m, src) +} +func (m *ParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *ParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_ParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_ParamsResponse proto.InternalMessageInfo + +func (m *ParamsResponse) GetParams() types1.Params { + if m != nil { + return m.Params + } + return types1.Params{} +} + +func init() { + proto.RegisterType((*RecoveredSinceDowntimeOfLengthRequest)(nil), "osmosis.downtimedetector.v1beta1.RecoveredSinceDowntimeOfLengthRequest") + proto.RegisterType((*RecoveredSinceDowntimeOfLengthResponse)(nil), "osmosis.downtimedetector.v1beta1.RecoveredSinceDowntimeOfLengthResponse") + proto.RegisterType((*ParamsRequest)(nil), "osmosis.downtimedetector.v1beta1.ParamsRequest") + proto.RegisterType((*ParamsResponse)(nil), "osmosis.downtimedetector.v1beta1.ParamsResponse") +} + +func init() { + proto.RegisterFile("osmosis/downtime-detector/v1beta1/query.proto", fileDescriptor_b748b3d07fa8b8cb) +} + +var fileDescriptor_b748b3d07fa8b8cb = []byte{ + // 527 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4f, 0x8b, 0xd3, 0x4c, + 0x18, 0x6f, 0xf6, 0x7d, 0x2d, 0xcb, 0x88, 0x0a, 0x61, 0x85, 0x6e, 0x91, 0x74, 0x09, 0x2a, 0xab, + 0xd2, 0x8c, 0xdd, 0xde, 0xbc, 0x59, 0x17, 0x75, 0x41, 0x50, 0xe3, 0x45, 0x14, 0x29, 0x93, 0xe9, + 0xd3, 0x6c, 0x20, 0x99, 0xc9, 0x66, 0x26, 0xd5, 0x5c, 0xfd, 0x04, 0x82, 0x17, 0x4f, 0xde, 0xfd, + 0x26, 0x7b, 0x5c, 0xf0, 0xe2, 0x69, 0xd5, 0xd6, 0x4f, 0xe0, 0x07, 0x10, 0x49, 0x66, 0x26, 0x94, + 0x22, 0xdb, 0x88, 0xa7, 0x36, 0xf3, 0xfc, 0xfe, 0x3e, 0x4c, 0x82, 0xfa, 0x5c, 0x24, 0x5c, 0x44, + 0x02, 0x4f, 0xf8, 0x6b, 0x26, 0xa3, 0x04, 0xfa, 0x13, 0x90, 0x40, 0x25, 0xcf, 0xf0, 0x6c, 0x10, + 0x80, 0x24, 0x03, 0x7c, 0x94, 0x43, 0x56, 0x78, 0x69, 0xc6, 0x25, 0xb7, 0x77, 0x34, 0xdc, 0x33, + 0x70, 0x83, 0xf6, 0x34, 0xba, 0xbb, 0x15, 0xf2, 0x90, 0x57, 0x60, 0x5c, 0xfe, 0x53, 0xbc, 0x2e, + 0x5e, 0x6f, 0x13, 0x02, 0x83, 0x52, 0x59, 0x11, 0x1c, 0x5a, 0x31, 0x70, 0x40, 0x04, 0xd4, 0x10, + 0xca, 0x23, 0xa6, 0xe7, 0x37, 0x97, 0xe7, 0x55, 0xc2, 0x1a, 0x95, 0x92, 0x30, 0x62, 0x44, 0x46, + 0xdc, 0x60, 0xaf, 0x84, 0x9c, 0x87, 0x31, 0x60, 0x92, 0x46, 0x98, 0x30, 0xc6, 0x65, 0x35, 0x34, + 0x4e, 0xdb, 0x7a, 0x5a, 0x3d, 0x05, 0xf9, 0x14, 0x13, 0x56, 0x98, 0x91, 0x32, 0x19, 0xab, 0x3a, + 0xea, 0xc1, 0xe4, 0x5b, 0x65, 0x4d, 0xf2, 0x6c, 0xd9, 0xb3, 0xb7, 0x3a, 0x2f, 0x4b, 0x0b, 0x49, + 0x92, 0x54, 0x01, 0xdc, 0xef, 0x16, 0xba, 0xe6, 0x03, 0xe5, 0x33, 0xc8, 0x60, 0xf2, 0x2c, 0x62, + 0x14, 0xf6, 0xf5, 0x6a, 0x1e, 0x4f, 0x1f, 0x01, 0x0b, 0xe5, 0xa1, 0x0f, 0x47, 0x39, 0x08, 0x69, + 0xbf, 0x44, 0x9b, 0x66, 0x6b, 0x1d, 0x6b, 0xc7, 0xda, 0x3d, 0xbf, 0xb7, 0xed, 0x29, 0x75, 0xcf, + 0xa8, 0x7b, 0xfb, 0xda, 0x7d, 0x74, 0xf5, 0xf8, 0xb4, 0xd7, 0xfa, 0x79, 0xda, 0xeb, 0x14, 0x24, + 0x89, 0xef, 0xb8, 0x86, 0x38, 0x36, 0xf1, 0xdc, 0x0f, 0x5f, 0x7b, 0x96, 0x5f, 0x0b, 0x96, 0xe2, + 0x99, 0x4a, 0x51, 0x74, 0x36, 0xfe, 0x52, 0xdc, 0x10, 0x57, 0xc5, 0xcd, 0xb9, 0xfb, 0x0a, 0x5d, + 0x5f, 0x57, 0x51, 0xa4, 0x9c, 0x09, 0xb0, 0x87, 0xe8, 0xb2, 0xc8, 0x29, 0x05, 0x31, 0xcd, 0xe3, + 0xb8, 0x18, 0x67, 0x86, 0x55, 0x15, 0xde, 0xf4, 0xb7, 0x96, 0x86, 0xb5, 0xa2, 0x7b, 0x09, 0x5d, + 0x78, 0x42, 0x32, 0x92, 0x08, 0xbd, 0x29, 0xf7, 0x39, 0xba, 0x68, 0x0e, 0xb4, 0xee, 0x7d, 0xd4, + 0x4e, 0xab, 0x13, 0xbd, 0xb9, 0x5d, 0x6f, 0xdd, 0x05, 0xf6, 0x94, 0xc2, 0xe8, 0xff, 0xb2, 0xab, + 0xaf, 0xd9, 0x7b, 0x9f, 0xfe, 0x43, 0xe7, 0x9e, 0x96, 0xb7, 0xcc, 0xfe, 0x68, 0xa1, 0xb6, 0x82, + 0xd8, 0xb8, 0xa9, 0x98, 0xce, 0xd7, 0xbd, 0xdd, 0x9c, 0xa0, 0xf2, 0xbb, 0x83, 0xb7, 0x9f, 0x7f, + 0xbc, 0xdf, 0xb8, 0x65, 0xdf, 0x68, 0xf0, 0x02, 0xe9, 0x54, 0xbf, 0x2c, 0xe4, 0x9c, 0xbd, 0x75, + 0xfb, 0xc1, 0xfa, 0x1c, 0x8d, 0xae, 0x66, 0xf7, 0xe1, 0xbf, 0x0b, 0xe9, 0xa2, 0x07, 0x55, 0xd1, + 0x7b, 0xf6, 0xdd, 0x06, 0x45, 0xcf, 0x96, 0x1c, 0xd1, 0xe3, 0xb9, 0x63, 0x9d, 0xcc, 0x1d, 0xeb, + 0xdb, 0xdc, 0xb1, 0xde, 0x2d, 0x9c, 0xd6, 0xc9, 0xc2, 0x69, 0x7d, 0x59, 0x38, 0xad, 0x17, 0x07, + 0x61, 0x24, 0x0f, 0xf3, 0xc0, 0xa3, 0x3c, 0x31, 0x36, 0xfd, 0x98, 0x04, 0xa2, 0xf6, 0x9c, 0x0d, + 0x86, 0xf8, 0xcd, 0x1f, 0x9c, 0x69, 0x1c, 0x01, 0x93, 0xea, 0x3b, 0xa3, 0x5e, 0x8b, 0x76, 0xf5, + 0x33, 0xfc, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xb1, 0x09, 0x15, 0x2a, 0x40, 0x05, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + Params(ctx context.Context, in *ParamsRequest, opts ...grpc.CallOption) (*ParamsResponse, error) + RecoveredSinceDowntimeOfLength(ctx context.Context, in *RecoveredSinceDowntimeOfLengthRequest, opts ...grpc.CallOption) (*RecoveredSinceDowntimeOfLengthResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Params(ctx context.Context, in *ParamsRequest, opts ...grpc.CallOption) (*ParamsResponse, error) { + out := new(ParamsResponse) + err := c.cc.Invoke(ctx, "/osmosis.downtimedetector.v1beta1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) RecoveredSinceDowntimeOfLength(ctx context.Context, in *RecoveredSinceDowntimeOfLengthRequest, opts ...grpc.CallOption) (*RecoveredSinceDowntimeOfLengthResponse, error) { + out := new(RecoveredSinceDowntimeOfLengthResponse) + err := c.cc.Invoke(ctx, "/osmosis.downtimedetector.v1beta1.Query/RecoveredSinceDowntimeOfLength", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + Params(context.Context, *ParamsRequest) (*ParamsResponse, error) + RecoveredSinceDowntimeOfLength(context.Context, *RecoveredSinceDowntimeOfLengthRequest) (*RecoveredSinceDowntimeOfLengthResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Params(ctx context.Context, req *ParamsRequest) (*ParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} +func (*UnimplementedQueryServer) RecoveredSinceDowntimeOfLength(ctx context.Context, req *RecoveredSinceDowntimeOfLengthRequest) (*RecoveredSinceDowntimeOfLengthResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RecoveredSinceDowntimeOfLength not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/osmosis.downtimedetector.v1beta1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*ParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_RecoveredSinceDowntimeOfLength_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RecoveredSinceDowntimeOfLengthRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).RecoveredSinceDowntimeOfLength(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/osmosis.downtimedetector.v1beta1.Query/RecoveredSinceDowntimeOfLength", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).RecoveredSinceDowntimeOfLength(ctx, req.(*RecoveredSinceDowntimeOfLengthRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "osmosis.downtimedetector.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + { + MethodName: "RecoveredSinceDowntimeOfLength", + Handler: _Query_RecoveredSinceDowntimeOfLength_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "osmosis/downtime-detector/v1beta1/query.proto", +} + +func (m *RecoveredSinceDowntimeOfLengthRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RecoveredSinceDowntimeOfLengthRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RecoveredSinceDowntimeOfLengthRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.Recovery, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.Recovery):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintQuery(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x12 + n2, err2 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.Downtime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.Downtime):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintQuery(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *RecoveredSinceDowntimeOfLengthResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RecoveredSinceDowntimeOfLengthResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RecoveredSinceDowntimeOfLengthResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.SuccesfullyRecovered { + i-- + if m.SuccesfullyRecovered { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *ParamsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *ParamsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *RecoveredSinceDowntimeOfLengthRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.Downtime) + n += 1 + l + sovQuery(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.Recovery) + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *RecoveredSinceDowntimeOfLengthResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SuccesfullyRecovered { + n += 2 + } + return n +} + +func (m *ParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *ParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *RecoveredSinceDowntimeOfLengthRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RecoveredSinceDowntimeOfLengthRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RecoveredSinceDowntimeOfLengthRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Downtime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.Downtime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Recovery", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.Recovery, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RecoveredSinceDowntimeOfLengthResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RecoveredSinceDowntimeOfLengthResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RecoveredSinceDowntimeOfLengthResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SuccesfullyRecovered", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.SuccesfullyRecovered = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ParamsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/downtime-detector/client/queryproto/query.pb.gw.go b/x/downtime-detector/client/queryproto/query.pb.gw.go new file mode 100644 index 00000000000..0ff2bcbe174 --- /dev/null +++ b/x/downtime-detector/client/queryproto/query.pb.gw.go @@ -0,0 +1,236 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: osmosis/downtime-detector/v1beta1/query.proto + +/* +Package queryproto is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package queryproto + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_RecoveredSinceDowntimeOfLength_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_RecoveredSinceDowntimeOfLength_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq RecoveredSinceDowntimeOfLengthRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_RecoveredSinceDowntimeOfLength_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.RecoveredSinceDowntimeOfLength(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_RecoveredSinceDowntimeOfLength_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq RecoveredSinceDowntimeOfLengthRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_RecoveredSinceDowntimeOfLength_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.RecoveredSinceDowntimeOfLength(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_RecoveredSinceDowntimeOfLength_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_RecoveredSinceDowntimeOfLength_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_RecoveredSinceDowntimeOfLength_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_RecoveredSinceDowntimeOfLength_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_RecoveredSinceDowntimeOfLength_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_RecoveredSinceDowntimeOfLength_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "downtime-detector", "v1beta1", "Params"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_RecoveredSinceDowntimeOfLength_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "downtime-detector", "v1beta1", "RecoveredSinceDowntimeOfLength"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_Params_0 = runtime.ForwardResponseMessage + + forward_Query_RecoveredSinceDowntimeOfLength_0 = runtime.ForwardResponseMessage +) diff --git a/x/downtime-detector/downtimedetector_module/module.go b/x/downtime-detector/downtimedetector_module/module.go new file mode 100644 index 00000000000..fc3c2ec7852 --- /dev/null +++ b/x/downtime-detector/downtimedetector_module/module.go @@ -0,0 +1,119 @@ +package downtimemodule + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + downtimedetector "github.com/osmosis-labs/osmosis/v13/x/downtime-detector" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" + twapcli "github.com/osmosis-labs/osmosis/v13/x/twap/client/cli" + "github.com/osmosis-labs/osmosis/v13/x/twap/client/queryproto" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +type AppModuleBasic struct{} + +func (AppModuleBasic) Name() string { return types.ModuleName } + +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { +} + +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesis()) +} + +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var genState types.GenesisState + if err := cdc.UnmarshalJSON(bz, &genState); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + return genState.Validate() +} + +func (b AppModuleBasic) RegisterRESTRoutes(ctx client.Context, r *mux.Router) { +} + +func (b AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + queryproto.RegisterQueryHandlerClient(context.Background(), mux, queryproto.NewQueryClient(clientCtx)) //nolint:errcheck +} + +func (b AppModuleBasic) GetTxCmd() *cobra.Command { + return nil +} + +func (b AppModuleBasic) GetQueryCmd() *cobra.Command { + return twapcli.GetQueryCmd() +} + +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { +} + +type AppModule struct { + AppModuleBasic + + k downtimedetector.Keeper +} + +func (am AppModule) RegisterServices(cfg module.Configurator) { + // queryproto.RegisterQueryServer(cfg.QueryServer(), grpc.Querier{Q: twapclient.Querier{K: am.k}}) +} + +func NewAppModule(k downtimedetector.Keeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + k: k, + } +} + +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { +} + +func (am AppModule) Route() sdk.Route { + return sdk.Route{} +} + +func (AppModule) QuerierRoute() string { return types.RouterKey } + +func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { + return func(sdk.Context, []string, abci.RequestQuery) ([]byte, error) { + return nil, fmt.Errorf("legacy querier not supported for the x/%s module", types.ModuleName) + } +} + +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate { + var genesisState types.GenesisState + + cdc.MustUnmarshalJSON(gs, &genesisState) + + am.k.InitGenesis(ctx, &genesisState) + return []abci.ValidatorUpdate{} +} + +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + genState := am.k.ExportGenesis(ctx) + return cdc.MustMarshalJSON(genState) +} + +func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} + +func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/downtime-detector/keeper.go b/x/downtime-detector/keeper.go new file mode 100644 index 00000000000..c9c10f994f8 --- /dev/null +++ b/x/downtime-detector/keeper.go @@ -0,0 +1,52 @@ +package downtimedetector + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" + + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" +) + +type Keeper struct { + storeKey sdk.StoreKey + + paramSpace paramtypes.Subspace +} + +func NewKeeper(storeKey sdk.StoreKey, paramSpace paramtypes.Subspace) *Keeper { + // set KeyTable if it has not already been set + // if !paramSpace.HasKeyTable() { + // paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable()) + // } + + return &Keeper{storeKey: storeKey, paramSpace: paramSpace} +} + +// GetParams returns the total set of twap parameters. +// func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { +// k.paramSpace.GetParamSet(ctx, ¶ms) +// return params +// } + +// // SetParams sets the total set of twap parameters. +// func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { +// k.paramSpace.SetParamSet(ctx, ¶ms) +// } + +// InitGenesis initializes the twap module's state from a provided genesis +// state. +func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { + if err := genState.Validate(); err != nil { + panic(err) + } + + // k.SetParams(ctx, genState.Params) +} + +// ExportGenesis returns the twap module's exported genesis. +func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { + return &types.GenesisState{ + // Params: k.GetParams(ctx), + } +} diff --git a/x/downtime-detector/types/constants.go b/x/downtime-detector/types/constants.go new file mode 100644 index 00000000000..e01b37548c9 --- /dev/null +++ b/x/downtime-detector/types/constants.go @@ -0,0 +1,9 @@ +package types + +const ( + ModuleName = "downtime-detector" + StoreKey = ModuleName + RouterKey = ModuleName + + QuerierRoute = ModuleName +) diff --git a/x/downtime-detector/types/genesis.go b/x/downtime-detector/types/genesis.go new file mode 100644 index 00000000000..39508cca25b --- /dev/null +++ b/x/downtime-detector/types/genesis.go @@ -0,0 +1,9 @@ +package types + +func DefaultGenesis() *GenesisState { + return &GenesisState{} +} + +func (g *GenesisState) Validate() error { + return nil +} diff --git a/x/downtime-detector/types/genesis.pb.go b/x/downtime-detector/types/genesis.pb.go new file mode 100644 index 00000000000..75e41db1a3d --- /dev/null +++ b/x/downtime-detector/types/genesis.pb.go @@ -0,0 +1,798 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: osmosis/downtime-detector/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + _ "github.com/gogo/protobuf/types" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Params holds parameters for the downtime-detector module +type Params struct { +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_4581e137a44782af, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +type GenesisDowntimeEntry struct { + DowntimeDuration time.Duration `protobuf:"bytes,1,opt,name=downtime_duration,json=downtimeDuration,proto3,stdduration" json:"downtime_duration" yaml:"downtime_duration"` + LastDowntime time.Time `protobuf:"bytes,2,opt,name=last_downtime,json=lastDowntime,proto3,stdtime" json:"last_downtime" yaml:"last_downtime"` +} + +func (m *GenesisDowntimeEntry) Reset() { *m = GenesisDowntimeEntry{} } +func (m *GenesisDowntimeEntry) String() string { return proto.CompactTextString(m) } +func (*GenesisDowntimeEntry) ProtoMessage() {} +func (*GenesisDowntimeEntry) Descriptor() ([]byte, []int) { + return fileDescriptor_4581e137a44782af, []int{1} +} +func (m *GenesisDowntimeEntry) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisDowntimeEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisDowntimeEntry.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisDowntimeEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisDowntimeEntry.Merge(m, src) +} +func (m *GenesisDowntimeEntry) XXX_Size() int { + return m.Size() +} +func (m *GenesisDowntimeEntry) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisDowntimeEntry.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisDowntimeEntry proto.InternalMessageInfo + +func (m *GenesisDowntimeEntry) GetDowntimeDuration() time.Duration { + if m != nil { + return m.DowntimeDuration + } + return 0 +} + +func (m *GenesisDowntimeEntry) GetLastDowntime() time.Time { + if m != nil { + return m.LastDowntime + } + return time.Time{} +} + +// GenesisState defines the twap module's genesis state. +type GenesisState struct { + Downtimes []GenesisDowntimeEntry `protobuf:"bytes,1,rep,name=downtimes,proto3" json:"downtimes"` + LastBlockTime time.Time `protobuf:"bytes,2,opt,name=last_block_time,json=lastBlockTime,proto3,stdtime" json:"last_block_time" yaml:"last_block_time"` + // params is the container of twap parameters. + Params Params `protobuf:"bytes,3,opt,name=params,proto3" json:"params"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_4581e137a44782af, []int{2} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetDowntimes() []GenesisDowntimeEntry { + if m != nil { + return m.Downtimes + } + return nil +} + +func (m *GenesisState) GetLastBlockTime() time.Time { + if m != nil { + return m.LastBlockTime + } + return time.Time{} +} + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*Params)(nil), "osmosis.downtimedetector.v1beta1.Params") + proto.RegisterType((*GenesisDowntimeEntry)(nil), "osmosis.downtimedetector.v1beta1.GenesisDowntimeEntry") + proto.RegisterType((*GenesisState)(nil), "osmosis.downtimedetector.v1beta1.GenesisState") +} + +func init() { + proto.RegisterFile("osmosis/downtime-detector/v1beta1/genesis.proto", fileDescriptor_4581e137a44782af) +} + +var fileDescriptor_4581e137a44782af = []byte{ + // 432 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x4f, 0x8b, 0xd3, 0x40, + 0x18, 0xc6, 0x33, 0xbb, 0x52, 0x74, 0x76, 0x45, 0x0d, 0x45, 0xb2, 0x3d, 0x24, 0x21, 0x78, 0xe8, + 0x65, 0x67, 0xe8, 0x2e, 0x78, 0x10, 0xbc, 0x84, 0xaa, 0x57, 0xa9, 0x82, 0xd0, 0x4b, 0x98, 0xa4, + 0xd3, 0x18, 0x4c, 0x32, 0x21, 0x33, 0xad, 0xe6, 0x5b, 0xf4, 0x28, 0x7e, 0xa2, 0x1e, 0x7b, 0xf4, + 0x54, 0xa5, 0x3d, 0x78, 0xf7, 0x13, 0x48, 0xe6, 0x8f, 0xd5, 0xb6, 0xd0, 0xbd, 0x25, 0xf3, 0x3e, + 0xcf, 0xf3, 0xbe, 0xbf, 0x19, 0x5e, 0x88, 0x19, 0x2f, 0x18, 0xcf, 0x38, 0x9e, 0xb0, 0xcf, 0xa5, + 0xc8, 0x0a, 0x7a, 0x3d, 0xa1, 0x82, 0x26, 0x82, 0xd5, 0x78, 0x3e, 0x88, 0xa9, 0x20, 0x03, 0x9c, + 0xd2, 0x92, 0xf2, 0x8c, 0xa3, 0xaa, 0x66, 0x82, 0xd9, 0xbe, 0x36, 0x20, 0x63, 0x30, 0x7a, 0xa4, + 0xf5, 0xbd, 0x6e, 0xca, 0x52, 0x26, 0xc5, 0xb8, 0xfd, 0x52, 0xbe, 0xde, 0x55, 0xca, 0x58, 0x9a, + 0x53, 0x2c, 0xff, 0xe2, 0xd9, 0x14, 0x93, 0xb2, 0x31, 0xa5, 0x44, 0x66, 0x46, 0xca, 0xa3, 0x7e, + 0x74, 0xc9, 0xdd, 0x77, 0x4d, 0x66, 0x35, 0x11, 0x19, 0x2b, 0x75, 0xdd, 0xdb, 0xaf, 0xb7, 0x13, + 0x71, 0x41, 0x8a, 0x4a, 0x09, 0x82, 0xfb, 0xb0, 0xf3, 0x96, 0xd4, 0xa4, 0xe0, 0xc1, 0x2f, 0x00, + 0xbb, 0x6f, 0x14, 0xca, 0x50, 0x8f, 0xfe, 0xaa, 0x14, 0x75, 0x63, 0xe7, 0xf0, 0x89, 0x61, 0x89, + 0x4c, 0xbc, 0x03, 0x7c, 0xd0, 0xbf, 0xb8, 0xb9, 0x42, 0x2a, 0x1f, 0x99, 0x7c, 0x34, 0xd4, 0x82, + 0xf0, 0xd9, 0x72, 0xed, 0x59, 0xbf, 0xd7, 0x9e, 0xd3, 0x90, 0x22, 0x7f, 0x11, 0x1c, 0x24, 0x04, + 0x5f, 0x7f, 0x78, 0x60, 0xf4, 0xd8, 0x9c, 0x1b, 0x9f, 0x4d, 0xe0, 0xc3, 0x9c, 0x70, 0x11, 0x99, + 0x82, 0x73, 0x26, 0x3b, 0xf5, 0x0e, 0x3a, 0xbd, 0x37, 0x24, 0xa1, 0xaf, 0x5b, 0x75, 0x55, 0xab, + 0xff, 0xec, 0xc1, 0xa2, 0x6d, 0x73, 0xd9, 0x9e, 0x19, 0xaa, 0xe0, 0xdb, 0x19, 0xbc, 0xd4, 0xa4, + 0xef, 0x04, 0x11, 0xd4, 0x1e, 0xc3, 0x07, 0x46, 0xcf, 0x1d, 0xe0, 0x9f, 0xf7, 0x2f, 0x6e, 0x9e, + 0xa3, 0x53, 0xef, 0x88, 0x8e, 0x5d, 0x56, 0x78, 0xaf, 0x9d, 0x65, 0xb4, 0x8b, 0xb3, 0xa7, 0xf0, + 0x91, 0x1c, 0x28, 0xce, 0x59, 0xf2, 0x29, 0xba, 0x23, 0x51, 0xa0, 0x89, 0x9e, 0xfe, 0x43, 0xb4, + 0x0b, 0x50, 0x4c, 0xf2, 0x9a, 0xc2, 0xf6, 0xb0, 0xf5, 0xd9, 0xaf, 0x61, 0xa7, 0x92, 0x0f, 0xe9, + 0x9c, 0xcb, 0xf8, 0xfe, 0x69, 0x00, 0xf5, 0xf0, 0x7a, 0x64, 0xed, 0x0e, 0x3f, 0x2c, 0x37, 0x2e, + 0x58, 0x6d, 0x5c, 0xf0, 0x73, 0xe3, 0x82, 0xc5, 0xd6, 0xb5, 0x56, 0x5b, 0xd7, 0xfa, 0xbe, 0x75, + 0xad, 0xf1, 0xcb, 0x34, 0x13, 0x1f, 0x67, 0x31, 0x4a, 0x58, 0x61, 0xb6, 0xe2, 0x3a, 0x27, 0x31, + 0xff, 0xbb, 0x22, 0xf3, 0xc1, 0x2d, 0xfe, 0x72, 0x64, 0x51, 0x44, 0x53, 0x51, 0x1e, 0x77, 0x24, + 0xe7, 0xed, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x54, 0x1c, 0x59, 0x62, 0x52, 0x03, 0x00, 0x00, +} + +func (m *Params) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *GenesisDowntimeEntry) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisDowntimeEntry) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisDowntimeEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastDowntime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.LastDowntime):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintGenesis(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x12 + n2, err2 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.DowntimeDuration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.DowntimeDuration):]) + if err2 != nil { + return 0, err2 + } + i -= n2 + i = encodeVarintGenesis(dAtA, i, uint64(n2)) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + n4, err4 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastBlockTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.LastBlockTime):]) + if err4 != nil { + return 0, err4 + } + i -= n4 + i = encodeVarintGenesis(dAtA, i, uint64(n4)) + i-- + dAtA[i] = 0x12 + if len(m.Downtimes) > 0 { + for iNdEx := len(m.Downtimes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Downtimes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *GenesisDowntimeEntry) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.DowntimeDuration) + n += 1 + l + sovGenesis(uint64(l)) + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.LastDowntime) + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Downtimes) > 0 { + for _, e := range m.Downtimes { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.LastBlockTime) + n += 1 + l + sovGenesis(uint64(l)) + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Params) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenesisDowntimeEntry) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisDowntimeEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisDowntimeEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DowntimeDuration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.DowntimeDuration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastDowntime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.LastDowntime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Downtimes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Downtimes = append(m.Downtimes, GenesisDowntimeEntry{}) + if err := m.Downtimes[len(m.Downtimes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.LastBlockTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/ibc-rate-limit/testutil/wasm.go b/x/ibc-rate-limit/testutil/wasm.go index a11133baec6..75be4e54ec5 100644 --- a/x/ibc-rate-limit/testutil/wasm.go +++ b/x/ibc-rate-limit/testutil/wasm.go @@ -3,7 +3,7 @@ package osmosisibctesting import ( "crypto/sha256" "fmt" - "io/ioutil" + "os" "github.com/stretchr/testify/require" @@ -21,7 +21,7 @@ func (chain *TestChain) StoreContractCode(suite *suite.Suite, path string) { osmosisApp := chain.GetOsmosisApp() govKeeper := osmosisApp.GovKeeper - wasmCode, err := ioutil.ReadFile(path) + wasmCode, err := os.ReadFile(path) suite.Require().NoError(err) addr := osmosisApp.AccountKeeper.GetModuleAddress(govtypes.ModuleName) From 7ec5e4ed741a286efc4ba1b0984cd005d0d6e0cc Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Wed, 14 Dec 2022 11:34:17 -0600 Subject: [PATCH 15/30] Add downtime detector module (#3688) * WIP * Switch to enum * Remove params query * Add query * Add wiring, add import/export test * Start begin block test * Finish keeper tests * Add CLI * Wire downtime detector CLI + queries * more module wiring * add types test * Fix state alteration test * Fix superfluid test * Add stargate whitelist support * Apply code comment * Rename folder * Add requested godoc * Update x/downtime-detector/genesis.go Co-authored-by: Adam Tucker * Apply adam suggestion for having a `-` * move genesis test to own file Co-authored-by: Adam Tucker --- app/apptesting/test_suite.go | 2 +- app/keepers/keepers.go | 7 + app/keepers/modules.go | 2 + app/modules.go | 5 + app/upgrades/v14/constants.go | 1 + go.mod | 1 + go.sum | 2 + .../v1beta1/downtime_duration.proto | 38 ++ .../downtime-detector/v1beta1/genesis.proto | 13 +- .../downtime-detector/v1beta1/query.proto | 14 +- .../downtime-detector/v1beta1/query.yml | 8 + wasmbinding/stargate_whitelist.go | 4 + x/downtime-detector/abci.go | 37 ++ x/downtime-detector/client/cli/query.go | 40 ++ x/downtime-detector/client/cli/query_test.go | 50 ++ x/downtime-detector/client/grpc/grpc_query.go | 32 ++ .../client/query_proto_wrap.go | 22 + .../client/queryproto/query.pb.go | 440 ++---------------- .../client/queryproto/query.pb.gw.go | 65 --- x/downtime-detector/genesis.go | 48 ++ x/downtime-detector/genesis_test.go | 46 ++ x/downtime-detector/keeper.go | 43 +- x/downtime-detector/keeper_test.go | 159 +++++++ .../module.go | 17 +- x/downtime-detector/query.go | 26 ++ x/downtime-detector/store.go | 49 ++ x/downtime-detector/types/constants.go | 74 ++- x/downtime-detector/types/constants_test.go | 19 + .../types/downtime_duration.pb.go | 156 +++++++ x/downtime-detector/types/genesis.go | 18 +- x/downtime-detector/types/genesis.pb.go | 291 ++---------- x/downtime-detector/types/keys.go | 15 + x/superfluid/client/cli/query_test.go | 15 +- 33 files changed, 980 insertions(+), 779 deletions(-) create mode 100644 proto/osmosis/downtime-detector/v1beta1/downtime_duration.proto create mode 100644 proto/osmosis/downtime-detector/v1beta1/query.yml create mode 100644 x/downtime-detector/abci.go create mode 100644 x/downtime-detector/client/cli/query.go create mode 100644 x/downtime-detector/client/cli/query_test.go create mode 100644 x/downtime-detector/client/grpc/grpc_query.go create mode 100644 x/downtime-detector/client/query_proto_wrap.go create mode 100644 x/downtime-detector/genesis.go create mode 100644 x/downtime-detector/genesis_test.go create mode 100644 x/downtime-detector/keeper_test.go rename x/downtime-detector/{downtimedetector_module => module}/module.go (85%) create mode 100644 x/downtime-detector/query.go create mode 100644 x/downtime-detector/store.go create mode 100644 x/downtime-detector/types/constants_test.go create mode 100644 x/downtime-detector/types/downtime_duration.pb.go create mode 100644 x/downtime-detector/types/keys.go diff --git a/app/apptesting/test_suite.go b/app/apptesting/test_suite.go index c52ebae6f13..2599879edcb 100644 --- a/app/apptesting/test_suite.go +++ b/app/apptesting/test_suite.go @@ -364,7 +364,7 @@ func (s *KeeperTestHelper) BuildTx( // StateNotAltered validates that app state is not altered. Fails if it is. func (s *KeeperTestHelper) StateNotAltered() { oldState := s.App.ExportState(s.Ctx) - s.Commit() + s.App.Commit() newState := s.App.ExportState(s.Ctx) s.Require().Equal(oldState, newState) } diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 595a7a308af..9f7c3e20b50 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -34,6 +34,8 @@ import ( upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + downtimedetector "github.com/osmosis-labs/osmosis/v13/x/downtime-detector" + downtimetypes "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" ibcratelimit "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit" ibcratelimittypes "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types" ibchooks "github.com/osmosis-labs/osmosis/x/ibc-hooks" @@ -188,6 +190,10 @@ func (appKeepers *AppKeepers) InitNormalKeepers( ) appKeepers.DistrKeeper = &distrKeeper + appKeepers.DowntimeKeeper = downtimedetector.NewKeeper( + appKeepers.keys[downtimetypes.StoreKey], + ) + slashingKeeper := slashingkeeper.NewKeeper( appCodec, appKeepers.keys[slashingtypes.StoreKey], @@ -572,6 +578,7 @@ func KVStoreKeys() []string { stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, + downtimetypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, diff --git a/app/keepers/modules.go b/app/keepers/modules.go index 2b91ec88a7e..18c4aa39bca 100644 --- a/app/keepers/modules.go +++ b/app/keepers/modules.go @@ -28,6 +28,7 @@ import ( ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" _ "github.com/osmosis-labs/osmosis/v13/client/docs/statik" + downtimemodule "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/module" "github.com/osmosis-labs/osmosis/v13/x/epochs" "github.com/osmosis-labs/osmosis/v13/x/gamm" ibc_rate_limit "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit" @@ -52,6 +53,7 @@ var AppModuleBasics = []module.AppModuleBasic{ capability.AppModuleBasic{}, staking.AppModuleBasic{}, mint.AppModuleBasic{}, + downtimemodule.AppModuleBasic{}, distr.AppModuleBasic{}, gov.NewAppModuleBasic( append( diff --git a/app/modules.go b/app/modules.go index 7974a215c9d..3acbc8329e7 100644 --- a/app/modules.go +++ b/app/modules.go @@ -14,6 +14,8 @@ import ( ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" icatypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/types" + downtimemodule "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/module" + downtimetypes "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" ibc_hooks "github.com/osmosis-labs/osmosis/x/ibc-hooks" "github.com/cosmos/cosmos-sdk/types/module" @@ -120,6 +122,7 @@ func appModules( mint.NewAppModule(appCodec, *app.MintKeeper, app.AccountKeeper, app.BankKeeper), slashing.NewAppModule(appCodec, *app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, *app.StakingKeeper), distr.NewAppModule(appCodec, *app.DistrKeeper, app.AccountKeeper, app.BankKeeper, *app.StakingKeeper), + downtimemodule.NewAppModule(*app.DowntimeKeeper), staking.NewAppModule(appCodec, *app.StakingKeeper, app.AccountKeeper, app.BankKeeper), upgrade.NewAppModule(*app.UpgradeKeeper), wasm.NewAppModule(appCodec, app.WasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), @@ -168,6 +171,7 @@ func orderBeginBlockers(allModuleNames []string) []string { // IBChost came after staking, before superfluid. // TODO: Come back and delete this line after testing the base change. ord.Sequence(stakingtypes.ModuleName, ibchost.ModuleName, superfluidtypes.ModuleName) + // We leave downtime-detector un-constrained. // every remaining module's begin block is a no-op. return ord.TotalOrdering() } @@ -197,6 +201,7 @@ func OrderInitGenesis(allModuleNames []string) []string { authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, + downtimetypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, diff --git a/app/upgrades/v14/constants.go b/app/upgrades/v14/constants.go index ac64426faef..6486632baaf 100644 --- a/app/upgrades/v14/constants.go +++ b/app/upgrades/v14/constants.go @@ -2,6 +2,7 @@ package v14 import ( store "github.com/cosmos/cosmos-sdk/store/types" + ibchookstypes "github.com/osmosis-labs/osmosis/x/ibc-hooks/types" "github.com/osmosis-labs/osmosis/v13/app/upgrades" diff --git a/go.mod b/go.mod index 12a10ba8151..8489b5111be 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( github.com/tendermint/tendermint v0.34.24 github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b go.uber.org/multierr v1.9.0 + github.com/tidwall/btree v1.6.0 golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e google.golang.org/grpc v1.50.1 diff --git a/go.sum b/go.sum index 001887aebaf..331132926c0 100644 --- a/go.sum +++ b/go.sum @@ -1099,6 +1099,8 @@ github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpR github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= +github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= +github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= diff --git a/proto/osmosis/downtime-detector/v1beta1/downtime_duration.proto b/proto/osmosis/downtime-detector/v1beta1/downtime_duration.proto new file mode 100644 index 00000000000..39b13561bb6 --- /dev/null +++ b/proto/osmosis/downtime-detector/v1beta1/downtime_duration.proto @@ -0,0 +1,38 @@ +syntax = "proto3"; +package osmosis.downtimedetector.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "cosmos_proto/cosmos.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types"; + +enum Downtime { + DURATION_30S = 0; + DURATION_1M = 1; + DURATION_2M = 2; + DURATION_3M = 3; + DURATION_4M = 4; + DURATION_5M = 5; + DURATION_10M = 6; + DURATION_20M = 7; + DURATION_30M = 8; + DURATION_40M = 9; + DURATION_50M = 10; + DURATION_1H = 11; + DURATION_1_5H = 12; + DURATION_2H = 13; + DURATION_2_5H = 14; + DURATION_3H = 15; + DURATION_4H = 16; + DURATION_5H = 17; + DURATION_6H = 18; + DURATION_9H = 19; + DURATION_12H = 20; + DURATION_18H = 21; + DURATION_24H = 22; + DURATION_36H = 23; + DURATION_48H = 24; +} diff --git a/proto/osmosis/downtime-detector/v1beta1/genesis.proto b/proto/osmosis/downtime-detector/v1beta1/genesis.proto index a1ce25eedce..3e4f3c105fc 100644 --- a/proto/osmosis/downtime-detector/v1beta1/genesis.proto +++ b/proto/osmosis/downtime-detector/v1beta1/genesis.proto @@ -6,18 +6,12 @@ import "google/protobuf/any.proto"; import "cosmos_proto/cosmos.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; +import "osmosis/downtime-detector/v1beta1/downtime_duration.proto"; option go_package = "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types"; -// Params holds parameters for the downtime-detector module -message Params {} - message GenesisDowntimeEntry { - google.protobuf.Duration downtime_duration = 1 [ - (gogoproto.nullable) = false, - (gogoproto.stdduration) = true, - (gogoproto.moretags) = "yaml:\"downtime_duration\"" - ]; + Downtime duration = 1 [ (gogoproto.moretags) = "yaml:\"duration\"" ]; google.protobuf.Timestamp last_downtime = 2 [ (gogoproto.nullable) = false, (gogoproto.stdtime) = true, @@ -34,7 +28,4 @@ message GenesisState { (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"last_block_time\"" ]; - - // params is the container of twap parameters. - Params params = 3 [ (gogoproto.nullable) = false ]; } diff --git a/proto/osmosis/downtime-detector/v1beta1/query.proto b/proto/osmosis/downtime-detector/v1beta1/query.proto index 97c07b26930..7c435de52a3 100644 --- a/proto/osmosis/downtime-detector/v1beta1/query.proto +++ b/proto/osmosis/downtime-detector/v1beta1/query.proto @@ -3,6 +3,7 @@ package osmosis.downtimedetector.v1beta1; import "gogoproto/gogo.proto"; import "osmosis/downtime-detector/v1beta1/genesis.proto"; +import "osmosis/downtime-detector/v1beta1/downtime_duration.proto"; import "cosmos/base/v1beta1/coin.proto"; import "cosmos/base/query/v1beta1/pagination.proto"; @@ -15,9 +16,6 @@ import "google/protobuf/timestamp.proto"; option go_package = "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto"; service Query { - rpc Params(ParamsRequest) returns (ParamsResponse) { - option (google.api.http).get = "/osmosis/downtime-detector/v1beta1/Params"; - } rpc RecoveredSinceDowntimeOfLength(RecoveredSinceDowntimeOfLengthRequest) returns (RecoveredSinceDowntimeOfLengthResponse) { option (google.api.http).get = @@ -27,13 +25,8 @@ service Query { // Query for has it been at least $RECOVERY_DURATION units of time, // since the chain has been down for $DOWNTIME_DURATION. -// Note: $DOWNTIME_DURATION must be in set {SPECIFY_SET} message RecoveredSinceDowntimeOfLengthRequest { - google.protobuf.Duration downtime = 1 [ - (gogoproto.nullable) = false, - (gogoproto.stdduration) = true, - (gogoproto.moretags) = "yaml:\"downtime_duration\"" - ]; + Downtime downtime = 1 [ (gogoproto.moretags) = "yaml:\"downtime\"" ]; google.protobuf.Duration recovery = 2 [ (gogoproto.nullable) = false, (gogoproto.stdduration) = true, @@ -44,6 +37,3 @@ message RecoveredSinceDowntimeOfLengthRequest { message RecoveredSinceDowntimeOfLengthResponse { bool succesfully_recovered = 1; } - -message ParamsRequest {} -message ParamsResponse { Params params = 1 [ (gogoproto.nullable) = false ]; } diff --git a/proto/osmosis/downtime-detector/v1beta1/query.yml b/proto/osmosis/downtime-detector/v1beta1/query.yml new file mode 100644 index 00000000000..178b70ea7b4 --- /dev/null +++ b/proto/osmosis/downtime-detector/v1beta1/query.yml @@ -0,0 +1,8 @@ +keeper: + path: "github.com/osmosis-labs/osmosis/v13/x/downtime-detector" + struct: "Keeper" +client_path: "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client" +queries: + RecoveredSinceDowntimeOfLength: + proto_wrapper: + query_func: "k.RecoveredSinceDowntimeOfLength" \ No newline at end of file diff --git a/wasmbinding/stargate_whitelist.go b/wasmbinding/stargate_whitelist.go index b7217e50527..54ebef26bb6 100644 --- a/wasmbinding/stargate_whitelist.go +++ b/wasmbinding/stargate_whitelist.go @@ -13,6 +13,7 @@ import ( slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + downtimequerytypes "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto" epochtypes "github.com/osmosis-labs/osmosis/v13/x/epochs/types" gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types" gammv2types "github.com/osmosis-labs/osmosis/v13/x/gamm/v2types" @@ -126,6 +127,9 @@ func init() { setWhitelistedQuery("/osmosis.twap.v1beta1.Query/GeometricTwap", &twapquerytypes.GeometricTwapResponse{}) setWhitelistedQuery("/osmosis.twap.v1beta1.Query/GeometricTwapToNow", &twapquerytypes.GeometricTwapToNowResponse{}) setWhitelistedQuery("/osmosis.twap.v1beta1.Query/Params", &twapquerytypes.ParamsResponse{}) + + // downtime-detector + setWhitelistedQuery("/osmosis.downtimedetector.v1beta1.Query/RecoveredSinceDowntimeOfLength", &downtimequerytypes.RecoveredSinceDowntimeOfLengthResponse{}) } // GetWhitelistedQuery returns the whitelisted query at the provided path. diff --git a/x/downtime-detector/abci.go b/x/downtime-detector/abci.go new file mode 100644 index 00000000000..43803817652 --- /dev/null +++ b/x/downtime-detector/abci.go @@ -0,0 +1,37 @@ +package downtimedetector + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" +) + +func (k *Keeper) BeginBlock(ctx sdk.Context) { + curTime := ctx.BlockTime() + lastBlockTime, err := k.GetLastBlockTime(ctx) + if err != nil { + ctx.Logger().Error("Downtime-detector, could not get last block time, did initialization happen correctly. " + err.Error()) + } + downtime := curTime.Sub(lastBlockTime) + k.saveDowntimeUpdates(ctx, downtime) + k.StoreLastBlockTime(ctx, curTime) +} + +// saveDowntimeUpdates saves the current block time as the +// last time the chain was down for all downtime lengths that are LTE the provided downtime. +func (k *Keeper) saveDowntimeUpdates(ctx sdk.Context, downtime time.Duration) { + // minimum stored downtime is 30S, so if downtime is less than that, don't update anything. + if downtime < 30*time.Second { + return + } + types.DowntimeToDuration.Ascend(0, func(downType types.Downtime, duration time.Duration) bool { + // if downtime < duration of this entry, stop iterating further, don't update this entry. + if downtime < duration { + return false + } + k.StoreLastDowntimeOfLength(ctx, downType, ctx.BlockTime()) + return true + }) +} diff --git a/x/downtime-detector/client/cli/query.go b/x/downtime-detector/client/cli/query.go new file mode 100644 index 00000000000..87f6fbb7bb8 --- /dev/null +++ b/x/downtime-detector/client/cli/query.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "github.com/osmosis-labs/osmosis/v13/osmoutils/osmocli" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" +) + +func GetQueryCmd() *cobra.Command { + cmd := osmocli.QueryIndexCmd(types.ModuleName) + osmocli.AddQueryCmd(cmd, queryproto.NewQueryClient, RecoveredSinceQueryCmd) + + return cmd +} + +func RecoveredSinceQueryCmd() (*osmocli.QueryDescriptor, *queryproto.RecoveredSinceDowntimeOfLengthRequest) { + return &osmocli.QueryDescriptor{ + Use: "recovered-since downtime-duration recovery-duration", + Short: "Queries if it has been at least since the chain was down for ", + Long: `{{.Short}} +downtime-duration is a duration, but is restricted to a smaller set. Heres a few from the set: 30s, 1m, 5m, 10m, 30m, 1h, 3 h, 6h, 12h, 24h, 36h, 48h] +{{.ExampleHeader}} +{{.CommandPrefix}} recovered-since 24h 30m`, + CustomFieldParsers: map[string]osmocli.CustomFieldParserFn{"Downtime": parseDowntimeDuration}, + }, &queryproto.RecoveredSinceDowntimeOfLengthRequest{} +} + +func parseDowntimeDuration(arg string, _ *pflag.FlagSet) (any, osmocli.FieldReadLocation, error) { + dur, err := time.ParseDuration(arg) + if err != nil { + return nil, osmocli.UsedArg, err + } + downtime, err := types.DowntimeByDuration(dur) + return downtime, osmocli.UsedArg, err +} diff --git a/x/downtime-detector/client/cli/query_test.go b/x/downtime-detector/client/cli/query_test.go new file mode 100644 index 00000000000..8444e0f1352 --- /dev/null +++ b/x/downtime-detector/client/cli/query_test.go @@ -0,0 +1,50 @@ +package cli_test + +import ( + "testing" + "time" + + "github.com/osmosis-labs/osmosis/v13/osmoutils/osmocli" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/cli" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" +) + +// We test the custom duration parser via this +func TestRecoveredSinceQueryCmd(t *testing.T) { + desc, _ := cli.RecoveredSinceQueryCmd() + tcs := map[string]osmocli.QueryCliTestCase[*queryproto.RecoveredSinceDowntimeOfLengthRequest]{ + "basic test": { + Cmd: "30s 10m", + ExpectedQuery: &queryproto.RecoveredSinceDowntimeOfLengthRequest{ + Downtime: types.Downtime_DURATION_30S, + Recovery: time.Minute * 10}, + }, + "invalid duration": { + Cmd: "31s 10m", + ExpectedQuery: &queryproto.RecoveredSinceDowntimeOfLengthRequest{ + Downtime: types.Downtime_DURATION_30S, + Recovery: time.Minute * 10}, + ExpectedErr: true, + }, + "90m": { + Cmd: "90m 10m", + ExpectedQuery: &queryproto.RecoveredSinceDowntimeOfLengthRequest{ + Downtime: types.Downtime_DURATION_1_5H, + Recovery: time.Minute * 10}, + }, + "1.5h": { + Cmd: "1.5h 10m", + ExpectedQuery: &queryproto.RecoveredSinceDowntimeOfLengthRequest{ + Downtime: types.Downtime_DURATION_1_5H, + Recovery: time.Minute * 10}, + }, + "1h30m": { + Cmd: "1h30m 10m", + ExpectedQuery: &queryproto.RecoveredSinceDowntimeOfLengthRequest{ + Downtime: types.Downtime_DURATION_1_5H, + Recovery: time.Minute * 10}, + }, + } + osmocli.RunQueryTestCases(t, desc, tcs) +} diff --git a/x/downtime-detector/client/grpc/grpc_query.go b/x/downtime-detector/client/grpc/grpc_query.go new file mode 100644 index 00000000000..f304afd87ab --- /dev/null +++ b/x/downtime-detector/client/grpc/grpc_query.go @@ -0,0 +1,32 @@ +package grpc + +// THIS FILE IS GENERATED CODE, DO NOT EDIT +// SOURCE AT `proto/osmosis/downtime-detector/v1beta1/query.yml` + +import ( + context "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto" +) + +type Querier struct { + Q client.Querier +} + +var _ queryproto.QueryServer = Querier{} + +func (q Querier) RecoveredSinceDowntimeOfLength(grpcCtx context.Context, + req *queryproto.RecoveredSinceDowntimeOfLengthRequest, +) (*queryproto.RecoveredSinceDowntimeOfLengthResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + ctx := sdk.UnwrapSDKContext(grpcCtx) + return q.Q.RecoveredSinceDowntimeOfLength(ctx, *req) +} + diff --git a/x/downtime-detector/client/query_proto_wrap.go b/x/downtime-detector/client/query_proto_wrap.go new file mode 100644 index 00000000000..35feb27c1eb --- /dev/null +++ b/x/downtime-detector/client/query_proto_wrap.go @@ -0,0 +1,22 @@ +package client + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + downtimedetector "github.com/osmosis-labs/osmosis/v13/x/downtime-detector" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto" +) + +type Querier struct { + K downtimedetector.Keeper +} + +func (querier *Querier) RecoveredSinceDowntimeOfLength(ctx sdk.Context, req queryproto.RecoveredSinceDowntimeOfLengthRequest) (*queryproto.RecoveredSinceDowntimeOfLengthResponse, error) { + val, err := querier.K.RecoveredSinceDowntimeOfLength(ctx, req.Downtime, req.Recovery) + if err != nil { + return nil, err + } + return &queryproto.RecoveredSinceDowntimeOfLengthResponse{ + SuccesfullyRecovered: val, + }, nil +} diff --git a/x/downtime-detector/client/queryproto/query.pb.go b/x/downtime-detector/client/queryproto/query.pb.go index a31ccb14e87..0007c7010ee 100644 --- a/x/downtime-detector/client/queryproto/query.pb.go +++ b/x/downtime-detector/client/queryproto/query.pb.go @@ -15,7 +15,7 @@ import ( proto "github.com/gogo/protobuf/proto" _ "github.com/gogo/protobuf/types" github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" - types1 "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" + types "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" @@ -40,10 +40,9 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Query for has it been at least $RECOVERY_DURATION units of time, // since the chain has been down for $DOWNTIME_DURATION. -// Note: $DOWNTIME_DURATION must be in set {SPECIFY_SET} type RecoveredSinceDowntimeOfLengthRequest struct { - Downtime time.Duration `protobuf:"bytes,1,opt,name=downtime,proto3,stdduration" json:"downtime" yaml:"downtime_duration"` - Recovery time.Duration `protobuf:"bytes,2,opt,name=recovery,proto3,stdduration" json:"recovery" yaml:"recovery_duration"` + Downtime types.Downtime `protobuf:"varint,1,opt,name=downtime,proto3,enum=osmosis.downtimedetector.v1beta1.Downtime" json:"downtime,omitempty" yaml:"downtime"` + Recovery time.Duration `protobuf:"bytes,2,opt,name=recovery,proto3,stdduration" json:"recovery" yaml:"recovery_duration"` } func (m *RecoveredSinceDowntimeOfLengthRequest) Reset() { *m = RecoveredSinceDowntimeOfLengthRequest{} } @@ -79,11 +78,11 @@ func (m *RecoveredSinceDowntimeOfLengthRequest) XXX_DiscardUnknown() { var xxx_messageInfo_RecoveredSinceDowntimeOfLengthRequest proto.InternalMessageInfo -func (m *RecoveredSinceDowntimeOfLengthRequest) GetDowntime() time.Duration { +func (m *RecoveredSinceDowntimeOfLengthRequest) GetDowntime() types.Downtime { if m != nil { return m.Downtime } - return 0 + return types.Downtime_DURATION_30S } func (m *RecoveredSinceDowntimeOfLengthRequest) GetRecovery() time.Duration { @@ -139,91 +138,9 @@ func (m *RecoveredSinceDowntimeOfLengthResponse) GetSuccesfullyRecovered() bool return false } -type ParamsRequest struct { -} - -func (m *ParamsRequest) Reset() { *m = ParamsRequest{} } -func (m *ParamsRequest) String() string { return proto.CompactTextString(m) } -func (*ParamsRequest) ProtoMessage() {} -func (*ParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_b748b3d07fa8b8cb, []int{2} -} -func (m *ParamsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ParamsRequest.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ParamsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_ParamsRequest.Merge(m, src) -} -func (m *ParamsRequest) XXX_Size() int { - return m.Size() -} -func (m *ParamsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_ParamsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_ParamsRequest proto.InternalMessageInfo - -type ParamsResponse struct { - Params types1.Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` -} - -func (m *ParamsResponse) Reset() { *m = ParamsResponse{} } -func (m *ParamsResponse) String() string { return proto.CompactTextString(m) } -func (*ParamsResponse) ProtoMessage() {} -func (*ParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_b748b3d07fa8b8cb, []int{3} -} -func (m *ParamsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ParamsResponse.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ParamsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_ParamsResponse.Merge(m, src) -} -func (m *ParamsResponse) XXX_Size() int { - return m.Size() -} -func (m *ParamsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_ParamsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_ParamsResponse proto.InternalMessageInfo - -func (m *ParamsResponse) GetParams() types1.Params { - if m != nil { - return m.Params - } - return types1.Params{} -} - func init() { proto.RegisterType((*RecoveredSinceDowntimeOfLengthRequest)(nil), "osmosis.downtimedetector.v1beta1.RecoveredSinceDowntimeOfLengthRequest") proto.RegisterType((*RecoveredSinceDowntimeOfLengthResponse)(nil), "osmosis.downtimedetector.v1beta1.RecoveredSinceDowntimeOfLengthResponse") - proto.RegisterType((*ParamsRequest)(nil), "osmosis.downtimedetector.v1beta1.ParamsRequest") - proto.RegisterType((*ParamsResponse)(nil), "osmosis.downtimedetector.v1beta1.ParamsResponse") } func init() { @@ -231,40 +148,38 @@ func init() { } var fileDescriptor_b748b3d07fa8b8cb = []byte{ - // 527 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4f, 0x8b, 0xd3, 0x4c, - 0x18, 0x6f, 0xf6, 0x7d, 0x2d, 0xcb, 0x88, 0x0a, 0x61, 0x85, 0x6e, 0x91, 0x74, 0x09, 0x2a, 0xab, - 0xd2, 0x8c, 0xdd, 0xde, 0xbc, 0x59, 0x17, 0x75, 0x41, 0x50, 0xe3, 0x45, 0x14, 0x29, 0x93, 0xe9, - 0xd3, 0x6c, 0x20, 0x99, 0xc9, 0x66, 0x26, 0xd5, 0x5c, 0xfd, 0x04, 0x82, 0x17, 0x4f, 0xde, 0xfd, - 0x26, 0x7b, 0x5c, 0xf0, 0xe2, 0x69, 0xd5, 0xd6, 0x4f, 0xe0, 0x07, 0x10, 0x49, 0x66, 0x26, 0x94, - 0x22, 0xdb, 0x88, 0xa7, 0x36, 0xf3, 0xfc, 0xfe, 0x3e, 0x4c, 0x82, 0xfa, 0x5c, 0x24, 0x5c, 0x44, - 0x02, 0x4f, 0xf8, 0x6b, 0x26, 0xa3, 0x04, 0xfa, 0x13, 0x90, 0x40, 0x25, 0xcf, 0xf0, 0x6c, 0x10, - 0x80, 0x24, 0x03, 0x7c, 0x94, 0x43, 0x56, 0x78, 0x69, 0xc6, 0x25, 0xb7, 0x77, 0x34, 0xdc, 0x33, - 0x70, 0x83, 0xf6, 0x34, 0xba, 0xbb, 0x15, 0xf2, 0x90, 0x57, 0x60, 0x5c, 0xfe, 0x53, 0xbc, 0x2e, - 0x5e, 0x6f, 0x13, 0x02, 0x83, 0x52, 0x59, 0x11, 0x1c, 0x5a, 0x31, 0x70, 0x40, 0x04, 0xd4, 0x10, - 0xca, 0x23, 0xa6, 0xe7, 0x37, 0x97, 0xe7, 0x55, 0xc2, 0x1a, 0x95, 0x92, 0x30, 0x62, 0x44, 0x46, - 0xdc, 0x60, 0xaf, 0x84, 0x9c, 0x87, 0x31, 0x60, 0x92, 0x46, 0x98, 0x30, 0xc6, 0x65, 0x35, 0x34, - 0x4e, 0xdb, 0x7a, 0x5a, 0x3d, 0x05, 0xf9, 0x14, 0x13, 0x56, 0x98, 0x91, 0x32, 0x19, 0xab, 0x3a, - 0xea, 0xc1, 0xe4, 0x5b, 0x65, 0x4d, 0xf2, 0x6c, 0xd9, 0xb3, 0xb7, 0x3a, 0x2f, 0x4b, 0x0b, 0x49, - 0x92, 0x54, 0x01, 0xdc, 0xef, 0x16, 0xba, 0xe6, 0x03, 0xe5, 0x33, 0xc8, 0x60, 0xf2, 0x2c, 0x62, - 0x14, 0xf6, 0xf5, 0x6a, 0x1e, 0x4f, 0x1f, 0x01, 0x0b, 0xe5, 0xa1, 0x0f, 0x47, 0x39, 0x08, 0x69, - 0xbf, 0x44, 0x9b, 0x66, 0x6b, 0x1d, 0x6b, 0xc7, 0xda, 0x3d, 0xbf, 0xb7, 0xed, 0x29, 0x75, 0xcf, - 0xa8, 0x7b, 0xfb, 0xda, 0x7d, 0x74, 0xf5, 0xf8, 0xb4, 0xd7, 0xfa, 0x79, 0xda, 0xeb, 0x14, 0x24, - 0x89, 0xef, 0xb8, 0x86, 0x38, 0x36, 0xf1, 0xdc, 0x0f, 0x5f, 0x7b, 0x96, 0x5f, 0x0b, 0x96, 0xe2, - 0x99, 0x4a, 0x51, 0x74, 0x36, 0xfe, 0x52, 0xdc, 0x10, 0x57, 0xc5, 0xcd, 0xb9, 0xfb, 0x0a, 0x5d, - 0x5f, 0x57, 0x51, 0xa4, 0x9c, 0x09, 0xb0, 0x87, 0xe8, 0xb2, 0xc8, 0x29, 0x05, 0x31, 0xcd, 0xe3, - 0xb8, 0x18, 0x67, 0x86, 0x55, 0x15, 0xde, 0xf4, 0xb7, 0x96, 0x86, 0xb5, 0xa2, 0x7b, 0x09, 0x5d, - 0x78, 0x42, 0x32, 0x92, 0x08, 0xbd, 0x29, 0xf7, 0x39, 0xba, 0x68, 0x0e, 0xb4, 0xee, 0x7d, 0xd4, - 0x4e, 0xab, 0x13, 0xbd, 0xb9, 0x5d, 0x6f, 0xdd, 0x05, 0xf6, 0x94, 0xc2, 0xe8, 0xff, 0xb2, 0xab, - 0xaf, 0xd9, 0x7b, 0x9f, 0xfe, 0x43, 0xe7, 0x9e, 0x96, 0xb7, 0xcc, 0xfe, 0x68, 0xa1, 0xb6, 0x82, - 0xd8, 0xb8, 0xa9, 0x98, 0xce, 0xd7, 0xbd, 0xdd, 0x9c, 0xa0, 0xf2, 0xbb, 0x83, 0xb7, 0x9f, 0x7f, - 0xbc, 0xdf, 0xb8, 0x65, 0xdf, 0x68, 0xf0, 0x02, 0xe9, 0x54, 0xbf, 0x2c, 0xe4, 0x9c, 0xbd, 0x75, - 0xfb, 0xc1, 0xfa, 0x1c, 0x8d, 0xae, 0x66, 0xf7, 0xe1, 0xbf, 0x0b, 0xe9, 0xa2, 0x07, 0x55, 0xd1, - 0x7b, 0xf6, 0xdd, 0x06, 0x45, 0xcf, 0x96, 0x1c, 0xd1, 0xe3, 0xb9, 0x63, 0x9d, 0xcc, 0x1d, 0xeb, - 0xdb, 0xdc, 0xb1, 0xde, 0x2d, 0x9c, 0xd6, 0xc9, 0xc2, 0x69, 0x7d, 0x59, 0x38, 0xad, 0x17, 0x07, - 0x61, 0x24, 0x0f, 0xf3, 0xc0, 0xa3, 0x3c, 0x31, 0x36, 0xfd, 0x98, 0x04, 0xa2, 0xf6, 0x9c, 0x0d, - 0x86, 0xf8, 0xcd, 0x1f, 0x9c, 0x69, 0x1c, 0x01, 0x93, 0xea, 0x3b, 0xa3, 0x5e, 0x8b, 0x76, 0xf5, - 0x33, 0xfc, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xb1, 0x09, 0x15, 0x2a, 0x40, 0x05, 0x00, 0x00, + // 484 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x53, 0xcf, 0x8b, 0xd3, 0x4e, + 0x14, 0x6f, 0x0a, 0xdf, 0x2f, 0x4b, 0x04, 0x85, 0xb8, 0x42, 0xb7, 0x48, 0x52, 0x82, 0xca, 0xb2, + 0xd0, 0x19, 0xda, 0x9e, 0xf4, 0x66, 0x5d, 0xd0, 0x05, 0x41, 0x8c, 0x37, 0x45, 0xca, 0x64, 0xfa, + 0x9a, 0x1d, 0x48, 0x66, 0xb2, 0x99, 0x49, 0x35, 0x57, 0x4f, 0x1e, 0x05, 0x2f, 0xfe, 0x49, 0x7b, + 0x5c, 0xf0, 0xe2, 0xa9, 0x6a, 0xeb, 0x5f, 0xb0, 0x7f, 0x80, 0x48, 0x32, 0x99, 0x50, 0x8a, 0x6c, + 0x16, 0x3c, 0x25, 0xc3, 0xe7, 0xc7, 0x7b, 0x9f, 0xf7, 0x66, 0xec, 0xa1, 0x90, 0x89, 0x90, 0x4c, + 0xe2, 0xb9, 0x78, 0xc7, 0x15, 0x4b, 0x60, 0x38, 0x07, 0x05, 0x54, 0x89, 0x0c, 0x2f, 0x47, 0x21, + 0x28, 0x32, 0xc2, 0x67, 0x39, 0x64, 0x05, 0x4a, 0x33, 0xa1, 0x84, 0x33, 0xa8, 0xe9, 0xc8, 0xd0, + 0x0d, 0x1b, 0xd5, 0xec, 0xfe, 0x7e, 0x24, 0x22, 0x51, 0x91, 0x71, 0xf9, 0xa7, 0x75, 0x7d, 0xdc, + 0x5e, 0x26, 0x02, 0x0e, 0xa5, 0xb3, 0x16, 0x3c, 0x6c, 0x17, 0x18, 0x64, 0x36, 0xcf, 0x33, 0xa2, + 0x98, 0xe0, 0xb5, 0xd4, 0xa5, 0x95, 0x16, 0x87, 0x44, 0x42, 0x43, 0xa6, 0x82, 0x19, 0xfc, 0x68, + 0x1b, 0xaf, 0xc2, 0x35, 0xac, 0x94, 0x44, 0x8c, 0x6f, 0x7b, 0xdd, 0x8d, 0x84, 0x88, 0x62, 0xc0, + 0x24, 0x65, 0x98, 0x70, 0x2e, 0x54, 0x05, 0x9a, 0x26, 0x0f, 0x6a, 0xb4, 0x3a, 0x85, 0xf9, 0x02, + 0x13, 0x5e, 0x18, 0x48, 0x17, 0x99, 0xe9, 0x49, 0xe8, 0x83, 0xe9, 0x6f, 0x57, 0xb5, 0xd3, 0xbf, + 0xb7, 0x8b, 0x97, 0x21, 0xa5, 0x22, 0x49, 0xaa, 0x09, 0xfe, 0x4f, 0xcb, 0xbe, 0x1f, 0x00, 0x15, + 0x4b, 0xc8, 0x60, 0xfe, 0x8a, 0x71, 0x0a, 0xc7, 0xf5, 0x28, 0x5e, 0x2c, 0x9e, 0x03, 0x8f, 0xd4, + 0x69, 0x00, 0x67, 0x39, 0x48, 0xe5, 0xbc, 0xb1, 0xf7, 0xcc, 0x94, 0x7a, 0xd6, 0xc0, 0x3a, 0xbc, + 0x39, 0x3e, 0x42, 0x6d, 0x1b, 0x44, 0xc6, 0x6c, 0x7a, 0xfb, 0x72, 0xe5, 0xdd, 0x2a, 0x48, 0x12, + 0x3f, 0xf2, 0x0d, 0xd9, 0x0f, 0x1a, 0xc3, 0xd2, 0x3c, 0xd3, 0x5d, 0x14, 0xbd, 0xee, 0xc0, 0x3a, + 0xbc, 0x31, 0x3e, 0x40, 0xba, 0x75, 0x64, 0x5a, 0x47, 0xc7, 0x75, 0xb4, 0xe9, 0xbd, 0xf3, 0x95, + 0xd7, 0xb9, 0x5c, 0x79, 0x3d, 0xed, 0x67, 0x84, 0xcd, 0xee, 0xfc, 0x2f, 0xdf, 0x3d, 0x2b, 0x68, + 0x0c, 0xfd, 0xb7, 0xf6, 0x83, 0xb6, 0x88, 0x32, 0x15, 0x5c, 0x82, 0x33, 0xb1, 0xef, 0xc8, 0x9c, + 0x52, 0x90, 0x8b, 0x3c, 0x8e, 0x8b, 0x59, 0x66, 0x54, 0x55, 0xe0, 0xbd, 0x60, 0x7f, 0x0b, 0x6c, + 0x1c, 0xc7, 0x1f, 0xbb, 0xf6, 0x7f, 0x2f, 0xcb, 0xd5, 0x3b, 0xbf, 0x2d, 0xdb, 0xbd, 0xba, 0x92, + 0xf3, 0xb4, 0x7d, 0x66, 0xd7, 0x5a, 0x47, 0xff, 0xd9, 0xbf, 0x1b, 0xe9, 0xd0, 0xfe, 0xc9, 0x87, + 0xaf, 0xbf, 0x3e, 0x77, 0x9f, 0x38, 0x8f, 0xaf, 0xf1, 0xb0, 0xae, 0xb6, 0x9c, 0xd2, 0xf3, 0xb5, + 0x6b, 0x5d, 0xac, 0x5d, 0xeb, 0xc7, 0xda, 0xb5, 0x3e, 0x6d, 0xdc, 0xce, 0xc5, 0xc6, 0xed, 0x7c, + 0xdb, 0xb8, 0x9d, 0xd7, 0x27, 0x11, 0x53, 0xa7, 0x79, 0x88, 0xa8, 0x48, 0x4c, 0x99, 0x61, 0x4c, + 0x42, 0xd9, 0xd4, 0x5c, 0x8e, 0x26, 0xf8, 0xfd, 0x5f, 0x2a, 0xd3, 0x98, 0x01, 0x57, 0xfa, 0x6d, + 0xe9, 0xab, 0xf0, 0x7f, 0xf5, 0x99, 0xfc, 0x09, 0x00, 0x00, 0xff, 0xff, 0x28, 0x46, 0xbb, 0x35, + 0x6f, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -279,7 +194,6 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type QueryClient interface { - Params(ctx context.Context, in *ParamsRequest, opts ...grpc.CallOption) (*ParamsResponse, error) RecoveredSinceDowntimeOfLength(ctx context.Context, in *RecoveredSinceDowntimeOfLengthRequest, opts ...grpc.CallOption) (*RecoveredSinceDowntimeOfLengthResponse, error) } @@ -291,15 +205,6 @@ func NewQueryClient(cc grpc1.ClientConn) QueryClient { return &queryClient{cc} } -func (c *queryClient) Params(ctx context.Context, in *ParamsRequest, opts ...grpc.CallOption) (*ParamsResponse, error) { - out := new(ParamsResponse) - err := c.cc.Invoke(ctx, "/osmosis.downtimedetector.v1beta1.Query/Params", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *queryClient) RecoveredSinceDowntimeOfLength(ctx context.Context, in *RecoveredSinceDowntimeOfLengthRequest, opts ...grpc.CallOption) (*RecoveredSinceDowntimeOfLengthResponse, error) { out := new(RecoveredSinceDowntimeOfLengthResponse) err := c.cc.Invoke(ctx, "/osmosis.downtimedetector.v1beta1.Query/RecoveredSinceDowntimeOfLength", in, out, opts...) @@ -311,7 +216,6 @@ func (c *queryClient) RecoveredSinceDowntimeOfLength(ctx context.Context, in *Re // QueryServer is the server API for Query service. type QueryServer interface { - Params(context.Context, *ParamsRequest) (*ParamsResponse, error) RecoveredSinceDowntimeOfLength(context.Context, *RecoveredSinceDowntimeOfLengthRequest) (*RecoveredSinceDowntimeOfLengthResponse, error) } @@ -319,9 +223,6 @@ type QueryServer interface { type UnimplementedQueryServer struct { } -func (*UnimplementedQueryServer) Params(ctx context.Context, req *ParamsRequest) (*ParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") -} func (*UnimplementedQueryServer) RecoveredSinceDowntimeOfLength(ctx context.Context, req *RecoveredSinceDowntimeOfLengthRequest) (*RecoveredSinceDowntimeOfLengthResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RecoveredSinceDowntimeOfLength not implemented") } @@ -330,24 +231,6 @@ func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) } -func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ParamsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).Params(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/osmosis.downtimedetector.v1beta1.Query/Params", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).Params(ctx, req.(*ParamsRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _Query_RecoveredSinceDowntimeOfLength_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(RecoveredSinceDowntimeOfLengthRequest) if err := dec(in); err != nil { @@ -370,10 +253,6 @@ var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "osmosis.downtimedetector.v1beta1.Query", HandlerType: (*QueryServer)(nil), Methods: []grpc.MethodDesc{ - { - MethodName: "Params", - Handler: _Query_Params_Handler, - }, { MethodName: "RecoveredSinceDowntimeOfLength", Handler: _Query_RecoveredSinceDowntimeOfLength_Handler, @@ -411,14 +290,11 @@ func (m *RecoveredSinceDowntimeOfLengthRequest) MarshalToSizedBuffer(dAtA []byte i = encodeVarintQuery(dAtA, i, uint64(n1)) i-- dAtA[i] = 0x12 - n2, err2 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.Downtime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.Downtime):]) - if err2 != nil { - return 0, err2 + if m.Downtime != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Downtime)) + i-- + dAtA[i] = 0x8 } - i -= n2 - i = encodeVarintQuery(dAtA, i, uint64(n2)) - i-- - dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -455,62 +331,6 @@ func (m *RecoveredSinceDowntimeOfLengthResponse) MarshalToSizedBuffer(dAtA []byt return len(dAtA) - i, nil } -func (m *ParamsRequest) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ParamsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *ParamsResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ParamsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - return len(dAtA) - i, nil -} - func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -528,8 +348,9 @@ func (m *RecoveredSinceDowntimeOfLengthRequest) Size() (n int) { } var l int _ = l - l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.Downtime) - n += 1 + l + sovQuery(uint64(l)) + if m.Downtime != 0 { + n += 1 + sovQuery(uint64(m.Downtime)) + } l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.Recovery) n += 1 + l + sovQuery(uint64(l)) return n @@ -547,26 +368,6 @@ func (m *RecoveredSinceDowntimeOfLengthResponse) Size() (n int) { return n } -func (m *ParamsRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *ParamsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.Params.Size() - n += 1 + l + sovQuery(uint64(l)) - return n -} - func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -603,10 +404,10 @@ func (m *RecoveredSinceDowntimeOfLengthRequest) Unmarshal(dAtA []byte) error { } switch fieldNum { case 1: - if wireType != 2 { + if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field Downtime", wireType) } - var msglen int + m.Downtime = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowQuery @@ -616,25 +417,11 @@ func (m *RecoveredSinceDowntimeOfLengthRequest) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + m.Downtime |= types.Downtime(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.Downtime, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 2: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Recovery", wireType) @@ -759,139 +546,6 @@ func (m *RecoveredSinceDowntimeOfLengthResponse) Unmarshal(dAtA []byte) error { } return nil } -func (m *ParamsRequest) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ParamsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ParamsResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ParamsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/downtime-detector/client/queryproto/query.pb.gw.go b/x/downtime-detector/client/queryproto/query.pb.gw.go index 0ff2bcbe174..0d025dcb19f 100644 --- a/x/downtime-detector/client/queryproto/query.pb.gw.go +++ b/x/downtime-detector/client/queryproto/query.pb.gw.go @@ -33,24 +33,6 @@ var _ = utilities.NewDoubleArray var _ = descriptor.ForMessage var _ = metadata.Join -func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ParamsRequest - var metadata runtime.ServerMetadata - - msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ParamsRequest - var metadata runtime.ServerMetadata - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - var ( filter_Query_RecoveredSinceDowntimeOfLength_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -93,29 +75,6 @@ func local_request_Query_RecoveredSinceDowntimeOfLength_0(ctx context.Context, m // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - mux.Handle("GET", pattern_Query_RecoveredSinceDowntimeOfLength_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -180,26 +139,6 @@ func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc // "QueryClient" to call the correct interceptors. func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { - mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - mux.Handle("GET", pattern_Query_RecoveredSinceDowntimeOfLength_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -224,13 +163,9 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } var ( - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "downtime-detector", "v1beta1", "Params"}, "", runtime.AssumeColonVerbOpt(false))) - pattern_Query_RecoveredSinceDowntimeOfLength_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "downtime-detector", "v1beta1", "RecoveredSinceDowntimeOfLength"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( - forward_Query_Params_0 = runtime.ForwardResponseMessage - forward_Query_RecoveredSinceDowntimeOfLength_0 = runtime.ForwardResponseMessage ) diff --git a/x/downtime-detector/genesis.go b/x/downtime-detector/genesis.go new file mode 100644 index 00000000000..0c90258e4ba --- /dev/null +++ b/x/downtime-detector/genesis.go @@ -0,0 +1,48 @@ +package downtimedetector + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" +) + +func (k *Keeper) InitGenesis(ctx sdk.Context, gen *types.GenesisState) { + k.StoreLastBlockTime(ctx, gen.LastBlockTime) + // set all default genesis down times, in case the provided list in genesis misses some. + k.setGenDowntimes(ctx, types.DefaultGenesis().GetDowntimes()) + // override with genesis list + k.setGenDowntimes(ctx, gen.Downtimes) +} + +func (k *Keeper) setGenDowntimes(ctx sdk.Context, genDowntimes []types.GenesisDowntimeEntry) { + for _, downtime := range genDowntimes { + k.StoreLastDowntimeOfLength(ctx, downtime.Duration, downtime.LastDowntime) + } +} + +// ExportGenesis returns the downtime detector module's exported genesis. +func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { + t, err := k.GetLastBlockTime(ctx) + if err != nil { + panic(err) + } + return &types.GenesisState{ + Downtimes: k.getGenDowntimes(ctx), + LastBlockTime: t, + } +} + +func (k *Keeper) getGenDowntimes(ctx sdk.Context) []types.GenesisDowntimeEntry { + downtimes := []types.GenesisDowntimeEntry{} + for _, downtime := range types.DowntimeToDuration.Keys() { + t, err := k.GetLastDowntimeOfLength(ctx, downtime) + if err != nil { + panic(err) + } + downtimes = append(downtimes, types.GenesisDowntimeEntry{ + Duration: downtime, + LastDowntime: t, + }) + } + return downtimes +} diff --git a/x/downtime-detector/genesis_test.go b/x/downtime-detector/genesis_test.go new file mode 100644 index 00000000000..da7d6191a3e --- /dev/null +++ b/x/downtime-detector/genesis_test.go @@ -0,0 +1,46 @@ +package downtimedetector_test + +import ( + "time" + + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" +) + +func (suite *KeeperTestSuite) TestImportExport() { + tests := map[string]struct { + Downtimes []types.GenesisDowntimeEntry + LastBlockTime time.Time + }{ + "no downtimes": { + LastBlockTime: baseTime, + }, + "some downtimes": { + LastBlockTime: baseTime, + Downtimes: []types.GenesisDowntimeEntry{ + {Duration: types.Downtime_DURATION_10M, LastDowntime: baseTime.Add(-time.Hour)}, + {Duration: types.Downtime_DURATION_30M, LastDowntime: baseTime.Add(-time.Hour)}, + }, + }, + } + for name, test := range tests { + suite.Run(name, func() { + suite.Ctx = suite.Ctx.WithBlockTime(test.LastBlockTime.Add(time.Hour)) + genState := &types.GenesisState{Downtimes: test.Downtimes, LastBlockTime: test.LastBlockTime} + suite.App.DowntimeKeeper.InitGenesis(suite.Ctx, genState) + exportedState := suite.App.DowntimeKeeper.ExportGenesis(suite.Ctx) + suite.Require().Equal(test.LastBlockTime, exportedState.LastBlockTime) + // O(N^2) method of checking downtimes, not concerned with run-time as its bounded. + for _, downtime := range test.Downtimes { + found := false + for _, exportedDowntime := range exportedState.Downtimes { + if exportedDowntime.Duration == downtime.Duration { + suite.Require().Equal(downtime.LastDowntime, exportedDowntime.LastDowntime) + found = true + break + } + } + suite.Require().True(found, "downtime %s not found in exported state", downtime.Duration.String()) + } + }) + } +} diff --git a/x/downtime-detector/keeper.go b/x/downtime-detector/keeper.go index c9c10f994f8..5ac6d5ad103 100644 --- a/x/downtime-detector/keeper.go +++ b/x/downtime-detector/keeper.go @@ -2,51 +2,12 @@ package downtimedetector import ( sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" - - paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" ) type Keeper struct { storeKey sdk.StoreKey - - paramSpace paramtypes.Subspace -} - -func NewKeeper(storeKey sdk.StoreKey, paramSpace paramtypes.Subspace) *Keeper { - // set KeyTable if it has not already been set - // if !paramSpace.HasKeyTable() { - // paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable()) - // } - - return &Keeper{storeKey: storeKey, paramSpace: paramSpace} -} - -// GetParams returns the total set of twap parameters. -// func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { -// k.paramSpace.GetParamSet(ctx, ¶ms) -// return params -// } - -// // SetParams sets the total set of twap parameters. -// func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { -// k.paramSpace.SetParamSet(ctx, ¶ms) -// } - -// InitGenesis initializes the twap module's state from a provided genesis -// state. -func (k Keeper) InitGenesis(ctx sdk.Context, genState *types.GenesisState) { - if err := genState.Validate(); err != nil { - panic(err) - } - - // k.SetParams(ctx, genState.Params) } -// ExportGenesis returns the twap module's exported genesis. -func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { - return &types.GenesisState{ - // Params: k.GetParams(ctx), - } +func NewKeeper(storeKey sdk.StoreKey) *Keeper { + return &Keeper{storeKey: storeKey} } diff --git a/x/downtime-detector/keeper_test.go b/x/downtime-detector/keeper_test.go new file mode 100644 index 00000000000..058e08efe27 --- /dev/null +++ b/x/downtime-detector/keeper_test.go @@ -0,0 +1,159 @@ +package downtimedetector_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + "github.com/osmosis-labs/osmosis/v13/app/apptesting" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" +) + +var baseTime = time.Unix(1257894000, 0).UTC() +var sec = time.Second +var min = time.Minute + +type blocktimes []time.Duration + +func (b blocktimes) EndTime() time.Time { + endTime := baseTime + for _, d := range b { + endTime = endTime.Add(d) + } + return endTime +} + +func (suite *KeeperTestSuite) runBlocktimes(times blocktimes) { + suite.Ctx = suite.Ctx.WithBlockTime(baseTime) + suite.App.DowntimeKeeper.BeginBlock(suite.Ctx) + for _, duration := range times { + suite.Ctx = suite.Ctx.WithBlockTime(suite.Ctx.BlockTime().Add(duration)) + suite.App.DowntimeKeeper.BeginBlock(suite.Ctx) + } +} + +var abruptRecovery5minDowntime10min blocktimes = []time.Duration{sec, 10 * min, 5 * min} +var smootherRecovery5minDowntime10min blocktimes = []time.Duration{sec, 10 * min, min, min, min, min, min} +var fifteenMinEndtime = abruptRecovery5minDowntime10min.EndTime() +var tenMinEndtime = abruptRecovery5minDowntime10min.EndTime().Add(-5 * min) + +func (suite *KeeperTestSuite) TestBeginBlock() { + tests := map[string]struct { + times blocktimes + downtimes []types.GenesisDowntimeEntry + }{ + "10 min halt, then 5 min halt": { + times: abruptRecovery5minDowntime10min, + downtimes: []types.GenesisDowntimeEntry{ + types.NewGenesisDowntimeEntry(types.Downtime_DURATION_1M, fifteenMinEndtime), + types.NewGenesisDowntimeEntry(types.Downtime_DURATION_3M, fifteenMinEndtime), + types.NewGenesisDowntimeEntry(types.Downtime_DURATION_5M, fifteenMinEndtime), + types.NewGenesisDowntimeEntry(types.Downtime_DURATION_10M, tenMinEndtime), + }, + }, + "10 min halt, then 1 min sequence": { + times: smootherRecovery5minDowntime10min, + downtimes: []types.GenesisDowntimeEntry{ + types.NewGenesisDowntimeEntry(types.Downtime_DURATION_1M, fifteenMinEndtime), + types.NewGenesisDowntimeEntry(types.Downtime_DURATION_2M, tenMinEndtime), + types.NewGenesisDowntimeEntry(types.Downtime_DURATION_5M, tenMinEndtime), + types.NewGenesisDowntimeEntry(types.Downtime_DURATION_10M, tenMinEndtime), + }, + }, + } + for name, test := range tests { + suite.Run(name, func() { + suite.runBlocktimes(test.times) + suite.Require().Equal(test.times.EndTime(), suite.Ctx.BlockTime()) + for _, downtime := range test.downtimes { + lastDowntime, err := suite.App.DowntimeKeeper.GetLastDowntimeOfLength(suite.Ctx, downtime.Duration) + suite.Require().NoError(err) + suite.Require().Equal(downtime.LastDowntime, lastDowntime) + } + }) + } +} + +func (suite *KeeperTestSuite) TestRecoveryQuery() { + type queryTestcase struct { + downtime types.Downtime + recovTime time.Duration + expectRecovered bool + } + + tests := map[string]struct { + times blocktimes + cases []queryTestcase + }{ + "10 min halt, then 5 min halt": { + times: abruptRecovery5minDowntime10min, + cases: []queryTestcase{ + {types.Downtime_DURATION_10M, 4 * min, true}, + {types.Downtime_DURATION_10M, 5 * min, true}, + {types.Downtime_DURATION_10M, 6 * min, false}, + {types.Downtime_DURATION_30S, 1 * min, false}, + }, + }, + "10 min halt, then 1 min sequence": { + times: smootherRecovery5minDowntime10min, + cases: []queryTestcase{ + {types.Downtime_DURATION_10M, 4 * min, true}, + {types.Downtime_DURATION_10M, 5 * min, true}, + {types.Downtime_DURATION_10M, 6 * min, false}, + {types.Downtime_DURATION_30S, 1 * min, false}, + }, + }, + } + for name, test := range tests { + suite.Run(name, func() { + suite.runBlocktimes(test.times) + suite.Require().Equal(test.times.EndTime(), suite.Ctx.BlockTime()) + for _, query := range test.cases { + recovered, err := suite.App.DowntimeKeeper.RecoveredSinceDowntimeOfLength( + suite.Ctx, query.downtime, query.recovTime) + suite.Require().NoError(err) + suite.Require().Equal(query.expectRecovered, recovered) + } + }) + } +} + +func (suite *KeeperTestSuite) TestRecoveryQueryErrors() { + tests := map[string]struct { + times blocktimes + downtime types.Downtime + recovTime time.Duration + }{ + "invalid downtime": { + times: abruptRecovery5minDowntime10min, + downtime: types.Downtime(0x7F), + recovTime: min, + }, + "0 recovery time": { + times: abruptRecovery5minDowntime10min, + downtime: types.Downtime_DURATION_1H, + recovTime: time.Duration(0), + }, + } + for name, test := range tests { + suite.Run(name, func() { + suite.runBlocktimes(test.times) + _, err := suite.App.DowntimeKeeper.RecoveredSinceDowntimeOfLength( + suite.Ctx, test.downtime, test.recovTime) + suite.Require().Error(err) + }) + } +} + +type KeeperTestSuite struct { + apptesting.KeeperTestHelper +} + +func (suite *KeeperTestSuite) SetupTest() { + suite.Setup() +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} diff --git a/x/downtime-detector/downtimedetector_module/module.go b/x/downtime-detector/module/module.go similarity index 85% rename from x/downtime-detector/downtimedetector_module/module.go rename to x/downtime-detector/module/module.go index fc3c2ec7852..72a79b794c7 100644 --- a/x/downtime-detector/downtimedetector_module/module.go +++ b/x/downtime-detector/module/module.go @@ -17,9 +17,11 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" downtimedetector "github.com/osmosis-labs/osmosis/v13/x/downtime-detector" + downtimeclient "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client" + downtimecli "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/cli" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/grpc" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto" "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" - twapcli "github.com/osmosis-labs/osmosis/v13/x/twap/client/cli" - "github.com/osmosis-labs/osmosis/v13/x/twap/client/queryproto" ) var ( @@ -58,7 +60,7 @@ func (b AppModuleBasic) GetTxCmd() *cobra.Command { } func (b AppModuleBasic) GetQueryCmd() *cobra.Command { - return twapcli.GetQueryCmd() + return downtimecli.GetQueryCmd() } func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { @@ -71,7 +73,7 @@ type AppModule struct { } func (am AppModule) RegisterServices(cfg module.Configurator) { - // queryproto.RegisterQueryServer(cfg.QueryServer(), grpc.Querier{Q: twapclient.Querier{K: am.k}}) + queryproto.RegisterQueryServer(cfg.QueryServer(), grpc.Querier{Q: downtimeclient.Querier{K: am.k}}) } func NewAppModule(k downtimedetector.Keeper) AppModule { @@ -81,8 +83,7 @@ func NewAppModule(k downtimedetector.Keeper) AppModule { } } -func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { -} +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} func (am AppModule) Route() sdk.Route { return sdk.Route{} @@ -110,7 +111,9 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(genState) } -func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} +func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { + am.k.BeginBlock(ctx) +} func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { return []abci.ValidatorUpdate{} diff --git a/x/downtime-detector/query.go b/x/downtime-detector/query.go new file mode 100644 index 00000000000..4523ca24455 --- /dev/null +++ b/x/downtime-detector/query.go @@ -0,0 +1,26 @@ +package downtimedetector + +import ( + "errors" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" +) + +func (k *Keeper) RecoveredSinceDowntimeOfLength(ctx sdk.Context, downtime types.Downtime, recoveryDuration time.Duration) (bool, error) { + lastDowntime, err := k.GetLastDowntimeOfLength(ctx, downtime) + if err != nil { + return false, err + } + if recoveryDuration == time.Duration(0) { + return false, errors.New("invalid recovery duration of 0") + } + // Check if current time < lastDowntime + recovery duration + // if LTE, then we have not waited recovery duration. + if ctx.BlockTime().Before(lastDowntime.Add(recoveryDuration)) { + return false, nil + } + return true, nil +} diff --git a/x/downtime-detector/store.go b/x/downtime-detector/store.go new file mode 100644 index 00000000000..bda12e2d177 --- /dev/null +++ b/x/downtime-detector/store.go @@ -0,0 +1,49 @@ +package downtimedetector + +import ( + "errors" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/v13/osmoutils" + "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" +) + +func (k *Keeper) GetLastBlockTime(ctx sdk.Context) (time.Time, error) { + store := ctx.KVStore(k.storeKey) + timeBz := store.Get(types.GetLastBlockTimestampKey()) + if len(timeBz) == 0 { + return time.Time{}, errors.New("no last block time stored in state. Should not happen, did initialization happen correctly?") + } + timeV, err := osmoutils.ParseTimeString(string(timeBz)) + if err != nil { + return time.Time{}, err + } + return timeV, nil +} + +func (k *Keeper) StoreLastBlockTime(ctx sdk.Context, t time.Time) { + store := ctx.KVStore(k.storeKey) + timeBz := osmoutils.FormatTimeString(t) + store.Set(types.GetLastBlockTimestampKey(), []byte(timeBz)) +} + +func (k *Keeper) GetLastDowntimeOfLength(ctx sdk.Context, dur types.Downtime) (time.Time, error) { + store := ctx.KVStore(k.storeKey) + timeBz := store.Get(types.GetLastDowntimeOfLengthKey(dur)) + if len(timeBz) == 0 { + return time.Time{}, errors.New("no last time stored in state. Should not happen, did initialization happen correctly?") + } + timeV, err := osmoutils.ParseTimeString(string(timeBz)) + if err != nil { + return time.Time{}, err + } + return timeV, nil +} + +func (k *Keeper) StoreLastDowntimeOfLength(ctx sdk.Context, dur types.Downtime, t time.Time) { + store := ctx.KVStore(k.storeKey) + timeBz := osmoutils.FormatTimeString(t) + store.Set(types.GetLastDowntimeOfLengthKey(dur), []byte(timeBz)) +} diff --git a/x/downtime-detector/types/constants.go b/x/downtime-detector/types/constants.go index e01b37548c9..86020ed6bb1 100644 --- a/x/downtime-detector/types/constants.go +++ b/x/downtime-detector/types/constants.go @@ -1,9 +1,81 @@ package types +import ( + fmt "fmt" + "strings" + time "time" + + "github.com/tidwall/btree" +) + const ( - ModuleName = "downtime-detector" + // we don't use a `-` as RouterKey must be alphanumeric + ModuleName = "downtimedetector" StoreKey = ModuleName RouterKey = ModuleName QuerierRoute = ModuleName ) + +var DowntimeToDuration = btree.NewMap[Downtime, time.Duration](16) +var DefaultLastDowntime = time.Unix(0, 0) + +// init initializes the DowntimeToDuration map with mappings +// from the Duration enum values to their corresponding +// time.Duration values. +func init() { + DowntimeToDuration.Set(Downtime_DURATION_30S, 30*time.Second) + DowntimeToDuration.Set(Downtime_DURATION_1M, time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_2M, 2*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_3M, 3*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_4M, 4*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_5M, 5*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_10M, 10*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_20M, 20*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_30M, 30*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_40M, 40*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_50M, 50*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_1H, time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_1_5H, time.Hour+30*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_2H, 2*time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_2_5H, 2*time.Hour+30*time.Minute) + DowntimeToDuration.Set(Downtime_DURATION_3H, 3*time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_4H, 4*time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_5H, 5*time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_6H, 6*time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_9H, 9*time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_12H, 12*time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_18H, 18*time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_24H, 24*time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_36H, 36*time.Hour) + DowntimeToDuration.Set(Downtime_DURATION_48H, 48*time.Hour) +} + +func DowntimeStrings() []string { + arr := []string{} + DowntimeToDuration.Ascend(Downtime(0), func(_ Downtime, v time.Duration) bool { + s := strings.Replace(v.String(), "m0s", "m", 1) + s = strings.Replace(s, "h0m", "h", 1) + arr = append(arr, s) + return true + }) + return arr +} + +func DowntimeByDuration(duration time.Duration) (Downtime, error) { + var result Downtime + found := false + DowntimeToDuration.Ascend(Downtime(0), func(k Downtime, v time.Duration) bool { + if v == duration { + result = k + found = true + return false + } + return true + }) + if found { + return result, nil + } + downtimeOptions := strings.Join(DowntimeStrings(), ", ") + return result, fmt.Errorf("downtime of %s does not exist. Chain-provided downtimes [%s]", duration.String(), downtimeOptions) +} diff --git a/x/downtime-detector/types/constants_test.go b/x/downtime-detector/types/constants_test.go new file mode 100644 index 00000000000..537e64432fa --- /dev/null +++ b/x/downtime-detector/types/constants_test.go @@ -0,0 +1,19 @@ +package types + +import ( + "testing" + time "time" + + "github.com/stretchr/testify/require" +) + +func TestDowntimeToDurationAscending(t *testing.T) { + numEntries := 0 + lastDur := time.Duration(0) + DowntimeToDuration.Ascend(Downtime(0), func(_ Downtime, v time.Duration) bool { + numEntries++ + require.Greater(t, v, lastDur) + return true + }) + require.Equal(t, numEntries, 25) +} diff --git a/x/downtime-detector/types/downtime_duration.pb.go b/x/downtime-detector/types/downtime_duration.pb.go new file mode 100644 index 00000000000..c86cc3cfea9 --- /dev/null +++ b/x/downtime-detector/types/downtime_duration.pb.go @@ -0,0 +1,156 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: osmosis/downtime-detector/v1beta1/downtime_duration.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + _ "github.com/gogo/protobuf/types" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type Downtime int32 + +const ( + Downtime_DURATION_30S Downtime = 0 + Downtime_DURATION_1M Downtime = 1 + Downtime_DURATION_2M Downtime = 2 + Downtime_DURATION_3M Downtime = 3 + Downtime_DURATION_4M Downtime = 4 + Downtime_DURATION_5M Downtime = 5 + Downtime_DURATION_10M Downtime = 6 + Downtime_DURATION_20M Downtime = 7 + Downtime_DURATION_30M Downtime = 8 + Downtime_DURATION_40M Downtime = 9 + Downtime_DURATION_50M Downtime = 10 + Downtime_DURATION_1H Downtime = 11 + Downtime_DURATION_1_5H Downtime = 12 + Downtime_DURATION_2H Downtime = 13 + Downtime_DURATION_2_5H Downtime = 14 + Downtime_DURATION_3H Downtime = 15 + Downtime_DURATION_4H Downtime = 16 + Downtime_DURATION_5H Downtime = 17 + Downtime_DURATION_6H Downtime = 18 + Downtime_DURATION_9H Downtime = 19 + Downtime_DURATION_12H Downtime = 20 + Downtime_DURATION_18H Downtime = 21 + Downtime_DURATION_24H Downtime = 22 + Downtime_DURATION_36H Downtime = 23 + Downtime_DURATION_48H Downtime = 24 +) + +var Downtime_name = map[int32]string{ + 0: "DURATION_30S", + 1: "DURATION_1M", + 2: "DURATION_2M", + 3: "DURATION_3M", + 4: "DURATION_4M", + 5: "DURATION_5M", + 6: "DURATION_10M", + 7: "DURATION_20M", + 8: "DURATION_30M", + 9: "DURATION_40M", + 10: "DURATION_50M", + 11: "DURATION_1H", + 12: "DURATION_1_5H", + 13: "DURATION_2H", + 14: "DURATION_2_5H", + 15: "DURATION_3H", + 16: "DURATION_4H", + 17: "DURATION_5H", + 18: "DURATION_6H", + 19: "DURATION_9H", + 20: "DURATION_12H", + 21: "DURATION_18H", + 22: "DURATION_24H", + 23: "DURATION_36H", + 24: "DURATION_48H", +} + +var Downtime_value = map[string]int32{ + "DURATION_30S": 0, + "DURATION_1M": 1, + "DURATION_2M": 2, + "DURATION_3M": 3, + "DURATION_4M": 4, + "DURATION_5M": 5, + "DURATION_10M": 6, + "DURATION_20M": 7, + "DURATION_30M": 8, + "DURATION_40M": 9, + "DURATION_50M": 10, + "DURATION_1H": 11, + "DURATION_1_5H": 12, + "DURATION_2H": 13, + "DURATION_2_5H": 14, + "DURATION_3H": 15, + "DURATION_4H": 16, + "DURATION_5H": 17, + "DURATION_6H": 18, + "DURATION_9H": 19, + "DURATION_12H": 20, + "DURATION_18H": 21, + "DURATION_24H": 22, + "DURATION_36H": 23, + "DURATION_48H": 24, +} + +func (x Downtime) String() string { + return proto.EnumName(Downtime_name, int32(x)) +} + +func (Downtime) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_21a1969f22fb2a7e, []int{0} +} + +func init() { + proto.RegisterEnum("osmosis.downtimedetector.v1beta1.Downtime", Downtime_name, Downtime_value) +} + +func init() { + proto.RegisterFile("osmosis/downtime-detector/v1beta1/downtime_duration.proto", fileDescriptor_21a1969f22fb2a7e) +} + +var fileDescriptor_21a1969f22fb2a7e = []byte{ + // 386 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xbb, 0x6e, 0xe2, 0x50, + 0x10, 0x86, 0xed, 0x65, 0x97, 0x65, 0x0d, 0x2c, 0x83, 0x97, 0xbd, 0x51, 0x78, 0xb7, 0x8e, 0x84, + 0x8f, 0x2f, 0x80, 0xa0, 0x48, 0x91, 0x88, 0xe2, 0xa4, 0x38, 0x89, 0x94, 0x8b, 0x22, 0xa5, 0xb1, + 0x6c, 0x70, 0x1c, 0x4b, 0x98, 0x83, 0xf0, 0x81, 0x84, 0xb7, 0xc8, 0x33, 0xa5, 0x4a, 0x49, 0x99, + 0x32, 0x82, 0x17, 0x89, 0xf0, 0x85, 0x68, 0x50, 0x3a, 0xcf, 0x37, 0xf3, 0xfb, 0xfc, 0xff, 0x68, + 0x94, 0x3e, 0x8f, 0x23, 0x1e, 0x87, 0x31, 0x19, 0xf1, 0xfb, 0x89, 0x08, 0x23, 0xbf, 0x35, 0xf2, + 0x85, 0x3f, 0x14, 0x7c, 0x46, 0x16, 0xa6, 0xe7, 0x0b, 0xd7, 0xdc, 0x75, 0x9c, 0xd1, 0x7c, 0xe6, + 0x8a, 0x90, 0x4f, 0xf4, 0xe9, 0x8c, 0x0b, 0xae, 0xfe, 0xcf, 0xa4, 0x7a, 0x3e, 0x90, 0x2b, 0xf5, + 0x4c, 0xd9, 0x6c, 0x04, 0x3c, 0xe0, 0xc9, 0x30, 0xd9, 0x7e, 0xa5, 0xba, 0xe6, 0xdf, 0x80, 0xf3, + 0x60, 0xec, 0x93, 0xa4, 0xf2, 0xe6, 0xb7, 0xc4, 0x9d, 0x2c, 0xf3, 0xd6, 0x30, 0xf9, 0xa7, 0x93, + 0x6a, 0xd2, 0x22, 0x6b, 0x69, 0xfb, 0x2a, 0xec, 0xa6, 0xf9, 0x6f, 0xbf, 0xbf, 0x75, 0x14, 0x0b, + 0x37, 0x9a, 0xa6, 0x03, 0x07, 0x4f, 0x05, 0xa5, 0x34, 0xc8, 0x9c, 0xaa, 0xa0, 0x54, 0x06, 0x57, + 0xe7, 0x47, 0x97, 0x27, 0x67, 0xa7, 0x8e, 0x6d, 0x5c, 0x80, 0xa4, 0xd6, 0x94, 0xf2, 0x8e, 0x98, + 0x0c, 0x64, 0x04, 0x2c, 0x06, 0x9f, 0x10, 0xb0, 0x19, 0x14, 0x10, 0x68, 0x33, 0xf8, 0x8c, 0x40, + 0x87, 0xc1, 0x17, 0xf4, 0x8c, 0x69, 0x30, 0x28, 0x22, 0x62, 0x19, 0x0c, 0xbe, 0xee, 0x59, 0x61, + 0x50, 0x42, 0xa4, 0x6d, 0x30, 0xf8, 0x86, 0x48, 0xc7, 0x60, 0xa0, 0x60, 0xbb, 0x14, 0xca, 0x6a, + 0x5d, 0xa9, 0xbe, 0x03, 0xa7, 0x43, 0xa1, 0x82, 0x13, 0x50, 0xa8, 0xa2, 0x19, 0x6b, 0x3b, 0xf3, + 0x1d, 0x87, 0xa2, 0x50, 0xc3, 0xa1, 0x28, 0x00, 0x0e, 0x45, 0xa1, 0x8e, 0x40, 0x97, 0x82, 0x8a, + 0x40, 0x9f, 0xc2, 0x0f, 0x1c, 0xdb, 0xa2, 0xd0, 0xc0, 0xa4, 0x47, 0xe1, 0x27, 0x5e, 0x44, 0x9b, + 0xc2, 0x2f, 0xbc, 0x88, 0x2e, 0x85, 0xdf, 0x78, 0x11, 0x3d, 0x0a, 0x7f, 0x8e, 0xaf, 0x9f, 0xd7, + 0x9a, 0xbc, 0x5a, 0x6b, 0xf2, 0xeb, 0x5a, 0x93, 0x1f, 0x37, 0x9a, 0xb4, 0xda, 0x68, 0xd2, 0xcb, + 0x46, 0x93, 0x6e, 0x0e, 0x83, 0x50, 0xdc, 0xcd, 0x3d, 0x7d, 0xc8, 0x23, 0x92, 0x1d, 0x66, 0x6b, + 0xec, 0x7a, 0x71, 0x5e, 0x90, 0x85, 0x69, 0x93, 0x87, 0x0f, 0xce, 0x5c, 0x2c, 0xa7, 0x7e, 0xec, + 0x15, 0x93, 0x23, 0xb1, 0xdf, 0x02, 0x00, 0x00, 0xff, 0xff, 0x48, 0x2b, 0x3d, 0xaf, 0x10, 0x03, + 0x00, 0x00, +} diff --git a/x/downtime-detector/types/genesis.go b/x/downtime-detector/types/genesis.go index 39508cca25b..257b3a079bc 100644 --- a/x/downtime-detector/types/genesis.go +++ b/x/downtime-detector/types/genesis.go @@ -1,9 +1,25 @@ package types +import "time" + func DefaultGenesis() *GenesisState { - return &GenesisState{} + genDowntimes := []GenesisDowntimeEntry{} + for _, downtime := range DowntimeToDuration.Keys() { + genDowntimes = append(genDowntimes, GenesisDowntimeEntry{ + Duration: downtime, + LastDowntime: DefaultLastDowntime, + }) + } + return &GenesisState{ + Downtimes: genDowntimes, + LastBlockTime: time.Unix(0, 0), + } } func (g *GenesisState) Validate() error { return nil } + +func NewGenesisDowntimeEntry(dur Downtime, time time.Time) GenesisDowntimeEntry { + return GenesisDowntimeEntry{Duration: dur, LastDowntime: time} +} diff --git a/x/downtime-detector/types/genesis.pb.go b/x/downtime-detector/types/genesis.pb.go index 75e41db1a3d..d2bef4b2bfb 100644 --- a/x/downtime-detector/types/genesis.pb.go +++ b/x/downtime-detector/types/genesis.pb.go @@ -29,53 +29,16 @@ var _ = time.Kitchen // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// Params holds parameters for the downtime-detector module -type Params struct { -} - -func (m *Params) Reset() { *m = Params{} } -func (m *Params) String() string { return proto.CompactTextString(m) } -func (*Params) ProtoMessage() {} -func (*Params) Descriptor() ([]byte, []int) { - return fileDescriptor_4581e137a44782af, []int{0} -} -func (m *Params) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Params.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *Params) XXX_Merge(src proto.Message) { - xxx_messageInfo_Params.Merge(m, src) -} -func (m *Params) XXX_Size() int { - return m.Size() -} -func (m *Params) XXX_DiscardUnknown() { - xxx_messageInfo_Params.DiscardUnknown(m) -} - -var xxx_messageInfo_Params proto.InternalMessageInfo - type GenesisDowntimeEntry struct { - DowntimeDuration time.Duration `protobuf:"bytes,1,opt,name=downtime_duration,json=downtimeDuration,proto3,stdduration" json:"downtime_duration" yaml:"downtime_duration"` - LastDowntime time.Time `protobuf:"bytes,2,opt,name=last_downtime,json=lastDowntime,proto3,stdtime" json:"last_downtime" yaml:"last_downtime"` + Duration Downtime `protobuf:"varint,1,opt,name=duration,proto3,enum=osmosis.downtimedetector.v1beta1.Downtime" json:"duration,omitempty" yaml:"duration"` + LastDowntime time.Time `protobuf:"bytes,2,opt,name=last_downtime,json=lastDowntime,proto3,stdtime" json:"last_downtime" yaml:"last_downtime"` } func (m *GenesisDowntimeEntry) Reset() { *m = GenesisDowntimeEntry{} } func (m *GenesisDowntimeEntry) String() string { return proto.CompactTextString(m) } func (*GenesisDowntimeEntry) ProtoMessage() {} func (*GenesisDowntimeEntry) Descriptor() ([]byte, []int) { - return fileDescriptor_4581e137a44782af, []int{1} + return fileDescriptor_4581e137a44782af, []int{0} } func (m *GenesisDowntimeEntry) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -104,11 +67,11 @@ func (m *GenesisDowntimeEntry) XXX_DiscardUnknown() { var xxx_messageInfo_GenesisDowntimeEntry proto.InternalMessageInfo -func (m *GenesisDowntimeEntry) GetDowntimeDuration() time.Duration { +func (m *GenesisDowntimeEntry) GetDuration() Downtime { if m != nil { - return m.DowntimeDuration + return m.Duration } - return 0 + return Downtime_DURATION_30S } func (m *GenesisDowntimeEntry) GetLastDowntime() time.Time { @@ -122,15 +85,13 @@ func (m *GenesisDowntimeEntry) GetLastDowntime() time.Time { type GenesisState struct { Downtimes []GenesisDowntimeEntry `protobuf:"bytes,1,rep,name=downtimes,proto3" json:"downtimes"` LastBlockTime time.Time `protobuf:"bytes,2,opt,name=last_block_time,json=lastBlockTime,proto3,stdtime" json:"last_block_time" yaml:"last_block_time"` - // params is the container of twap parameters. - Params Params `protobuf:"bytes,3,opt,name=params,proto3" json:"params"` } func (m *GenesisState) Reset() { *m = GenesisState{} } func (m *GenesisState) String() string { return proto.CompactTextString(m) } func (*GenesisState) ProtoMessage() {} func (*GenesisState) Descriptor() ([]byte, []int) { - return fileDescriptor_4581e137a44782af, []int{2} + return fileDescriptor_4581e137a44782af, []int{1} } func (m *GenesisState) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -173,15 +134,7 @@ func (m *GenesisState) GetLastBlockTime() time.Time { return time.Time{} } -func (m *GenesisState) GetParams() Params { - if m != nil { - return m.Params - } - return Params{} -} - func init() { - proto.RegisterType((*Params)(nil), "osmosis.downtimedetector.v1beta1.Params") proto.RegisterType((*GenesisDowntimeEntry)(nil), "osmosis.downtimedetector.v1beta1.GenesisDowntimeEntry") proto.RegisterType((*GenesisState)(nil), "osmosis.downtimedetector.v1beta1.GenesisState") } @@ -191,57 +144,33 @@ func init() { } var fileDescriptor_4581e137a44782af = []byte{ - // 432 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x4f, 0x8b, 0xd3, 0x40, - 0x18, 0xc6, 0x33, 0xbb, 0x52, 0x74, 0x76, 0x45, 0x0d, 0x45, 0xb2, 0x3d, 0x24, 0x21, 0x78, 0xe8, - 0x65, 0x67, 0xe8, 0x2e, 0x78, 0x10, 0xbc, 0x84, 0xaa, 0x57, 0xa9, 0x82, 0xd0, 0x4b, 0x98, 0xa4, - 0xd3, 0x18, 0x4c, 0x32, 0x21, 0x33, 0xad, 0xe6, 0x5b, 0xf4, 0x28, 0x7e, 0xa2, 0x1e, 0x7b, 0xf4, - 0x54, 0xa5, 0x3d, 0x78, 0xf7, 0x13, 0x48, 0xe6, 0x8f, 0xd5, 0xb6, 0xd0, 0xbd, 0x25, 0xf3, 0x3e, - 0xcf, 0xf3, 0xbe, 0xbf, 0x19, 0x5e, 0x88, 0x19, 0x2f, 0x18, 0xcf, 0x38, 0x9e, 0xb0, 0xcf, 0xa5, - 0xc8, 0x0a, 0x7a, 0x3d, 0xa1, 0x82, 0x26, 0x82, 0xd5, 0x78, 0x3e, 0x88, 0xa9, 0x20, 0x03, 0x9c, - 0xd2, 0x92, 0xf2, 0x8c, 0xa3, 0xaa, 0x66, 0x82, 0xd9, 0xbe, 0x36, 0x20, 0x63, 0x30, 0x7a, 0xa4, - 0xf5, 0xbd, 0x6e, 0xca, 0x52, 0x26, 0xc5, 0xb8, 0xfd, 0x52, 0xbe, 0xde, 0x55, 0xca, 0x58, 0x9a, - 0x53, 0x2c, 0xff, 0xe2, 0xd9, 0x14, 0x93, 0xb2, 0x31, 0xa5, 0x44, 0x66, 0x46, 0xca, 0xa3, 0x7e, - 0x74, 0xc9, 0xdd, 0x77, 0x4d, 0x66, 0x35, 0x11, 0x19, 0x2b, 0x75, 0xdd, 0xdb, 0xaf, 0xb7, 0x13, - 0x71, 0x41, 0x8a, 0x4a, 0x09, 0x82, 0xfb, 0xb0, 0xf3, 0x96, 0xd4, 0xa4, 0xe0, 0xc1, 0x2f, 0x00, - 0xbb, 0x6f, 0x14, 0xca, 0x50, 0x8f, 0xfe, 0xaa, 0x14, 0x75, 0x63, 0xe7, 0xf0, 0x89, 0x61, 0x89, - 0x4c, 0xbc, 0x03, 0x7c, 0xd0, 0xbf, 0xb8, 0xb9, 0x42, 0x2a, 0x1f, 0x99, 0x7c, 0x34, 0xd4, 0x82, - 0xf0, 0xd9, 0x72, 0xed, 0x59, 0xbf, 0xd7, 0x9e, 0xd3, 0x90, 0x22, 0x7f, 0x11, 0x1c, 0x24, 0x04, - 0x5f, 0x7f, 0x78, 0x60, 0xf4, 0xd8, 0x9c, 0x1b, 0x9f, 0x4d, 0xe0, 0xc3, 0x9c, 0x70, 0x11, 0x99, - 0x82, 0x73, 0x26, 0x3b, 0xf5, 0x0e, 0x3a, 0xbd, 0x37, 0x24, 0xa1, 0xaf, 0x5b, 0x75, 0x55, 0xab, - 0xff, 0xec, 0xc1, 0xa2, 0x6d, 0x73, 0xd9, 0x9e, 0x19, 0xaa, 0xe0, 0xdb, 0x19, 0xbc, 0xd4, 0xa4, - 0xef, 0x04, 0x11, 0xd4, 0x1e, 0xc3, 0x07, 0x46, 0xcf, 0x1d, 0xe0, 0x9f, 0xf7, 0x2f, 0x6e, 0x9e, - 0xa3, 0x53, 0xef, 0x88, 0x8e, 0x5d, 0x56, 0x78, 0xaf, 0x9d, 0x65, 0xb4, 0x8b, 0xb3, 0xa7, 0xf0, - 0x91, 0x1c, 0x28, 0xce, 0x59, 0xf2, 0x29, 0xba, 0x23, 0x51, 0xa0, 0x89, 0x9e, 0xfe, 0x43, 0xb4, - 0x0b, 0x50, 0x4c, 0xf2, 0x9a, 0xc2, 0xf6, 0xb0, 0xf5, 0xd9, 0xaf, 0x61, 0xa7, 0x92, 0x0f, 0xe9, - 0x9c, 0xcb, 0xf8, 0xfe, 0x69, 0x00, 0xf5, 0xf0, 0x7a, 0x64, 0xed, 0x0e, 0x3f, 0x2c, 0x37, 0x2e, - 0x58, 0x6d, 0x5c, 0xf0, 0x73, 0xe3, 0x82, 0xc5, 0xd6, 0xb5, 0x56, 0x5b, 0xd7, 0xfa, 0xbe, 0x75, - 0xad, 0xf1, 0xcb, 0x34, 0x13, 0x1f, 0x67, 0x31, 0x4a, 0x58, 0x61, 0xb6, 0xe2, 0x3a, 0x27, 0x31, - 0xff, 0xbb, 0x22, 0xf3, 0xc1, 0x2d, 0xfe, 0x72, 0x64, 0x51, 0x44, 0x53, 0x51, 0x1e, 0x77, 0x24, - 0xe7, 0xed, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x54, 0x1c, 0x59, 0x62, 0x52, 0x03, 0x00, 0x00, -} - -func (m *Params) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *Params) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil + // 404 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x6a, 0xe2, 0x40, + 0x1c, 0xc6, 0x33, 0xbb, 0xcb, 0xb2, 0x1b, 0xdd, 0x15, 0xb2, 0xb2, 0x58, 0x0f, 0x49, 0xc8, 0x49, + 0x0a, 0xce, 0xa0, 0x42, 0xa1, 0x85, 0x5e, 0x42, 0x4b, 0xef, 0xb6, 0x50, 0xb0, 0x87, 0x30, 0x89, + 0x63, 0x1a, 0x9a, 0x64, 0x24, 0x33, 0xda, 0xe6, 0x2d, 0x7c, 0x2c, 0x8f, 0xd2, 0x43, 0xe9, 0xc9, + 0x16, 0x7d, 0x03, 0x9f, 0xa0, 0x24, 0x99, 0xd1, 0x2a, 0x82, 0xbd, 0x25, 0xf3, 0xff, 0xbe, 0x8f, + 0xef, 0xf7, 0xe7, 0xaf, 0x22, 0xca, 0x22, 0xca, 0x02, 0x86, 0xfa, 0xf4, 0x31, 0xe6, 0x41, 0x44, + 0x9a, 0x7d, 0xc2, 0x89, 0xc7, 0x69, 0x82, 0xc6, 0x2d, 0x97, 0x70, 0xdc, 0x42, 0x3e, 0x89, 0x09, + 0x0b, 0x18, 0x1c, 0x26, 0x94, 0x53, 0xcd, 0x14, 0x06, 0x28, 0x0d, 0x52, 0x0f, 0x85, 0xbe, 0x5e, + 0xf5, 0xa9, 0x4f, 0x73, 0x31, 0xca, 0xbe, 0x0a, 0x5f, 0xfd, 0xc8, 0xa7, 0xd4, 0x0f, 0x09, 0xca, + 0xff, 0xdc, 0xd1, 0x00, 0xe1, 0x38, 0x95, 0x23, 0x2f, 0xcf, 0x74, 0x0a, 0x4f, 0xf1, 0x23, 0x46, + 0xfa, 0xae, 0xab, 0x3f, 0x4a, 0x30, 0x0f, 0x68, 0x2c, 0xe6, 0xc6, 0xee, 0x3c, 0x6b, 0xc4, 0x38, + 0x8e, 0x86, 0x42, 0x70, 0x7a, 0x98, 0x4f, 0x4e, 0x9c, 0xed, 0x6c, 0xeb, 0x05, 0xa8, 0xd5, 0xab, + 0x82, 0xfd, 0x42, 0x48, 0x2e, 0x63, 0x9e, 0xa4, 0xda, 0x9d, 0xfa, 0x4b, 0x4a, 0x6b, 0xc0, 0x04, + 0x8d, 0xbf, 0xed, 0x63, 0x78, 0x68, 0x2b, 0x50, 0x46, 0xd8, 0xff, 0x56, 0x73, 0xa3, 0x92, 0xe2, + 0x28, 0x3c, 0xb3, 0x64, 0x8a, 0xd5, 0x5d, 0x07, 0x6a, 0x58, 0xfd, 0x13, 0x62, 0xc6, 0x1d, 0x19, + 0x54, 0xfb, 0x66, 0x82, 0x46, 0xa9, 0x5d, 0x87, 0x05, 0x29, 0x94, 0xa4, 0xf0, 0x46, 0x92, 0xda, + 0xe6, 0x74, 0x6e, 0x28, 0xab, 0xb9, 0x51, 0x2d, 0x52, 0xb7, 0xec, 0xd6, 0xe4, 0xcd, 0x00, 0xdd, + 0x72, 0xf6, 0x26, 0x1b, 0x58, 0xcf, 0x40, 0x2d, 0x0b, 0xb0, 0x6b, 0x8e, 0x39, 0xd1, 0x7a, 0xea, + 0x6f, 0xa9, 0x67, 0x35, 0x60, 0x7e, 0x6f, 0x94, 0xda, 0x27, 0x87, 0x89, 0xf6, 0xed, 0xc6, 0xfe, + 0x91, 0x75, 0xe9, 0x6e, 0xe2, 0xb4, 0x81, 0x5a, 0xc9, 0x0b, 0xb9, 0x21, 0xf5, 0x1e, 0x9c, 0x2f, + 0x12, 0x59, 0x82, 0xe8, 0xff, 0x27, 0xa2, 0x4d, 0x40, 0xc1, 0x94, 0xaf, 0xc9, 0xce, 0x1e, 0x33, + 0x9f, 0x7d, 0x3b, 0x5d, 0xe8, 0x60, 0xb6, 0xd0, 0xc1, 0xfb, 0x42, 0x07, 0x93, 0xa5, 0xae, 0xcc, + 0x96, 0xba, 0xf2, 0xba, 0xd4, 0x95, 0xde, 0xb9, 0x1f, 0xf0, 0xfb, 0x91, 0x0b, 0x3d, 0x1a, 0xc9, + 0x6b, 0x6f, 0x86, 0xd8, 0x65, 0xeb, 0xd3, 0x1f, 0xb7, 0x3a, 0xe8, 0x69, 0xcf, 0x81, 0xf0, 0x74, + 0x48, 0x98, 0xfb, 0x33, 0xef, 0xd7, 0xf9, 0x08, 0x00, 0x00, 0xff, 0xff, 0xe8, 0xb3, 0x0b, 0xaf, + 0x2a, 0x03, 0x00, 0x00, } func (m *GenesisDowntimeEntry) Marshal() (dAtA []byte, err error) { @@ -272,14 +201,11 @@ func (m *GenesisDowntimeEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintGenesis(dAtA, i, uint64(n1)) i-- dAtA[i] = 0x12 - n2, err2 := github_com_gogo_protobuf_types.StdDurationMarshalTo(m.DowntimeDuration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(m.DowntimeDuration):]) - if err2 != nil { - return 0, err2 + if m.Duration != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Duration)) + i-- + dAtA[i] = 0x8 } - i -= n2 - i = encodeVarintGenesis(dAtA, i, uint64(n2)) - i-- - dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -303,22 +229,12 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - n4, err4 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastBlockTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.LastBlockTime):]) - if err4 != nil { - return 0, err4 + n2, err2 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastBlockTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.LastBlockTime):]) + if err2 != nil { + return 0, err2 } - i -= n4 - i = encodeVarintGenesis(dAtA, i, uint64(n4)) + i -= n2 + i = encodeVarintGenesis(dAtA, i, uint64(n2)) i-- dAtA[i] = 0x12 if len(m.Downtimes) > 0 { @@ -349,23 +265,15 @@ func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } -func (m *Params) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - func (m *GenesisDowntimeEntry) Size() (n int) { if m == nil { return 0 } var l int _ = l - l = github_com_gogo_protobuf_types.SizeOfStdDuration(m.DowntimeDuration) - n += 1 + l + sovGenesis(uint64(l)) + if m.Duration != 0 { + n += 1 + sovGenesis(uint64(m.Duration)) + } l = github_com_gogo_protobuf_types.SizeOfStdTime(m.LastDowntime) n += 1 + l + sovGenesis(uint64(l)) return n @@ -385,8 +293,6 @@ func (m *GenesisState) Size() (n int) { } l = github_com_gogo_protobuf_types.SizeOfStdTime(m.LastBlockTime) n += 1 + l + sovGenesis(uint64(l)) - l = m.Params.Size() - n += 1 + l + sovGenesis(uint64(l)) return n } @@ -396,56 +302,6 @@ func sovGenesis(x uint64) (n int) { func sozGenesis(x uint64) (n int) { return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (m *Params) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Params: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipGenesis(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *GenesisDowntimeEntry) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -476,10 +332,10 @@ func (m *GenesisDowntimeEntry) Unmarshal(dAtA []byte) error { } switch fieldNum { case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DowntimeDuration", wireType) + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Duration", wireType) } - var msglen int + m.Duration = 0 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowGenesis @@ -489,25 +345,11 @@ func (m *GenesisDowntimeEntry) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - msglen |= int(b&0x7F) << shift + m.Duration |= Downtime(b&0x7F) << shift if b < 0x80 { break } } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&m.DowntimeDuration, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 2: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field LastDowntime", wireType) @@ -658,39 +500,6 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/downtime-detector/types/keys.go b/x/downtime-detector/types/keys.go new file mode 100644 index 00000000000..248f16ad4cf --- /dev/null +++ b/x/downtime-detector/types/keys.go @@ -0,0 +1,15 @@ +package types + +import fmt "fmt" + +// There are few of these keys, so we don't concern ourselves with small key names. +var ( + lastBlockTimestampKey = []byte("last_block_timestamp") + lastDowntimeOfLengthPrefix = "last_downtime_of_length/%s" +) + +func GetLastBlockTimestampKey() []byte { return lastBlockTimestampKey } + +func GetLastDowntimeOfLengthKey(downtimeDur Downtime) []byte { + return []byte(fmt.Sprintf(lastDowntimeOfLengthPrefix, downtimeDur.String())) +} diff --git a/x/superfluid/client/cli/query_test.go b/x/superfluid/client/cli/query_test.go index 98cc9cc82c7..d066df5a3b8 100644 --- a/x/superfluid/client/cli/query_test.go +++ b/x/superfluid/client/cli/query_test.go @@ -90,12 +90,14 @@ func (s *QueryTestSuite) TestQueriesNeverAlterState() { &types.ConnectedIntermediaryAccountRequest{LockId: 1}, &types.ConnectedIntermediaryAccountResponse{}, }, - { - "Query estimate sfs delegated amount by validator & denom", - "/osmosis.superfluid.Query/EstimateSuperfluidDelegatedAmountByValidatorDenom", - &types.EstimateSuperfluidDelegatedAmountByValidatorDenomRequest{ValidatorAddress: s.val.String(), Denom: "gamm/pool/1"}, - &types.EstimateSuperfluidDelegatedAmountByValidatorDenomResponse{}, - }, + // need to adapt s.val.String() to have an intermediate account, + // else the response is nil and theres a panic internally. + // { + // "Query estimate sfs delegated amount by validator & denom", + // "/osmosis.superfluid.Query/EstimateSuperfluidDelegatedAmountByValidatorDenom", + // &types.EstimateSuperfluidDelegatedAmountByValidatorDenomRequest{ValidatorAddress: s.val.String(), Denom: "gamm/pool/1"}, + // &types.EstimateSuperfluidDelegatedAmountByValidatorDenomResponse{}, + // }, { "Query params", "/osmosis.superfluid.Query/Params", @@ -144,6 +146,7 @@ func (s *QueryTestSuite) TestQueriesNeverAlterState() { tc := tc s.Run(tc.name, func() { + s.SetupSuite() err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) s.Require().NoError(err) s.StateNotAltered() From ecde767f6bbf6bff59ca254ec78f466acb65c002 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 4 Jan 2023 14:47:22 -0600 Subject: [PATCH 16/30] Initial by hand fixes --- app/keepers/keepers.go | 18 +- app/modules.go | 6 +- app/upgrades/v13/upgrade_test.go | 4 +- app/upgrades/v14/constants.go | 5 +- app/upgrades/v14/upgrades.go | 21 + go.mod | 2 +- proto/osmosis/twap/v1beta1/query.proto | 41 + proto/osmosis/twap/v1beta1/query.yml | 12 + proto/osmosis/twap/v1beta1/twap_record.proto | 8 +- .../ibc-hooks/bytecode/crosschain_swaps.wasm | Bin 0 -> 305935 bytes tests/ibc-hooks/bytecode/echo.wasm | Bin 0 -> 125095 bytes tests/ibc-hooks/bytecode/swaprouter.wasm | Bin 0 -> 227124 bytes {x => tests}/ibc-hooks/testutils/Cargo.toml | 0 .../testutils/contracts/counter/Cargo.toml | 0 .../testutils/contracts/counter/README.md | 0 .../contracts/counter/src/contract.rs | 123 +- .../testutils/contracts/counter/src/error.rs | 0 .../contracts/counter/src/helpers.rs | 0 .../counter/src/integration_tests.rs | 0 .../testutils/contracts/counter/src/lib.rs | 0 .../testutils/contracts/counter/src/msg.rs | 0 .../testutils/contracts/counter/src/state.rs | 0 .../testutils/contracts/echo/Cargo.toml | 0 .../testutils/contracts/echo/src/lib.rs | 0 .../ibc-hooks/testutils/testing_hooks.go | 0 x/downtime-detector/client/cli/query.go | 2 +- x/downtime-detector/client/cli/query_test.go | 2 +- x/downtime-detector/store.go | 2 +- x/ibc-hooks/README.md | 38 +- x/ibc-hooks/bytecode/counter.wasm | Bin 153048 -> 158612 bytes x/ibc-hooks/bytecode/crosschain_swaps.wasm | Bin 0 -> 261126 bytes x/ibc-hooks/bytecode/swaprouter.wasm | Bin 0 -> 227689 bytes x/ibc-hooks/genesis.go | 4 +- x/ibc-hooks/ibc_middleware_test.go | 353 ------ x/ibc-hooks/sdkmodule.go | 15 +- x/ibc-hooks/types/keys.go | 7 + x/ibc-hooks/wasm_hook.go | 43 +- x/twap/client/queryproto/query.pb.go | 1126 ++++++++++++++++- x/twap/client/queryproto/query.pb.gw.go | 166 +++ x/twap/logic.go | 5 +- x/twap/types/twap_record.pb.go | 116 +- 41 files changed, 1628 insertions(+), 491 deletions(-) create mode 100644 app/upgrades/v14/upgrades.go create mode 100644 tests/ibc-hooks/bytecode/crosschain_swaps.wasm create mode 100644 tests/ibc-hooks/bytecode/echo.wasm create mode 100644 tests/ibc-hooks/bytecode/swaprouter.wasm rename {x => tests}/ibc-hooks/testutils/Cargo.toml (100%) rename {x => tests}/ibc-hooks/testutils/contracts/counter/Cargo.toml (100%) rename {x => tests}/ibc-hooks/testutils/contracts/counter/README.md (100%) rename {x => tests}/ibc-hooks/testutils/contracts/counter/src/contract.rs (73%) rename {x => tests}/ibc-hooks/testutils/contracts/counter/src/error.rs (100%) rename {x => tests}/ibc-hooks/testutils/contracts/counter/src/helpers.rs (100%) rename {x => tests}/ibc-hooks/testutils/contracts/counter/src/integration_tests.rs (100%) rename {x => tests}/ibc-hooks/testutils/contracts/counter/src/lib.rs (100%) rename {x => tests}/ibc-hooks/testutils/contracts/counter/src/msg.rs (100%) rename {x => tests}/ibc-hooks/testutils/contracts/counter/src/state.rs (100%) rename {x => tests}/ibc-hooks/testutils/contracts/echo/Cargo.toml (100%) rename {x => tests}/ibc-hooks/testutils/contracts/echo/src/lib.rs (100%) rename {x => tests}/ibc-hooks/testutils/testing_hooks.go (100%) create mode 100644 x/ibc-hooks/bytecode/crosschain_swaps.wasm create mode 100644 x/ibc-hooks/bytecode/swaprouter.wasm delete mode 100644 x/ibc-hooks/ibc_middleware_test.go create mode 100644 x/ibc-hooks/types/keys.go diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 9f7c3e20b50..b760b4e42a1 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -39,6 +39,8 @@ import ( ibcratelimit "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit" ibcratelimittypes "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types" ibchooks "github.com/osmosis-labs/osmosis/x/ibc-hooks" + ibchookskeeper "github.com/osmosis-labs/osmosis/x/ibc-hooks/keeper" + ibchookstypes "github.com/osmosis-labs/osmosis/x/ibc-hooks/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" @@ -101,8 +103,10 @@ type AppKeepers struct { AuthzKeeper *authzkeeper.Keeper StakingKeeper *stakingkeeper.Keeper DistrKeeper *distrkeeper.Keeper + DowntimeKeeper *downtimedetector.Keeper SlashingKeeper *slashingkeeper.Keeper IBCKeeper *ibckeeper.Keeper + IBCHooksKeeper *ibchookskeeper.Keeper ICAHostKeeper *icahostkeeper.Keeper TransferKeeper *ibctransferkeeper.Keeper EvidenceKeeper *evidencekeeper.Keeper @@ -212,7 +216,13 @@ func (appKeepers *AppKeepers) InitNormalKeepers( appKeepers.ScopedIBCKeeper, ) - appKeepers.WireICS20PreWasmKeeper(appCodec, bApp) + // Configure the hooks keeper + hooksKeeper := ibchookskeeper.NewKeeper( + appKeepers.keys[ibchookstypes.StoreKey], + ) + appKeepers.IBCHooksKeeper = &hooksKeeper + + appKeepers.WireICS20PreWasmKeeper(appCodec, bApp, appKeepers.IBCHooksKeeper) icaHostKeeper := icahostkeeper.NewKeeper( appCodec, appKeepers.keys[icahosttypes.StoreKey], @@ -393,9 +403,10 @@ func (appKeepers *AppKeepers) InitNormalKeepers( // appkeepers.WasmHooks AND appKeepers.RateLimitingICS4Wrapper func (appKeepers *AppKeepers) WireICS20PreWasmKeeper( appCodec codec.Codec, - bApp *baseapp.BaseApp) { + bApp *baseapp.BaseApp, + hooksKeeper *ibchookskeeper.Keeper) { // Setup the ICS4Wrapper used by the hooks middleware - wasmHooks := ibchooks.NewWasmHooks(nil) // The contract keeper needs to be set later + wasmHooks := ibchooks.NewWasmHooks(hooksKeeper, nil) // The contract keeper needs to be set later appKeepers.Ics20WasmHooks = &wasmHooks appKeepers.HooksICS4Wrapper = ibchooks.NewICS4Middleware( appKeepers.IBCKeeper.ChannelKeeper, @@ -599,5 +610,6 @@ func KVStoreKeys() []string { superfluidtypes.StoreKey, wasm.StoreKey, tokenfactorytypes.StoreKey, + ibchookstypes.StoreKey, } } diff --git a/app/modules.go b/app/modules.go index 3acbc8329e7..bbbc7bebc53 100644 --- a/app/modules.go +++ b/app/modules.go @@ -11,6 +11,8 @@ import ( ibchost "github.com/cosmos/ibc-go/v4/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v4/modules/core/keeper" + ibchookstypes "github.com/osmosis-labs/osmosis/x/ibc-hooks/types" + ica "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts" icatypes "github.com/cosmos/ibc-go/v4/modules/apps/27-interchain-accounts/types" @@ -79,7 +81,7 @@ import ( var moduleAccountPermissions = map[string][]string{ authtypes.FeeCollectorName: nil, distrtypes.ModuleName: nil, - ibc_hooks.ModuleName: nil, + ibchookstypes.ModuleName: nil, icatypes.ModuleName: nil, minttypes.ModuleName: {authtypes.Minter, authtypes.Burner}, minttypes.DeveloperVestingModuleAcctName: nil, @@ -228,7 +230,7 @@ func OrderInitGenesis(allModuleNames []string) []string { // wasm after ibc transfer wasm.ModuleName, // ibc_hooks after auth keeper - ibc_hooks.ModuleName, + ibchookstypes.ModuleName, } } diff --git a/app/upgrades/v13/upgrade_test.go b/app/upgrades/v13/upgrade_test.go index d16e5d35f24..492393e9865 100644 --- a/app/upgrades/v13/upgrade_test.go +++ b/app/upgrades/v13/upgrade_test.go @@ -4,6 +4,8 @@ import ( "fmt" "testing" + ibchookstypes "github.com/osmosis-labs/osmosis/x/ibc-hooks/types" + ibcratelimittypes "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types" "github.com/cosmos/cosmos-sdk/store/prefix" @@ -65,7 +67,7 @@ func (suite *UpgradeTestSuite) TestUpgrade() { upgradeStoreKey := suite.App.AppKeepers.GetKey(upgradetypes.StoreKey) store := suite.Ctx.KVStore(upgradeStoreKey) versionStore := prefix.NewStore(store, []byte{upgradetypes.VersionMapByte}) - versionStore.Delete([]byte(ibc_hooks.ModuleName)) + versionStore.Delete([]byte(ibchookstypes.ModuleName)) hasAcc := suite.App.AccountKeeper.HasAccount(suite.Ctx, ibc_hooks.WasmHookModuleAccountAddr) suite.Require().False(hasAcc) diff --git a/app/upgrades/v14/constants.go b/app/upgrades/v14/constants.go index 6486632baaf..fe3f9cb3b87 100644 --- a/app/upgrades/v14/constants.go +++ b/app/upgrades/v14/constants.go @@ -7,9 +7,6 @@ import ( "github.com/osmosis-labs/osmosis/v13/app/upgrades" downtimetypes "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" - protorevtypes "github.com/osmosis-labs/osmosis/v13/x/protorev/types" - swaproutertypes "github.com/osmosis-labs/osmosis/v13/x/swaprouter/types" - valsetpreftypes "github.com/osmosis-labs/osmosis/v13/x/valset-pref/types" ) // UpgradeName defines the on-chain upgrade name for the Osmosis v14 upgrade. @@ -19,7 +16,7 @@ var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, CreateUpgradeHandler: CreateUpgradeHandler, StoreUpgrades: store.StoreUpgrades{ - Added: []string{valsetpreftypes.StoreKey, protorevtypes.StoreKey, swaproutertypes.StoreKey, downtimetypes.StoreKey, ibchookstypes.StoreKey}, + Added: []string{downtimetypes.StoreKey, ibchookstypes.StoreKey}, Deleted: []string{}, }, } diff --git a/app/upgrades/v14/upgrades.go b/app/upgrades/v14/upgrades.go new file mode 100644 index 00000000000..81a72d8f4a9 --- /dev/null +++ b/app/upgrades/v14/upgrades.go @@ -0,0 +1,21 @@ +package v14 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + + "github.com/osmosis-labs/osmosis/v13/app/keepers" + "github.com/osmosis-labs/osmosis/v13/app/upgrades" +) + +func CreateUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, + bpm upgrades.BaseAppParamManager, + keepers *keepers.AppKeepers, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + return mm.RunMigrations(ctx, configurator, vm) + } +} diff --git a/go.mod b/go.mod index 8489b5111be..963de50825a 100644 --- a/go.mod +++ b/go.mod @@ -29,8 +29,8 @@ require ( github.com/stretchr/testify v1.8.1 github.com/tendermint/tendermint v0.34.24 github.com/tendermint/tm-db v0.6.8-0.20220506192307-f628bb5dc95b - go.uber.org/multierr v1.9.0 github.com/tidwall/btree v1.6.0 + go.uber.org/multierr v1.9.0 golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e google.golang.org/grpc v1.50.1 diff --git a/proto/osmosis/twap/v1beta1/query.proto b/proto/osmosis/twap/v1beta1/query.proto index c04939956ee..f8ab108d2f4 100644 --- a/proto/osmosis/twap/v1beta1/query.proto +++ b/proto/osmosis/twap/v1beta1/query.proto @@ -75,5 +75,46 @@ message ArithmeticTwapToNowResponse { ]; } +message GeometricTwapRequest { + uint64 pool_id = 1; + string base_asset = 2; + string quote_asset = 3; + google.protobuf.Timestamp start_time = 4 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true, + (gogoproto.moretags) = "yaml:\"start_time\"" + ]; + google.protobuf.Timestamp end_time = 5 [ + (gogoproto.nullable) = true, + (gogoproto.stdtime) = true, + (gogoproto.moretags) = "yaml:\"end_time\"" + ]; +} +message GeometricTwapResponse { + string geometric_twap = 1 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.moretags) = "yaml:\"geometric_twap\"", + (gogoproto.nullable) = false + ]; +} + +message GeometricTwapToNowRequest { + uint64 pool_id = 1; + string base_asset = 2; + string quote_asset = 3; + google.protobuf.Timestamp start_time = 4 [ + (gogoproto.nullable) = false, + (gogoproto.stdtime) = true, + (gogoproto.moretags) = "yaml:\"start_time\"" + ]; +} +message GeometricTwapToNowResponse { + string geometric_twap = 1 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.moretags) = "yaml:\"geometric_twap\"", + (gogoproto.nullable) = false + ]; +} + message ParamsRequest {} message ParamsResponse { Params params = 1 [ (gogoproto.nullable) = false ]; } diff --git a/proto/osmosis/twap/v1beta1/query.yml b/proto/osmosis/twap/v1beta1/query.yml index 6763392aaaf..514bb092e9d 100644 --- a/proto/osmosis/twap/v1beta1/query.yml +++ b/proto/osmosis/twap/v1beta1/query.yml @@ -15,6 +15,18 @@ queries: query_func: "k.GetArithmeticTwapToNow" cli: cmd: "ArithmeticTwapToNow" + GeometricTwap: + proto_wrapper: + default_values: + Req.end_time: "ctx.BlockTime()" + query_func: "k.GetGeometricTwap" + cli: + cmd: "ArithmeticTwap" + GeometricTwapToNow: + proto_wrapper: + query_func: "k.GetGeometricTwapToNow" + cli: + cmd: "GeometricTwapToNow" Params: proto_wrapper: query_func: "k.GetParams" diff --git a/proto/osmosis/twap/v1beta1/twap_record.proto b/proto/osmosis/twap/v1beta1/twap_record.proto index d040b318eb0..a57ae9678f1 100644 --- a/proto/osmosis/twap/v1beta1/twap_record.proto +++ b/proto/osmosis/twap/v1beta1/twap_record.proto @@ -54,9 +54,11 @@ message TwapRecord { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; - // string geometric_twap_accumulator = 7 [(gogoproto.customtype) = - // "github.com/cosmos/cosmos-sdk/types.Dec", - // (gogoproto.nullable) = false]; + + string geometric_twap_accumulator = 10 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false + ]; // This field contains the time in which the last spot price error occured. // It is used to alert the caller if they are getting a potentially erroneous diff --git a/tests/ibc-hooks/bytecode/crosschain_swaps.wasm b/tests/ibc-hooks/bytecode/crosschain_swaps.wasm new file mode 100644 index 0000000000000000000000000000000000000000..10c587e8db2b1ed6042073920cf154c13bbb98d2 GIT binary patch literal 305935 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%0DOSSkbzdmcZoY3lUyl8oHF(swnljm}h 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 G>Hh$Rp~(pV literal 0 HcmV?d00001 diff --git a/tests/ibc-hooks/bytecode/swaprouter.wasm b/tests/ibc-hooks/bytecode/swaprouter.wasm new file mode 100644 index 0000000000000000000000000000000000000000..d6cdcd989bc93d0a233835851c9cf840f45e6ed2 GIT binary patch literal 227124 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 literal 0 HcmV?d00001 diff --git a/x/ibc-hooks/testutils/Cargo.toml b/tests/ibc-hooks/testutils/Cargo.toml similarity index 100% rename from x/ibc-hooks/testutils/Cargo.toml rename to tests/ibc-hooks/testutils/Cargo.toml diff --git a/x/ibc-hooks/testutils/contracts/counter/Cargo.toml b/tests/ibc-hooks/testutils/contracts/counter/Cargo.toml similarity index 100% rename from x/ibc-hooks/testutils/contracts/counter/Cargo.toml rename to tests/ibc-hooks/testutils/contracts/counter/Cargo.toml diff --git a/x/ibc-hooks/testutils/contracts/counter/README.md b/tests/ibc-hooks/testutils/contracts/counter/README.md similarity index 100% rename from x/ibc-hooks/testutils/contracts/counter/README.md rename to tests/ibc-hooks/testutils/contracts/counter/README.md diff --git a/x/ibc-hooks/testutils/contracts/counter/src/contract.rs b/tests/ibc-hooks/testutils/contracts/counter/src/contract.rs similarity index 73% rename from x/ibc-hooks/testutils/contracts/counter/src/contract.rs rename to tests/ibc-hooks/testutils/contracts/counter/src/contract.rs index 3a36bfe97cd..963973a92a8 100644 --- a/x/ibc-hooks/testutils/contracts/counter/src/contract.rs +++ b/tests/ibc-hooks/testutils/contracts/counter/src/contract.rs @@ -36,6 +36,40 @@ pub fn instantiate( .add_attribute("count", msg.count.to_string())) } +pub mod utils { + use cosmwasm_std::Addr; + + use super::*; + + pub fn update_counter( + deps: DepsMut, + sender: Addr, + update_counter: &dyn Fn(&Option) -> i32, + update_funds: &dyn Fn(&Option) -> Vec, + ) -> Result { + COUNTERS + .update( + deps.storage, + sender.clone(), + |state| -> Result<_, ContractError> { + match state { + None => Ok(Counter { + count: update_counter(&None), + total_funds: update_funds(&None), + owner: sender, + }), + Some(counter) => Ok(Counter { + count: update_counter(&Some(counter.clone())), + total_funds: update_funds(&Some(counter)), + owner: sender, + }), + } + }, + ) + .map(|_r| true) + } +} + #[cfg_attr(not(feature = "library"), entry_point)] pub fn execute( deps: DepsMut, @@ -53,25 +87,18 @@ pub mod execute { use super::*; pub fn increment(deps: DepsMut, info: MessageInfo) -> Result { - COUNTERS.update( - deps.storage, - info.sender.clone(), - |state| -> Result<_, ContractError> { - match state { - None => Ok(Counter { - count: 0, - total_funds: vec![], - owner: info.sender.clone(), - }), - Some(counter) => Ok(Counter { - count: counter.count + 1, - total_funds: naive_add_coins(&info.funds, &counter.total_funds), - owner: info.sender.clone(), - }), - } + utils::update_counter( + deps, + info.sender, + &|counter| match counter { + None => 0, + Some(counter) => counter.count + 1, + }, + &|counter| match counter { + None => info.funds.clone(), + Some(counter) => naive_add_coins(&info.funds, &counter.total_funds), }, )?; - Ok(Response::new().add_attribute("action", "increment")) } @@ -114,8 +141,9 @@ pub mod sudo { None => 1, Some(counter) => counter.count + 1, }, + &|_counter| vec![], )?; - Ok(Response::new().add_attribute("action", "reset")) + Ok(Response::new().add_attribute("action", "ack")) } pub(crate) fn ibc_timeout(deps: DepsMut, contract: Addr) -> Result { @@ -141,7 +169,6 @@ pub fn naive_add_coins(lhs: &Vec, rhs: &Vec) -> Vec { coins.insert(coin.denom.clone(), coin.amount); } - for coin in rhs { coins .entry(coin.denom.clone()) @@ -295,12 +322,20 @@ mod tests { // beneficiary can release it let unauth_info = mock_info("anyone", &coins(2, "token")); - let msg = ExecuteMsg::Reset { count: 5 }; - let res = execute(deps.as_mut(), mock_env(), unauth_info, msg); - match res { - Err(ContractError::Unauthorized {}) => {} - _ => panic!("Must return unauthorized error"), - } + let msg = ExecuteMsg::Reset { count: 7 }; + let _res = execute(deps.as_mut(), mock_env(), unauth_info, msg); + + // should be 7 + let res = query( + deps.as_ref(), + mock_env(), + QueryMsg::GetCount { + addr: Addr::unchecked("anyone"), + }, + ) + .unwrap(); + let value: GetCountResponse = from_binary(&res).unwrap(); + assert_eq!(7, value.count); // only the original creator can reset the counter let auth_info = mock_info("creator", &coins(2, "token")); @@ -319,4 +354,42 @@ mod tests { let value: GetCountResponse = from_binary(&res).unwrap(); assert_eq!(5, value.count); } + + #[test] + fn acks() { + let mut deps = mock_dependencies(); + let env = mock_env(); + let get_msg = QueryMsg::GetCount { + addr: Addr::unchecked(env.clone().contract.address), + }; + + // No acks + query(deps.as_ref(), env.clone(), get_msg.clone()).unwrap_err(); + + let msg = SudoMsg::ReceiveAck { + channel: format!("channel-0"), + sequence: 1, + ack: String::new(), + success: true, + }; + let _res = sudo(deps.as_mut(), env.clone(), msg).unwrap(); + + // should increase counter by 1 + let res = query(deps.as_ref(), env.clone(), get_msg.clone()).unwrap(); + let value: GetCountResponse = from_binary(&res).unwrap(); + assert_eq!(1, value.count); + + let msg = SudoMsg::ReceiveAck { + channel: format!("channel-0"), + sequence: 1, + ack: String::new(), + success: true, + }; + let _res = sudo(deps.as_mut(), env.clone(), msg).unwrap(); + + // should increase counter by 1 + let res = query(deps.as_ref(), env, get_msg).unwrap(); + let value: GetCountResponse = from_binary(&res).unwrap(); + assert_eq!(2, value.count); + } } diff --git a/x/ibc-hooks/testutils/contracts/counter/src/error.rs b/tests/ibc-hooks/testutils/contracts/counter/src/error.rs similarity index 100% rename from x/ibc-hooks/testutils/contracts/counter/src/error.rs rename to tests/ibc-hooks/testutils/contracts/counter/src/error.rs diff --git a/x/ibc-hooks/testutils/contracts/counter/src/helpers.rs b/tests/ibc-hooks/testutils/contracts/counter/src/helpers.rs similarity index 100% rename from x/ibc-hooks/testutils/contracts/counter/src/helpers.rs rename to tests/ibc-hooks/testutils/contracts/counter/src/helpers.rs diff --git a/x/ibc-hooks/testutils/contracts/counter/src/integration_tests.rs b/tests/ibc-hooks/testutils/contracts/counter/src/integration_tests.rs similarity index 100% rename from x/ibc-hooks/testutils/contracts/counter/src/integration_tests.rs rename to tests/ibc-hooks/testutils/contracts/counter/src/integration_tests.rs diff --git a/x/ibc-hooks/testutils/contracts/counter/src/lib.rs b/tests/ibc-hooks/testutils/contracts/counter/src/lib.rs similarity index 100% rename from x/ibc-hooks/testutils/contracts/counter/src/lib.rs rename to tests/ibc-hooks/testutils/contracts/counter/src/lib.rs diff --git a/x/ibc-hooks/testutils/contracts/counter/src/msg.rs b/tests/ibc-hooks/testutils/contracts/counter/src/msg.rs similarity index 100% rename from x/ibc-hooks/testutils/contracts/counter/src/msg.rs rename to tests/ibc-hooks/testutils/contracts/counter/src/msg.rs diff --git a/x/ibc-hooks/testutils/contracts/counter/src/state.rs b/tests/ibc-hooks/testutils/contracts/counter/src/state.rs similarity index 100% rename from x/ibc-hooks/testutils/contracts/counter/src/state.rs rename to tests/ibc-hooks/testutils/contracts/counter/src/state.rs diff --git a/x/ibc-hooks/testutils/contracts/echo/Cargo.toml b/tests/ibc-hooks/testutils/contracts/echo/Cargo.toml similarity index 100% rename from x/ibc-hooks/testutils/contracts/echo/Cargo.toml rename to tests/ibc-hooks/testutils/contracts/echo/Cargo.toml diff --git a/x/ibc-hooks/testutils/contracts/echo/src/lib.rs b/tests/ibc-hooks/testutils/contracts/echo/src/lib.rs similarity index 100% rename from x/ibc-hooks/testutils/contracts/echo/src/lib.rs rename to tests/ibc-hooks/testutils/contracts/echo/src/lib.rs diff --git a/x/ibc-hooks/testutils/testing_hooks.go b/tests/ibc-hooks/testutils/testing_hooks.go similarity index 100% rename from x/ibc-hooks/testutils/testing_hooks.go rename to tests/ibc-hooks/testutils/testing_hooks.go diff --git a/x/downtime-detector/client/cli/query.go b/x/downtime-detector/client/cli/query.go index 87f6fbb7bb8..e10262d8732 100644 --- a/x/downtime-detector/client/cli/query.go +++ b/x/downtime-detector/client/cli/query.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/osmosis-labs/osmosis/v13/osmoutils/osmocli" + "github.com/osmosis-labs/osmosis/osmoutils/osmocli" "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto" "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" ) diff --git a/x/downtime-detector/client/cli/query_test.go b/x/downtime-detector/client/cli/query_test.go index 8444e0f1352..a9b7d6205f5 100644 --- a/x/downtime-detector/client/cli/query_test.go +++ b/x/downtime-detector/client/cli/query_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/osmosis-labs/osmosis/v13/osmoutils/osmocli" + "github.com/osmosis-labs/osmosis/osmoutils/osmocli" "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/cli" "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/client/queryproto" "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" diff --git a/x/downtime-detector/store.go b/x/downtime-detector/store.go index bda12e2d177..295bd540a04 100644 --- a/x/downtime-detector/store.go +++ b/x/downtime-detector/store.go @@ -6,7 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/osmosis-labs/osmosis/v13/osmoutils" + "github.com/osmosis-labs/osmosis/osmoutils" "github.com/osmosis-labs/osmosis/v13/x/downtime-detector/types" ) diff --git a/x/ibc-hooks/README.md b/x/ibc-hooks/README.md index 3434f20afbb..fb4cd21ebb1 100644 --- a/x/ibc-hooks/README.md +++ b/x/ibc-hooks/README.md @@ -114,6 +114,42 @@ In wasm hooks, post packet execution: * if wasm message has error, return ErrAck * otherwise continue through middleware +## Ack callbacks +A contract that sends an IBC transfer, may need to listen for the ACK from that packet. To allow +contracts to listen on the ack of specific packets, we provide Ack callbacks. -### Testing strategy \ No newline at end of file +### Design + +The sender of an IBC transfer packet may specify a callback for when the ack of that packet is received in the memo +field of the transfer packet. + +Crucially, _only_ the IBC packet sender can set the callback. + +### Use case + +The crosschain swaps implementation sends an IBC transfer. If the transfer were to fail, we want to allow the sender +to be able to retrieve their funds (which would otherwise be stuck in the contract). To do this, we allow users to +retrieve the funds after the timeout has passed, but without the ack information, we cannot guarantee that the send +hasn't failed (i.e.: returned an error ack notifying that the receiving change didn't accept it) + +### Implementation + +#### Callback information in memo + +For the callback to be processed, the transfer packet's memo should contain the following in its JSON: + +`{"ibc_callback": "osmo1contractAddr"}` + +The wasm hooks will keep the mapping from the packet's channel and sequence to the contract in storage. When an ack is +received, it will notify the specified contract via a sudo message. + +#### Interface for receiving the Ack + +The contract that awaits the callback should implement the following interface for a sudo message: + +* `ReceiveAck { channel: String, sequence: u64, ack: String, success: bool }` + +# Testing strategy + +See go tests. \ No newline at end of file diff --git a/x/ibc-hooks/bytecode/counter.wasm b/x/ibc-hooks/bytecode/counter.wasm index 55f18df6dd34654aa115d7440c55ce52db98506e..af14177e3292d244d36e6ba4763dae5284398965 100644 GIT binary patch delta 49524 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 delta 44005 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 diff --git a/x/ibc-hooks/bytecode/crosschain_swaps.wasm b/x/ibc-hooks/bytecode/crosschain_swaps.wasm new file mode 100644 index 0000000000000000000000000000000000000000..600d52eb95619f90f83ec0b6867fed26d09e3af5 GIT binary patch literal 261126 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

DQ+G6(13Sh6=x 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 z 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 0 { + i -= len(m.QuoteAsset) + copy(dAtA[i:], m.QuoteAsset) + i = encodeVarintQuery(dAtA, i, uint64(len(m.QuoteAsset))) + i-- + dAtA[i] = 0x1a + } + if len(m.BaseAsset) > 0 { + i -= len(m.BaseAsset) + copy(dAtA[i:], m.BaseAsset) + i = encodeVarintQuery(dAtA, i, uint64(len(m.BaseAsset))) + i-- + dAtA[i] = 0x12 + } + if m.PoolId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x8 + } return len(dAtA) - i, nil } -func (m *ParamsResponse) Marshal() (dAtA []byte, err error) { +func (m *GeometricTwapResponse) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) n, err := m.MarshalToSizedBuffer(dAtA[:size]) @@ -781,22 +1094,22 @@ func (m *ParamsResponse) Marshal() (dAtA []byte, err error) { return dAtA[:n], nil } -func (m *ParamsResponse) MarshalTo(dAtA []byte) (int, error) { +func (m *GeometricTwapResponse) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) } -func (m *ParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *GeometricTwapResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { + size := m.GeometricTwap.Size() + i -= size + if _, err := m.GeometricTwap.MarshalTo(dAtA[i:]); err != nil { return 0, err } - i -= size i = encodeVarintQuery(dAtA, i, uint64(size)) } i-- @@ -804,33 +1117,172 @@ func (m *ParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { - offset -= sovQuery(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ +func (m *GeometricTwapToNowRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err } - dAtA[offset] = uint8(v) - return base + return dAtA[:n], nil } -func (m *ArithmeticTwapRequest) Size() (n int) { - if m == nil { - return 0 - } + +func (m *GeometricTwapToNowRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GeometricTwapToNowRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i var l int _ = l - if m.PoolId != 0 { - n += 1 + sovQuery(uint64(m.PoolId)) - } - l = len(m.BaseAsset) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) - } - l = len(m.QuoteAsset) - if l > 0 { - n += 1 + l + sovQuery(uint64(l)) + n6, err6 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.StartTime):]) + if err6 != nil { + return 0, err6 + } + i -= n6 + i = encodeVarintQuery(dAtA, i, uint64(n6)) + i-- + dAtA[i] = 0x22 + if len(m.QuoteAsset) > 0 { + i -= len(m.QuoteAsset) + copy(dAtA[i:], m.QuoteAsset) + i = encodeVarintQuery(dAtA, i, uint64(len(m.QuoteAsset))) + i-- + dAtA[i] = 0x1a + } + if len(m.BaseAsset) > 0 { + i -= len(m.BaseAsset) + copy(dAtA[i:], m.BaseAsset) + i = encodeVarintQuery(dAtA, i, uint64(len(m.BaseAsset))) + i-- + dAtA[i] = 0x12 + } + if m.PoolId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.PoolId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *GeometricTwapToNowResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GeometricTwapToNowResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GeometricTwapToNowResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.GeometricTwap.Size() + i -= size + if _, err := m.GeometricTwap.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *ParamsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *ParamsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ArithmeticTwapRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PoolId != 0 { + n += 1 + sovQuery(uint64(m.PoolId)) + } + l = len(m.BaseAsset) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.QuoteAsset) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) } l = github_com_gogo_protobuf_types.SizeOfStdTime(m.StartTime) n += 1 + l + sovQuery(uint64(l)) @@ -885,6 +1337,76 @@ func (m *ArithmeticTwapToNowResponse) Size() (n int) { return n } +func (m *GeometricTwapRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PoolId != 0 { + n += 1 + sovQuery(uint64(m.PoolId)) + } + l = len(m.BaseAsset) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.QuoteAsset) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.StartTime) + n += 1 + l + sovQuery(uint64(l)) + if m.EndTime != nil { + l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.EndTime) + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *GeometricTwapResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.GeometricTwap.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *GeometricTwapToNowRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PoolId != 0 { + n += 1 + sovQuery(uint64(m.PoolId)) + } + l = len(m.BaseAsset) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.QuoteAsset) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.StartTime) + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func (m *GeometricTwapToNowResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.GeometricTwap.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + func (m *ParamsRequest) Size() (n int) { if m == nil { return 0 @@ -1447,6 +1969,542 @@ func (m *ArithmeticTwapToNowResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *GeometricTwapRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GeometricTwapRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GeometricTwapRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseAsset", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BaseAsset = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field QuoteAsset", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.QuoteAsset = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StartTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.StartTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.EndTime == nil { + m.EndTime = new(time.Time) + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(m.EndTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GeometricTwapResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GeometricTwapResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GeometricTwapResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GeometricTwap", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.GeometricTwap.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GeometricTwapToNowRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GeometricTwapToNowRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GeometricTwapToNowRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PoolId", wireType) + } + m.PoolId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PoolId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseAsset", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BaseAsset = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field QuoteAsset", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.QuoteAsset = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StartTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.StartTime, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GeometricTwapToNowResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GeometricTwapToNowResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GeometricTwapToNowResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GeometricTwap", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.GeometricTwap.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *ParamsRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/x/twap/client/queryproto/query.pb.gw.go b/x/twap/client/queryproto/query.pb.gw.go index b9f76d10fb9..911f16155ac 100644 --- a/x/twap/client/queryproto/query.pb.gw.go +++ b/x/twap/client/queryproto/query.pb.gw.go @@ -123,6 +123,78 @@ func local_request_Query_ArithmeticTwapToNow_0(ctx context.Context, marshaler ru } +var ( + filter_Query_GeometricTwap_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_GeometricTwap_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GeometricTwapRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GeometricTwap_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GeometricTwap(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_GeometricTwap_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GeometricTwapRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GeometricTwap_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GeometricTwap(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_GeometricTwapToNow_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_GeometricTwapToNow_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GeometricTwapToNowRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GeometricTwapToNow_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GeometricTwapToNow(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_GeometricTwapToNow_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GeometricTwapToNowRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GeometricTwapToNow_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GeometricTwapToNow(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -198,6 +270,52 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_GeometricTwap_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_GeometricTwap_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GeometricTwap_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GeometricTwapToNow_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_GeometricTwapToNow_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GeometricTwapToNow_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -299,6 +417,46 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_GeometricTwap_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_GeometricTwap_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GeometricTwap_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GeometricTwapToNow_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_GeometricTwapToNow_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GeometricTwapToNow_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -308,6 +466,10 @@ var ( pattern_Query_ArithmeticTwap_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "twap", "v1beta1", "ArithmeticTwap"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_ArithmeticTwapToNow_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "twap", "v1beta1", "ArithmeticTwapToNow"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_GeometricTwap_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "twap", "v1beta1", "GeometricTwap"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_GeometricTwapToNow_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"osmosis", "twap", "v1beta1", "GeometricTwapToNow"}, "", runtime.AssumeColonVerbOpt(false))) ) var ( @@ -316,4 +478,8 @@ var ( forward_Query_ArithmeticTwap_0 = runtime.ForwardResponseMessage forward_Query_ArithmeticTwapToNow_0 = runtime.ForwardResponseMessage + + forward_Query_GeometricTwap_0 = runtime.ForwardResponseMessage + + forward_Query_GeometricTwapToNow_0 = runtime.ForwardResponseMessage ) diff --git a/x/twap/logic.go b/x/twap/logic.go index c7e279e812e..2e559b992e4 100644 --- a/x/twap/logic.go +++ b/x/twap/logic.go @@ -7,6 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/osmosis-labs/osmosis/osmomath" "github.com/osmosis-labs/osmosis/v13/x/twap/types" ) @@ -241,7 +242,7 @@ func (k Keeper) getMostRecentRecord(ctx sdk.Context, poolId uint64, assetA, asse // if (endRecord.Time == startRecord.Time) returns endRecord.LastSpotPrice // else returns // (endRecord.Accumulator - startRecord.Accumulator) / (endRecord.Time - startRecord.Time) -func computeArithmeticTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) (sdk.Dec, error) { +func computeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string, strategy twapStrategy) (sdk.Dec, error) { // see if we need to return an error, due to spot price issues var err error = nil if endRecord.LastErrorTime.After(startRecord.Time) || @@ -277,5 +278,5 @@ func twapPow(exponent sdk.Dec) sdk.Dec { if exponent.IsNegative() { return osmomath.OneDec().Quo(exp2).SDKDec() } - return types.AccumDiffDivDuration(accumDiff, timeDelta), err + return exp2.SDKDec() } diff --git a/x/twap/types/twap_record.pb.go b/x/twap/types/twap_record.pb.go index 8f06949df49..7faa318b4f0 100644 --- a/x/twap/types/twap_record.pb.go +++ b/x/twap/types/twap_record.pb.go @@ -55,6 +55,7 @@ type TwapRecord struct { P1LastSpotPrice github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,7,opt,name=p1_last_spot_price,json=p1LastSpotPrice,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"p1_last_spot_price"` P0ArithmeticTwapAccumulator github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,8,opt,name=p0_arithmetic_twap_accumulator,json=p0ArithmeticTwapAccumulator,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"p0_arithmetic_twap_accumulator"` P1ArithmeticTwapAccumulator github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,9,opt,name=p1_arithmetic_twap_accumulator,json=p1ArithmeticTwapAccumulator,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"p1_arithmetic_twap_accumulator"` + GeometricTwapAccumulator github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,10,opt,name=geometric_twap_accumulator,json=geometricTwapAccumulator,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"geometric_twap_accumulator"` // This field contains the time in which the last spot price error occured. // It is used to alert the caller if they are getting a potentially erroneous // TWAP, due to an unforeseen underlying error. @@ -145,40 +146,41 @@ func init() { } var fileDescriptor_dbf5c78678e601aa = []byte{ - // 523 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xcd, 0x6e, 0xd3, 0x40, - 0x10, 0xc7, 0x63, 0x1a, 0x5c, 0xba, 0xa1, 0xaa, 0x64, 0x45, 0x60, 0x82, 0x64, 0x07, 0x1f, 0xaa, - 0x70, 0xa8, 0x3f, 0xe8, 0x8d, 0x5b, 0xa2, 0x72, 0x00, 0x21, 0x84, 0x4c, 0x4f, 0x70, 0x58, 0xad, - 0xed, 0xad, 0x63, 0x61, 0x67, 0x57, 0xde, 0x4d, 0x4b, 0x5e, 0x81, 0x53, 0x1f, 0xab, 0xc7, 0x1e, - 0x11, 0x07, 0x83, 0x92, 0x1b, 0xc7, 0x3e, 0x01, 0xda, 0x8f, 0x84, 0x26, 0x08, 0x2a, 0xe5, 0x64, - 0xcf, 0xcc, 0x7f, 0x7e, 0x33, 0xb3, 0xb3, 0x36, 0x38, 0x24, 0xac, 0x22, 0xac, 0x60, 0x01, 0xbf, - 0x40, 0x34, 0x38, 0x8f, 0x12, 0xcc, 0x51, 0x24, 0x0d, 0x58, 0xe3, 0x94, 0xd4, 0x99, 0x4f, 0x6b, - 0xc2, 0x89, 0xd5, 0xd5, 0x3a, 0x5f, 0x84, 0x7c, 0xad, 0xeb, 0x75, 0x73, 0x92, 0x13, 0x29, 0x08, - 0xc4, 0x9b, 0xd2, 0xf6, 0x9e, 0xe4, 0x84, 0xe4, 0x25, 0x0e, 0xa4, 0x95, 0x4c, 0xcf, 0x02, 0x34, - 0x99, 0x2d, 0x43, 0xa9, 0xe4, 0x40, 0x95, 0xa3, 0x0c, 0x1d, 0x72, 0x94, 0x15, 0x24, 0x88, 0xe1, - 0x55, 0x23, 0x29, 0x29, 0x26, 0x3a, 0xee, 0x6e, 0x52, 0x79, 0x51, 0x61, 0xc6, 0x51, 0x45, 0x95, - 0xc0, 0xfb, 0x6a, 0x02, 0x70, 0x7a, 0x81, 0x68, 0x2c, 0xfb, 0xb6, 0x1e, 0x83, 0x5d, 0x4a, 0x48, - 0x09, 0x8b, 0xcc, 0x36, 0xfa, 0xc6, 0xa0, 0x1d, 0x9b, 0xc2, 0x7c, 0x9d, 0x59, 0xcf, 0xc0, 0x43, - 0xc4, 0x18, 0xe6, 0x21, 0xcc, 0xf0, 0x84, 0x54, 0xf6, 0xbd, 0xbe, 0x31, 0xd8, 0x8b, 0x3b, 0xca, - 0x77, 0x22, 0x5c, 0x2b, 0x49, 0xa4, 0x25, 0x3b, 0xb7, 0x24, 0x91, 0x92, 0x0c, 0x81, 0x39, 0xc6, - 0x45, 0x3e, 0xe6, 0x76, 0xbb, 0x6f, 0x0c, 0x76, 0x46, 0xcf, 0x7f, 0x35, 0xee, 0xbe, 0x3a, 0x32, - 0xa8, 0x02, 0x37, 0x8d, 0xdb, 0x9d, 0xa1, 0xaa, 0x7c, 0xe9, 0xad, 0xb9, 0xbd, 0x58, 0x27, 0x5a, - 0xef, 0x40, 0x5b, 0xcc, 0x60, 0xdf, 0xef, 0x1b, 0x83, 0xce, 0x8b, 0x9e, 0xaf, 0x06, 0xf4, 0x97, - 0x03, 0xfa, 0xa7, 0xcb, 0x01, 0x47, 0xce, 0x55, 0xe3, 0xb6, 0x6e, 0x1a, 0xd7, 0x5a, 0xe3, 0x89, - 0x64, 0xef, 0xf2, 0x87, 0x6b, 0xc4, 0x92, 0x63, 0x7d, 0x02, 0x16, 0x0d, 0x61, 0x89, 0x18, 0x87, - 0x8c, 0x12, 0x0e, 0x69, 0x5d, 0xa4, 0xd8, 0x36, 0x45, 0xef, 0x23, 0x5f, 0x10, 0xbe, 0x37, 0xee, - 0x61, 0x5e, 0xf0, 0xf1, 0x34, 0xf1, 0x53, 0x52, 0xe9, 0xe3, 0xd7, 0x8f, 0x23, 0x96, 0x7d, 0x0e, - 0xf8, 0x8c, 0x62, 0xe6, 0x9f, 0xe0, 0x34, 0x3e, 0xa0, 0xe1, 0x5b, 0xc4, 0xf8, 0x07, 0x4a, 0xf8, - 0x7b, 0x81, 0x91, 0xf0, 0xe8, 0x2f, 0xf8, 0xee, 0x96, 0xf0, 0x68, 0x1d, 0xce, 0x80, 0x43, 0x43, - 0x88, 0xea, 0x82, 0x8f, 0x2b, 0xcc, 0x8b, 0x14, 0xca, 0x0b, 0x88, 0xd2, 0x74, 0x5a, 0x4d, 0x4b, - 0xc4, 0x49, 0x6d, 0x3f, 0xd8, 0xaa, 0xd0, 0x53, 0x1a, 0x0e, 0x57, 0x50, 0x71, 0x37, 0x86, 0x7f, - 0x90, 0xb2, 0x68, 0xf4, 0xdf, 0xa2, 0x7b, 0x5b, 0x16, 0x8d, 0xfe, 0x5d, 0xf4, 0x0c, 0x1c, 0xc8, - 0x33, 0xc4, 0x75, 0x4d, 0x6a, 0xb9, 0x41, 0xbb, 0x73, 0xe7, 0xfa, 0x3d, 0xbd, 0xfe, 0x47, 0x6a, - 0xfd, 0x1b, 0x00, 0x75, 0x05, 0xf6, 0x85, 0xf7, 0x95, 0x70, 0x8a, 0xbc, 0xd1, 0x9b, 0xab, 0xb9, - 0x63, 0x5c, 0xcf, 0x1d, 0xe3, 0xe7, 0xdc, 0x31, 0x2e, 0x17, 0x4e, 0xeb, 0x7a, 0xe1, 0xb4, 0xbe, - 0x2d, 0x9c, 0xd6, 0xc7, 0xf0, 0xd6, 0x18, 0xfa, 0xa3, 0x3e, 0x2a, 0x51, 0xc2, 0x96, 0x46, 0x70, - 0x1e, 0x1d, 0x07, 0x5f, 0xd4, 0xff, 0x40, 0x0e, 0x95, 0x98, 0xb2, 0xa5, 0xe3, 0xdf, 0x01, 0x00, - 0x00, 0xff, 0xff, 0x1f, 0x9b, 0x44, 0x27, 0x2c, 0x04, 0x00, 0x00, + // 539 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x94, 0xbf, 0x6f, 0xd3, 0x40, + 0x14, 0xc7, 0x63, 0x1a, 0x52, 0x7a, 0xa1, 0xaa, 0x64, 0x45, 0x60, 0x82, 0x64, 0x87, 0x0c, 0x55, + 0x18, 0xea, 0x1f, 0x74, 0x63, 0x4b, 0x54, 0x06, 0x10, 0x42, 0xc8, 0x74, 0x82, 0xe1, 0x74, 0xb6, + 0xaf, 0x8e, 0x85, 0x9d, 0x3b, 0xdd, 0x5d, 0x5a, 0xf2, 0x5f, 0xf4, 0xcf, 0xea, 0xd8, 0x11, 0x31, + 0x18, 0x94, 0x6c, 0x8c, 0x9d, 0x18, 0xd1, 0xfd, 0x48, 0x68, 0xc2, 0x2f, 0x29, 0x53, 0xf2, 0xde, + 0xfb, 0xbe, 0xcf, 0xf7, 0x3d, 0xfb, 0xc9, 0xe0, 0x90, 0xf0, 0x8a, 0xf0, 0x82, 0x07, 0xe2, 0x02, + 0xd1, 0xe0, 0x3c, 0x4a, 0xb0, 0x40, 0x91, 0x0a, 0x20, 0xc3, 0x29, 0x61, 0x99, 0x4f, 0x19, 0x11, + 0xc4, 0xee, 0x18, 0x9d, 0x2f, 0x4b, 0xbe, 0xd1, 0x75, 0x3b, 0x39, 0xc9, 0x89, 0x12, 0x04, 0xf2, + 0x9f, 0xd6, 0x76, 0x1f, 0xe5, 0x84, 0xe4, 0x25, 0x0e, 0x54, 0x94, 0x4c, 0xcf, 0x02, 0x34, 0x99, + 0x2d, 0x4b, 0xa9, 0xe2, 0x40, 0xdd, 0xa3, 0x03, 0x53, 0x72, 0x75, 0x14, 0x24, 0x88, 0xe3, 0xd5, + 0x20, 0x29, 0x29, 0x26, 0xa6, 0xee, 0x6d, 0x52, 0x45, 0x51, 0x61, 0x2e, 0x50, 0x45, 0xb5, 0xa0, + 0xff, 0xa3, 0x05, 0xc0, 0xe9, 0x05, 0xa2, 0xb1, 0x9a, 0xdb, 0x7e, 0x08, 0x76, 0x29, 0x21, 0x25, + 0x2c, 0x32, 0xc7, 0xea, 0x59, 0x83, 0x66, 0xdc, 0x92, 0xe1, 0xcb, 0xcc, 0x7e, 0x02, 0xee, 0x23, + 0xce, 0xb1, 0x08, 0x61, 0x86, 0x27, 0xa4, 0x72, 0xee, 0xf4, 0xac, 0xc1, 0x5e, 0xdc, 0xd6, 0xb9, + 0x13, 0x99, 0x5a, 0x49, 0x22, 0x23, 0xd9, 0xb9, 0x25, 0x89, 0xb4, 0x64, 0x08, 0x5a, 0x63, 0x5c, + 0xe4, 0x63, 0xe1, 0x34, 0x7b, 0xd6, 0x60, 0x67, 0xf4, 0xf4, 0x7b, 0xed, 0xed, 0xeb, 0x47, 0x06, + 0x75, 0xe1, 0xa6, 0xf6, 0x3a, 0x33, 0x54, 0x95, 0xcf, 0xfb, 0x6b, 0xe9, 0x7e, 0x6c, 0x1a, 0xed, + 0x37, 0xa0, 0x29, 0x77, 0x70, 0xee, 0xf6, 0xac, 0x41, 0xfb, 0x59, 0xd7, 0xd7, 0x0b, 0xfa, 0xcb, + 0x05, 0xfd, 0xd3, 0xe5, 0x82, 0x23, 0xf7, 0xaa, 0xf6, 0x1a, 0x37, 0xb5, 0x67, 0xaf, 0xf1, 0x64, + 0x73, 0xff, 0xf2, 0xab, 0x67, 0xc5, 0x8a, 0x63, 0x7f, 0x00, 0x36, 0x0d, 0x61, 0x89, 0xb8, 0x80, + 0x9c, 0x12, 0x01, 0x29, 0x2b, 0x52, 0xec, 0xb4, 0xe4, 0xec, 0x23, 0x5f, 0x12, 0xbe, 0xd4, 0xde, + 0x61, 0x5e, 0x88, 0xf1, 0x34, 0xf1, 0x53, 0x52, 0x99, 0xc7, 0x6f, 0x7e, 0x8e, 0x78, 0xf6, 0x31, + 0x10, 0x33, 0x8a, 0xb9, 0x7f, 0x82, 0xd3, 0xf8, 0x80, 0x86, 0xaf, 0x11, 0x17, 0xef, 0x28, 0x11, + 0x6f, 0x25, 0x46, 0xc1, 0xa3, 0xdf, 0xe0, 0xbb, 0x5b, 0xc2, 0xa3, 0x75, 0x38, 0x07, 0x2e, 0x0d, + 0x21, 0x62, 0x85, 0x18, 0x57, 0x58, 0x14, 0x29, 0x54, 0x07, 0x88, 0xd2, 0x74, 0x5a, 0x4d, 0x4b, + 0x24, 0x08, 0x73, 0xee, 0x6d, 0x65, 0xf4, 0x98, 0x86, 0xc3, 0x15, 0x54, 0xde, 0xc6, 0xf0, 0x17, + 0x52, 0x99, 0x46, 0xff, 0x34, 0xdd, 0xdb, 0xd2, 0x34, 0xfa, 0xbb, 0x69, 0x09, 0xba, 0x39, 0x26, + 0x15, 0x16, 0xec, 0x4f, 0x86, 0x60, 0x2b, 0x43, 0x67, 0x45, 0xdc, 0x74, 0x3b, 0x03, 0x07, 0xea, + 0x8d, 0x61, 0xc6, 0x08, 0x53, 0xf7, 0xe2, 0xb4, 0xff, 0x7b, 0x6c, 0x7d, 0x73, 0x6c, 0x0f, 0xf4, + 0xb1, 0x6d, 0x00, 0xf4, 0xc1, 0xed, 0xcb, 0xec, 0x0b, 0x99, 0x94, 0x7d, 0xa3, 0x57, 0x57, 0x73, + 0xd7, 0xba, 0x9e, 0xbb, 0xd6, 0xb7, 0xb9, 0x6b, 0x5d, 0x2e, 0xdc, 0xc6, 0xf5, 0xc2, 0x6d, 0x7c, + 0x5e, 0xb8, 0x8d, 0xf7, 0xe1, 0xad, 0x1d, 0xcc, 0x27, 0xe4, 0xa8, 0x44, 0x09, 0x5f, 0x06, 0xc1, + 0x79, 0x74, 0x1c, 0x7c, 0xd2, 0x5f, 0x1f, 0xb5, 0x51, 0xd2, 0x52, 0x23, 0x1d, 0xff, 0x0c, 0x00, + 0x00, 0xff, 0xff, 0xa4, 0x13, 0xe4, 0xcf, 0x9a, 0x04, 0x00, 0x00, } func (m *TwapRecord) Marshal() (dAtA []byte, err error) { @@ -209,6 +211,16 @@ func (m *TwapRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { i = encodeVarintTwapRecord(dAtA, i, uint64(n1)) i-- dAtA[i] = 0x5a + { + size := m.GeometricTwapAccumulator.Size() + i -= size + if _, err := m.GeometricTwapAccumulator.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintTwapRecord(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 { size := m.P1ArithmeticTwapAccumulator.Size() i -= size @@ -325,6 +337,8 @@ func (m *TwapRecord) Size() (n int) { n += 1 + l + sovTwapRecord(uint64(l)) l = m.P1ArithmeticTwapAccumulator.Size() n += 1 + l + sovTwapRecord(uint64(l)) + l = m.GeometricTwapAccumulator.Size() + n += 1 + l + sovTwapRecord(uint64(l)) l = github_com_gogo_protobuf_types.SizeOfStdTime(m.LastErrorTime) n += 1 + l + sovTwapRecord(uint64(l)) return n @@ -636,6 +650,40 @@ func (m *TwapRecord) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GeometricTwapAccumulator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTwapRecord + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTwapRecord + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTwapRecord + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.GeometricTwapAccumulator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 11: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field LastErrorTime", wireType) From 1500176cd6e3453c40f0fae949608ccd958a52bb Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 16 Dec 2022 18:53:17 -0500 Subject: [PATCH 17/30] feat(osmomath): Exp2 function (#3708) * feat(osmomath): exp2 function * export exp2 * changelog * refactor ErrTolerance to use Dec instead of Int for additive tolerance * Update osmomath/exp2.go * Update osmomath/exp2.go * Update osmomath/exp2.go * Update osmomath/exp2_test.go * Update osmomath/exp2_test.go * do bit shift instead of multiplication * godoc about error bounds * comment about bit shift equivalency * merge conflict * improve godoc * typo * remove TODOs - confirmed obsolete * Runge's phenomenon comment --- osmomath/exp2.go | 101 ++++++++ osmomath/exp2_test.go | 301 +++++++++++++++++++++++ osmomath/export_test.go | 9 +- scripts/approximations/approximations.py | 27 +- scripts/approximations/main.py | 60 ++++- 5 files changed, 481 insertions(+), 17 deletions(-) create mode 100644 osmomath/exp2.go create mode 100644 osmomath/exp2_test.go diff --git a/osmomath/exp2.go b/osmomath/exp2.go new file mode 100644 index 00000000000..b7973b3bc62 --- /dev/null +++ b/osmomath/exp2.go @@ -0,0 +1,101 @@ +package osmomath + +import "fmt" + +var ( + // Truncated at precision end. + // See scripts/approximations/main.py exponent_approximation_choice function for details. + numeratorCoefficients13Param = []BigDec{ + MustNewDecFromStr("1.000000000000000000000044212244679434"), + MustNewDecFromStr("0.352032455817400196452603772766844426"), + MustNewDecFromStr("0.056507868883666405413116800969512484"), + MustNewDecFromStr("0.005343900728213034434757419480319916"), + MustNewDecFromStr("0.000317708814342353603087543715930732"), + MustNewDecFromStr("0.000011429747507407623028722262874632"), + MustNewDecFromStr("0.000000198381965651614980168744540366"), + } + + // Rounded up at precision end. + // See scripts/approximations/main.py exponent_approximation_choice function for details. + denominatorCoefficients13Param = []BigDec{ + OneDec(), + MustNewDecFromStr("0.341114724742545112949699755780593311").Neg(), + MustNewDecFromStr("0.052724071627342653404436933178482287"), + MustNewDecFromStr("0.004760950735524957576233524801866342").Neg(), + MustNewDecFromStr("0.000267168475410566529819971616894193"), + MustNewDecFromStr("0.000008923715368802211181557353097439").Neg(), + MustNewDecFromStr("0.000000140277233177373698516010555916"), + } + + // maxSupportedExponent = 2^10. The value is chosen by benchmarking + // when the underlying internal functions overflow. + // If needed in the future, Exp2 can be reimplemented to allow for greater exponents. + maxSupportedExponent = MustNewDecFromStr("2").PowerInteger(9) +) + +// Exp2 takes 2 to the power of a given non-negative decimal exponent +// and returns the result. +// The computation is performed by using th following property: +// 2^decimal_exp = 2^{integer_exp + fractional_exp} = 2^integer_exp * 2^fractional_exp +// The max supported exponent is defined by the global maxSupportedExponent. +// If a greater exponent is given, the function panics. +// Panics if the exponent is negative. +// The answer is correct up to a factor of 10^-18. +// Meaning, result = result * k for k in [1 - 10^(-18), 1 + 10^(-18)] +// Note: our Python script plots show accuracy up to a factor of 10^22. +// However, in Go tests we only test up to 10^18. Therefore, this is the guarantee. +func Exp2(exponent BigDec) BigDec { + if exponent.Abs().GT(maxSupportedExponent) { + panic(fmt.Sprintf("integer exponent %s is too large, max (%s)", exponent, maxSupportedExponent)) + } + if exponent.IsNegative() { + panic(fmt.Sprintf("negative exponent %s is not supported", exponent)) + } + + integerExponent := exponent.TruncateDec() + + fractionalExponent := exponent.Sub(integerExponent) + fractionalResult := exp2ChebyshevRationalApprox(fractionalExponent) + + // Left bit shift is equivalent to multiplying by 2^integerExponent. + fractionalResult.i = fractionalResult.i.Lsh(fractionalResult.i, uint(integerExponent.TruncateInt().Uint64())) + + return fractionalResult +} + +// exp2ChebyshevRationalApprox takes 2 to the power of a given decimal exponent. +// The result is approximated by a 13 parameter Chebyshev rational approximation. +// f(x) = h(x) / p(x) (7, 7) terms. We set the first term of p(x) to 1. +// As a result, this ends up being 7 + 6 = 13 parameters. +// The numerator coefficients are truncated at precision end. The denominator +// coefficients are rounded up at precision end. +// See scripts/approximations/README.md for details of the scripts used +// to compute the coefficients. +// CONTRACT: exponent must be in the range [0, 1], panics if not. +// The answer is correct up to a factor of 10^-18. +// Meaning, result = result * k for k in [1 - 10^(-18), 1 + 10^(-18)] +// Note: our Python script plots show accuracy up to a factor of 10^22. +// However, in Go tests we only test up to 10^18. Therefore, this is the guarantee. +func exp2ChebyshevRationalApprox(x BigDec) BigDec { + if x.LT(ZeroDec()) || x.GT(OneDec()) { + panic(fmt.Sprintf("exponent must be in the range [0, 1], got %s", x)) + } + if x.IsZero() { + return OneDec() + } + if x.Equal(OneDec()) { + return twoBigDec + } + + h_x := numeratorCoefficients13Param[0].Clone() + p_x := denominatorCoefficients13Param[0].Clone() + x_exp_i := OneDec() + for i := 1; i < len(numeratorCoefficients13Param); i++ { + x_exp_i.MulMut(x) + + h_x = h_x.Add(numeratorCoefficients13Param[i].Mul(x_exp_i)) + p_x = p_x.Add(denominatorCoefficients13Param[i].Mul(x_exp_i)) + } + + return h_x.Quo(p_x) +} diff --git a/osmomath/exp2_test.go b/osmomath/exp2_test.go new file mode 100644 index 00000000000..0955251dd76 --- /dev/null +++ b/osmomath/exp2_test.go @@ -0,0 +1,301 @@ +package osmomath_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + + "github.com/osmosis-labs/osmosis/v13/app/apptesting/osmoassert" + "github.com/osmosis-labs/osmosis/v13/osmomath" +) + +var ( + // minDecTolerance minimum tolerance for sdk.Dec, given its precision of 18. + minDecTolerance = sdk.MustNewDecFromStr("0.000000000000000001") +) + +func TestExp2ChebyshevRationalApprox(t *testing.T) { + // These values are used to test the approximated results close + // to 0 and 1 boundaries. + // With other types of approximations, there is a high likelyhood + // of larger errors clsoer to the boundaries. This is known as Runge's phenomenon. + // https://en.wikipedia.org/wiki/Runge%27s_phenomenon + // + // Chebyshev approximation should be able to handle this better. + // Tests at the boundaries help to validate there is no Runge's phenomenon. + smallValue := osmomath.MustNewDecFromStr("0.00001") + smallerValue := osmomath.MustNewDecFromStr("0.00000000000000000001") + + tests := map[string]struct { + exponent osmomath.BigDec + expectedResult osmomath.BigDec + errTolerance osmomath.ErrTolerance + expectPanic bool + }{ + "exp2(0.5)": { + exponent: osmomath.MustNewDecFromStr("0.5"), + // https://www.wolframalpha.com/input?i=2%5E0.5+37+digits + expectedResult: osmomath.MustNewDecFromStr("1.414213562373095048801688724209698079"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: minDecTolerance, + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundDown, + }, + }, + "exp2(0)": { + exponent: osmomath.ZeroDec(), + expectedResult: osmomath.OneDec(), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.ZeroDec(), + MultiplicativeTolerance: sdk.ZeroDec(), + RoundingDir: osmomath.RoundDown, + }, + }, + "exp2(1)": { + exponent: osmomath.OneDec(), + expectedResult: osmomath.MustNewDecFromStr("2"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.ZeroDec(), + MultiplicativeTolerance: sdk.ZeroDec(), + RoundingDir: osmomath.RoundDown, + }, + }, + "exp2(0.00001)": { + exponent: smallValue, + // https://www.wolframalpha.com/input?i=2%5E0.00001+37+digits + expectedResult: osmomath.MustNewDecFromStr("1.000006931495828305653209089800561681"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: minDecTolerance, + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundUnconstrained, + }, + }, + "exp2(0.99999)": { + exponent: osmomath.OneDec().Sub(smallValue), + // https://www.wolframalpha.com/input?i=2%5E0.99999+37+digits + expectedResult: osmomath.MustNewDecFromStr("1.999986137104433991477606830496602898"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.MustNewDecFromStr("0.00000000000000007"), + MultiplicativeTolerance: minDecTolerance.Mul(sdk.NewDec(100)), + RoundingDir: osmomath.RoundDown, + }, + }, + "exp2(0.99999...)": { + exponent: osmomath.OneDec().Sub(smallerValue), + // https://www.wolframalpha.com/input?i=2%5E%281+-+0.00000000000000000001%29+37+digits + expectedResult: osmomath.MustNewDecFromStr("1.999999999999999999986137056388801094"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: minDecTolerance, + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundDown, + }, + }, + "exp2(0.0000...1)": { + exponent: osmomath.ZeroDec().Add(smallerValue), + // https://www.wolframalpha.com/input?i=2%5E0.00000000000000000001+37+digits + expectedResult: osmomath.MustNewDecFromStr("1.000000000000000000006931471805599453"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: minDecTolerance, + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundUnconstrained, + }, + }, + "exp2(0.3334567)": { + exponent: osmomath.MustNewDecFromStr("0.3334567"), + // https://www.wolframalpha.com/input?i=2%5E0.3334567+37+digits + expectedResult: osmomath.MustNewDecFromStr("1.260028791934303989065848870753742298"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.MustNewDecFromStr("0.00000000000000007"), + MultiplicativeTolerance: minDecTolerance.Mul(sdk.NewDec(10)), + RoundingDir: osmomath.RoundDown, + }, + }, + "exp2(0.84864288)": { + exponent: osmomath.MustNewDecFromStr("0.84864288"), + // https://www.wolframalpha.com/input?i=2%5E0.84864288+37+digits + expectedResult: osmomath.MustNewDecFromStr("1.800806138872630518880998772777747572"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.MustNewDecFromStr("0.00000000000000002"), + MultiplicativeTolerance: minDecTolerance.Mul(sdk.NewDec(10)), + RoundingDir: osmomath.RoundUnconstrained, + }, + }, + "exp2(0.999999999999999999999999999999999956)": { + exponent: osmomath.MustNewDecFromStr("0.999999999999999999999999999999999956"), + // https://www.wolframalpha.com/input?i=2%5E0.999999999999999999999999999999999956+37+digits + expectedResult: osmomath.MustNewDecFromStr("1.999999999999999999999999999999999939"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: minDecTolerance, + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundDown, + }, + }, + // out of bounds. + "exponent < 0 - panic": { + exponent: osmomath.ZeroDec().Sub(smallValue), + expectPanic: true, + }, + "exponent > 1 - panic": { + exponent: osmomath.OneDec().Add(smallValue), + expectPanic: true, + }, + } + + for name, tc := range tests { + tc := tc + t.Run(name, func(t *testing.T) { + osmoassert.ConditionalPanic(t, tc.expectPanic, func() { + // System under test. + result := osmomath.Exp2ChebyshevRationalApprox(tc.exponent) + + // Reuse the same test cases for exp2 that is a wrapper around Exp2ChebyshevRationalApprox. + // This is done to reduce boilerplate from duplicating test cases. + resultExp2 := osmomath.Exp2(tc.exponent) + require.Equal(t, result, resultExp2) + + require.Equal(t, 0, tc.errTolerance.CompareBigDec(tc.expectedResult, result)) + }) + }) + } +} + +func TestExp2(t *testing.T) { + tests := map[string]struct { + exponent osmomath.BigDec + expectedResult osmomath.BigDec + errTolerance osmomath.ErrTolerance + expectPanic bool + }{ + "exp2(28.5)": { + exponent: osmomath.MustNewDecFromStr("28.5"), + // https://www.wolframalpha.com/input?i=2%5E%2828.5%29+45+digits + expectedResult: osmomath.MustNewDecFromStr("379625062.497006211556423566253288543343173698"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: minDecTolerance, + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundUnconstrained, + }, + }, + "exp2(63.84864288)": { + exponent: osmomath.MustNewDecFromStr("63.84864288"), + // https://www.wolframalpha.com/input?i=2%5E%2863.84864288%29+56+digits + expectedResult: osmomath.MustNewDecFromStr("16609504985074238416.013387053450559984846024066925604094"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.MustNewDecFromStr("0.00042"), + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundUnconstrained, + }, + }, + "exp2(64.5)": { + exponent: osmomath.MustNewDecFromStr("64.5"), + // https://www.wolframalpha.com/input?i=2%5E%2864.5%29+56+digits + expectedResult: osmomath.MustNewDecFromStr("26087635650665564424.699143612505016737766552579185717157"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.MustNewDecFromStr("0.000000000000000008"), + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundUnconstrained, + }, + }, + "exp2(80.5)": { + exponent: osmomath.MustNewDecFromStr("80.5"), + // https://www.wolframalpha.com/input?i=2%5E%2880.5%29+61+digits + expectedResult: osmomath.MustNewDecFromStr("1709679290002018430137083.075789128776926268789829515159631571"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.MustNewDecFromStr("0.0000000000006"), + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundUnconstrained, + }, + }, + "exp2(100.5)": { + exponent: osmomath.MustNewDecFromStr("100.5"), + // https://www.wolframalpha.com/input?i=2%5E%28100.5%29+67+digits + expectedResult: osmomath.MustNewDecFromStr("1792728671193156477399422023278.661496394239222564273688025833797661"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.MustNewDecFromStr("0.0000006"), + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundUnconstrained, + }, + }, + "exp2(128.5)": { + exponent: osmomath.MustNewDecFromStr("128.5"), + // https://www.wolframalpha.com/input?i=2%5E%28128.5%29+75+digits + expectedResult: osmomath.MustNewDecFromStr("481231938336009023090067544955250113854.229961482126296754016435255422777776"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.MustNewDecFromStr("146.5"), + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundUnconstrained, + }, + }, + "exp2(127.999999999999999999999999999999999999)": { + exponent: osmomath.MustNewDecFromStr("127.999999999999999999999999999999999999"), + // https://www.wolframalpha.com/input?i=2%5E%28127.999999999999999999999999999999999999%29+75+digits + expectedResult: osmomath.MustNewDecFromStr("340282366920938463463374607431768211220.134236774486705862055857235845515682"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.MustNewDecFromStr("15044647266406936"), + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundDown, + }, + }, + "exp2(127.84864288)": { + exponent: osmomath.MustNewDecFromStr("127.84864288"), + // https://www.wolframalpha.com/input?i=2%5E%28127.84864288%29+75+digits + expectedResult: osmomath.MustNewDecFromStr("306391287650667462068703337664945630660.398687487527674545778353588077174571"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: sdk.MustNewDecFromStr("7707157415597963"), + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundUnconstrained, + }, + }, + "panic, too large - positive": { + exponent: osmomath.MaxSupportedExponent.Add(osmomath.OneDec()), + expectPanic: true, + }, + "panic - negative exponent": { + exponent: osmomath.OneDec().Neg(), + expectPanic: true, + }, + "at exponent boundary - positive": { + exponent: osmomath.MaxSupportedExponent, + // https://www.wolframalpha.com/input?i=2%5E%282%5E9%29 + expectedResult: osmomath.MustNewDecFromStr("13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096"), + + errTolerance: osmomath.ErrTolerance{ + AdditiveTolerance: minDecTolerance, + MultiplicativeTolerance: minDecTolerance, + RoundingDir: osmomath.RoundDown, + }, + }, + } + + for name, tc := range tests { + tc := tc + t.Run(name, func(t *testing.T) { + osmoassert.ConditionalPanic(t, tc.expectPanic, func() { + + // System under test. + result := osmomath.Exp2(tc.exponent) + + require.Equal(t, 0, tc.errTolerance.CompareBigDec(tc.expectedResult, result)) + }) + }) + } +} diff --git a/osmomath/export_test.go b/osmomath/export_test.go index bdb6c71f959..d723e106095 100644 --- a/osmomath/export_test.go +++ b/osmomath/export_test.go @@ -8,8 +8,9 @@ import ( ) var ( - EulersNumber = eulersNumber - TwoBigDec = twoBigDec + MaxSupportedExponent = maxSupportedExponent + EulersNumber = eulersNumber + TwoBigDec = twoBigDec ) // 2^128 - 1, needs to be the same as gammtypes.MaxSpotPrice @@ -28,3 +29,7 @@ func ConditionalPanic(t *testing.T, expectPanic bool, sut func()) { } require.NotPanics(t, sut) } + +func Exp2ChebyshevRationalApprox(exponent BigDec) BigDec { + return exp2ChebyshevRationalApprox(exponent) +} diff --git a/scripts/approximations/approximations.py b/scripts/approximations/approximations.py index 19849698088..1a434509667 100644 --- a/scripts/approximations/approximations.py +++ b/scripts/approximations/approximations.py @@ -84,9 +84,9 @@ def compute_max_error(y_approximation, y_actual) -> sp.Float: max = sp.Max(max, cur_abs) return max -def compute_error_range(y_approximation: list, y_actual: list) -> list[sp.Float]: +def compute_absolute_error_range(y_approximation: list, y_actual: list) -> list[sp.Float]: """ Given an approximated list of y values and actual y values, computes and returns - error deltas between them. + absolute error between them, computed as | y_approximation[i] - y_actual[i] |. CONTRACT: - y_approximation and y_actual must be the same length @@ -101,6 +101,29 @@ def compute_error_range(y_approximation: list, y_actual: list) -> list[sp.Float] result.append(cur_abs) return result +def compute_relative_error_range(y_approximation: list, y_actual: list) -> list[sp.Float]: + """ Given an approximated list of y values and actual y values, computes and returns + relative error between them, computed as | y_approximation[i] - y_actual[i] | / y_actual[i]. + + For y_actual[i] = 0, relative error is defined as 0. + + CONTRACT: + - y_approximation and y_actual must be the same length + - for every i in range(len(y_approximation)), y_approximation[i] and y_actual[i] must correspond to the + same x coordinate + """ + result = [] + for i in range(len(y_approximation)): + if y_actual[i] == 0: + result.append(0) + continue + + cur_relative_error = sp.Abs(y_approximation[i] - y_actual[i]) / y_actual[i] + if cur_relative_error is sp.nan: + raise ValueError(F"cur_abs is nan. y_approximation[i] ({y_approximation[i]}) and y_actual[i] ({y_actual[i]})") + result.append(cur_relative_error) + return result + def equispaced_poly_approx(fn, x_start: sp.Float, x_end: sp.Float, num_terms: int): """ Returns the coefficients for an equispaced polynomial between x_start and x_end with num_terms terms. diff --git a/scripts/approximations/main.py b/scripts/approximations/main.py index b91433855c9..47875ed7b24 100644 --- a/scripts/approximations/main.py +++ b/scripts/approximations/main.py @@ -20,10 +20,10 @@ num_parameters_errors = 30 # number of (x,y) coordinates used to plot the resulting approximation. -num_points_plot = 100000 +num_points_plot = 10000 # function to approximate -approximated_fn = lambda x: sp.Pow(sp.E, x) +approximated_fn = lambda x: sp.Pow(2, x) # fixed point precision used in Osmosis `osmomath` package. osmomath_precision = 36 @@ -48,16 +48,23 @@ # Plots if true. shouldPlotMaxError = True -def plot_error_range(x_coordinates, y_approximation, y_actual): +def plot_error_range(x_coordinates, y_approximation, y_actual, is_absolute: bool): """ Given x coordinates that correspond to approximated y coordinates and actual y coordinates, - compute the deltas between y approximated and y actual and plot them in log scale on y. + computes the error between y approximated and y actual and plot them in log scale on y. + + If is_absolute, plots the absolute error. Otherwise, plots the relative error. """ - error_deltas = approximations.compute_error_range(y_approximation, y_actual) + if is_absolute: + error_kind_str = "Absolute" + error_deltas = approximations.compute_absolute_error_range(y_approximation, y_actual) + else: + error_kind_str = "Relative" + error_deltas = approximations.compute_relative_error_range(y_approximation, y_actual) plt.semilogy(x_coordinates, error_deltas) plt.grid(True) - plt.title(f"Chebyshev Rational e^x Errors on [{x_start}, {x_end}]. {num_parameters} params, {num_points_plot} points") + plt.title(f"Chebyshev Rational e^x {error_kind_str} Errors on [{x_start}, {x_end}]. {num_parameters} params, {num_points_plot} points") plt.show() # This script does the following: @@ -171,14 +178,41 @@ def main(): def exponent_approximation_choice(): # Equispaced x coordinates to be used for plotting every approximation. x_coordinates = approximations.linspace(x_start, x_end, num_points_plot) - x_coordinates = [sp.Float(sp.N(coef, osmomath_precision + 1), osmomath_precision + 1) for coef in x_coordinates] + x_coordinates = [sp.N(sp.Float(coef, osmomath_precision), n=osmomath_precision) for coef in x_coordinates] - # Chebyshev Rational Approximation to get the coefficients. - coef_numerator, coef_denominator = approximations.chebyshev_rational_approx(approximated_fn, x_start, x_end, num_parameters) + print(x_coordinates) - # Truncate the coefficients to osmomath precision. - coef_numerator = [sp.Float(sp.N(coef, osmomath_precision + 1), osmomath_precision + 1) for coef in coef_numerator] - coef_denominator = [sp.Float(sp.N(coef, osmomath_precision + 1), osmomath_precision + 1) for coef in coef_denominator] + # Chebyshev Rational Approximation to get the coefficients. + # coef_numerator, coef_denominator = approximations.chebyshev_rational_approx(approximated_fn, x_start, x_end, num_parameters) + # coef_numerator = [sp.N(coef, osmomath_precision + 2) for coef in coef_numerator] + # coef_denominator = [sp.N(coef, osmomath_precision + 2) for coef in coef_denominator] + + # Hard code and round up numerator coefficientst that are to be used in production + # Hard code and round down numerator coefficientst that are to be used in production + # Both of these are calculated us=ing the above commented out code. + + coef_numerator = [ + sp.N(sp.Float("1.000000000000000000000044212244679434", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("0.352032455817400196452603772766844426", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("0.056507868883666405413116800969512484", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("0.005343900728213034434757419480319916", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("0.000317708814342353603087543715930732", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("0.000011429747507407623028722262874632", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("0.000000198381965651614980168744540366", osmomath_precision), n=osmomath_precision), + ] + + coef_denominator = [ + sp.N(sp.Float("1.0000000000000000000000000000000000000", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("-0.341114724742545112949699755780593311", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("0.052724071627342653404436933178482287", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("-0.004760950735524957576233524801866342", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("0.000267168475410566529819971616894193", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("-0.000008923715368802211181557353097439", osmomath_precision), n=osmomath_precision), + sp.N(sp.Float("0.000000140277233177373698516010555916", osmomath_precision), n=osmomath_precision), + ] + + print(coef_numerator) + print(coef_denominator) # Evaluate approximation. y_chebyshev_rational = rational.evaluate(x_coordinates, coef_numerator, coef_denominator) @@ -186,7 +220,7 @@ def exponent_approximation_choice(): # Compute Actual Values y_actual = approximations.get_y_actual(approximated_fn, x_coordinates) - plot_error_range(x_coordinates, y_chebyshev_rational, y_actual) + plot_error_range(x_coordinates, y_chebyshev_rational, y_actual, True) if __name__ == "__main__": # Uncomment to run the main script. From 048a2a50c5f48d728c594787cc3bb92e9f5bc1d7 Mon Sep 17 00:00:00 2001 From: Sishir Giri Date: Thu, 1 Dec 2022 08:58:49 -0800 Subject: [PATCH 18/30] [x/TWAP] Expose a geometric TWAP API (#3529) * refactored twap api.go for geometric TWAP * added barebon docs * romans feedback * new * fix * nichola feedback * final roman comments --- x/twap/api.go | 46 +++++++++++++++++++++++++++++++++++++--------- x/twap/strategy.go | 24 ++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 x/twap/strategy.go diff --git a/x/twap/api.go b/x/twap/api.go index 4a850873136..68ed88b9162 100644 --- a/x/twap/api.go +++ b/x/twap/api.go @@ -41,12 +41,40 @@ func (k Keeper) GetArithmeticTwap( quoteAssetDenom string, startTime time.Time, endTime time.Time, +) (sdk.Dec, error) { + arithmeticStrategy := &arithmetic{k} + return k.getTwap(ctx, poolId, baseAssetDenom, quoteAssetDenom, startTime, endTime, arithmeticStrategy) +} + +// GetArithmeticTwapToNow returns arithmetic twap from start time until the current block time for quote and base +// assets in a given pool. +func (k Keeper) GetArithmeticTwapToNow( + ctx sdk.Context, + poolId uint64, + baseAssetDenom string, + quoteAssetDenom string, + startTime time.Time, +) (sdk.Dec, error) { + arithmeticStrategy := &arithmetic{k} + return k.getTwapToNow(ctx, poolId, baseAssetDenom, quoteAssetDenom, startTime, arithmeticStrategy) +} + +// getTwap computes and returns twap from the start time until the end time. The type +// of twap returned depends on the strategy given and can be either arithmetic or geometric. +func (k Keeper) getTwap( + ctx sdk.Context, + poolId uint64, + baseAssetDenom string, + quoteAssetDenom string, + startTime time.Time, + endTime time.Time, + strategy twapStrategy, ) (sdk.Dec, error) { if startTime.After(endTime) { return sdk.Dec{}, types.StartTimeAfterEndTimeError{StartTime: startTime, EndTime: endTime} } if endTime.Equal(ctx.BlockTime()) { - return k.GetArithmeticTwapToNow(ctx, poolId, baseAssetDenom, quoteAssetDenom, startTime) + return k.getTwapToNow(ctx, poolId, baseAssetDenom, quoteAssetDenom, startTime, strategy) } else if endTime.After(ctx.BlockTime()) { return sdk.Dec{}, types.EndTimeInFutureError{EndTime: endTime, BlockTime: ctx.BlockTime()} } @@ -58,17 +86,19 @@ func (k Keeper) GetArithmeticTwap( if err != nil { return sdk.Dec{}, err } - return computeArithmeticTwap(startRecord, endRecord, quoteAssetDenom) + + return strategy.computeTwap(startRecord, endRecord, quoteAssetDenom) } -// GetArithmeticTwapToNow returns GetArithmeticTwap on the input, with endTime being fixed to ctx.BlockTime() -// This function does not mutate records. -func (k Keeper) GetArithmeticTwapToNow( +// getTwapToNow computes and returns twap from the start time until the current block time. The type +// of twap returned depends on the strategy given and can be either arithmetic or geometric. +func (k Keeper) getTwapToNow( ctx sdk.Context, poolId uint64, baseAssetDenom string, quoteAssetDenom string, startTime time.Time, + strategy twapStrategy, ) (sdk.Dec, error) { if startTime.After(ctx.BlockTime()) { return sdk.Dec{}, types.StartTimeAfterEndTimeError{StartTime: startTime, EndTime: ctx.BlockTime()} @@ -82,14 +112,12 @@ func (k Keeper) GetArithmeticTwapToNow( if err != nil { return sdk.Dec{}, err } - return computeArithmeticTwap(startRecord, endRecord, quoteAssetDenom) + + return strategy.computeTwap(startRecord, endRecord, quoteAssetDenom) } // GetBeginBlockAccumulatorRecord returns a TwapRecord struct corresponding to the state of pool `poolId` // as of the beginning of the block this is called on. -// This uses the state of the beginning of the block, as if there were swaps since the block has started, -// these swaps have had no time to be arbitraged back. -// This accumulator can be stored, to compute wider ranged twaps. func (k Keeper) GetBeginBlockAccumulatorRecord(ctx sdk.Context, poolId uint64, asset0Denom string, asset1Denom string) (types.TwapRecord, error) { return k.getMostRecentRecord(ctx, poolId, asset0Denom, asset1Denom) } diff --git a/x/twap/strategy.go b/x/twap/strategy.go new file mode 100644 index 00000000000..426454a163a --- /dev/null +++ b/x/twap/strategy.go @@ -0,0 +1,24 @@ +package twap + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/osmosis-labs/osmosis/v13/x/twap/types" +) + +// twapStrategy is an interface for computing TWAPs. +// We have two strategies implementing the interface - arithmetic and geometric. +// We expose a common TWAP API to reduce duplication and avoid complexity. +type twapStrategy interface { + // computeTwap calculates the TWAP with specific startRecord and endRecord. + computeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) (sdk.Dec, error) +} + +type arithmetic struct { + keeper Keeper +} + +var _ twapStrategy = &arithmetic{} + +func (s *arithmetic) computeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) (sdk.Dec, error) { + return computeTwap(startRecord, endRecord, quoteAsset, arithmeticTwapType) +} From 7ade440e076e90cc93a3088fbf466d60fc3d09b5 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 4 Jan 2023 14:55:57 -0600 Subject: [PATCH 19/30] fix twap by hand --- x/twap/README.md | 23 ++ x/twap/api.go | 31 ++- x/twap/api_test.go | 50 +++- x/twap/client/grpc/grpc_query.go | 20 ++ x/twap/client/query_proto_wrap.go | 29 ++- x/twap/client/query_proto_wrap_test.go | 49 +++- x/twap/export_test.go | 25 +- x/twap/keeper.go | 10 + x/twap/keeper_test.go | 53 +++- x/twap/logic.go | 8 +- x/twap/logic_test.go | 249 +++---------------- x/twap/migrate_test.go | 29 +++ x/twap/store_test.go | 6 +- x/twap/strategy.go | 45 +++- x/twap/strategy_test.go | 323 +++++++++++++++++++++++++ x/twap/types/expected_interfaces.go | 2 +- x/twap/types/genesis.go | 4 + x/twap/types/genesis_test.go | 20 ++ x/twap/types/twapmock/amminterface.go | 8 +- 19 files changed, 721 insertions(+), 263 deletions(-) create mode 100644 x/twap/strategy_test.go diff --git a/x/twap/README.md b/x/twap/README.md index 1a00a8369e3..72ef865a956 100644 --- a/x/twap/README.md +++ b/x/twap/README.md @@ -12,6 +12,29 @@ Notice that the latest price `p_n` isn't used, as it has lasted for a time inter To illustrate with an example, given the sequence: `(0s, $1), (4s, $6), (5s, $1)`, the arithmetic mean TWAP is: $$\frac{\$1 * (4s - 0s) + \$6 * (5s - 4s)}{5s - 0s} = \frac{\$10}{5} = \$2$$ +## Geometric mean TWAP + +While the arithmetic mean TWAPs are much more widely used, they should theoretically be less accurate in measuring a geometric Brownian motion process (which is how price movements are usually modeled) + +Arithmetic TWAP tends to overweight higher prices relative to lower ones. + +Therefore, we also support a geometric mean TWAP. + +The core functionality stays similar to the arithmetic mean TWAP. However, instead of computing the geometric mean TWAP naively as +a [weighted geometric mean](https://en.wikipedia.org//wiki/Weighted_geometric_mean), we use the following property: + + +$$GeometricMean(P) = 2^{ArithmeticMean(log_{2}{P})}$$ + +$$ {(\prod_{i=a}^{b} P_i)}^{\frac{1}\{b-a}} = exp(\sum_{i=a}^{b}{\frac{1}{b-a} ln{(P_i)}}) $$ + +Note that in the second expression we use a different logarithm and power bases of `e`. +This is for brevity, and the true value used in our implementation is currently `2`. + +Naive computation is expensive and easily overflows. As a result, we track logarithms of prices instead of prices themselves in the accumulators. +When geometric twap is requested, we first compute the arithmetic mean of the logarithms, and then exponentiate it with the same base as the logarithm +to get the final result. + ## Computation via accumulators method The prior example for how to compute the TWAP takes linear time in the number of time entries in a range, which is too inefficient. We require TWAP operations to have constant time complexity (in the number of records). diff --git a/x/twap/api.go b/x/twap/api.go index 68ed88b9162..03ac8206e27 100644 --- a/x/twap/api.go +++ b/x/twap/api.go @@ -42,8 +42,18 @@ func (k Keeper) GetArithmeticTwap( startTime time.Time, endTime time.Time, ) (sdk.Dec, error) { - arithmeticStrategy := &arithmetic{k} - return k.getTwap(ctx, poolId, baseAssetDenom, quoteAssetDenom, startTime, endTime, arithmeticStrategy) + return k.getTwap(ctx, poolId, baseAssetDenom, quoteAssetDenom, startTime, endTime, k.GetArithmeticStrategy()) +} + +func (k Keeper) GetGeometricTwap( + ctx sdk.Context, + poolId uint64, + baseAssetDenom string, + quoteAssetDenom string, + startTime time.Time, + endTime time.Time, +) (sdk.Dec, error) { + return k.getTwap(ctx, poolId, baseAssetDenom, quoteAssetDenom, startTime, endTime, k.GetGeometricStrategy()) } // GetArithmeticTwapToNow returns arithmetic twap from start time until the current block time for quote and base @@ -55,8 +65,17 @@ func (k Keeper) GetArithmeticTwapToNow( quoteAssetDenom string, startTime time.Time, ) (sdk.Dec, error) { - arithmeticStrategy := &arithmetic{k} - return k.getTwapToNow(ctx, poolId, baseAssetDenom, quoteAssetDenom, startTime, arithmeticStrategy) + return k.getTwapToNow(ctx, poolId, baseAssetDenom, quoteAssetDenom, startTime, k.GetArithmeticStrategy()) +} + +func (k Keeper) GetGeometricTwapToNow( + ctx sdk.Context, + poolId uint64, + baseAssetDenom string, + quoteAssetDenom string, + startTime time.Time, +) (sdk.Dec, error) { + return k.getTwapToNow(ctx, poolId, baseAssetDenom, quoteAssetDenom, startTime, k.GetGeometricStrategy()) } // getTwap computes and returns twap from the start time until the end time. The type @@ -87,7 +106,7 @@ func (k Keeper) getTwap( return sdk.Dec{}, err } - return strategy.computeTwap(startRecord, endRecord, quoteAssetDenom) + return computeTwap(startRecord, endRecord, quoteAssetDenom, strategy) } // getTwapToNow computes and returns twap from the start time until the current block time. The type @@ -113,7 +132,7 @@ func (k Keeper) getTwapToNow( return sdk.Dec{}, err } - return strategy.computeTwap(startRecord, endRecord, quoteAssetDenom) + return computeTwap(startRecord, endRecord, quoteAssetDenom, strategy) } // GetBeginBlockAccumulatorRecord returns a TwapRecord struct corresponding to the state of pool `poolId` diff --git a/x/twap/api_test.go b/x/twap/api_test.go index b77f8243327..2964d00d071 100644 --- a/x/twap/api_test.go +++ b/x/twap/api_test.go @@ -26,28 +26,38 @@ var ( ThreePlusOneThird sdk.Dec = sdk.MustNewDecFromStr("3.333333333333333333") // base record is a record with t=baseTime, sp0=10(sp1=0.1) accumulators set to 0 - baseRecord types.TwapRecord = newTwoAssetPoolTwapRecordWithDefaults(baseTime, sdk.NewDec(10), sdk.ZeroDec(), sdk.ZeroDec()) + baseRecord types.TwapRecord = newTwoAssetPoolTwapRecordWithDefaults(baseTime, sdk.NewDec(10), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) threeAssetRecordAB, threeAssetRecordAC, threeAssetRecordBC types.TwapRecord = newThreeAssetPoolTwapRecordWithDefaults( baseTime, sdk.NewDec(10), // spot price 0 sdk.ZeroDec(), // accum A sdk.ZeroDec(), // accum B - sdk.ZeroDec()) // accum C + sdk.ZeroDec(), // accum C + sdk.ZeroDec(), // geomAccum AB + sdk.ZeroDec(), // geomAccum AC + sdk.ZeroDec(), // geomAccum BC + ) // accumA = 10 seconds * (spot price = 10) = OneSec * 10 * 10 // accumB = 10 seconds * (spot price = 0.1) = OneSec // accumC = 10 seconds * (spot price = 20) = OneSec * 10 * 20 accumA, accumB, accumC sdk.Dec = OneSec.MulInt64(10 * 10), OneSec, OneSec.MulInt64(10 * 20) + // geomAccumAB = 10 seconds * (log_{1.0001}{spot price = 10}) + geomAccumAB = geometricTenSecAccum.MulInt64(10) + geomAccumAC = geomAccumAB + // geomAccumBC = 10 seconds * (log_{1.0001}{spot price = 0.1}) + geomAccumBC = OneSec.Mul(logOneOverTen).MulInt64(10) + // accumulators updated from baseRecord with // t = baseTime + 10 // spA = 5, spB = 0.2, spC = 10 tPlus10sp5Record = newTwoAssetPoolTwapRecordWithDefaults( - baseTime.Add(10*time.Second), sdk.NewDec(5), accumA, accumB) + baseTime.Add(10*time.Second), sdk.NewDec(5), accumA, accumB, geomAccumAB) tPlus10sp5ThreeAssetRecordAB, tPlus10sp5ThreeAssetRecordAC, tPlus10sp5ThreeAssetRecordBC = newThreeAssetPoolTwapRecordWithDefaults( - baseTime.Add(10*time.Second), sdk.NewDec(5), accumA, accumB, accumC) + baseTime.Add(10*time.Second), sdk.NewDec(5), accumA, accumB, accumC, geomAccumAB, geomAccumAC, geomAccumBC) // accumulators updated from tPlus10sp5Record with // t = baseTime + 20 @@ -56,21 +66,27 @@ var ( baseTime.Add(20*time.Second), sdk.NewDec(2), // spot price 0 OneSec.MulInt64(10*10+5*10), // accum A - OneSec.MulInt64(3)) // accum B + OneSec.MulInt64(3), // accum B + sdk.ZeroDec(), // TODO: choose correct + ) tPlus20sp2ThreeAssetRecordAB, tPlus20sp2ThreeAssetRecordAC, tPlus20sp2ThreeAssetRecordBC = newThreeAssetPoolTwapRecordWithDefaults( baseTime.Add(20*time.Second), sdk.NewDec(2), // spot price 0 OneSec.MulInt64(10*10+5*10), // accum A OneSec.MulInt64(3), // accum B - OneSec.MulInt64(20*10+10*10)) // accum C + OneSec.MulInt64(20*10+10*10), // accum C + sdk.ZeroDec(), // TODO: choose correct + sdk.ZeroDec(), // TODO: choose correct + sdk.ZeroDec(), // TODO: choose correct + ) spotPriceError = errors.New("twap: error in pool spot price occurred between start and end time, twap result may be faulty") ) func (s *TestSuite) TestGetBeginBlockAccumulatorRecord() { poolId, denomA, denomB := s.setupDefaultPool() - initStartRecord := newRecord(poolId, s.Ctx.BlockTime(), sdk.OneDec(), sdk.ZeroDec(), sdk.ZeroDec()) + initStartRecord := newRecord(poolId, s.Ctx.BlockTime(), sdk.OneDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) initStartRecord.PoolId, initStartRecord.Height = poolId, s.Ctx.BlockHeight() initStartRecord.Asset0Denom, initStartRecord.Asset1Denom = denomB, denomA @@ -91,12 +107,12 @@ func (s *TestSuite) TestGetBeginBlockAccumulatorRecord() { "default record": {initStartRecord, initStartRecord, baseTime, 1, denomA, denomB, nil}, "default record but same denom": {initStartRecord, initStartRecord, baseTime, 1, denomA, denomA, fmt.Errorf("both assets cannot be of the same denom: assetA: %s, assetB: %s", denomA, denomA)}, "default record wrong order (should get reordered)": {initStartRecord, initStartRecord, baseTime, 1, denomB, denomA, nil}, - "one second later record": {initStartRecord, recordWithUpdatedAccum(initStartRecord, OneSec, OneSec), tPlusOne, 1, denomA, denomB, nil}, + "one second later record": {initStartRecord, recordWithUpdatedAccum(initStartRecord, OneSec, OneSec, sdk.ZeroDec()), tPlusOne, 1, denomA, denomB, nil}, "idempotent overwrite": {initStartRecord, initStartRecord, baseTime, 1, denomA, denomB, nil}, - "idempotent overwrite2": {initStartRecord, recordWithUpdatedAccum(initStartRecord, OneSec, OneSec), tPlusOne, 1, denomA, denomB, nil}, + "idempotent overwrite2": {initStartRecord, recordWithUpdatedAccum(initStartRecord, OneSec, OneSec, sdk.ZeroDec()), tPlusOne, 1, denomA, denomB, nil}, "diff spot price": { zeroAccumTenPoint1Record, - recordWithUpdatedAccum(zeroAccumTenPoint1Record, OneSec.MulInt64(10), OneSec.QuoInt64(10)), + recordWithUpdatedAccum(zeroAccumTenPoint1Record, OneSec.MulInt64(10), OneSec.QuoInt64(10), geometricTenSecAccum), tPlusOne, 1, denomA, denomB, nil, }, } @@ -456,8 +472,9 @@ func (s *TestSuite) TestGetArithmeticTwap_PruningRecordKeepPeriod() { periodBetweenBaseAndOneHourBeforeThreshold = (defaultRecordHistoryKeepPeriod.Milliseconds() - time.Hour.Milliseconds()) accumBeforeKeepThreshold0, accumBeforeKeepThreshold1 = sdk.NewDec(periodBetweenBaseAndOneHourBeforeThreshold * 10), sdk.NewDec(periodBetweenBaseAndOneHourBeforeThreshold * 10) + geomAccumBeforeKeepThreshold = sdk.NewDec(periodBetweenBaseAndOneHourBeforeThreshold).Mul(logTen) // recordBeforeKeepThreshold is a record with t=baseTime+keepPeriod-1h, sp0=30(sp1=0.3) accumulators set relative to baseRecord - recordBeforeKeepThreshold types.TwapRecord = newTwoAssetPoolTwapRecordWithDefaults(oneHourBeforeKeepThreshold, sdk.NewDec(30), accumBeforeKeepThreshold0, accumBeforeKeepThreshold1) + recordBeforeKeepThreshold types.TwapRecord = newTwoAssetPoolTwapRecordWithDefaults(oneHourBeforeKeepThreshold, sdk.NewDec(30), accumBeforeKeepThreshold0, accumBeforeKeepThreshold1, geomAccumBeforeKeepThreshold) ) // N.B.: when ctxTime = end time, we trigger the "TWAP to now path". @@ -594,7 +611,16 @@ func (s *TestSuite) TestGetArithmeticTwap_PruningRecordKeepPeriod_ThreeAsset() { periodBetweenBaseAndOneHourBeforeThreshold = (defaultRecordHistoryKeepPeriod.Milliseconds() - time.Hour.Milliseconds()) accumBeforeKeepThresholdA, accumBeforeKeepThresholdB, accumBeforeKeepThresholdC = sdk.NewDec(periodBetweenBaseAndOneHourBeforeThreshold * 10), sdk.NewDecWithPrec(1, 1).MulInt64(periodBetweenBaseAndOneHourBeforeThreshold), sdk.NewDec(periodBetweenBaseAndOneHourBeforeThreshold * 20) // recordBeforeKeepThreshold is a record with t=baseTime+keepPeriod-1h, spA=30(spB=0.3)(spC=60) accumulators set relative to baseRecord - recordBeforeKeepThresholdAB, recordBeforeKeepThresholdAC, recordBeforeKeepThresholdBC = newThreeAssetPoolTwapRecordWithDefaults(oneHourBeforeKeepThreshold, sdk.NewDec(30), accumBeforeKeepThresholdA, accumBeforeKeepThresholdB, accumBeforeKeepThresholdC) + recordBeforeKeepThresholdAB, recordBeforeKeepThresholdAC, recordBeforeKeepThresholdBC = newThreeAssetPoolTwapRecordWithDefaults( + oneHourBeforeKeepThreshold, + sdk.NewDec(30), + accumBeforeKeepThresholdA, + accumBeforeKeepThresholdB, + accumBeforeKeepThresholdC, + sdk.ZeroDec(), // TODO: choose correct + sdk.ZeroDec(), // TODO: choose correct + sdk.ZeroDec(), // TODO: choose correct + ) ) tests := map[string]struct { diff --git a/x/twap/client/grpc/grpc_query.go b/x/twap/client/grpc/grpc_query.go index b40021bf7eb..49277d1fc3c 100644 --- a/x/twap/client/grpc/grpc_query.go +++ b/x/twap/client/grpc/grpc_query.go @@ -30,6 +30,26 @@ func (q Querier) Params(grpcCtx context.Context, return q.Q.Params(ctx, *req) } +func (q Querier) GeometricTwapToNow(grpcCtx context.Context, + req *queryproto.GeometricTwapToNowRequest, +) (*queryproto.GeometricTwapToNowResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + ctx := sdk.UnwrapSDKContext(grpcCtx) + return q.Q.GeometricTwapToNow(ctx, *req) +} + +func (q Querier) GeometricTwap(grpcCtx context.Context, + req *queryproto.GeometricTwapRequest, +) (*queryproto.GeometricTwapResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "empty request") + } + ctx := sdk.UnwrapSDKContext(grpcCtx) + return q.Q.GeometricTwap(ctx, *req) +} + func (q Querier) ArithmeticTwapToNow(grpcCtx context.Context, req *queryproto.ArithmeticTwapToNowRequest, ) (*queryproto.ArithmeticTwapToNowResponse, error) { diff --git a/x/twap/client/query_proto_wrap.go b/x/twap/client/query_proto_wrap.go index 1d03b34e579..ab5eb51f1af 100644 --- a/x/twap/client/query_proto_wrap.go +++ b/x/twap/client/query_proto_wrap.go @@ -16,7 +16,7 @@ type Querier struct { } func (q Querier) ArithmeticTwap(ctx sdk.Context, - req queryproto.ArithmeticTwapRequest, // nolint: staticcheck + req queryproto.ArithmeticTwapRequest, ) (*queryproto.ArithmeticTwapResponse, error) { if req.EndTime == nil { req.EndTime = &time.Time{} @@ -27,19 +27,40 @@ func (q Querier) ArithmeticTwap(ctx sdk.Context, twap, err := q.K.GetArithmeticTwap(ctx, req.PoolId, req.BaseAsset, req.QuoteAsset, req.StartTime, *req.EndTime) - // nolint: staticcheck return &queryproto.ArithmeticTwapResponse{ArithmeticTwap: twap}, err } func (q Querier) ArithmeticTwapToNow(ctx sdk.Context, - req queryproto.ArithmeticTwapToNowRequest, // nolint: staticcheck + req queryproto.ArithmeticTwapToNowRequest, ) (*queryproto.ArithmeticTwapToNowResponse, error) { twap, err := q.K.GetArithmeticTwapToNow(ctx, req.PoolId, req.BaseAsset, req.QuoteAsset, req.StartTime) - // nolint: staticcheck return &queryproto.ArithmeticTwapToNowResponse{ArithmeticTwap: twap}, err } +func (q Querier) GeometricTwap(ctx sdk.Context, + req queryproto.GeometricTwapRequest, +) (*queryproto.GeometricTwapResponse, error) { + if req.EndTime == nil { + req.EndTime = &time.Time{} + } + if (*req.EndTime == time.Time{}) { + *req.EndTime = ctx.BlockTime() + } + + twap, err := q.K.GetGeometricTwap(ctx, req.PoolId, req.BaseAsset, req.QuoteAsset, req.StartTime, *req.EndTime) + + return &queryproto.GeometricTwapResponse{GeometricTwap: twap}, err +} + +func (q Querier) GeometricTwapToNow(ctx sdk.Context, + req queryproto.GeometricTwapToNowRequest, +) (*queryproto.GeometricTwapToNowResponse, error) { + twap, err := q.K.GetGeometricTwapToNow(ctx, req.PoolId, req.BaseAsset, req.QuoteAsset, req.StartTime) + + return &queryproto.GeometricTwapToNowResponse{GeometricTwap: twap}, err +} + func (q Querier) Params(ctx sdk.Context, req queryproto.ParamsRequest, ) (*queryproto.ParamsResponse, error) { diff --git a/x/twap/client/query_proto_wrap_test.go b/x/twap/client/query_proto_wrap_test.go index d66a01b28dd..1157bbeb230 100644 --- a/x/twap/client/query_proto_wrap_test.go +++ b/x/twap/client/query_proto_wrap_test.go @@ -110,6 +110,15 @@ func (suite *QueryTestSuite) TestQueryTwap() { result: sdk.MustNewDecFromStr("1.333333330000000000").String(), }, + { + name: "tokenB in terms of tokenC (rounded decimal of 2/3)", + poolId: poolID, + baseAssetDenom: "tokenC", + quoteAssetDenom: "tokenB", + endTime: &newBlockTime, + + result: sdk.MustNewDecFromStr("0.666666670000000000").String(), + }, { name: "tokenD in terms of tokenE (1)", poolId: poolID, @@ -151,7 +160,7 @@ func (suite *QueryTestSuite) TestQueryTwap() { for _, tc := range testCases { tc := tc - suite.Run(tc.name, func() { + suite.Run(tc.name+" arithmetic", func() { client := client.Querier{K: *suite.App.TwapKeeper} startTime := validStartTime @@ -188,5 +197,43 @@ func (suite *QueryTestSuite) TestQueryTwap() { suite.Require().Equal(tc.result, resultToNow.ArithmeticTwap.String()) } }) + + suite.Run(tc.name+" geometric", func() { + client := client.Querier{K: *suite.App.TwapKeeper} + + startTime := validStartTime + if tc.startTimeOverwrite != nil { + startTime = *tc.startTimeOverwrite + } + + result, err := client.GeometricTwap(ctx, queryproto.GeometricTwapRequest{ + PoolId: tc.poolId, + BaseAsset: tc.baseAssetDenom, + QuoteAsset: tc.quoteAssetDenom, + StartTime: startTime, + EndTime: tc.endTime, + }) + + if tc.expectErr { + suite.Require().Error(err, "expected error - GeometricTwap") + } else { + suite.Require().NoError(err, "unexpected error - GeometricTwap") + suite.Require().Equal(result.GeometricTwap.String(), result.GeometricTwap.String()) + } + + resultToNow, err := client.GeometricTwapToNow(ctx, queryproto.GeometricTwapToNowRequest{ + PoolId: tc.poolId, + BaseAsset: tc.baseAssetDenom, + QuoteAsset: tc.quoteAssetDenom, + StartTime: startTime, + }) + + if tc.expectErr { + suite.Require().Error(err, "expected error - GeometricTwapToNow") + } else { + suite.Require().NoError(err, "unexpected error - GeometricTwapToNow") + suite.Require().Equal(result.GeometricTwap.String(), resultToNow.GeometricTwap.String()) + } + }) } } diff --git a/x/twap/export_test.go b/x/twap/export_test.go index 30f32542bd0..1ccbbd47ab8 100644 --- a/x/twap/export_test.go +++ b/x/twap/export_test.go @@ -9,7 +9,10 @@ import ( ) type ( - TimeTooOldError = timeTooOldError + TimeTooOldError = timeTooOldError + TwapStrategy = twapStrategy + ArithmeticTwapStrategy = arithmetic + GeometricTwapStrategy = geometric ) func (k Keeper) StoreNewRecord(ctx sdk.Context, record types.TwapRecord) { @@ -64,8 +67,16 @@ func (k Keeper) GetInterpolatedRecord(ctx sdk.Context, poolId uint64, asset0Deno return k.getInterpolatedRecord(ctx, poolId, t, asset0Denom, asset1Denom) } -func ComputeArithmeticTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) (sdk.Dec, error) { - return computeArithmeticTwap(startRecord, endRecord, quoteAsset) +func ComputeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string, strategy twapStrategy) (sdk.Dec, error) { + return computeTwap(startRecord, endRecord, quoteAsset, strategy) +} + +func (as arithmetic) ComputeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) sdk.Dec { + return as.computeTwap(startRecord, endRecord, quoteAsset) +} + +func (gs geometric) ComputeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) sdk.Dec { + return gs.computeTwap(startRecord, endRecord, quoteAsset) } func RecordWithUpdatedAccumulators(record types.TwapRecord, t time.Time) types.TwapRecord { @@ -76,6 +87,14 @@ func NewTwapRecord(k types.AmmInterface, ctx sdk.Context, poolId uint64, denom0, return newTwapRecord(k, ctx, poolId, denom0, denom1) } +func TwapLog(x sdk.Dec) sdk.Dec { + return twapLog(x) +} + +func TwapPow(x sdk.Dec) sdk.Dec { + return twapPow(x) +} + func GetSpotPrices( ctx sdk.Context, k types.AmmInterface, diff --git a/x/twap/keeper.go b/x/twap/keeper.go index c7924f0d17e..1fe357e352e 100644 --- a/x/twap/keeper.go +++ b/x/twap/keeper.go @@ -83,3 +83,13 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { Twaps: twapRecords, } } + +// GetGeometricStrategy gets geometric TWAP keeper. +func (k Keeper) GetGeometricStrategy() *geometric { + return &geometric{k} +} + +// GetArithmeticStrategy gets arithmetic TWAP keeper. +func (k Keeper) GetArithmeticStrategy() *arithmetic { + return &arithmetic{k} +} diff --git a/x/twap/keeper_test.go b/x/twap/keeper_test.go index d0c40c145f5..60244f5a32b 100644 --- a/x/twap/keeper_test.go +++ b/x/twap/keeper_test.go @@ -56,6 +56,7 @@ var ( P1LastSpotPrice: sdk.OneDec(), P0ArithmeticTwapAccumulator: sdk.OneDec(), P1ArithmeticTwapAccumulator: sdk.OneDec(), + GeometricTwapAccumulator: sdk.OneDec(), } basicCustomGenesis = types.NewGenesisState( @@ -77,6 +78,7 @@ var ( P1LastSpotPrice: sdk.OneDec(), P0ArithmeticTwapAccumulator: sdk.OneDec(), P1ArithmeticTwapAccumulator: sdk.OneDec(), + GeometricTwapAccumulator: sdk.OneDec(), }, { PoolId: basePoolId, @@ -88,6 +90,7 @@ var ( P1LastSpotPrice: sdk.OneDec(), P0ArithmeticTwapAccumulator: sdk.OneDec(), P1ArithmeticTwapAccumulator: sdk.OneDec(), + GeometricTwapAccumulator: sdk.OneDec(), }, mostRecentRecordPoolOne, }) @@ -102,6 +105,7 @@ var ( P1LastSpotPrice: sdk.OneDec(), P0ArithmeticTwapAccumulator: sdk.OneDec(), P1ArithmeticTwapAccumulator: sdk.OneDec(), + GeometricTwapAccumulator: sdk.OneDec(), } decreasingOrderByTimeRecordsPoolTwo = types.NewGenesisState( @@ -118,6 +122,7 @@ var ( P1LastSpotPrice: sdk.OneDec(), P0ArithmeticTwapAccumulator: sdk.OneDec(), P1ArithmeticTwapAccumulator: sdk.OneDec(), + GeometricTwapAccumulator: sdk.OneDec(), }, { PoolId: basePoolId, @@ -129,6 +134,7 @@ var ( P1LastSpotPrice: sdk.OneDec(), P0ArithmeticTwapAccumulator: sdk.OneDec(), P1ArithmeticTwapAccumulator: sdk.OneDec(), + GeometricTwapAccumulator: sdk.OneDec(), }, }) @@ -214,6 +220,7 @@ func (suite *TestSuite) TestTwapInitGenesis() { P1LastSpotPrice: sdk.OneDec(), P0ArithmeticTwapAccumulator: sdk.OneDec(), P1ArithmeticTwapAccumulator: sdk.OneDec(), + GeometricTwapAccumulator: sdk.OneDec(), }, }), @@ -399,7 +406,7 @@ func (s *TestSuite) createTestRecordsFromTimeInPool(t time.Time, poolId uint64) // newTwoAssetPoolTwapRecordWithDefaults creates a single twap records, mimicking what one would expect from a two asset pool. // given a spot price 0 (sp0), this spot price is assigned to denomA and sp0 is then created and assigned to denomB by // calculating (1 / spA). -func newTwoAssetPoolTwapRecordWithDefaults(t time.Time, sp0, accum0, accum1 sdk.Dec) types.TwapRecord { +func newTwoAssetPoolTwapRecordWithDefaults(t time.Time, sp0, accum0, accum1, geomAccum sdk.Dec) types.TwapRecord { return types.TwapRecord{ PoolId: 1, Time: t, @@ -410,13 +417,14 @@ func newTwoAssetPoolTwapRecordWithDefaults(t time.Time, sp0, accum0, accum1 sdk. P1LastSpotPrice: sdk.OneDec().Quo(sp0), P0ArithmeticTwapAccumulator: accum0, P1ArithmeticTwapAccumulator: accum1, + GeometricTwapAccumulator: geomAccum, } } // newThreeAssetPoolTwapRecordWithDefaults creates three twap records, mimicking what one would expect from a three asset pool. // given a spot price 0 (sp0), this spot price is assigned to denomA and referred to as spA. spB is then created and assigned by // calculating (1 / spA). Finally spC is created and assigned by calculating (2 * spA). -func newThreeAssetPoolTwapRecordWithDefaults(t time.Time, sp0, accumA, accumB, accumC sdk.Dec) (types.TwapRecord, types.TwapRecord, types.TwapRecord) { +func newThreeAssetPoolTwapRecordWithDefaults(t time.Time, sp0, accumA, accumB, accumC, geomAccumAB, geomAccumAC, geomAccumBC sdk.Dec) (types.TwapRecord, types.TwapRecord, types.TwapRecord) { spA := sp0 spB := sdk.OneDec().Quo(sp0) spC := sp0.Mul(sdk.NewDec(2)) @@ -430,15 +438,18 @@ func newThreeAssetPoolTwapRecordWithDefaults(t time.Time, sp0, accumA, accumB, a P1LastSpotPrice: spB, P0ArithmeticTwapAccumulator: accumA, P1ArithmeticTwapAccumulator: accumB, + GeometricTwapAccumulator: geomAccumAB, } twapAC := twapAB twapAC.Asset1Denom = denom2 twapAC.P1LastSpotPrice = spC twapAC.P1ArithmeticTwapAccumulator = accumC + twapAC.GeometricTwapAccumulator = geomAccumAC twapBC := twapAC twapBC.Asset0Denom = denom1 twapBC.P0LastSpotPrice = spB twapBC.P0ArithmeticTwapAccumulator = accumB + twapBC.GeometricTwapAccumulator = geomAccumBC return twapAB, twapAC, twapBC } @@ -454,10 +465,21 @@ func newEmptyPriceRecord(poolId uint64, t time.Time, asset0 string, asset1 strin P1LastSpotPrice: sdk.ZeroDec(), P0ArithmeticTwapAccumulator: sdk.ZeroDec(), P1ArithmeticTwapAccumulator: sdk.ZeroDec(), + GeometricTwapAccumulator: sdk.ZeroDec(), } } -func newRecord(poolId uint64, t time.Time, sp0, accum0, accum1 sdk.Dec) types.TwapRecord { +func withPrice0Set(twapRecord types.TwapRecord, price0ToSet sdk.Dec) types.TwapRecord { + twapRecord.P0LastSpotPrice = price0ToSet + return twapRecord +} + +func withPrice1Set(twapRecord types.TwapRecord, price1ToSet sdk.Dec) types.TwapRecord { + twapRecord.P1LastSpotPrice = price1ToSet + return twapRecord +} + +func newRecord(poolId uint64, t time.Time, sp0, accum0, accum1, geomAccum sdk.Dec) types.TwapRecord { return types.TwapRecord{ PoolId: poolId, Asset0Denom: defaultTwoAssetCoins[0].Denom, @@ -468,21 +490,23 @@ func newRecord(poolId uint64, t time.Time, sp0, accum0, accum1 sdk.Dec) types.Tw // make new copies P0ArithmeticTwapAccumulator: accum0.Add(sdk.ZeroDec()), P1ArithmeticTwapAccumulator: accum1.Add(sdk.ZeroDec()), + GeometricTwapAccumulator: geomAccum.Add(sdk.ZeroDec()), } } // make an expected record for math tests, we adjust other values in the test runner. -func newExpRecord(accum0, accum1 sdk.Dec) types.TwapRecord { +func newExpRecord(accum0, accum1, geomAccum sdk.Dec) types.TwapRecord { return types.TwapRecord{ Asset0Denom: defaultTwoAssetCoins[0].Denom, Asset1Denom: defaultTwoAssetCoins[1].Denom, // make new copies P0ArithmeticTwapAccumulator: accum0.Add(sdk.ZeroDec()), P1ArithmeticTwapAccumulator: accum1.Add(sdk.ZeroDec()), + GeometricTwapAccumulator: geomAccum.Add(sdk.ZeroDec()), } } -func newThreeAssetRecord(poolId uint64, t time.Time, sp0, accumA, accumB, accumC sdk.Dec) []types.TwapRecord { +func newThreeAssetRecord(poolId uint64, t time.Time, sp0, accumA, accumB, accumC, geomAccumAB, geomAccumAC, geomAccumBC sdk.Dec) []types.TwapRecord { spA := sp0 spB := sdk.OneDec().Quo(sp0) spC := sp0.Mul(sdk.NewDec(2)) @@ -496,20 +520,23 @@ func newThreeAssetRecord(poolId uint64, t time.Time, sp0, accumA, accumB, accumC // make new copies P0ArithmeticTwapAccumulator: accumA.Add(sdk.ZeroDec()), P1ArithmeticTwapAccumulator: accumB.Add(sdk.ZeroDec()), + GeometricTwapAccumulator: geomAccumAB.Add(sdk.ZeroDec()), } twapAC := twapAB twapAC.Asset1Denom = denom2 twapAC.P1LastSpotPrice = spC twapAC.P1ArithmeticTwapAccumulator = accumC + twapAC.GeometricTwapAccumulator = geomAccumAC.Add(sdk.ZeroDec()) twapBC := twapAC twapBC.Asset0Denom = denom1 twapBC.P0LastSpotPrice = spB twapBC.P0ArithmeticTwapAccumulator = accumB + twapBC.GeometricTwapAccumulator = geomAccumBC.Add(sdk.ZeroDec()) return []types.TwapRecord{twapAB, twapAC, twapBC} } // make an expected record for math tests, we adjust other values in the test runner. -func newThreeAssetExpRecord(poolId uint64, accumA, accumB, accumC sdk.Dec) []types.TwapRecord { +func newThreeAssetExpRecord(poolId uint64, accumA, accumB, accumC, geomAccumAB, geomAccumAC, geomAccumBC sdk.Dec) []types.TwapRecord { twapAB := types.TwapRecord{ PoolId: poolId, Asset0Denom: defaultThreeAssetCoins[0].Denom, @@ -517,13 +544,16 @@ func newThreeAssetExpRecord(poolId uint64, accumA, accumB, accumC sdk.Dec) []typ // make new copies P0ArithmeticTwapAccumulator: accumA.Add(sdk.ZeroDec()), P1ArithmeticTwapAccumulator: accumB.Add(sdk.ZeroDec()), + GeometricTwapAccumulator: geomAccumAB.Add(sdk.ZeroDec()), } twapAC := twapAB twapAC.Asset1Denom = denom2 twapAC.P1ArithmeticTwapAccumulator = accumC + twapAC.GeometricTwapAccumulator = geomAccumAC.Add(sdk.ZeroDec()) twapBC := twapAC twapBC.Asset0Denom = denom1 twapBC.P0ArithmeticTwapAccumulator = accumB + twapBC.GeometricTwapAccumulator = geomAccumBC.Add(sdk.ZeroDec()) return []types.TwapRecord{twapAB, twapAC, twapBC} } @@ -539,6 +569,13 @@ func newOneSidedRecord(time time.Time, accum sdk.Dec, useP0 bool) types.TwapReco return record } +func newOneSidedGeometricRecord(time time.Time, accum sdk.Dec) types.TwapRecord { + record := types.TwapRecord{Time: time, Asset0Denom: denom0, Asset1Denom: denom1} + record.GeometricTwapAccumulator = accum + record.P0LastSpotPrice = sdk.NewDec(10) + return record +} + func newThreeAssetOneSidedRecord(time time.Time, accum sdk.Dec, useP0 bool) []types.TwapRecord { record := types.TwapRecord{Time: time, Asset0Denom: denom0, Asset1Denom: denom1} if useP0 { @@ -546,6 +583,7 @@ func newThreeAssetOneSidedRecord(time time.Time, accum sdk.Dec, useP0 bool) []ty } else { record.P1ArithmeticTwapAccumulator = accum } + record.GeometricTwapAccumulator = accum record.P0LastSpotPrice = sdk.ZeroDec() record.P1LastSpotPrice = sdk.OneDec() records := []types.TwapRecord{record, record, record} @@ -555,9 +593,10 @@ func newThreeAssetOneSidedRecord(time time.Time, accum sdk.Dec, useP0 bool) []ty return records } -func recordWithUpdatedAccum(record types.TwapRecord, accum0 sdk.Dec, accum1 sdk.Dec) types.TwapRecord { +func recordWithUpdatedAccum(record types.TwapRecord, accum0 sdk.Dec, accum1, geomAccum sdk.Dec) types.TwapRecord { record.P0ArithmeticTwapAccumulator = accum0 record.P1ArithmeticTwapAccumulator = accum1 + record.GeometricTwapAccumulator = geomAccum return record } diff --git a/x/twap/logic.go b/x/twap/logic.go index 2e559b992e4..e807d0cff29 100644 --- a/x/twap/logic.go +++ b/x/twap/logic.go @@ -28,6 +28,7 @@ func newTwapRecord(k types.AmmInterface, ctx sdk.Context, poolId uint64, denom0, P1LastSpotPrice: sp1, P0ArithmeticTwapAccumulator: sdk.ZeroDec(), P1ArithmeticTwapAccumulator: sdk.ZeroDec(), + GeometricTwapAccumulator: sdk.ZeroDec(), LastErrorTime: lastErrorTime, }, nil } @@ -45,7 +46,9 @@ func getSpotPrices( previousErrorTime time.Time, ) (sp0 sdk.Dec, sp1 sdk.Dec, latestErrTime time.Time) { latestErrTime = previousErrorTime + // sp0 = denom0 quote, denom1 base. sp0, err0 := k.CalculateSpotPrice(ctx, poolId, denom0, denom1) + // sp1 = denom0 base, denom1 quote. sp1, err1 := k.CalculateSpotPrice(ctx, poolId, denom1, denom0) if err0 != nil || err1 != nil { latestErrTime = ctx.BlockTime() @@ -234,8 +237,9 @@ func (k Keeper) getMostRecentRecord(ctx sdk.Context, poolId uint64, assetA, asse return record, nil } -// computeArithmeticTwap computes and returns an arithmetic TWAP between -// two records given the quote asset. +// computeTwap computes and returns a TWAP of a given +// type - arithmetic or geometric. +// Between two records given the quote asset. // precondition: endRecord.Time >= startRecord.Time // if (endRecord.LastErrorTime >= startRecord.Time) returns an error at end + result // if (startRecord.LastErrorTime == startRecord.Time) returns an error at end + result diff --git a/x/twap/logic_test.go b/x/twap/logic_test.go index 0d347e8b6e0..9d3b92df26f 100644 --- a/x/twap/logic_test.go +++ b/x/twap/logic_test.go @@ -19,10 +19,15 @@ import ( ) var ( - zeroDec = sdk.ZeroDec() - oneDec = sdk.OneDec() - twoDec = oneDec.Add(oneDec) - OneSec = sdk.MustNewDecFromStr("1000.000000000000000000") + zeroDec = sdk.ZeroDec() + oneDec = sdk.OneDec() + twoDec = oneDec.Add(oneDec) + pointFiveDec = sdk.OneDec().Quo(twoDec) + OneSec = sdk.MustNewDecFromStr("1000.000000000000000000") + logTen = twap.TwapLog(sdk.NewDec(10)) + logOneOverTen = twap.TwapLog(sdk.OneDec().QuoInt64(10)) + tenSecAccum = OneSec.MulInt64(10) + geometricTenSecAccum = OneSec.Mul(logTen) ) func (s *TestSuite) TestGetSpotPrices() { @@ -144,6 +149,7 @@ func (s *TestSuite) TestNewTwapRecord() { s.Require().Equal(s.Ctx.BlockTime(), twapRecord.Time) s.Require().Equal(sdk.ZeroDec(), twapRecord.P0ArithmeticTwapAccumulator) s.Require().Equal(sdk.ZeroDec(), twapRecord.P1ArithmeticTwapAccumulator) + s.Require().Equal(sdk.ZeroDec(), twapRecord.GeometricTwapAccumulator) } }) } @@ -161,8 +167,8 @@ func (s *TestSuite) TestUpdateRecord() { updateTime := time.Unix(3, 0).UTC() baseTimeMinusOne := time.Unix(1, 0).UTC() - zeroAccumNoErrSp10Record := newRecord(poolId, baseTime, sdk.NewDec(10), zeroDec, zeroDec) - sp10OneTimeUnitAccumRecord := newExpRecord(OneSec.MulInt64(10), OneSec.QuoInt64(10)) + zeroAccumNoErrSp10Record := newRecord(poolId, baseTime, sdk.NewDec(10), zeroDec, zeroDec, zeroDec) + sp10OneTimeUnitAccumRecord := newExpRecord(OneSec.MulInt64(10), OneSec.QuoInt64(10), geometricTenSecAccum) // all tests occur with updateTime = base time + time.Unix(1, 0) tests := map[string]struct { record types.TwapRecord @@ -237,26 +243,27 @@ func (s *TestSuite) TestUpdateRecord() { func TestRecordWithUpdatedAccumulators(t *testing.T) { poolId := uint64(1) - defaultRecord := newRecord(poolId, time.Unix(1, 0), sdk.NewDec(10), oneDec, twoDec) + defaultRecord := newRecord(poolId, time.Unix(1, 0), sdk.NewDec(10), oneDec, twoDec, pointFiveDec) tests := map[string]struct { - record types.TwapRecord - newTime time.Time - expRecord types.TwapRecord + record types.TwapRecord + newTime time.Time + expRecord types.TwapRecord + expectPanic bool }{ "accum with zero value": { - record: newRecord(poolId, time.Unix(1, 0), sdk.NewDec(10), zeroDec, zeroDec), + record: newRecord(poolId, time.Unix(1, 0), sdk.NewDec(10), zeroDec, zeroDec, zeroDec), newTime: time.Unix(2, 0), - expRecord: newExpRecord(OneSec.MulInt64(10), OneSec.QuoInt64(10)), + expRecord: newExpRecord(OneSec.MulInt64(10), OneSec.QuoInt64(10), geometricTenSecAccum), }, "small starting accumulators": { record: defaultRecord, newTime: time.Unix(2, 0), - expRecord: newExpRecord(oneDec.Add(OneSec.MulInt64(10)), twoDec.Add(OneSec.QuoInt64(10))), + expRecord: newExpRecord(oneDec.Add(OneSec.MulInt64(10)), twoDec.Add(OneSec.QuoInt64(10)), pointFiveDec.Add(geometricTenSecAccum)), }, "larger time interval": { - record: newRecord(poolId, time.Unix(11, 0), sdk.NewDec(10), oneDec, twoDec), + record: newRecord(poolId, time.Unix(11, 0), sdk.NewDec(10), oneDec, twoDec, pointFiveDec), newTime: time.Unix(55, 0), - expRecord: newExpRecord(oneDec.Add(OneSec.MulInt64(44*10)), twoDec.Add(OneSec.MulInt64(44).QuoInt64(10))), + expRecord: newExpRecord(oneDec.Add(OneSec.MulInt64(44*10)), twoDec.Add(OneSec.MulInt64(44).QuoInt64(10)), pointFiveDec.Add(OneSec.MulInt64(44).Mul(logTen))), }, "same time, accumulator should not change": { record: defaultRecord, @@ -293,8 +300,10 @@ func TestRecordWithUpdatedAccumulators(t *testing.T) { test.expRecord.P0LastSpotPrice = test.record.P0LastSpotPrice test.expRecord.P1LastSpotPrice = test.record.P1LastSpotPrice - gotRecord := twap.RecordWithUpdatedAccumulators(test.record, test.newTime) - require.Equal(t, test.expRecord, gotRecord) + osmoassert.ConditionalPanic(t, test.expectPanic, func() { + gotRecord := twap.RecordWithUpdatedAccumulators(test.record, test.newTime) + require.Equal(t, test.expRecord, gotRecord) + }) }) } } @@ -307,19 +316,19 @@ func TestRecordWithUpdatedAccumulators_ThreeAsset(t *testing.T) { expRecord []types.TwapRecord }{ "accum with zero value": { - record: newThreeAssetRecord(poolId, time.Unix(1, 0), sdk.NewDec(10), zeroDec, zeroDec, zeroDec), + record: newThreeAssetRecord(poolId, time.Unix(1, 0), sdk.NewDec(10), zeroDec, zeroDec, zeroDec, zeroDec, zeroDec, zeroDec), interpolateTime: time.Unix(2, 0), - expRecord: newThreeAssetExpRecord(poolId, OneSec.MulInt64(10), OneSec.QuoInt64(10), OneSec.MulInt64(20)), + expRecord: newThreeAssetExpRecord(poolId, OneSec.MulInt64(10), OneSec.QuoInt64(10), OneSec.MulInt64(20), geometricTenSecAccum, geometricTenSecAccum, OneSec.Mul(logOneOverTen)), }, "small starting accumulators": { - record: newThreeAssetRecord(poolId, time.Unix(1, 0), sdk.NewDec(10), twoDec, oneDec, twoDec), + record: newThreeAssetRecord(poolId, time.Unix(1, 0), sdk.NewDec(10), twoDec, oneDec, twoDec, oneDec, twoDec, oneDec), interpolateTime: time.Unix(2, 0), - expRecord: newThreeAssetExpRecord(poolId, twoDec.Add(OneSec.MulInt64(10)), oneDec.Add(OneSec.QuoInt64(10)), twoDec.Add(OneSec.MulInt64(20))), + expRecord: newThreeAssetExpRecord(poolId, twoDec.Add(OneSec.MulInt64(10)), oneDec.Add(OneSec.QuoInt64(10)), twoDec.Add(OneSec.MulInt64(20)), oneDec.Add(geometricTenSecAccum), twoDec.Add(geometricTenSecAccum), oneDec.Add(OneSec.Mul(logOneOverTen))), }, "larger time interval": { - record: newThreeAssetRecord(poolId, time.Unix(11, 0), sdk.NewDec(10), twoDec, oneDec, twoDec), + record: newThreeAssetRecord(poolId, time.Unix(11, 0), sdk.NewDec(10), twoDec, oneDec, twoDec, oneDec, twoDec, oneDec), interpolateTime: time.Unix(55, 0), - expRecord: newThreeAssetExpRecord(poolId, twoDec.Add(OneSec.MulInt64(44*10)), oneDec.Add(OneSec.MulInt64(44).QuoInt64(10)), twoDec.Add(OneSec.MulInt64(44*20))), + expRecord: newThreeAssetExpRecord(poolId, twoDec.Add(OneSec.MulInt64(44*10)), oneDec.Add(OneSec.MulInt64(44).QuoInt64(10)), twoDec.Add(OneSec.MulInt64(44*20)), oneDec.Add(OneSec.MulInt64(44).Mul(logTen)), twoDec.Add(OneSec.MulInt64(44).Mul(logTen)), oneDec.Add(OneSec.MulInt64(44).Mul(logOneOverTen))), }, } @@ -339,7 +348,7 @@ func TestRecordWithUpdatedAccumulators_ThreeAsset(t *testing.T) { } func (s *TestSuite) TestGetInterpolatedRecord() { - baseRecord := newTwoAssetPoolTwapRecordWithDefaults(baseTime, sdk.OneDec(), sdk.OneDec(), sdk.OneDec()) + baseRecord := newTwoAssetPoolTwapRecordWithDefaults(baseTime, sdk.OneDec(), sdk.OneDec(), sdk.OneDec(), sdk.OneDec().Quo(twoDec)) // all tests occur with updateTime = base time + time.Unix(1, 0) tests := map[string]struct { @@ -437,7 +446,7 @@ func (s *TestSuite) TestGetInterpolatedRecord() { } func (s *TestSuite) TestGetInterpolatedRecord_ThreeAsset() { - baseRecord := newThreeAssetRecord(2, baseTime, sdk.NewDec(10), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) + baseRecord := newThreeAssetRecord(2, baseTime, sdk.NewDec(10), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()) // all tests occur with updateTime = base time + time.Unix(1, 0) tests := map[string]struct { recordsToPreSet []types.TwapRecord @@ -539,14 +548,6 @@ func (s *TestSuite) TestGetInterpolatedRecord_ThreeAsset() { } } -type computeArithmeticTwapTestCase struct { - startRecord types.TwapRecord - endRecord types.TwapRecord - quoteAsset string - expTwap sdk.Dec - expErr bool -} - type computeThreeAssetArithmeticTwapTestCase struct { startRecord []types.TwapRecord endRecord []types.TwapRecord @@ -555,188 +556,6 @@ type computeThreeAssetArithmeticTwapTestCase struct { expErr bool } -// TestComputeArithmeticTwap tests ComputeArithmeticTwap on various inputs. -// The test vectors are structured by setting up different start and records, -// based on time interval, and their accumulator values. -// Then an expected TWAP is provided in each test case, to compare against computed. -func TestComputeArithmeticTwap(t *testing.T) { - testCaseFromDeltas := func(startAccum, accumDiff sdk.Dec, timeDelta time.Duration, expectedTwap sdk.Dec) computeArithmeticTwapTestCase { - return computeArithmeticTwapTestCase{ - newOneSidedRecord(baseTime, startAccum, true), - newOneSidedRecord(baseTime.Add(timeDelta), startAccum.Add(accumDiff), true), - denom0, - expectedTwap, - false, - } - } - testCaseFromDeltasAsset1 := func(startAccum, accumDiff sdk.Dec, timeDelta time.Duration, expectedTwap sdk.Dec) computeArithmeticTwapTestCase { - return computeArithmeticTwapTestCase{ - newOneSidedRecord(baseTime, startAccum, false), - newOneSidedRecord(baseTime.Add(timeDelta), startAccum.Add(accumDiff), false), - denom1, - expectedTwap, - false, - } - } - tenSecAccum := OneSec.MulInt64(10) - pointOneAccum := OneSec.QuoInt64(10) - tests := map[string]computeArithmeticTwapTestCase{ - "basic: spot price = 1 for one second, 0 init accumulator": { - startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), - endRecord: newOneSidedRecord(tPlusOne, OneSec, true), - quoteAsset: denom0, - expTwap: sdk.OneDec(), - }, - // this test just shows what happens in case the records are reversed. - // It should return the correct result, even though this is incorrect internal API usage - "invalid call: reversed records of above": { - startRecord: newOneSidedRecord(tPlusOne, OneSec, true), - endRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), - quoteAsset: denom0, - expTwap: sdk.OneDec(), - }, - "same record: denom0, end spot price = 0": { - startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), - endRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), - quoteAsset: denom0, - expTwap: sdk.ZeroDec(), - }, - "same record: denom1, end spot price = 1": { - startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), - endRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), - quoteAsset: denom1, - expTwap: sdk.OneDec(), - }, - "accumulator = 10*OneSec, t=5s. 0 base accum": testCaseFromDeltas( - sdk.ZeroDec(), tenSecAccum, 5*time.Second, sdk.NewDec(2)), - "accumulator = 10*OneSec, t=3s. 0 base accum": testCaseFromDeltas( - sdk.ZeroDec(), tenSecAccum, 3*time.Second, ThreePlusOneThird), - "accumulator = 10*OneSec, t=100s. 0 base accum": testCaseFromDeltas( - sdk.ZeroDec(), tenSecAccum, 100*time.Second, sdk.NewDecWithPrec(1, 1)), - - // test that base accum has no impact - "accumulator = 10*OneSec, t=5s. 10 base accum": testCaseFromDeltas( - sdk.NewDec(10), tenSecAccum, 5*time.Second, sdk.NewDec(2)), - "accumulator = 10*OneSec, t=3s. 10*second base accum": testCaseFromDeltas( - tenSecAccum, tenSecAccum, 3*time.Second, ThreePlusOneThird), - "accumulator = 10*OneSec, t=100s. .1*second base accum": testCaseFromDeltas( - pointOneAccum, tenSecAccum, 100*time.Second, sdk.NewDecWithPrec(1, 1)), - - "accumulator = 10*OneSec, t=100s. 0 base accum (asset 1)": testCaseFromDeltasAsset1(sdk.ZeroDec(), OneSec.MulInt64(10), 100*time.Second, sdk.NewDecWithPrec(1, 1)), - } - for name, test := range tests { - t.Run(name, func(t *testing.T) { - actualTwap, err := twap.ComputeArithmeticTwap(test.startRecord, test.endRecord, test.quoteAsset) - require.Equal(t, test.expTwap, actualTwap) - require.NoError(t, err) - }) - } -} - -func TestComputeArithmeticTwap_ThreeAsset(t *testing.T) { - testThreeAssetCaseFromDeltas := func(startAccum, accumDiff sdk.Dec, timeDelta time.Duration, expectedTwap sdk.Dec) computeThreeAssetArithmeticTwapTestCase { - return computeThreeAssetArithmeticTwapTestCase{ - newThreeAssetOneSidedRecord(baseTime, startAccum, true), - newThreeAssetOneSidedRecord(baseTime.Add(timeDelta), startAccum.Add(accumDiff), true), - []string{denom0, denom0, denom1}, - []sdk.Dec{expectedTwap, expectedTwap, expectedTwap}, - false, - } - } - - tenSecAccum := OneSec.MulInt64(10) - pointOneAccum := OneSec.QuoInt64(10) - tests := map[string]computeThreeAssetArithmeticTwapTestCase{ - "three asset basic: spot price = 1 for one second, 0 init accumulator": { - startRecord: newThreeAssetOneSidedRecord(baseTime, sdk.ZeroDec(), true), - endRecord: newThreeAssetOneSidedRecord(tPlusOne, OneSec, true), - quoteAsset: []string{denom0, denom0, denom1}, - expTwap: []sdk.Dec{sdk.OneDec(), sdk.OneDec(), sdk.OneDec()}, - }, - "three asset same record: asset1, end spot price = 1": { - startRecord: newThreeAssetOneSidedRecord(baseTime, sdk.ZeroDec(), true), - endRecord: newThreeAssetOneSidedRecord(baseTime, sdk.ZeroDec(), true), - quoteAsset: []string{denom1, denom2, denom2}, - expTwap: []sdk.Dec{sdk.OneDec(), sdk.OneDec(), sdk.OneDec()}, - }, - "three asset. accumulator = 10*OneSec, t=5s. 0 base accum": testThreeAssetCaseFromDeltas( - sdk.ZeroDec(), tenSecAccum, 5*time.Second, sdk.NewDec(2)), - - // test that base accum has no impact - "three asset. accumulator = 10*OneSec, t=5s. 10 base accum": testThreeAssetCaseFromDeltas( - sdk.NewDec(10), tenSecAccum, 5*time.Second, sdk.NewDec(2)), - "three asset. accumulator = 10*OneSec, t=100s. .1*second base accum": testThreeAssetCaseFromDeltas( - pointOneAccum, tenSecAccum, 100*time.Second, sdk.NewDecWithPrec(1, 1)), - } - for name, test := range tests { - t.Run(name, func(t *testing.T) { - for i, startRec := range test.startRecord { - actualTwap, err := twap.ComputeArithmeticTwap(startRec, test.endRecord[i], test.quoteAsset[i]) - require.Equal(t, test.expTwap[i], actualTwap) - require.NoError(t, err) - } - }) - } -} - -// This tests the behavior of computeArithmeticTwap, around error returning -// when there has been an intermediate spot price error. -func TestComputeArithmeticTwapWithSpotPriceError(t *testing.T) { - newOneSidedRecordWErrorTime := func(time time.Time, accum sdk.Dec, useP0 bool, errTime time.Time) types.TwapRecord { - record := newOneSidedRecord(time, accum, useP0) - record.LastErrorTime = errTime - return record - } - tests := map[string]computeArithmeticTwapTestCase{ - // should error, since end time may have been used to interpolate this value - "errAtEndTime from end record": { - startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), - endRecord: newOneSidedRecordWErrorTime(tPlusOne, OneSec, true, tPlusOne), - quoteAsset: denom0, - expTwap: sdk.OneDec(), - expErr: true, - }, - // should error, since start time may have been used to interpolate this value - "err at StartTime exactly from end record": { - startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), - endRecord: newOneSidedRecordWErrorTime(tPlusOne, OneSec, true, baseTime), - quoteAsset: denom0, - expTwap: sdk.OneDec(), - expErr: true, - }, - // should error, since start record is erroneous - "err at StartTime exactly from start record": { - startRecord: newOneSidedRecordWErrorTime(baseTime, sdk.ZeroDec(), true, baseTime), - endRecord: newOneSidedRecord(tPlusOne, OneSec, true), - quoteAsset: denom0, - expTwap: sdk.OneDec(), - expErr: true, - }, - "err before StartTime": { - startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), - endRecord: newOneSidedRecordWErrorTime(tPlusOne, OneSec, true, tMinOne), - quoteAsset: denom0, - expTwap: sdk.OneDec(), - expErr: false, - }, - // Should not happen, but if it did would error - "err after EndTime": { - startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), - endRecord: newOneSidedRecordWErrorTime(tPlusOne, OneSec.MulInt64(2), true, baseTime.Add(20*time.Second)), - quoteAsset: denom0, - expTwap: sdk.OneDec().MulInt64(2), - expErr: true, - }, - } - for name, test := range tests { - t.Run(name, func(t *testing.T) { - actualTwap, err := twap.ComputeArithmeticTwap(test.startRecord, test.endRecord, test.quoteAsset) - require.Equal(t, test.expTwap, actualTwap) - osmoassert.ConditionalError(t, test.expErr, err) - }) - } -} - // TestPruneRecords tests that twap records earlier than // current block time - RecordHistoryKeepPeriod are pruned from the store // while keeping the newest record before the above time threshold. diff --git a/x/twap/migrate_test.go b/x/twap/migrate_test.go index 37c7905f1e3..1410a2d0884 100644 --- a/x/twap/migrate_test.go +++ b/x/twap/migrate_test.go @@ -3,6 +3,9 @@ package twap_test import ( "time" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/gogo/protobuf/proto" + "github.com/osmosis-labs/osmosis/v13/x/twap/types" ) @@ -64,3 +67,29 @@ func (s *TestSuite) TestMigrateExistingPoolsError() { err := s.twapkeeper.MigrateExistingPools(s.Ctx, latestPoolIdPlusOne) s.Require().Error(err) } + +// TestTwapRecord_GeometricTwap_MarshalUnmarshal this test proves that migrations +// to initialize geometric twap accumulators are not required. +// This is because proto marshalling will initialize the field to the zero value. +// Zero value is the expected initialization value for the geometric twap accumulator. +func (suite *TestSuite) TestTwapRecord_GeometricTwap_MarshalUnmarshal() { + originalRecord := types.TwapRecord{ + Asset0Denom: "uatom", + Asset1Denom: "uusd", + } + + suite.Require().True(originalRecord.GeometricTwapAccumulator.IsNil()) + + bz, err := proto.Marshal(&originalRecord) + suite.Require().NoError(err) + + var deserialized types.TwapRecord + err = proto.Unmarshal(bz, &deserialized) + suite.Require().NoError(err) + + suite.Require().Equal(originalRecord, deserialized) + suite.Require().Equal(originalRecord.String(), deserialized.String()) + + suite.Require().False(originalRecord.GeometricTwapAccumulator.IsNil()) + suite.Require().Equal(sdk.ZeroDec(), originalRecord.GeometricTwapAccumulator) +} diff --git a/x/twap/store_test.go b/x/twap/store_test.go index 61dd87b2e3c..6d8b2bea0e4 100644 --- a/x/twap/store_test.go +++ b/x/twap/store_test.go @@ -162,11 +162,11 @@ func (s *TestSuite) TestGetRecordAtOrBeforeTime() { defaultInputAt := func(t time.Time) getRecordInput { return getRecordInput{1, t, denom0, denom1} } wrongPoolIdInputAt := func(t time.Time) getRecordInput { return getRecordInput{2, t, denom0, denom1} } defaultRevInputAt := func(t time.Time) getRecordInput { return getRecordInput{1, t, denom1, denom0} } - baseRecord := newEmptyPriceRecord(1, baseTime, denom0, denom1) + baseRecord := withPrice0Set(newEmptyPriceRecord(1, baseTime, denom0, denom1), sdk.OneDec()) tMin1 := baseTime.Add(-time.Second) - tMin1Record := newEmptyPriceRecord(1, tMin1, denom0, denom1) + tMin1Record := withPrice0Set(newEmptyPriceRecord(1, tMin1, denom0, denom1), sdk.OneDec()) tPlus1 := baseTime.Add(time.Second) - tPlus1Record := newEmptyPriceRecord(1, tPlus1, denom0, denom1) + tPlus1Record := withPrice0Set(newEmptyPriceRecord(1, tPlus1, denom0, denom1), sdk.OneDec()) tests := map[string]struct { recordsToSet []types.TwapRecord diff --git a/x/twap/strategy.go b/x/twap/strategy.go index 426454a163a..7863ff93a4b 100644 --- a/x/twap/strategy.go +++ b/x/twap/strategy.go @@ -2,7 +2,11 @@ package twap import ( sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/osmomath" "github.com/osmosis-labs/osmosis/v13/x/twap/types" + + gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types" ) // twapStrategy is an interface for computing TWAPs. @@ -10,15 +14,46 @@ import ( // We expose a common TWAP API to reduce duplication and avoid complexity. type twapStrategy interface { // computeTwap calculates the TWAP with specific startRecord and endRecord. - computeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) (sdk.Dec, error) + computeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) sdk.Dec } type arithmetic struct { - keeper Keeper + TwapKeeper Keeper +} + +type geometric struct { + TwapKeeper Keeper } -var _ twapStrategy = &arithmetic{} +// computeTwap computes and returns an arithmetic TWAP between +// two records given the quote asset. +func (s *arithmetic) computeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) sdk.Dec { + var accumDiff sdk.Dec + if quoteAsset == startRecord.Asset0Denom { + accumDiff = endRecord.P0ArithmeticTwapAccumulator.Sub(startRecord.P0ArithmeticTwapAccumulator) + } else { + accumDiff = endRecord.P1ArithmeticTwapAccumulator.Sub(startRecord.P1ArithmeticTwapAccumulator) + } + timeDelta := endRecord.Time.Sub(startRecord.Time) + return types.AccumDiffDivDuration(accumDiff, timeDelta) +} + +// computeTwap computes and returns a geometric TWAP between +// two records given the quote asset. +func (s *geometric) computeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) sdk.Dec { + accumDiff := endRecord.GeometricTwapAccumulator.Sub(startRecord.GeometricTwapAccumulator) + + timeDelta := endRecord.Time.Sub(startRecord.Time) + arithmeticMeanOfLogPrices := types.AccumDiffDivDuration(accumDiff, timeDelta) + + result := twapPow(arithmeticMeanOfLogPrices) + // N.B.: Geometric mean of recprocals is reciprocal of geometric mean. + // https://proofwiki.org/wiki/Geometric_Mean_of_Reciprocals_is_Reciprocal_of_Geometric_Mean + if quoteAsset == startRecord.Asset1Denom { + result = sdk.OneDec().Quo(result) + } -func (s *arithmetic) computeTwap(startRecord types.TwapRecord, endRecord types.TwapRecord, quoteAsset string) (sdk.Dec, error) { - return computeTwap(startRecord, endRecord, quoteAsset, arithmeticTwapType) + // N.B. we round because this is the max number of significant figures supported + // by the underlying spot price function. + return osmomath.SigFigRound(result, gammtypes.SpotPriceSigFigs) } diff --git a/x/twap/strategy_test.go b/x/twap/strategy_test.go new file mode 100644 index 00000000000..f5208f4c948 --- /dev/null +++ b/x/twap/strategy_test.go @@ -0,0 +1,323 @@ +package twap_test + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/osmosis-labs/osmosis/osmomath" + "github.com/osmosis-labs/osmosis/osmoutils/osmoassert" + gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types" + "github.com/osmosis-labs/osmosis/v13/x/twap" + "github.com/osmosis-labs/osmosis/v13/x/twap/types" +) + +type computeTwapTestCase struct { + startRecord types.TwapRecord + endRecord types.TwapRecord + twapStrategies []twap.TwapStrategy + quoteAsset string + expTwap sdk.Dec + expErr bool + expPanic bool +} + +var ( + oneHundredYears = OneSec.MulInt64(60 * 60 * 24 * 365 * 100) +) + +// TestComputeArithmeticTwap tests computeTwap on various inputs. +// The test vectors are structured by setting up different start and records, +// based on time interval, and their accumulator values. +// Then an expected TWAP is provided in each test case, to compare against computed. +func (s *TestSuite) TestComputeTwap() { + arithStrategy := &twap.ArithmeticTwapStrategy{ + TwapKeeper: *s.App.TwapKeeper, + } + + geomStrategy := &twap.GeometricTwapStrategy{ + TwapKeeper: *s.App.TwapKeeper, + } + + tests := map[string]computeTwapTestCase{ + "arithmetic only, basic: spot price = 1 for one second, 0 init accumulator": { + startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newOneSidedRecord(tPlusOne, OneSec, true), + quoteAsset: denom0, + twapStrategies: []twap.TwapStrategy{ + arithStrategy, + }, + expTwap: sdk.OneDec(), + }, + // this test just shows what happens in case the records are reversed. + // It should return the correct result, even though this is incorrect internal API usage + "arithmetic only: invalid call: reversed records of above": { + startRecord: newOneSidedRecord(tPlusOne, OneSec, true), + endRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + quoteAsset: denom0, + twapStrategies: []twap.TwapStrategy{ + arithStrategy, + }, + expTwap: sdk.OneDec(), + }, + "same record: denom0, end spot price = 0": { + startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + quoteAsset: denom0, + twapStrategies: []twap.TwapStrategy{ + arithStrategy, + geomStrategy, + }, + expTwap: sdk.ZeroDec(), + }, + "same record: denom1, end spot price = 1": { + startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + quoteAsset: denom1, + twapStrategies: []twap.TwapStrategy{ + arithStrategy, + geomStrategy, + }, + expTwap: sdk.OneDec(), + }, + "arithmetic only: accumulator = 10*OneSec, t=5s. 0 base accum": testCaseFromDeltas( + s, sdk.ZeroDec(), tenSecAccum, 5*time.Second, sdk.NewDec(2)), + "arithmetic only: accumulator = 10*OneSec, t=100s. 0 base accum (asset 1)": testCaseFromDeltasAsset1(s, sdk.ZeroDec(), OneSec.MulInt64(10), 100*time.Second, sdk.NewDecWithPrec(1, 1)), + "geometric only: accumulator = log(10)*OneSec, t=5s. 0 base accum": geometricTestCaseFromDeltas0( + s, sdk.ZeroDec(), geometricTenSecAccum, 5*time.Second, twap.TwapPow(geometricTenSecAccum.QuoInt64(5*1000))), + "geometric only: accumulator = log(10)*OneSec, t=100s. 0 base accum (asset 1)": geometricTestCaseFromDeltas1(s, sdk.ZeroDec(), geometricTenSecAccum, 100*time.Second, sdk.OneDec().Quo(twap.TwapPow(geometricTenSecAccum.QuoInt64(100*1000)))), + "three asset same record: asset1, end spot price = 1": { + startRecord: newThreeAssetOneSidedRecord(baseTime, sdk.ZeroDec(), true)[1], + endRecord: newThreeAssetOneSidedRecord(baseTime, sdk.ZeroDec(), true)[1], + quoteAsset: denom2, + expTwap: sdk.OneDec(), + twapStrategies: []twap.TwapStrategy{ + arithStrategy, + geomStrategy, + }, + }, + } + for name, test := range tests { + s.Run(name, func() { + for _, twapStrategy := range test.twapStrategies { + actualTwap, err := twap.ComputeTwap(test.startRecord, test.endRecord, test.quoteAsset, twapStrategy) + s.Require().NoError(err) + osmoassert.DecApproxEq(s.T(), test.expTwap, actualTwap, osmomath.GetPowPrecision()) + } + }) + } +} + +// TestComputeArithmeticStrategyTwap tests arithmetic strategy's computeTwap +// Contrary to computeTwap function (logic.go) that handles the cases with zero delta correctly, +// this function should panic in case of zero delta. +func (s *TestSuite) TestComputeArithmeticStrategyTwap() { + pointOneAccum := OneSec.QuoInt64(10) + tests := map[string]computeTwapTestCase{ + "basic: spot price = 1 for one second, 0 init accumulator": { + startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newOneSidedRecord(tPlusOne, OneSec, true), + quoteAsset: denom0, + expTwap: sdk.OneDec(), + }, + // this test just shows what happens in case the records are reversed. + // It should return the correct result, even though this is incorrect internal API usage + "invalid call: reversed records of above": { + startRecord: newOneSidedRecord(tPlusOne, OneSec, true), + endRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + quoteAsset: denom0, + expTwap: sdk.OneDec(), + }, + "same record (zero time delta), division by 0 - panic": { + startRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newOneSidedRecord(baseTime, sdk.ZeroDec(), true), + quoteAsset: denom0, + expPanic: true, + }, + "accumulator = 10*OneSec, t=5s. 0 base accum": testCaseFromDeltas( + s, sdk.ZeroDec(), tenSecAccum, 5*time.Second, sdk.NewDec(2)), + "accumulator = 10*OneSec, t=3s. 0 base accum": testCaseFromDeltas( + s, sdk.ZeroDec(), tenSecAccum, 3*time.Second, ThreePlusOneThird), + "accumulator = 10*OneSec, t=100s. 0 base accum": testCaseFromDeltas( + s, sdk.ZeroDec(), tenSecAccum, 100*time.Second, sdk.NewDecWithPrec(1, 1)), + + // test that base accum has no impact + "accumulator = 10*OneSec, t=5s. 10 base accum": testCaseFromDeltas( + s, sdk.NewDec(10), tenSecAccum, 5*time.Second, sdk.NewDec(2)), + "accumulator = 10*OneSec, t=3s. 10*second base accum": testCaseFromDeltas( + s, tenSecAccum, tenSecAccum, 3*time.Second, ThreePlusOneThird), + "accumulator = 10*OneSec, t=100s. .1*second base accum": testCaseFromDeltas( + s, pointOneAccum, tenSecAccum, 100*time.Second, sdk.NewDecWithPrec(1, 1)), + + "accumulator = 10*OneSec, t=100s. 0 base accum (asset 1)": testCaseFromDeltasAsset1(s, sdk.ZeroDec(), OneSec.MulInt64(10), 100*time.Second, sdk.NewDecWithPrec(1, 1)), + } + for name, test := range tests { + s.Run(name, func() { + osmoassert.ConditionalPanic(s.T(), test.expPanic, func() { + arithmeticStrategy := &twap.ArithmeticTwapStrategy{TwapKeeper: *s.App.TwapKeeper} + actualTwap := arithmeticStrategy.ComputeTwap(test.startRecord, test.endRecord, test.quoteAsset) + s.Require().Equal(test.expTwap, actualTwap) + }) + }) + } +} + +// TestComputeGeometricStrategyTwap tests geometric strategy's computeTwap +// Contrary to computeTwap function (logic.go) that handles the cases with zero delta correctly, +// this function should panic in case of zero delta. +func (s *TestSuite) TestComputeGeometricStrategyTwap() { + tests := map[string]computeTwapTestCase{ + // basic test for both denom with zero start accumulator + "basic denom0: spot price = 1 for one second, 0 init accumulator": { + startRecord: newOneSidedGeometricRecord(baseTime, sdk.ZeroDec()), + endRecord: newOneSidedGeometricRecord(tPlusOne, geometricTenSecAccum), + quoteAsset: denom0, + expTwap: sdk.NewDec(10), + }, + "basic denom1: spot price = 1 for one second, 0 init accumulator": { + startRecord: newOneSidedGeometricRecord(baseTime, sdk.ZeroDec()), + endRecord: newOneSidedGeometricRecord(tPlusOne, geometricTenSecAccum), + quoteAsset: denom1, + expTwap: sdk.OneDec().Quo(sdk.NewDec(10)), + }, + + // basic test for both denom with non-zero start accumulator + "denom0: start accumulator of 10 * 1s, end accumulator 10 * 1s + 20 * 2s = 20": { + startRecord: newOneSidedGeometricRecord(baseTime, geometricTenSecAccum), + endRecord: newOneSidedGeometricRecord(baseTime.Add(time.Second*2), geometricTenSecAccum.Add(OneSec.MulInt64(2).Mul(twap.TwapLog(sdk.NewDec(20))))), + quoteAsset: denom0, + expTwap: sdk.NewDec(20), + }, + "denom1 start accumulator of 10 * 1s, end accumulator 10 * 1s + 20 * 2s = 20": { + startRecord: newOneSidedGeometricRecord(baseTime, geometricTenSecAccum), + endRecord: newOneSidedGeometricRecord(baseTime.Add(time.Second*2), geometricTenSecAccum.Add(OneSec.MulInt64(2).Mul(twap.TwapLog(sdk.NewDec(20))))), + quoteAsset: denom1, + expTwap: sdk.OneDec().Quo(sdk.NewDec(20)), + }, + + // toggle time delta. + "accumulator = log(10)*OneSec, t=5s. 0 base accum": geometricTestCaseFromDeltas0( + s, sdk.ZeroDec(), geometricTenSecAccum, 5*time.Second, twap.TwapPow(geometricTenSecAccum.QuoInt64(5*1000))), + "accumulator = log(10)*OneSec, t=3s. 0 base accum": geometricTestCaseFromDeltas0( + s, sdk.ZeroDec(), geometricTenSecAccum, 3*time.Second, twap.TwapPow(geometricTenSecAccum.QuoInt64(3*1000))), + "accumulator = log(10)*OneSec, t=100s. 0 base accum": geometricTestCaseFromDeltas0( + s, sdk.ZeroDec(), geometricTenSecAccum, 100*time.Second, twap.TwapPow(geometricTenSecAccum.QuoInt64(100*1000))), + + // test that base accum has no impact + "accumulator = log(10)*OneSec, t=5s. 10 base accum": geometricTestCaseFromDeltas0( + s, logTen, geometricTenSecAccum, 5*time.Second, twap.TwapPow(geometricTenSecAccum.QuoInt64(5*1000))), + "accumulator = log(10)*OneSec, t=3s. 10*second base accum": geometricTestCaseFromDeltas0( + s, OneSec.MulInt64(10).Mul(logTen), geometricTenSecAccum, 3*time.Second, twap.TwapPow(geometricTenSecAccum.QuoInt64(3*1000))), + "accumulator = 10*OneSec, t=100s. .1*second base accum": geometricTestCaseFromDeltas0( + s, OneSec.MulInt64(10).Mul(logOneOverTen), geometricTenSecAccum, 100*time.Second, twap.TwapPow(geometricTenSecAccum.QuoInt64(100*1000))), + + // TODO: this is the highest price we currently support with the given precision bounds. + // Need to choose better base and potentially improve math functions to mitigate. + "price of 1_000_000 for an hour": { + startRecord: newOneSidedGeometricRecord(baseTime, sdk.ZeroDec()), + endRecord: newOneSidedGeometricRecord(baseTime.Add(time.Hour), OneSec.MulInt64(60*60).Mul(twap.TwapLog(sdk.NewDec(1_000_000)))), + quoteAsset: denom0, + expTwap: sdk.NewDec(1_000_000), + }, + // TODO: overflow tests + // - max spot price + // - large time delta + // - both + + // TODO: hand calculated tests + } + + for name, tc := range tests { + s.Run(name, func() { + osmoassert.ConditionalPanic(s.T(), tc.expPanic, func() { + geometricStrategy := &twap.GeometricTwapStrategy{TwapKeeper: *s.App.TwapKeeper} + actualTwap := geometricStrategy.ComputeTwap(tc.startRecord, tc.endRecord, tc.quoteAsset) + osmoassert.DecApproxEq(s.T(), tc.expTwap, actualTwap, osmomath.GetPowPrecision()) + }) + }) + } +} + +func (s *TestSuite) TestComputeArithmeticStrategyTwap_ThreeAsset() { + tenSecAccum := OneSec.MulInt64(10) + pointOneAccum := OneSec.QuoInt64(10) + tests := map[string]computeThreeAssetArithmeticTwapTestCase{ + "three asset basic: spot price = 1 for one second, 0 init accumulator": { + startRecord: newThreeAssetOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newThreeAssetOneSidedRecord(tPlusOne, OneSec, true), + quoteAsset: []string{denom0, denom0, denom1}, + expTwap: []sdk.Dec{sdk.OneDec(), sdk.OneDec(), sdk.OneDec()}, + }, + "three asset. accumulator = 10*OneSec, t=5s. 0 base accum": testThreeAssetCaseFromDeltas( + sdk.ZeroDec(), tenSecAccum, 5*time.Second, sdk.NewDec(2)), + + // test that base accum has no impact + "three asset. accumulator = 10*OneSec, t=5s. 10 base accum": testThreeAssetCaseFromDeltas( + sdk.NewDec(10), tenSecAccum, 5*time.Second, sdk.NewDec(2)), + "three asset. accumulator = 10*OneSec, t=100s. .1*second base accum": testThreeAssetCaseFromDeltas( + pointOneAccum, tenSecAccum, 100*time.Second, sdk.NewDecWithPrec(1, 1)), + } + for name, test := range tests { + s.Run(name, func() { + for i, startRec := range test.startRecord { + arithmeticStrategy := &twap.ArithmeticTwapStrategy{TwapKeeper: *s.App.TwapKeeper} + actualTwap := arithmeticStrategy.ComputeTwap(startRec, test.endRecord[i], test.quoteAsset[i]) + s.Require().Equal(test.expTwap[i], actualTwap) + } + }) + } +} + +func (s *TestSuite) TestComputeGeometricStrategyTwap_ThreeAsset() { + var ( + five = sdk.NewDec(5) + fiveFor3Sec = OneSec.MulInt64(3).Mul(twap.TwapLog(five)) + + ten = five.MulInt64(2) + tenFor100Sec = OneSec.MulInt64(100).Mul(twap.TwapLog(ten)) + + errTolerance = sdk.MustNewDecFromStr("0.00000001") + ) + + tests := map[string]computeThreeAssetArithmeticTwapTestCase{ + "three asset basic: spot price = 10 for one second, 0 init accumulator": { + startRecord: newThreeAssetOneSidedRecord(baseTime, sdk.ZeroDec(), true), + endRecord: newThreeAssetOneSidedRecord(tPlusOne, geometricTenSecAccum, true), + quoteAsset: []string{denom0, denom0, denom1}, + expTwap: []sdk.Dec{sdk.NewDec(10), sdk.NewDec(10), sdk.NewDec(10)}, + }, + "three asset. accumulator = 5*3Sec, t=3s, no start accum": testThreeAssetCaseFromDeltas( + sdk.ZeroDec(), fiveFor3Sec, 3*time.Second, five), + + // test that base accum has no impact + "three asset. accumulator = 5*3Sec, t=3s. 10 base accum": testThreeAssetCaseFromDeltas( + geometricTenSecAccum, fiveFor3Sec, 3*time.Second, five), + "three asset. accumulator = 100*100s, t=100s. .1*second base accum": testThreeAssetCaseFromDeltas( + twap.TwapLog(OneSec.Quo(ten)), tenFor100Sec, 100*time.Second, ten), + } + for name, test := range tests { + s.Run(name, func() { + for i, startRec := range test.startRecord { + geometricStrategy := &twap.GeometricTwapStrategy{TwapKeeper: *s.App.TwapKeeper} + actualTwap := geometricStrategy.ComputeTwap(startRec, test.endRecord[i], test.quoteAsset[i]) + osmoassert.DecApproxEq(s.T(), test.expTwap[i], actualTwap, errTolerance) + } + }) + } +} + +// TestTwapPow_MaxSpotPrice_NoOverflow tests that no overflow occurs at log_2{max spot price values}. +// and that the epsilon is within the tolerated multiplicative error. +func (s *TestSuite) TestTwapLogPow_MaxSpotPrice_NoOverflow() { + errTolerance := osmomath.ErrTolerance{ + MultiplicativeTolerance: sdk.OneDec().Quo(sdk.NewDec(10).Power(18)), + RoundingDir: osmomath.RoundDown, + } + + oneHundredYearsTimesMaxSpotPrice := oneHundredYears.Mul(gammtypes.MaxSpotPrice) + + exponentValue := twap.TwapLog(oneHundredYearsTimesMaxSpotPrice) + finalValue := twap.TwapPow(exponentValue) + + s.Require().Equal(0, errTolerance.CompareBigDec(osmomath.BigDecFromSDKDec(oneHundredYearsTimesMaxSpotPrice), osmomath.BigDecFromSDKDec(finalValue))) +} diff --git a/x/twap/types/expected_interfaces.go b/x/twap/types/expected_interfaces.go index 8ed0bfe4e58..1a8dadb6d78 100644 --- a/x/twap/types/expected_interfaces.go +++ b/x/twap/types/expected_interfaces.go @@ -12,7 +12,7 @@ type AmmInterface interface { CalculateSpotPrice( ctx sdk.Context, poolID uint64, - baseAssetDenom string, quoteAssetDenom string, + baseAssetDenom string, ) (price sdk.Dec, err error) } diff --git a/x/twap/types/genesis.go b/x/twap/types/genesis.go index ac47da89bbd..fdd273bcd7b 100644 --- a/x/twap/types/genesis.go +++ b/x/twap/types/genesis.go @@ -81,5 +81,9 @@ func (t TwapRecord) validate() error { if t.P1ArithmeticTwapAccumulator.IsNil() || t.P1ArithmeticTwapAccumulator.IsNegative() { return fmt.Errorf("twap record p1 accumulator cannot be negative, was (%s)", t.P1ArithmeticTwapAccumulator) } + + if t.GeometricTwapAccumulator.IsNil() || t.GeometricTwapAccumulator.IsNegative() { + return fmt.Errorf("twap record geometric accumulator cannot be negative, was (%s)", t.GeometricTwapAccumulator) + } return nil } diff --git a/x/twap/types/genesis_test.go b/x/twap/types/genesis_test.go index 313668b1002..bc65efe03ad 100644 --- a/x/twap/types/genesis_test.go +++ b/x/twap/types/genesis_test.go @@ -28,6 +28,7 @@ var ( P1LastSpotPrice: sdk.OneDec(), P0ArithmeticTwapAccumulator: sdk.OneDec(), P1ArithmeticTwapAccumulator: sdk.OneDec(), + GeometricTwapAccumulator: sdk.OneDec(), } ) @@ -55,6 +56,7 @@ func TestGenesisState_Validate(t *testing.T) { P1LastSpotPrice: sdk.OneDec(), P0ArithmeticTwapAccumulator: sdk.OneDec(), P1ArithmeticTwapAccumulator: sdk.OneDec(), + GeometricTwapAccumulator: sdk.OneDec(), }, { PoolId: basePoolId, @@ -66,6 +68,7 @@ func TestGenesisState_Validate(t *testing.T) { P1LastSpotPrice: sdk.OneDec(), P0ArithmeticTwapAccumulator: sdk.OneDec(), P1ArithmeticTwapAccumulator: sdk.OneDec(), + GeometricTwapAccumulator: sdk.OneDec(), }, }) ) @@ -294,6 +297,23 @@ func TestTWAPRecord_Validate(t *testing.T) { }(), expectedErr: true, }, + "invalid geometric accum: nil": { + twapRecord: func() TwapRecord { + r := TwapRecord{ + PoolId: basePoolId, + Asset0Denom: denom0, + Asset1Denom: denom1, + Height: 3, + Time: tPlusOne.Add(time.Second), + P0LastSpotPrice: sdk.OneDec(), + P1LastSpotPrice: sdk.OneDec(), + P0ArithmeticTwapAccumulator: sdk.OneDec(), + P1ArithmeticTwapAccumulator: sdk.OneDec(), + } + return r + }(), + expectedErr: true, + }, } // make test cases symmetric testCasesSym := map[string]testcase{} diff --git a/x/twap/types/twapmock/amminterface.go b/x/twap/types/twapmock/amminterface.go index 4b7b408d306..3f2ba2df9ab 100644 --- a/x/twap/types/twapmock/amminterface.go +++ b/x/twap/types/twapmock/amminterface.go @@ -52,7 +52,7 @@ func (p *ProgrammedAmmInterface) ProgramPoolDenomsOverride(poolId uint64, overri } func (p *ProgrammedAmmInterface) ProgramPoolSpotPriceOverride(poolId uint64, - baseDenom, quoteDenom string, overrideSp sdk.Dec, overrideErr error, + quoteDenom, baseDenom string, overrideSp sdk.Dec, overrideErr error, ) { input := SpotPriceInput{poolId, baseDenom, quoteDenom} p.programmedSpotPrice[input] = SpotPriceResult{overrideSp, overrideErr} @@ -71,12 +71,12 @@ func (p *ProgrammedAmmInterface) GetPoolDenoms(ctx sdk.Context, poolId uint64) ( func (p *ProgrammedAmmInterface) CalculateSpotPrice(ctx sdk.Context, poolId uint64, - baseDenom, - quoteDenom string, + quoteDenom, + baseDenom string, ) (price sdk.Dec, err error) { input := SpotPriceInput{poolId, baseDenom, quoteDenom} if res, ok := p.programmedSpotPrice[input]; ok { return res.Sp, res.Err } - return p.underlyingKeeper.CalculateSpotPrice(ctx, poolId, baseDenom, quoteDenom) + return p.underlyingKeeper.CalculateSpotPrice(ctx, poolId, quoteDenom, baseDenom) } From ea3af42d234e59998be1901e65c68c89c1b58a3d Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 4 Jan 2023 15:03:56 -0600 Subject: [PATCH 20/30] change to gamm --- osmomath/exp2_test.go | 7 +++---- tests/ibc-hooks/ibc_middleware_test.go | 8 ++++---- x/ibc-rate-limit/testutil/wasm.go | 3 +-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/osmomath/exp2_test.go b/osmomath/exp2_test.go index 0955251dd76..0d62bcb3a73 100644 --- a/osmomath/exp2_test.go +++ b/osmomath/exp2_test.go @@ -6,8 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" - "github.com/osmosis-labs/osmosis/v13/app/apptesting/osmoassert" - "github.com/osmosis-labs/osmosis/v13/osmomath" + "github.com/osmosis-labs/osmosis/osmomath" ) var ( @@ -155,7 +154,7 @@ func TestExp2ChebyshevRationalApprox(t *testing.T) { for name, tc := range tests { tc := tc t.Run(name, func(t *testing.T) { - osmoassert.ConditionalPanic(t, tc.expectPanic, func() { + osmomath.ConditionalPanic(t, tc.expectPanic, func() { // System under test. result := osmomath.Exp2ChebyshevRationalApprox(tc.exponent) @@ -289,7 +288,7 @@ func TestExp2(t *testing.T) { for name, tc := range tests { tc := tc t.Run(name, func(t *testing.T) { - osmoassert.ConditionalPanic(t, tc.expectPanic, func() { + osmomath.ConditionalPanic(t, tc.expectPanic, func() { // System under test. result := osmomath.Exp2(tc.exponent) diff --git a/tests/ibc-hooks/ibc_middleware_test.go b/tests/ibc-hooks/ibc_middleware_test.go index 35bd95ffd30..0bc35313625 100644 --- a/tests/ibc-hooks/ibc_middleware_test.go +++ b/tests/ibc-hooks/ibc_middleware_test.go @@ -510,12 +510,12 @@ const ( ) // This is a copy of the SetupGammPoolsWithBondDenomMultiplier from the test helpers, but using chainA instead of the default -func (suite *HooksTestSuite) SetupPools(chainName Chain, multipliers []sdk.Dec) []gammtypes.CFMMPoolI { +func (suite *HooksTestSuite) SetupPools(chainName Chain, multipliers []sdk.Dec) []gammtypes.PoolI { chain := suite.GetChain(chainName) acc1 := chain.SenderAccount.GetAddress() bondDenom := chain.GetOsmosisApp().StakingKeeper.BondDenom(chain.GetContext()) - pools := []gammtypes.CFMMPoolI{} + pools := []gammtypes.PoolI{} for index, multiplier := range multipliers { token := fmt.Sprintf("token%d", index) uosmoAmount := gammtypes.InitPoolSharesSupply.ToDec().Mul(multiplier).RoundInt() @@ -542,7 +542,7 @@ func (suite *HooksTestSuite) SetupPools(chainName Chain, multipliers []sdk.Dec) } msg := balancer.NewMsgCreateBalancerPool(acc1, poolParams, poolAssets, defaultFutureGovernor) - poolId, err := chain.GetOsmosisApp().SwapRouterKeeper.CreatePool(chain.GetContext(), msg) + poolId, err := chain.GetOsmosisApp().GAMMKeeper.CreatePool(chain.GetContext(), msg) suite.Require().NoError(err) pool, err := chain.GetOsmosisApp().GAMMKeeper.GetPoolAndPoke(chain.GetContext(), poolId) @@ -827,7 +827,7 @@ func (suite *HooksTestSuite) CreateIBCPoolOnChainB() { } msg := balancer.NewMsgCreateBalancerPool(acc1, poolParams, poolAssets, defaultFutureGovernor) - poolId, err := chain.GetOsmosisApp().SwapRouterKeeper.CreatePool(chain.GetContext(), msg) + poolId, err := chain.GetOsmosisApp().GAMMKeeper.CreatePool(chain.GetContext(), msg) suite.Require().NoError(err) _, err = chain.GetOsmosisApp().GAMMKeeper.GetPoolAndPoke(chain.GetContext(), poolId) diff --git a/x/ibc-rate-limit/testutil/wasm.go b/x/ibc-rate-limit/testutil/wasm.go index 75be4e54ec5..48206fbe6ae 100644 --- a/x/ibc-rate-limit/testutil/wasm.go +++ b/x/ibc-rate-limit/testutil/wasm.go @@ -62,10 +62,9 @@ func (chain *TestChain) InstantiateRLContract(suite *suite.Suite, quotas string) return addr } -func (chain *TestChain) InstantiateContract(suite *suite.Suite, msg string) sdk.AccAddress { +func (chain *TestChain) InstantiateContract(suite *suite.Suite, msg string, codeID uint64) sdk.AccAddress { osmosisApp := chain.GetOsmosisApp() contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisApp.WasmKeeper) - codeID := uint64(1) creator := osmosisApp.AccountKeeper.GetModuleAddress(govtypes.ModuleName) addr, _, err := contractKeeper.Instantiate(chain.GetContext(), codeID, creator, creator, []byte(msg), "contract", nil) suite.Require().NoError(err) From 813a6e8f6d714922ea4bbcce1af42f4470c95f82 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 4 Jan 2023 15:14:01 -0600 Subject: [PATCH 21/30] fix balancer test --- .../pool-models/balancer/pool_suite_test.go | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/x/gamm/pool-models/balancer/pool_suite_test.go b/x/gamm/pool-models/balancer/pool_suite_test.go index 8cddfa5acf6..848636f992b 100644 --- a/x/gamm/pool-models/balancer/pool_suite_test.go +++ b/x/gamm/pool-models/balancer/pool_suite_test.go @@ -713,57 +713,57 @@ func (suite *KeeperTestSuite) TestBalancerSpotPriceBounds() { tests := []struct { name string - baseDenomPoolInput sdk.Coin - baseDenomWeight sdk.Int quoteDenomPoolInput sdk.Coin quoteDenomWeight sdk.Int + baseDenomPoolInput sdk.Coin + baseDenomWeight sdk.Int expectError bool expectedOutput sdk.Dec }{ { name: "spot price check at max bitlen supply", // 2^196, as >= 2^197 trips max bitlen of 256 - baseDenomPoolInput: sdk.NewCoin(baseDenom, sdk.MustNewDecFromStr("100433627766186892221372630771322662657637687111424552206336").TruncateInt()), - baseDenomWeight: sdk.NewInt(100), - quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.MustNewDecFromStr("100433627766186892221372630771322662657637687111424552206337").TruncateInt()), + quoteDenomPoolInput: sdk.NewCoin(baseDenom, sdk.MustNewDecFromStr("100433627766186892221372630771322662657637687111424552206336").TruncateInt()), quoteDenomWeight: sdk.NewInt(100), + baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.MustNewDecFromStr("100433627766186892221372630771322662657637687111424552206337").TruncateInt()), + baseDenomWeight: sdk.NewInt(100), expectError: false, expectedOutput: sdk.MustNewDecFromStr("1.000000000000000000"), }, { name: "spot price check at min supply", - baseDenomPoolInput: sdk.NewCoin(baseDenom, sdk.OneInt()), - baseDenomWeight: sdk.NewInt(100), - quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()), + quoteDenomPoolInput: sdk.NewCoin(baseDenom, sdk.OneInt()), quoteDenomWeight: sdk.NewInt(100), + baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()), + baseDenomWeight: sdk.NewInt(100), expectError: false, expectedOutput: sdk.MustNewDecFromStr("1.000000000000000000"), }, { name: "max spot price with equal weights", - baseDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt()), - baseDenomWeight: sdk.NewInt(100), - quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()), + quoteDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt()), quoteDenomWeight: sdk.NewInt(100), + baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()), + baseDenomWeight: sdk.NewInt(100), expectError: false, expectedOutput: types.MaxSpotPrice, }, { // test int overflows name: "max spot price with extreme weights", - baseDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt()), - baseDenomWeight: sdk.OneInt(), - quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()), - quoteDenomWeight: sdk.NewInt(1 << 19), + quoteDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt()), + quoteDenomWeight: sdk.OneInt(), + baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()), + baseDenomWeight: sdk.NewInt(1 << 19), expectError: true, }, { name: "greater than max spot price with equal weights", // Max spot price capped at 2^160 - baseDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt().Add(sdk.OneInt())), - baseDenomWeight: sdk.NewInt(100), - quoteDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()), + quoteDenomPoolInput: sdk.NewCoin(baseDenom, types.MaxSpotPrice.TruncateInt().Add(sdk.OneInt())), quoteDenomWeight: sdk.NewInt(100), + baseDenomPoolInput: sdk.NewCoin(quoteDenom, sdk.OneInt()), + baseDenomWeight: sdk.NewInt(100), expectError: true, }, { @@ -806,7 +806,7 @@ func (suite *KeeperTestSuite) TestBalancerSpotPriceBounds() { sut := func() { spotPrice, err := suite.App.GAMMKeeper.CalculateSpotPrice(suite.Ctx, - poolId, tc.baseDenomPoolInput.Denom, tc.quoteDenomPoolInput.Denom) + poolId, tc.quoteDenomPoolInput.Denom, tc.baseDenomPoolInput.Denom) if tc.expectError { suite.Require().Error(err, "test: %s", tc.name) } else { @@ -820,7 +820,6 @@ func (suite *KeeperTestSuite) TestBalancerSpotPriceBounds() { }) } } - func (suite *KeeperTestSuite) TestCalcJoinPoolShares() { // We append shared calcSingleAssetJoinTestCases with multi-asset and edge // test cases defined in multiAssetExactInputTestCases and multiAssetUneverInputTestCases. From 640dfb9f9a06a149c7111086d063e4268a284cd9 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 4 Jan 2023 15:34:51 -0600 Subject: [PATCH 22/30] bump to v14 upgrade --- Makefile | 2 +- app/app.go | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2792b5bceed..d60e5033a3a 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ SDK_PACK := $(shell go list -m github.com/cosmos/cosmos-sdk | sed 's/ /\@/g') GO_VERSION := $(shell cat go.mod | grep -E 'go [0-9].[0-9]+' | cut -d ' ' -f 2) DOCKER := $(shell which docker) BUILDDIR ?= $(CURDIR)/build -E2E_UPGRADE_VERSION := "v13" +E2E_UPGRADE_VERSION := "v14" GO_MAJOR_VERSION = $(shell go version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f1) diff --git a/app/app.go b/app/app.go index 9c059c0da56..82a58967eaa 100644 --- a/app/app.go +++ b/app/app.go @@ -10,6 +10,7 @@ import ( "strings" vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + "github.com/osmosis-labs/osmosis/osmoutils" "github.com/CosmWasm/wasmd/x/wasm" @@ -49,6 +50,7 @@ import ( v11 "github.com/osmosis-labs/osmosis/v13/app/upgrades/v11" v12 "github.com/osmosis-labs/osmosis/v13/app/upgrades/v12" v13 "github.com/osmosis-labs/osmosis/v13/app/upgrades/v13" + v14 "github.com/osmosis-labs/osmosis/v13/app/upgrades/v14" v3 "github.com/osmosis-labs/osmosis/v13/app/upgrades/v3" v4 "github.com/osmosis-labs/osmosis/v13/app/upgrades/v4" v5 "github.com/osmosis-labs/osmosis/v13/app/upgrades/v5" @@ -95,7 +97,7 @@ var ( // _ sdksimapp.App = (*OsmosisApp)(nil) - Upgrades = []upgrades.Upgrade{v4.Upgrade, v5.Upgrade, v7.Upgrade, v9.Upgrade, v11.Upgrade, v12.Upgrade, v13.Upgrade} + Upgrades = []upgrades.Upgrade{v4.Upgrade, v5.Upgrade, v7.Upgrade, v9.Upgrade, v11.Upgrade, v12.Upgrade, v13.Upgrade, v14.Upgrade} Forks = []upgrades.Fork{v3.Fork, v6.Fork, v8.Fork, v10.Fork} ) From f7ded6ce47c3227150f5e19b93f237987b565caf Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 4 Jan 2023 15:56:47 -0600 Subject: [PATCH 23/30] e2e fix --- tests/e2e/e2e_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 1561a1ece7b..0ee4cff4f10 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -161,10 +161,9 @@ func (s *IntegrationTestSuite) TestIBCTokenTransferRateLimiting() { fmt.Println(wd, projectDir) err = copyFile(projectDir+"/x/ibc-rate-limit/bytecode/rate_limiter.wasm", wd+"/scripts/rate_limiter.wasm") s.NoError(err) - // set LatestCodeId to 1 since we upload a contract in the upgrade handler for v13 - chainA.LatestCodeId = 1 + node.StoreWasmCode("rate_limiter.wasm", initialization.ValidatorWalletName) - chainA.LatestCodeId += 1 + chainA.LatestCodeId = 1 node.InstantiateWasmContract( strconv.Itoa(chainA.LatestCodeId), fmt.Sprintf(`{"gov_module": "%s", "ibc_module": "%s", "paths": [{"channel_id": "channel-0", "denom": "%s", "quotas": [{"name":"testQuota", "duration": 86400, "send_recv": [1, 1]}] } ] }`, node.PublicAddress, node.PublicAddress, initialization.OsmoToken.Denom), From da63fa8e9d0d3554f8de9c9435fa002db7cd447b Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 4 Jan 2023 20:56:08 -0600 Subject: [PATCH 24/30] add remaining diff from main to ibc-rate-limit --- x/ibc-rate-limit/bytecode/rate_limiter.wasm | Bin 265786 -> 264433 bytes .../contracts/rate-limiter/.gitignore | 15 ------------- .../contracts/rate-limiter/src/error.rs | 2 +- .../rate-limiter/src/integration_tests.rs | 21 +++++++++++++----- x/ibc-rate-limit/ibc_module.go | 5 +++++ x/ibc-rate-limit/module.go | 4 +--- 6 files changed, 23 insertions(+), 24 deletions(-) delete mode 100644 x/ibc-rate-limit/contracts/rate-limiter/.gitignore diff --git a/x/ibc-rate-limit/bytecode/rate_limiter.wasm b/x/ibc-rate-limit/bytecode/rate_limiter.wasm index caaa0bd6975c2d52f31bc208d2ba8db2a825badd..30b545e0612d86ee2751dbcfa11595954e0575e5 100644 GIT binary patch literal 264433 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®DTRGfgV2Gtk)wKJ`nVy5}E!1e?-M*0_`U|ALXk z`N4Rq^T`A$!l(PM#T1M4f5hwAEGcj>&R0%%zK)T=jYE(6Xr`uSdiAoQ9!hO~JD3@B z+o5>q-0Q8WZx1vTho-W|z4_)nS46vL6-jXr>P_;;zX$KpIduxGTkogx3$tXp^XvL~ zD8|af0!1K6TEUS}2tH6y`HBprk%urrjCWJ7q8^xN! z7L>`)r)y4*%r!Aa`odFI=w|sM?=10w^7@}QNM+Ji@g_-Ih!@oYok~L}^ff4LEw(Zs zZLQFAjIE%RK#iP)b3g$aU=9kZQp?prE6>78E5$I;;tW#-^`PKm|00>(*D$qQFVyl3 z&Y)b`r1M4b@l&yAtU|TxgM`ib=T=V z*JWIPi=r2C{UzQ{a{UFaFUcF-3o-rn$^0w-*{{@oBmA(sdP#l}kf3{i99@Oo1^?tx zcO&*eUhj^##+nS!z%m=gDzMDj7~4?QWb|io7cppcsS1j(pq$?2rv{3g@*<-u@{KtE zZvp)FWoY4~eeQsNG?qP-pWqRcdou1d1?Hqnq<1np5kR~n>0U}_+buj|9)E$JC}w+G zH`ALPQTH-N>f`5c7;nYLTgm^sx{zhX2acCGViVx1qF?w1fX7+&&EGG{3JN+DFjJO))b-?H`plhYfJVoPFbOFbMlj z@F-t(RU2F0nDT%!7mFYRH662(&T{v~un*ni5nVeL_r}C>5e{3@9TA39&k-kohBq1gat!(DcXw30 z#($Ud-%DM(^if*g1xW<)49Okm!%;mHFLtqMndn(AnIewF^Jt;J>^(Hx3Gc_7*_dh!X}DVOigy0-C%PDC~>L z=%-88v@)S12yO~GYu;Dyjv5&2zzA?2tvibzsUvWWH32HM0o4kuS-^;4)~3g*nn+FH z&T9VP5$L-HcLEwPDo9lG-_*mp9@0G?+LynrhogEJfv{0=amoclD8QYjhHI}3*KQ8y zaNY6}EBR2(RG6nt23Hj`SIjOp+yFv4=t!f~9z>8sz9J^BjHQ)STzuKJuLHlO8Y=5g^xeU{F zL3S+1XQT9qeh1_#ruoT%2ix@ERQVvy=-d$riY;5yQwooq(i~TIF0D$Q(SbCd zvzI7jGzuK0b6#qkR_kua(u<=H)w<`=Hy2G`0cVB!xvI@DE{;CP-^u9bYk6nyo)(h@ zCZhRU$~O~~jD0J@+GVWsQ6Xdd9Fyix7@Cl@gEICgMIRUFh=j}r89QsNXfk%zWUMJ& zlmjiFcBlstoz8m8ttRA{$4Fy7@gA%%Xi*W5K#M!#?n_%l36~y*WUf?^SPx=1BKI!2 z@SZg(potI2Y!khg;9usH%^1tkF(PS?U=oTOOT`ytz=jqbFFFh_AqSuh3^WD_=Y z60-5eLZ|>;z{7fY+4rS~L3C}9x|!F*0OcimXh8Ns6mkmTAgJ;e60niL76PD1fI(pf zo`;Ns(nPEI;VOx_jakb%RMASH(@L5?m|$xNL}E>}Me3~0ljlER0Z4@fH#yEVMhi&3|Cs#}l_AcW+L z!@7=a0V#YVAwf+zB}kD1J7%rA&NfNnl0|gcLZ|48FNDwsyitaGvdP-oW`q6mfyrzLphW-Z%cDm^&$1G+My zw_n#yTap=FFEzV0%{FgM&p_$<=~VKbxSkVkcD~)s>eYdCDtj@pKbxDwi{~ z_{_S}a=+a}6tKu+=%MPz`aYm8s!vJrDYN%?xVv(9lC3Zin;%N1x`|Jj5qgzTl&w%O z*&K(&!@s?brh2h3_}66W8p{nErNY#8g<#$-U0E!jzUTe*Yw~n&cLg85n2D=fk_(g3JNsTq zMUR44@>Haf?v>oBzVn;P-`=YSGyhil=nm~*ZSoaxMrt(B+mUp);EX6dZ~^}%i#jFS z%K=DNSIlOudWfJZPXTMy=EKa?jtLc@gzW*f*6>Gw8a_!S8|hYM-qhVEA(qRn2Zl7z zn?i>x{V#cXGl4l(P&VsM3g1}MKvA`xOE>~AS?$^HRpQIp(15@`8C_5Haw2qpLlHHw zWVz5EVXGco6Ff(7^h!l&EQBy(6iEodQFwQ)S1rwQcxs@(vh$p&N-NsHiY22l_f|??t`2QpB00U<<+O}y?}&leZ?kT9O$!+l-gq56!maj4 zNPGk3%9hD_Cy>JC4kQ8rnyJNK%&t=Hg}BPmfp|u}h-Ww{IBkJyg1vWWw$~iF&1xMm zz1D&j0_%5$fp%v@i==}~vA*RgIuz>tFh?m+G=pYLB~F0IuI)1wL(SVx!IRNzdoRi- zr^hNQqNo)$vlr!;OpC4akspFz$8h3-i}A&a^3But@A#+qC%T(cHO!nFFMdD9_PJCI zT&)J$=*Y?F8ium@8u;>MuiC?tz*b1s&CK16YKD(7ZtF64#C+V2=ymNC*=GJx$XmFx zxA_fNOhCZBhXJD6faEhXyic0cUq*S#;bV^!@^5p04X3fsEViJe%F8*O&BK z28oqXlmdy?JV?NkHk20q6pXqp1B8?ba4^=QnhApg)I1q&>LDJ01WK-&UvW(vGqVMb zWwUxk_wN|Jt9SXm^y2az*@0`tZB7J;0>noxG&I#~Wz`=7B32xHY6zlNqxC-7h`)?z z%}Nd&YxJV#7OnHf;(vj= z0Hu`bYpgnWPGc&-t3=VZg?&M?Od>EErV7xA6LKj84 zS;Hg1HYn)FVL`se@R!#~bkohP5x>$N_5UhD>15_>_&VvDsz6Ctu)-`FH8Uur- zl8d9ChLt9xpJm?2ow3OX7r_vBchbGYV>`0F!!(D-28JQ3SS%0+q!yP0q#M*feAAx< zYWaI`R|fr4_cQTN&Cg_7Vx}T+$kOj#>}+$8BKYz`C8IOHv>p6XT%Z}i+t{fBugxyr zvj;^WP}*pU1`E2e$*7r1ms#jZ+H>3=s4y^s)0Jj-98u$@0;8^ED}c3mM3~fOvg30p z>nOiWwg)d!Ji4>yVmvV-^}U3-HeflfNl5Xka(q21%@o*G^v;ZRd?smzss=dt0NdBR z(o_?`oiF2v-7AaK72iaH;~XZ^E2kJdwXh3-MEFJjnFyy8Rj8+f8}9X zXRWKuB-i+Mx>vIvH`a77d#4olhy&6Di?YGMxw6T@b;JeQ zy#&!}Bq3^N{)`1CTNpW4=!SR%(}VBFfVYAqioj8t_N4`Bfr}_VmC8M6iJ4+HE+4LY6n=eM9JCQ8*H%lg? zZLqq}?C96au#CSMO^;omHFZnJ*4v27&Ti$@wiN!J?dOyDAq&HnqOF6BUVv~;GMX{+>YaC5-j&7Y}rdJ2NRmV)|iIyKliWi#S)=WzDg}wb?8L+B0Q3L zt#lnl{u5226fK!GraC60u97v%(P+-a(lZh@ieW}8tGji5xSrm1E07)OQl7DCHkY~K zHK9s!XwdHJVwu@j0$B#wmnSER8ra~bxIy_wafXc^}oNtwt zxeztCj?B=s35kq$ieMZj%w%+-Nq=+0FJd4_u?cb!d9e{)ZKf4?H+^WCv%FHDVxE=*Rl`WA9fStqb1!YIrtTKk5jDD+lAFXGCANMc##HaXtR$Y_8FxmvO0 zVS!GGqku%ilw74GEDh6YJ1QVb2)bKaAx7gTC#9@qeCCTkn5#%=u0*o=F?fUE?h>Vh zw3(Gv03}g4%aJT#7;-NXauwSVf=`w?xdFrA)_UC=mDO)J4Y;P`+@bXuX{IR=rhb*0 ztGg!XFFyB);)atzLrENztl5loRpIE0W}`(1H89>mGAmcyqdmb~DM_M@ToNsm)6b3m z^s{Pa`q|7Li#8D*sqj+)G4Xd{Eeg4!EzQ3d@4*!9iCNnTX z_hx8`jvKm1gl^XvV&)JQ$kY#JyBOj`a*^OaNaC`C`g~x3D4`H097>5*Kr8`bD9=$R zd-2Fb@@gu^x)r7xcaXsJjIl9$irls7L83=|Gb!R)wo65=X@y%o}_5ZWk;gcc5@zzqXNS2S`7$ z$t23ZPC*X)r9};|%Tg&qnVJ#`iS*^Ux+sLtBmu^Zo`WWmf!)-=#t2P`{32T!=Vifd zNAwH=V2~}zdY7h@(~>)|K#Yzz9raf=rmGQWPB+xU6j?)Nn!V}B9X9JN3A2a3n9dSd zpRrl?zz6?lG|Rpd7oxrx^>-EENROl%ud!^rXv;_m(C{!w`{#0VfEuM&?{BJ+^8y~Mh z*tvoQIU~awBzyr@`d;Q?kE1}Q-4eNQhAW{JuX7D zmR6)0g}mAXP9^Qd*cHv+8C>hO06x6W&m&Hf?KtNsM+{nl6nF6lnY55K$_km?nl3~P zYW_54HWXwItP>QZgIL4(6{O8_lGv0AD;~@(VurE_(1i_UvATOo=(`96sDj*6mA`)O{!^EO+_#I50(0x6%+o zNGK6h)QOOYAn;TyK~;}_sz0UZ+1?ff9F&<{(UTes!Q(bQl zHdsO^ka6+k9XRne$ta)oGVsSM^doxmA5rBz7{oO{=MjN<$X1RU5L9 zldRosN_@4|a91;O#`KI}pu(HNV0npss0g9zzPT_stwiX@3BcG27AJ|?Sk_9>7C0x8 zN8+woV<+OC5*^!MD{Bfx0MXFKBEx?2@$c%yW{Dg&Soq8k~CMIm!iSjwPuQ7tigsc|YE( zGZ@ec42rgGs*;>^Myr4Xh?fnqB0xj)dMEu+Tan&czkC?tobusgvyy=(mV8kqcA#a| zJU}yY3t4G3L?0f$>ZvLzr@AgSi*Q815}>V9SU3rU_LVVw)HhFzEos zKow&Us?0M%+y}wGl0bp00IU@Y9+={Q=7QqzV4;Xknp3|#^6er5TYXh3r7`Rl4VzBwFZW86uwiZvAoUGTlykDHt7hoGXb^0cDzSbO7v% zC)t&~G>zhV#s7w0<6wHP@kvV2dp(j;Ls70pv5aU`!w%w6lRmAGzVb$wif`yHGpE~n zaGY*y3DHC9z9KElkm)&z+&LQpsM>2ywp)znwS~e_lM7VRLt$u-p@$>`(%Xi6&6*E zhUGVTxv0mUgl35wEDNx>lHqPPZM)6a7N8PTl|_Nj5Rt|G9W?}mx-4(L&C>3f_UfLe zaWDGMgE&&IMZW)#avhQ4D->+q6l}Fnu>KBG3t9XV{p|kZ0k4&-39=Gq34^VKjF@g;#WI^4dLfBatR;97(hxne2+fqj6G7FU zjxD|eDORm9MlXj2O<5J72yjT#vX+2Qe^`T#It`ju@e|XNBeozg*BS$brKCN*{6Gz8 z+R6eo1Wj8Rs)5GJl>v;BZ59M?jMP0ngAIm{>D5ZmtBTCU?rFJ6<*VgA*GAG1knejhf;X0O=@h--D=Aza^mFI4j?#tG6PVmPNzE|VP1y#vf^V!;9({-| z_Y#OXOZ-<|ZvCP-h#t+jK`6TqG@0U$YyxcLY)CVJlRpk^n)uO>cgp3j( z^cj*RUBYWcUZb;74j}^{eZB~$yw&XWDH8yRKSOU0yI9y zcR_(3r)2NJ5E)Rnr==(@o^fsa>_ zIHnB#C|jkPMVo_UNj^fGhb>_<1q%z!lNJ{kzV@MfV+VKQ<|%Gc8fR1+)^aVuLK zWa#!7w~C!RT5uc`4`J4gzL>khgR{FU{XvMbq_QX`0~i$X0C#UECVPSAaf7`zEu;ho z$2!PwnRx1;ZcXeSjg^gHo7#XbB_3!v>c0^eLo(umsEoKUSy4<;e&74yShz}<^T~Ab z;kE5RHL3YlG@6CBiA@nCty(FN7?g*tSpn#y5qWhshl6T3Pgajw1G+Ao2n2i=Wj}=)rBgHSPoM3$|A9)os zw=BI`O(rB;IHeIQ()iiAvxjx?`aO!9Z%VUXOM8cat?}Y@4E@<+@rX-bKk#&&n){(gzD`^+v67-m@zT(z>kA zW=3y-=W$c(J}Neanrs&dHw1Q2!Dv+*wTM(L+AFp0 zibyr!FEXEZMRZ}t765Gh0Y-&Ehygp9n+r*LphnFSko2I}Z_F%R;??|m=&<7QSKEi% z`0x!pn~;ivcp}6@=jRmFuIwS&_4D$($#URh<`(E2mkFb1>*duxH(_p*`F4me+dl>+ zBOb)@fds!1m%G*x-xX~bQkdMwXdr9AWEGts-h+=|xh>3y6-Cew0_2&k%fLVly9**I zYhuMdtAE=-HnwVL&|9TCBPDWp)N+LU!!%Zql=nG@!)(zoDg5i520an2F;l$Sp98b`wD8@E)r?mzS8-7?U zvCeMUY+Efy$+w=hxFcXdp35+c^9S}HXHG|ptLYgJ^`)jvzV#=c{^-4*IQ45!GG!9U zagtX>Y8WW%PuR?Bq-FctmW`;k)^HOt<5~+eK)qUhU6q;5ysWXYp-6eq(1m%w6y4J^ z_>%r@tFK$d>TAV{nuOV$QhrOL3ac89TeMaj|43q*jL1xW!f#omYM^X-WKKk;4SE@X zd@Yoee>!MnAJ>|%U~f8tWN)e-P$8#If++u<74-&Pqhr=TOiI|3@Q0M!nc!zZ;^5f) ztTX0knJMTkKQ-)Uow1gw9Eo`>QIDG*oWmc>!-zLz%i1kZIZDi#kh4}`Ko+x?C3qr$ znNeGec<8Nxk&d}7U2tzPM)xZe;3??Z0y_{e(-oj=)ND@HD-4JY0*`^L6|Wfy0z)Ey z`?R2UwXK1I(unT%gD|8~8m-FAn2d5_KuC#E9<_H6IpM$V0%BlrO2XGY#V!bpUm16~ zC4(E*2m(Sf3eV)7@D70xa!?5K6qzf^dkZrYFY|N^O?OlaX`rP|#r`N`nG%3uWjEWY zy*uV>z=;zT^%dbE-q|3PF{*r_APTHN=!M9nNQL=c@P(gJYAKL=GKhvVCH=+Ln1sNf zL>SfFYBf$H+kv5y`$o-TeaQpcfx&i0dGc#E%PM(bJ1|s?T~Gexm%jZsfB4|zK^`o& z4Z~m))!`-t?CM0se)nYqk_OcUst?kDw3fc_?t3v{_jN~ssv<8vl;<9dGRK0+gKCfm zjQzZ@$_daF{qQi0$peI_)^CzhEaJ|(10Vn25*}flmUz-8KkVc4VH=BfYsI8i#>gFb zR9E7|Cv{aEK-Udh)8mObV-htG`2xJm2M~yBxz7&>ESCe=+e;ReqqXD*7O-);DI`>% zLel&R>lShffnSO1Yvvq3`58tIvYnl%X}&n&cjdRRiuBB2-+VHCim0Z5>R zp>5E@E`(MSSetRqYwsOOpAev`mPm3y?})oy&m3Clp%KxtUsqkHGdDJY-@3bb>X)U4BLM zum}LV`nax@mq)*2S4$`RywkJ*`#m&?u>ki^C5j3eBbYquEyxZc3i;8S(o;#d>(qfF z@c5T2Pr{5EidvkEKJP;z@I(|M(GFsh^o@8RgfwEiE%^{cWPxWxObC)7qoJU$emtm8 z|5%rs5S)rPv3^GkI>-t0s6W$)o%-eAEJ^)R;1kIcwxbs|aN>!Jk0-VuKy4M`e?(aF z+>zk+optCQOe2=_h~WhHT36g|!x{0m_dHG23!05m87lK|Q+aI-=M1+Yp=u$v2q2Q2HuD3{=85Hw#Qq z!X|5U$%?Q*DJBo=*~}Y3sMvetpx$?QkC-2KxuATGqDPj$L12fWy`w*WV}1#HL8(4q zq$aOwv!Qe=v-p&~7QMuCUSlW76!5U5LCeC8tC$Qy z{Wr-4s_kLsxx4}fWE!36Z2v5y2IBv?G@69I&>f47~Xi%t7 zna4D+CR-Z<)~vyrvdzs(O{(bjfPFtcXx}Rwo})MUyMRrA(v>uqpa#eTt(I)0%$9-- zZYr_1+^~j=)@CuM5uj+}=AgwYbG4YS7q;Af!>Uw@U}p<1EHpwJ{bjP(o7Rd{068Lj~|sC6Ah< z8=2j%X#m9-bHd3c`h*yiriuiuKum4uQ_q}m_+mQD_1tC!-3e?Q_=D@L%O_^d&F#|s zb^+UeBZ{7k-oVh+&w_g-0xDW!SSr*(6{htMP-${MJw`~e0r1Sstv|89XW~jtm?krA z!ax#ZdWN26nktc4g>p{oiWoLKjKH#WnaQ1`%UG>QQ%qJ$YUXZCQuC=v=$MZ{D} zHyJ%t$WTQdG-Pc937ISdzP4DUAG=x5Wi$8}@f$fl<^s6O=I{D0o1*K5l6}C(0Zg@3 z;90yjju)VJc&dG`t>c!&v4JX&6+`h|EvrE#{9k1Z$I1k2PK;bQZp3hG!Ukz+jvLa_ zq$WaT%!SGraO8iVfYl9sG#khIj+cuaHS-kG$t*OHdiIj>=gzT;$&vh0Zl z!dKF=OTdwwnxZFDj!j@h z28^>GU@>LA1Yef69N-#|dm*B-l(d}_O$kdg+>0_{x|FoFd?-hfrY`ynq2c>;W7mbo zH2Aqq5RoNS65cP1x*@tFq88bAE_oKJM-*psDqUqTdYXtlOOpu9t(ZhWGMGfb^OQtr z?gSruWaL@qpStoy0Q>0xc7z;!W@1t}l;s^2mFGDW@&%Cg!)Bgv1F zQ{*GDsZp9O+rpMVT$!#i^N?P8P;A4F3FfUwabYxneNMLFURD=3y638JAzNa}ugNHK zz+nGqF&KiPZGvH`up5(C_?0qijp@{#hv>$p^r6IN)DJK^o7)dw#ep&;LVF*OKOqjh z*i2YtmF{`OBJ*c9yt#+@z?(0ypSG-rn{CTNZ=Pny13Mk|bc@gtLgmCheZ3C_TAm2eV> zNi_N}V+%8>FSheQ;6i1c@M3?=Y#kfV1HeP9Y;GYWH40Ut9OqFS_5_-Q5Jq%71(T=Y zcnV5!D1;trzLQ@}+bJ2HC*Z>mr?4K=n-M!lL(PSLs9hHY2V$zOSS^wUx>FAOGdlyr zxLBv1kyO`@-He(odZoC63@y$svYtsESFG>es$Z>sQXRvgbu@u@& z^{FfV$+!HI?bE8I_(T(#{ZD)sC7TfD*t>p*Cz6{)VUy7e8OLA+W@Y)P22ghbGl`c!4(8MRpv}pbVY~gL?!K}AegVpOqnXc3m6lDm z)O)F~rQRD|LI}5jZ3wWgo>xVH3AtBcbWo>_s5<4x2=S^Msu!5fTOvTcXhVPolYS}k z*R`<{0b`w#*M{8k|JMI)g#zG;+Kd48LIgOcw&FMydo6xW@SB7K6dl`k zu29mM02U$?dU|%4$f-zjJ1mbv1nivgS>^(W%(ffgQ1>dt-c~VRlt_N#*2MW+kPSjd z+&zbdp9RmS12Aoh9V?*TSBD_=hdmUBf(m^E$K(S3j+84SuKj7?)VgsMcC=#*EzEw)z*{0nak*6)JWx{^FCcZXyBP!IaXB;CP zvjxIe6Djv7hITc8U;5|Qq>bL#*7OaS8T|wH#ynHRa{R3)8yAtW>peKLD0>RMR+cXY zS=Ud$v>x?DwHt@tu2+BPwNA+5(g-P80w6nemI5Gs1Dj68biCY}1VDFQq&5KtmeS{I zNwqwfuSV9CN-N`e=moX zJiGL_8j4=hA!~NJIHZxS{pZ(S2z(Vy%z(3ey7~nqF->b_V&1?rA-v>ETv=;KW;KJ6 zwULkR#-bR#W!es68p%m{b$c@(wKOs)e)Lv*CpD7h---xtsVF*gck!y8*X8=KQMXnY z>gDNr`LdSR?B$`aM8#Wf%h%*{*y|(js}--gEnh1yUsWI9|GyQlxh-F(92} zDcPhYb+t%^$+Vf=!$GC}&ai zh-n4v2-m$hoWMzEI(InwDP=?>fdS?4LWgkHJ->{EkSsM^DOq%5Bn27gqxnORaUA76 zWO4y*6zQC!cyxd+l5F5`O%4##fs0F@hE!v^4n}&$hiiV+w}PSj@NeWy{Ok_bd}46H zaeXl!t_cbTPUFzP!~g3Zql(DsOn_+g+Z;qMdW!1Oh^{-L50V+B&77Y7x@7G(f`ndl zT{4xEHyUqbmAlb~ERq6tQ)||9>b@H2fpp9)L@H+p=rV(HPWyM-S zoOdL9@%d3JPwqZjAS*xs=P@+j5t^AN?lOB;;qIb-rQ#v&n}DaY@Oo)1AH@!AlX+V& z9Tv;sNJ~CK<#a=Wj=P>Ol6Edv*wGWZpYdYpufHZ)zAsU}A|M-u_6dwk;pWqfbVp@7 zZ)TOu8(#HT_t!waa4`-*6QYOou!}P@3LJ=^N&I?!*kHNgv#M1Jb`Ct7MmStiG zw+43;i}0lJ^ODuiulEW$!J%4W0J1Dk%G)Gfqs(;a(+R+Cz$5N!${8O}XG!5fLl@?w z+onnu8DQ=`3=BoV!0a^xliDZ@KAzc_%r?bCV{Z~k(fl#<58dja{Y`3rCAk?f0pP;! z8Ov76?isTU8D!WdvR#U@qOwquqq`+<5-IY6`l6#= zU^=h6tATtjT#bII9e?x1FaN^NKk&HkV35=Qs~!ED0mfh z1@HJMB1Dc8@n8XV-w%W3nr+kORbFY6&I4>-&a%q7lEd*4L@SCADe`mNZ<+E14+PUy zTiXedixDEL4}ggtiV*n~D3B*5wggXVCFH1R$3Vxl#m6aP9D57G*^=BEzD=}wTYlUq zmQGGg_jE7<0f&-gxw*BAqc$1sEeI+VYDGJoe96T+I0tEtCqzs*ZWRRf3F--RU!9pe7U`l#8UO3233wa! zSyvCF7l8k~S|!LJNtO#tQ=*p|yNFgR`8y9-6Ms@P(G!t6y&mM58h%unBHSBwCvpSx zPbsB#ROcTP65{++u0-R!lhiQqr7!Km-o`Jr&)9LO5ToKe{Zi$`?AZV%Ze38Y5i3^T zGu*ZA)9PAiaHwmcO&1djHriqr2{g;IMbvkND3+zd_=BwfEYK8yS1I+4vJ;d15g@ey zPd;pm=#u<10%Xt;LoEGZ+og2;SvI0`Cy*!P8$g=#y7%-FvBhMBr z-w{}t;k3q3o%Lr&xQT#T%~y+l#92uknPzkf{&P|AXs4uL+mPz46#RrrwF~0q+8QEa zDj6W+e=I&W5;otaB=?~&Mdec+7Ks!VM+x~s8qb=o^?fpbx1|3-|JOY&GQSt0n2#*l ze=6zsU%i?xd)401TGwy=kXmo_p||$=Xq`$HZGBy9?XxGSuS+Dfo-;uKko7{h3j`;l zW2$;(9}sJv79f1SocfG7xtfG6i37qfSZ|O3fPe$2l7B$WuIV?c1x9C=za{n;Y<5vO zx3g6L?k(g_1a=YCZs2bdK5 z@HxYUh3A8v3mQETFr9R5T`2XTkLhO+al@5RDx2yLVTCpic($tJv3aJ?vrwj@Gyg}| zO7)@RT-XV&gziB}_W{)Nrhx9zSodxM9pOGmwIi57cS`^-sz8RQP9-O!qh{Y|+YQcd z^M&yi>*%ZX7UvukDF1nNs#VgXc`-{Bd(J&RYYPKo|EN00#=TA?L;6q~8Z16Q?G0)5 zRPtl0qyF>;sAAvW0hS$0av}FujU+Tc zTI(ffwD0udygD315|K-^-X)lyyz$#wL78nqVWp=v#;S|tzrn*Eto z^?*CV>MSc_q$s3y9*El;%wqzDv^byuU)eS@x^UbUh~)qhv+|d~jSTUnYgluZ4@!9G zG`U5!nzB8X@=(iK&e4a&c_8|RVv?T5J1gbAeS};j36ik|1@*_`1FAwD`7MW}>{;_5OW0svNbjp%b zMkD`}T&uM6P1||5c=#K7nCM~Y!Zz|x=wV$CEh;N%-pD_qhbzYq z2>D0hSJugvqf40e^nZ?Qw;x3aNiJdkJEq!!FGpqf4H63t^*>rb#WEe_?RYgyYf*A6 z20wm8ZJJcGNIizc8! zbD|a(AF%G?FJYp^UqW(=zEm%f<;MdbEt^#KmN9G=?bU*v8jKtac52}HVx6*WM_u?X-6^&YIBTaCYozWtpF8sYh#`ry zR_@|3pkZKSeW?c62c9q1nN(?!^GDq846o1HnZ+s}h_()bvtK#nIA?0lRM-^j_KN9? zU}yQbd@2UW7389sy$6ZA+GNWz?fC4r>M~6f>2}rPW@~6l6FtS0qFHo_&)F<$?uK%U zPS-Sw>6(%G6D-Vod=5PoGI*40nSYVrL2_zhb0kPkZ@!%Edm7UXPl+EakV1aH($r}9tkWakFF1vnP4-*3W(C581F@iLL?+Gogl_ zX9<{6UsxP%$n>b>-;(W68!|mA`Jd=vb;$In+GbIiZ4Eho6xq&RTZR6aAXCm=Jg&CA zT<49BY3s}4)7o@J`4Zr`Tj$P?NT{jkgioVtTPX={Y-(|kTH zw}@xB3&AZiDZB(c%(R2!!`!;%LM`NIF2;FYU^=fBoL8GqQDlAI{qIVf#ZvbV^ZVk+ zY*Z0gEf82S)t){><}11Gu~@|B;CI8sGaR~UNrXurTo}?4$Tnm}2HU0OtC@3WBg37V zlb5@s8F!y%w>24-??j9w0H2j}0ACMfuJbEQvO6>!^r9UZJk@f3OcsvYnpY5F)BS?s zx_=N!GfOUzD+_^Z8Kn>T091X1s%wGnY75ZaQs%cAK6CAeVxFx{0wz$XL6FSaj}&RH zS|nvDu5=o2&*t-OT3_yuGAw*{ccFxgAm;lC87Ag0@_e;tlE@L0B+^xqWSIpL94O^n zl=N>8n9D^)Cq^??Mr~9UFQ2T`C!`Qsg7ql5J(h$eDCsly?N75T%D?nJc>m9M zMw6WvdE;c0j=Fa6?%Verbw8p+(S6q1^)t!UXFHl`Hc65)ExYO|oej1wf|@P31~VbZ z_|?$rWU-d#tBKk(d`k}}5-rl$gH{fy1IRja6;=2d)M%M%ULg|DCg@ZXthHoCQAk>x z*Fz^@cu^5>{tTquqSlpm%Q5i7fbvsgahS5<9b17)v$2|x6>)NH_vt7 z%hk6SX#U_=zW$Q$Kw^s>LrU*8Prk@D1dj!!VsKV zQ@xe?g~%WUYvnC$7R>#6{aKCu!ATuL8h<*y#FEujL3bGyvO91%z6eyY425+vuOec$ z%q0@e4ZDP5pg?WaSFP(2PsAvxa7Uc$7M874^S^xLLoYRGVG7x{zNk?_i*wldM9^YG z1n3J2k=&_>;Ru$BGROvn`q(8@#wV4@!jyHz6tD!C`XI`R%uJ=jyru{5WdDh`+dhEG z%N5-V_kMg)#hAwi+J!9`aHB_UbcEy~@)9ix--pS06CK*JV|AUs!ry&tC2Turu}hzN zJf5e306SoJ&o)XM*T@?@j@e#>|E0HOZ92cKo2JDkeb|cn7Z!wTgSsTG=ulYsJdA?1 z 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

2L+KQ! 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%0DtRrm)^COJ(C@eeZ@KLkrxt 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

|}<3F(0K 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 diff --git a/x/ibc-rate-limit/contracts/rate-limiter/.gitignore b/x/ibc-rate-limit/contracts/rate-limiter/.gitignore deleted file mode 100644 index dfdaaa6bcda..00000000000 --- a/x/ibc-rate-limit/contracts/rate-limiter/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# Build results -/target - -# Cargo+Git helper file (https://github.com/rust-lang/cargo/blob/0.44.1/src/cargo/sources/git/utils.rs#L320-L327) -.cargo-ok - -# Text file backups -**/*.rs.bk - -# macOS -.DS_Store - -# IDEs -*.iml -.idea diff --git a/x/ibc-rate-limit/contracts/rate-limiter/src/error.rs b/x/ibc-rate-limit/contracts/rate-limiter/src/error.rs index 367180baf59..f5dcda94688 100644 --- a/x/ibc-rate-limit/contracts/rate-limiter/src/error.rs +++ b/x/ibc-rate-limit/contracts/rate-limiter/src/error.rs @@ -1,7 +1,7 @@ use cosmwasm_std::{StdError, Timestamp, Uint256}; use thiserror::Error; -#[derive(Error, Debug)] +#[derive(Error, Debug, PartialEq)] pub enum ContractError { #[error("{0}")] Std(#[from] StdError), diff --git a/x/ibc-rate-limit/contracts/rate-limiter/src/integration_tests.rs b/x/ibc-rate-limit/contracts/rate-limiter/src/integration_tests.rs index fb9c711eaa3..bd9befeb83c 100644 --- a/x/ibc-rate-limit/contracts/rate-limiter/src/integration_tests.rs +++ b/x/ibc-rate-limit/contracts/rate-limiter/src/integration_tests.rs @@ -1,6 +1,6 @@ #![cfg(test)] -use crate::{helpers::RateLimitingContract, msg::ExecuteMsg, test_msg_send}; -use cosmwasm_std::{Addr, Coin, Empty, Uint128}; +use crate::{helpers::RateLimitingContract, msg::ExecuteMsg, test_msg_send, ContractError}; +use cosmwasm_std::{Addr, Coin, Empty, Timestamp, Uint128, Uint256}; use cw_multi_test::{App, AppBuilder, Contract, ContractWrapper, Executor}; use crate::{ @@ -109,9 +109,20 @@ fn expiration() { funds: 300_u32.into() ); let cosmos_msg = cw_rate_limit_contract.sudo(msg); - let _err = app.sudo(cosmos_msg).unwrap_err(); - - // TODO: how do we check the error type here? + let err = app.sudo(cosmos_msg).unwrap_err(); + + assert_eq!( + err.downcast_ref::().unwrap(), + &ContractError::RateLimitExceded { + channel: "channel".to_string(), + denom: "denom".to_string(), + amount: Uint256::from_u128(300), + quota_name: "weekly".to_string(), + used: Uint256::from_u128(300), + max: Uint256::from_u128(300), + reset: Timestamp::from_nanos(1572402219879305533), + } + ); // ... Time passes app.update_block(|b| { diff --git a/x/ibc-rate-limit/ibc_module.go b/x/ibc-rate-limit/ibc_module.go index e9ee1577fa8..93bd8b255bb 100644 --- a/x/ibc-rate-limit/ibc_module.go +++ b/x/ibc-rate-limit/ibc_module.go @@ -154,6 +154,11 @@ func (im *IBCModule) OnAcknowledgementPacket( acknowledgement []byte, relayer sdk.AccAddress, ) error { + var ack channeltypes.Acknowledgement + if err := json.Unmarshal(acknowledgement, &ack); err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "cannot unmarshal ICS-20 transfer packet acknowledgement: %v", err) + } + if osmoutils.IsAckError(acknowledgement) { err := im.RevertSentPacket(ctx, packet) // If there is an error here we should still handle the ack if err != nil { diff --git a/x/ibc-rate-limit/module.go b/x/ibc-rate-limit/module.go index 1776ff8cc6c..74588000633 100644 --- a/x/ibc-rate-limit/module.go +++ b/x/ibc-rate-limit/module.go @@ -18,9 +18,7 @@ import ( "github.com/osmosis-labs/osmosis/v13/x/ibc-rate-limit/types" ) -var ( - _ module.AppModuleBasic = AppModuleBasic{} -) +var _ module.AppModuleBasic = AppModuleBasic{} type AppModuleBasic struct{} From 7d25928126bf3da7040efa7d9c7c43a262047c99 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 4 Jan 2023 21:16:22 -0600 Subject: [PATCH 25/30] update contracts test --- .github/workflows/contracts.yml | 35 ++++++++++++--------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/.github/workflows/contracts.yml b/.github/workflows/contracts.yml index dee6db05edc..a44a957f2e6 100644 --- a/.github/workflows/contracts.yml +++ b/.github/workflows/contracts.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - contract: [{workdir: ./x/ibc-rate-limit/, output: bytecode/rate_limiter.wasm, build: artifacts/rate_limiter-x86_64.wasm, name: rate_limiter}] + contract: [{workdir: ./x/ibc-rate-limit/, output: bytecode/rate_limiter.wasm, build: artifacts/rate_limiter.wasm, name: rate_limiter}] steps: - name: Checkout sources @@ -45,30 +45,13 @@ jobs: cargo test if: env.GIT_DIFF - - name: Set latest cw-optimizoor version - run: > - echo "CW_OPTIMIZOOR_VERSION=0.8.0" >> $GITHUB_ENV - - - name: Cache cw-optimizoor - id: cache-cw-optimizoor - uses: actions/cache@v3 - env: - cache-name: cache-cw-optimizoor - with: - # cargo bin files are stored in `~/.cargo/bin/` on Linux/macOS - path: ~/.cargo/bin/cargo-cw-optimizoor - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.CW_OPTIMIZOOR_VERSION }} - - - if: ${{ steps.cache-cw-optimizoor.outputs.cache-hit != 'true' }} - name: Install cw-optimizoor - continue-on-error: true - run: > - cargo install cw-optimizoor - - name: Optimize working-directory: ${{ matrix.contract.workdir }} run: > - cargo cw-optimizoor + docker run --rm -v "$(pwd)":/code \ + --mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \ + --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ + cosmwasm/workspace-optimizer:0.12.10 if: env.GIT_DIFF - name: 'Upload optimized contract artifact' @@ -79,6 +62,14 @@ jobs: retention-days: 1 if: env.GIT_DIFF + - name: 'Upload Cargo.lock artifact' + uses: actions/upload-artifact@v3 + with: + name: Cargo.lock + path: ${{ matrix.contract.workdir }}Cargo.lock + retention-days: 1 + if: env.GIT_DIFF + - name: Check Test Data working-directory: ${{ matrix.contract.workdir }} if: env.GIT_DIFF From f864dcf9105433b54a9e6d1bf17788bcd07497b4 Mon Sep 17 00:00:00 2001 From: Ruslan Akhtariev <46343690+RusAkh@users.noreply.github.com> Date: Thu, 22 Dec 2022 05:16:19 +0100 Subject: [PATCH 26/30] osmomath: `AddMut` and `QuoMut` (#3779) * mut add * test add mut * quo mut * test quo mut/ remove want from test struct * refactor exp * change mutatives code * change * not allocaing * exp change to quomut * remove file * refactor quo * refactor ad * refactor tests --- osmomath/exp2.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osmomath/exp2.go b/osmomath/exp2.go index b7973b3bc62..39b2333ebd3 100644 --- a/osmomath/exp2.go +++ b/osmomath/exp2.go @@ -93,9 +93,9 @@ func exp2ChebyshevRationalApprox(x BigDec) BigDec { for i := 1; i < len(numeratorCoefficients13Param); i++ { x_exp_i.MulMut(x) - h_x = h_x.Add(numeratorCoefficients13Param[i].Mul(x_exp_i)) - p_x = p_x.Add(denominatorCoefficients13Param[i].Mul(x_exp_i)) + h_x.AddMut(numeratorCoefficients13Param[i].Mul(x_exp_i)) + p_x.AddMut(denominatorCoefficients13Param[i].Mul(x_exp_i)) } - return h_x.Quo(p_x) + return h_x.QuoMut(p_x) } From 35ab94eb54b1afb589c2bbdf0eece9348765a500 Mon Sep 17 00:00:00 2001 From: mattverse Date: Thu, 5 Jan 2023 15:20:56 +0900 Subject: [PATCH 27/30] Modify CHANGELOG --- CHANGELOG.md | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21f67d49480..f15597c5a7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,35 +42,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -* IBC features - * Upgrade to IBC v4.2.0 -* Cosmwasm - * Upgrade to wasmd v0.30.x - -* [#3609](https://github.com/osmosis-labs/osmosis/pull/3609) Add Downtime-detection module. -* [#2788](https://github.com/osmosis-labs/osmosis/pull/2788) Add logarithm base 2 implementation. -* [#3677](https://github.com/osmosis-labs/osmosis/pull/3677) Add methods for cloning and mutative multiplication on osmomath.BigDec. -* [#3676](https://github.com/osmosis-labs/osmosis/pull/3676) implement `PowerInteger` function on `osmomath.BigDec` -* [#3678](https://github.com/osmosis-labs/osmosis/pull/3678) implement mutative `PowerIntegerMut` function on `osmomath.BigDec`. -* [#3708](https://github.com/osmosis-labs/osmosis/pull/3708) `Exp2` function to compute 2^decimal. -* [#3693](https://github.com/osmosis-labs/osmosis/pull/3693) Add `EstimateSwapExactAmountOut` query to stargate whitelist * [#3731](https://github.com/osmosis-labs/osmosis/pull/3731) BigDec Power functions with decimal exponent. -* [#3847](https://github.com/osmosis-labs/osmosis/pull/3847) GeometricTwap and GeometricTwapToNow queries added to Stargate whitelist. -* [#3899](https://github.com/osmosis-labs/osmosis/pull/3899) Fixed osmoutils so its importable by chains that don't use the osmosis CosmosSDK fork - -### API breaks - -* [#3763](https://github.com/osmosis-labs/osmosis/pull/3763) Move binary search and error tolerance code from `osmoutils` into `osmomath` * [#3817](https://github.com/osmosis-labs/osmosis/pull/3817) Move osmoassert from `app/apptesting/osmoassert` to `osmoutils/osmoassert`. -* [#3771](https://github.com/osmosis-labs/osmosis/pull/3771) Move osmomath into its own go.mod -* [#3827](https://github.com/osmosis-labs/osmosis/pull/3827) Move osmoutils into its own go.mod - +### API breaks ### Bug fixes -* [#3608](https://github.com/osmosis-labs/osmosis/pull/3608) Make it possible to state export from any directory. - ### Misc Improvements * [#3611](https://github.com/osmosis-labs/osmosis/pull/3611),[#3647](https://github.com/osmosis-labs/osmosis/pull/3647) Introduce osmocli, to automate thousands of lines of CLI boilerplate @@ -78,6 +56,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#3712](https://github.com/osmosis-labs/osmosis/pull/3712) replace `osmomath.BigDec` `Power` with `PowerInteger` * [#3711](https://github.com/osmosis-labs/osmosis/pull/3711) Use Dec instead of Int for additive `ErrTolerace` in `osmoutils`. +## v14.0.0 +### Features +* [#3609](https://github.com/osmosis-labs/osmosis/pull/3609) Add Downtime-detection module. +* [#2788](https://github.com/osmosis-labs/osmosis/pull/2788) Add logarithm base 2 implementation. +* [#3693](https://github.com/osmosis-labs/osmosis/pull/3693) Add `EstimateSwapExactAmountOut` query to stargate whitelist +* [#3852](https://github.com/osmosis-labs/osmosis/pull/3852) GeometricTwap and GeometricTwapToNow queries added to Stargate whitelist. +* [#3812](https://github.com/osmosis-labs/osmosis/pull/3812) Add geometric option to TWAP cli. +* IBC features + * [#3838](https://github.com/osmosis-labs/osmosis/pull/3838)Upgrade to IBC v4.2.0 +* Cosmwasm + * Upgrade to wasmd v0.30.x + +### Bug fixes +* [#3608](https://github.com/osmosis-labs/osmosis/pull/3608) Make it possible to state export from any directory. + +### Misc Improvements +* [#3678](https://github.com/osmosis-labs/osmosis/pull/3678) Add methods for cloning and mutative multiplication on osmomath.BigDec. +* [#3899](https://github.com/osmosis-labs/osmosis/pull/3899) Fixed osmoutils so its importable by chains that don't use the osmosis CosmosSDK fork +* [#3676](https://github.com/osmosis-labs/osmosis/pull/3676) Implement `PowerInteger` function on `osmomath.BigDec` +* [#3678](https://github.com/osmosis-labs/osmosis/pull/3678) Implement mutative `PowerIntegerMut` function on `osmomath.BigDec`. +* [#3708](https://github.com/osmosis-labs/osmosis/pull/3708) `Exp2` function to compute 2^decimal. +* [#3763](https://github.com/osmosis-labs/osmosis/pull/3763) Move binary search and error tolerance code from `osmoutils` into `osmomath` +* [#3771](https://github.com/osmosis-labs/osmosis/pull/3771) Move osmomath into its own go.mod +* [#3827](https://github.com/osmosis-labs/osmosis/pull/3827) Move osmoutils into its own go.mod + ## v13.0.0 This release includes stableswap, and expands the IBC safety & composability functionality of Osmosis. The primary features are: From 09ccc37f927e9f83478d7bd80e35f8fc20a1b871 Mon Sep 17 00:00:00 2001 From: ByeongSu Hong Date: Tue, 13 Dec 2022 23:55:12 +0900 Subject: [PATCH 28/30] Whitelist EstimateSwapExactAmountOut (#3693) * whitelist EstimateSwapExactAmountOut * doc: changelog --- wasmbinding/stargate_whitelist.go | 1 + 1 file changed, 1 insertion(+) diff --git a/wasmbinding/stargate_whitelist.go b/wasmbinding/stargate_whitelist.go index 54ebef26bb6..f1527345f0f 100644 --- a/wasmbinding/stargate_whitelist.go +++ b/wasmbinding/stargate_whitelist.go @@ -85,6 +85,7 @@ func init() { setWhitelistedQuery("/osmosis.gamm.v1beta1.Query/PoolType", &gammtypes.QueryPoolTypeResponse{}) setWhitelistedQuery("/osmosis.gamm.v2.Query/SpotPrice", &gammv2types.QuerySpotPriceResponse{}) setWhitelistedQuery("/osmosis.gamm.v1beta1.Query/EstimateSwapExactAmountIn", &gammtypes.QuerySwapExactAmountInResponse{}) + setWhitelistedQuery("/osmosis.gamm.v1beta1.Query/EstimateSwapExactAmountOut", &gammtypes.QuerySwapExactAmountOutResponse{}) // incentives setWhitelistedQuery("/osmosis.incentives.Query/ModuleToDistributeCoins", &incentivestypes.ModuleToDistributeCoinsResponse{}) From 3a4aac21eac3e9ffe5af143cdba1d105b7ddd958 Mon Sep 17 00:00:00 2001 From: Nicolas Lara Date: Thu, 5 Jan 2023 14:18:15 +0100 Subject: [PATCH 29/30] updated rate limit contract --- x/ibc-rate-limit/bytecode/rate_limiter.wasm | Bin 264433 -> 264433 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/x/ibc-rate-limit/bytecode/rate_limiter.wasm b/x/ibc-rate-limit/bytecode/rate_limiter.wasm index 30b545e0612d86ee2751dbcfa11595954e0575e5..83c5c4bc57791abaa6e9553853d6d4f6327c7e09 100644 GIT binary patch delta 3076 zcmZuydstOf7C&q4d*N~)+yh-f@B-(;MNt%dB9NjdK(sXSH9i=z(o`;7R6yrbQ=v4_ z;&D0Z_K~lw#t|x-GkToVPp5qQO+lYJX5%<~Ici_(fSFm=H0#`peoWu|v)5y zrcz-@o&0j<8mNZ!&2SYy#i{FI9lQo>p$10mf}M~xZtUxjm!rVS%~;1CBnQ?*8o;ScoErr(YVq79 zKtlUV=V?7KZyLm^q4Uo&aH?N;h8sy2w&(}aSr!+vUN;)ZL(hOaF-{WnTO)u%QoGi9HBqSdGeDS9M>1mZ;HM|nR(H1G*U=u{JPzYn4tV#d2@ z9W`FRCu2gTQFK{B_j(gNl2M8fUCNnBGs(g|xf$Y>w#lu;zcpnBS^qTUITre`o}!Y- z{xo>RICbXq1x#HORbqx1@4DoZz&IxsPwN}x{ey_3qK ze%r4T#Kb@Z`XQqfA||T$`cFiMqsAN%vA6-IC< zvCDd^-j@deZfj8AT=|KWcAj5+9gcFRMf~_pgViIO3iX7YTb?F`bIVY5+m=ZNV()C9LFE{`V*_HSVKhwy$VM zj*$$qM6aVn9NLXv)v13zWCxc+kc1>8hdMDNp*2hpEY?R#@hB*#4#(ggP#zxc#ox}u z93}3ILtSxXWh6cQ59deet&wptpVoC373$oWzugCjR~=vE8Pwli4Mw%#3ZOctJxL$A ztQ&5n<+=qXDTlA;b;(ILdiXiLyY&4xyJWX=@i8af4A{8Ur*9_fHc_3Ncb>4n|e z?q3Hh?YD}%xYf72I5p?mUx6s;oKSH^3e>J5v>-%Mfz-R^R!^KI;wTB}~MKJVOrKbK=ZG=nw=^`w*PPZB? zlHiAi>HNbWn8_QB;KL7)KU0LoJOSZ2T-Qy@_@*FOqTN7f1I-c)K%K#DA&?AqEh7Xj zq>^aQfLQ3MrDQ+|U}c?_kqHxMptb5Oc+U{)l*~5KiWVt^05M3uL~v;+lh0MsgA*q5 zN!dWq$Mez{!VH zL7~HGWfsYvOK>d8^*Y#^MW^;o6`TU{?0preXgW#Oa@N4VSs%MZeUxNl)NV-xkMaWw z>6_Q-Sg;gKF$J~_qj_@;#PHwMz`wAiRx4ZwubAk&wU(T@2xAVSCtjco)^m8mNEvjVhd%tooAh%@+SKjv48SzLdj}PBn)cTn z@CFr)&)fqpA}{ZOY%1ZgJ@lo~J@Py77Lok-VVD;6E_jRqp&x(03DU{@Mw95|1fYWg_WiV3 z2VjH<3EI|^aNaDQ3=Ap#I>ta+tJ036==~HVLxHF z)_Mu@3{<5EzOWtoYh$iJZ@oRd?XV<9tkgdd9Uu4F0#5J#2kt_kR&GuW)e1BCWx)P0 zLkmVcVx$~G{5cr)98f+;h^yytIT+_q_*o{@`-!A}+A$M$Lg;b*HFSjT(7!3|s2TgR z{Ew-{x}b^?=*Wk<%RN1^+Fd3nYw9i&l4 zFq=-Ka9=hK#Er;1axsSgn2n#nK)xsshiZ3nu?k?IMnXlLmgvDGyGb7D!lwk6Lz}t` zvx87!IzGhmrb0Ap|CoG9CIk8U z^fMe6Abq*qiZze;Z(C7%#E)$A^M!3Vh*S-2m`vnw8$KD3T$Yy8#|UP7QknevA=%;R)n28T9WiFoOWn*|`DU0DQFN=vTd!gc`*(F8ZqKcQwGBds9 z^D{FiFPXb=Liv3Dyq87t(h}z3cS~3*pIXX>@k?ITpTFQ`5&A|7KjUR~zP^-QrD66g zWYuAi!S7bG>G3KEf=v*F{=G!ud7@wbN@mDQs#p;Pd9jLphIH)RHLNW?Xz7he!+hMp@V+K delta 3033 zcmZuyeNa@_6@Ta4x9-C3vJbNI6&BvYiXZ}N07XT80VEnNYIOWyL`M^=>!MWAHi;-0 z6~Fj=;#CvBLQSj^%jCs8n`mXmG{Kk}$S5(UjxuA>w9!Cn&`g@7=j~!@o&Iyr=RNnF zbI<+V-g>FGUTR_JWWcP+7ywCNVrm4Y1sl9TDqvb6Ix#fsFy4ewuj5&m^?MkZ zIXYV{6Vso|-U8d;70B8H*Wn`0+74B)8MeYE7<&i~!njG#?0|wi71r&+vYk*3wa@@H zPzR+OVZ+OnPyyvHt-I&IS)XOmdJEr(Iq$9l@mzUiPEaWgB3{ z4LCtg$XACgb7@n&!N&I4%V!c%n|;}|cKZ&1tZpv(0%ElVD|!t3w9-0scGt8DN;;*} z!@QE)IHJeQ(~B@u`}K%0i#lOUy<>*WWR+2oys{{RG(){H<|NN3!eQ#M(YxUrey1E) zYrfSnApQkWCChI%o1c^3WzX zgGXKXY&-G8r_3eq9aE;UkY*z{nNn&4%1!&Ka4FMDqwcY>F4JyPpPo5*6j>nTcPAf)7$1>+>y=voEydIYViY_f6ppRFx3 z(SXFhn5dPkO9kw%(OxS*XCuqP?H`bXI;c9C*23y&h*W#(;?!-`MKMkpldv7^Pf}Iw z)F4#08f{W6%caPMnnl0ZqyLXxU0-vD0{Uv#(rN_6Iz#TMdx_TN^=^nztLr1cp&qGU zL>f!O(5Q#Uh5c_hDN>!<5KW#-8-5J#_sJJ0sKXBqR5z(AZJx3_K^?Ozfw%>`_V&xg zjSe-X@mF-rON||V-8kZ>>>i<=*UqyY7d7dMoQ{b&3s$Ef3rR?E4I(C?EmRPA>v)WGw4v4Z&?q$l zZz{liHSWAqd-+Ux1P#Uam&P08lHFNI>$Xmn#>Mq{AAm=5eo-K5i>?D|Mc2%zE$&J( zrf1wOkJ{30h3V?)?t*?f>DE9$XS_k2d*sig6-2YWu!gi&SFh z*ZckJ2(|0$<^9}-JN=yIx;xW&d8_Uv(z^HF>Tnm`uaJd@m@U+JFSnUjwi4>Ze`n<5 z{q8tL2=8m5wYM)^z1FvZN}7NFMKJ(L0sk;*x_a}698%GX`bDLs|GUbhyBQ1zeY6QW z0IvA4z&6h&T4lix7W4QG5$5qagnCZbep|Pi0cak$JqS|3sb>el<#ZAq*$@j6dRjIF z0lrym@*k`1kL5WVIB$`yL+;wt4rMc_g68M#33mLJO{1ef(O zd9cJ3@<|;TQ^@%!(h%r>oCJ9(Fo@S51UDbJ1}Y(5=WF0qE4cVml~C+-*_c&!9*s-X803|8%P&HR(s=tGOwXYGe)0p{|<2dJTQ^}il~ozyr!uL%fx z`MM^^r8c%U(Vs?VDM#RSB84X)Q;&KByrzIKgr7JLqsaZ%asRHMX1WcRp43cVXkb?w zzxo!GQFgR7%uF*S*{uq=g}_gCL-fjmEE5h?_Q>o=IGI#aFTvHz5NOlh}5ZY zzOoC3>JzU)qA?;RU9iR_ePVnS1~MMC2ZDb46MPGSet9?zRXfb)R{@8@Y~74_#zZv) z`D-v4HK1~eu-2&Isu>qk`r|BU%oIsO^i~V@LP$$BonT;dkMSAlXM-`B6;}Tjgc!k% zvgJ`Z(yRPLX(bDO5Mu_2^*t&Rh~0fu?ylh@L+~kT)bbEqCgOuyy)z7-F{+4j;(93J z2b}03a?Xh}rSpL{qH;y>SIqwwjEVZxfmoc(FF%djjK#s*$D>tmQg8(D_yh-z~>je!Lii)l*{&_4al60Q8$nFv($g zT5vm+95?FDwU|4A@7aI{Ayua=w%93~v(;EfWLgcD6PaF%3B0!k7mx?>r)B3pu*F$r zi*y0#)$JiHvq<}NcMD!M!G3W0qfKiEQecHu%SH1#}du?zk6Zvnz9%8 zQXlj1&Jvc%x36H=VTA5o$*MvjlYd*m=ET1Rf?yW}Vd#^Ru#o8G$K)S@`zqNoN~W`t zeTua0jZLg0Ix~Iss>SKcN=jF*DqEelYPIlAoFo*{exF{ynLPoaK@=y9ALBfK A@&Et; From d5dda290b13445a157f3aca2bd21061e2ca6ac42 Mon Sep 17 00:00:00 2001 From: Nicolas Lara Date: Wed, 30 Nov 2022 17:13:30 +0100 Subject: [PATCH 30/30] Fix rust checks (#3576) * added cargo.lock * added Cargo.lock as an artifact * added new bytecode with lock file --- .github/workflows/contracts.yml | 7 + .gitignore | 4 - x/ibc-rate-limit/Cargo.lock | 914 ++++++++++++++++++++ x/ibc-rate-limit/bytecode/rate_limiter.wasm | Bin 264433 -> 264433 bytes 4 files changed, 921 insertions(+), 4 deletions(-) create mode 100644 x/ibc-rate-limit/Cargo.lock diff --git a/.github/workflows/contracts.yml b/.github/workflows/contracts.yml index a44a957f2e6..ba93985263b 100644 --- a/.github/workflows/contracts.yml +++ b/.github/workflows/contracts.yml @@ -70,6 +70,13 @@ jobs: retention-days: 1 if: env.GIT_DIFF + - name: 'Upload Cargo.lock artifact' + uses: actions/upload-artifact@v3 + with: + name: Cargo.lock + path: ${{ matrix.contract.workdir }}Cargo.lock + retention-days: 1 + - name: Check Test Data working-directory: ${{ matrix.contract.workdir }} if: env.GIT_DIFF diff --git a/.gitignore b/.gitignore index 9298d99de92..fc3ab4bb663 100644 --- a/.gitignore +++ b/.gitignore @@ -216,10 +216,6 @@ target/ # Generated by rust-optimizer artifacts/ -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -Cargo.lock - # These are backup files generated by rustfmt **/*.rs.bk # Don't commit lock files for test utils diff --git a/x/ibc-rate-limit/Cargo.lock b/x/ibc-rate-limit/Cargo.lock new file mode 100644 index 00000000000..07e4f7e4a10 --- /dev/null +++ b/x/ibc-rate-limit/Cargo.lock @@ -0,0 +1,914 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "anyhow" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64ct" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "const-oid" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "722e23542a15cea1f65d4a1419c4cfd7a26706c70871a13a04238ca3f40f1661" + +[[package]] +name = "cosmwasm-crypto" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28376836c7677e1ea6d6656a754582e88b91e544ce22fae42956d5fe5549a958" +dependencies = [ + "digest 0.10.5", + "ed25519-zebra", + "k256", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eb69f4f7a8a4bce68c8fbd3646238fede1e77056e4ea31c5b6bfc37b709eec3" +dependencies = [ + "syn", +] + +[[package]] +name = "cosmwasm-schema" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a227cfeb9a7152b26a354b1c990e930e962f75fd68f57ab5ae2ef888c8524292" +dependencies = [ + "cosmwasm-schema-derive", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3626cb42eef870de67f791e873711255325224d86f281bf628c42abd295f3a14" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cosmwasm-std" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bf9157d060abbc55152aeadcace799d03dc630575daa66604079a1206cb060" +dependencies = [ + "base64", + "cosmwasm-crypto", + "cosmwasm-derive", + "derivative", + "forward_ref", + "hex", + "schemars", + "serde", + "serde-json-wasm", + "thiserror", + "uint", +] + +[[package]] +name = "cosmwasm-storage" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b61fcfef87d15af0263e2e4d792af80355929674a3b4e29ffb3c898ec6e25852" +dependencies = [ + "cosmwasm-std", + "serde", +] + +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "cw-multi-test" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f9a8ab7c3c29ec93cb7a39ce4b14a05e053153b4a17ef7cf2246af1b7c087e" +dependencies = [ + "anyhow", + "cosmwasm-std", + "cosmwasm-storage", + "cw-storage-plus 0.13.4", + "cw-utils", + "derivative", + "itertools", + "prost 0.9.0", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw-storage-plus" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "648b1507290bbc03a8d88463d7cd9b04b1fa0155e5eef366c4fa052b9caaac7a" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-storage-plus" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b6f91c0b94481a3e9ef1ceb183c37d00764f8751e39b45fc09f4d9b970d469" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbaecb78c8e8abfd6b4258c7f4fbeb5c49a5e45ee4d910d3240ee8e1d714e1b" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw2" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cf4639517490dd36b333bbd6c4fbd92e325fd0acf4683b41753bc5eb63bfc1" +dependencies = [ + "cosmwasm-std", + "cw-storage-plus 0.13.4", + "schemars", + "serde", +] + +[[package]] +name = "der" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dd2ae565c0a381dde7fade45fce95984c568bdcb4700a4fdbe3175e0380b2f" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +dependencies = [ + "block-buffer 0.10.3", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn-clone" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f94fa09c2aeea5b8839e414b7b841bf429fd25b9c522116ac97ee87856d88b2" + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek", + "hashbrown", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "digest 0.10.5", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.5", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2 0.10.6", +] + +[[package]] +name = "libc" +version = "0.2.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "osmosis-std" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b3792977036dc49cfc9af9fd7a6c021fd48dfffc8ebf09324201506c65a47a" +dependencies = [ + "chrono", + "cosmwasm-std", + "osmosis-std-derive", + "prost 0.11.2", + "prost-types", + "schemars", + "serde", + "serde-cw-value", +] + +[[package]] +name = "osmosis-std-derive" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c501f2b8ff88b1c60ab671d7b808e947f384fa2524fe4ec8c06f63ef4be29979" +dependencies = [ + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "proc-macro2" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +dependencies = [ + "bytes", + "prost-derive 0.9.0", +] + +[[package]] +name = "prost" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0841812012b2d4a6145fae9a6af1534873c32aa67fff26bd09f8fa42c83f95a" +dependencies = [ + "bytes", + "prost-derive 0.11.2", +] + +[[package]] +name = "prost-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "164ae68b6587001ca506d3bf7f1000bfa248d0e1217b618108fba4ec1d0cc306" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a" +dependencies = [ + "bytes", + "prost 0.11.2", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rate-limiter" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cosmwasm-storage", + "cw-multi-test", + "cw-storage-plus 0.16.0", + "cw2", + "hex", + "osmosis-std", + "osmosis-std-derive", + "prost 0.11.2", + "schemars", + "serde", + "serde-json-wasm", + "sha2 0.10.6", + "thiserror", +] + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "schemars" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a5fb6c61f29e723026dc8e923d94c694313212abbecbbe5f55a7748eec5b307" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f188d036977451159430f3b8dc82ec76364a42b7e289c2b18a9a18f4470058e9" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "serde" +version = "1.0.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-cw-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75d32da6b8ed758b7d850b6c3c08f1d7df51a4df3cb201296e63e34a78e99d4" +dependencies = [ + "serde", +] + +[[package]] +name = "serde-json-wasm" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479b4dbc401ca13ee8ce902851b834893251404c4f3c65370a49e047a6be09a5" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.5", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.5", + "rand_core 0.6.4", +] + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "uint" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" diff --git a/x/ibc-rate-limit/bytecode/rate_limiter.wasm b/x/ibc-rate-limit/bytecode/rate_limiter.wasm index 83c5c4bc57791abaa6e9553853d6d4f6327c7e09..30b545e0612d86ee2751dbcfa11595954e0575e5 100644 GIT binary patch delta 3033 zcmZuyeNa@_6@Ta4x9-C3vJbNI6&BvYiXZ}N07XT80VEnNYIOWyL`M^=>!MWAHi;-0 z6~Fj=;#CvBLQSj^%jCs8n`mXmG{Kk}$S5(UjxuA>w9!Cn&`g@7=j~!@o&Iyr=RNnF zbI<+V-g>FGUTR_JWWcP+7ywCNVrm4Y1sl9TDqvb6Ix#fsFy4ewuj5&m^?MkZ zIXYV{6Vso|-U8d;70B8H*Wn`0+74B)8MeYE7<&i~!njG#?0|wi71r&+vYk*3wa@@H zPzR+OVZ+OnPyyvHt-I&IS)XOmdJEr(Iq$9l@mzUiPEaWgB3{ z4LCtg$XACgb7@n&!N&I4%V!c%n|;}|cKZ&1tZpv(0%ElVD|!t3w9-0scGt8DN;;*} z!@QE)IHJeQ(~B@u`}K%0i#lOUy<>*WWR+2oys{{RG(){H<|NN3!eQ#M(YxUrey1E) zYrfSnApQkWCChI%o1c^3WzX zgGXKXY&-G8r_3eq9aE;UkY*z{nNn&4%1!&Ka4FMDqwcY>F4JyPpPo5*6j>nTcPAf)7$1>+>y=voEydIYViY_f6ppRFx3 z(SXFhn5dPkO9kw%(OxS*XCuqP?H`bXI;c9C*23y&h*W#(;?!-`MKMkpldv7^Pf}Iw z)F4#08f{W6%caPMnnl0ZqyLXxU0-vD0{Uv#(rN_6Iz#TMdx_TN^=^nztLr1cp&qGU zL>f!O(5Q#Uh5c_hDN>!<5KW#-8-5J#_sJJ0sKXBqR5z(AZJx3_K^?Ozfw%>`_V&xg zjSe-X@mF-rON||V-8kZ>>>i<=*UqyY7d7dMoQ{b&3s$Ef3rR?E4I(C?EmRPA>v)WGw4v4Z&?q$l zZz{liHSWAqd-+Ux1P#Uam&P08lHFNI>$Xmn#>Mq{AAm=5eo-K5i>?D|Mc2%zE$&J( zrf1wOkJ{30h3V?)?t*?f>DE9$XS_k2d*sig6-2YWu!gi&SFh z*ZckJ2(|0$<^9}-JN=yIx;xW&d8_Uv(z^HF>Tnm`uaJd@m@U+JFSnUjwi4>Ze`n<5 z{q8tL2=8m5wYM)^z1FvZN}7NFMKJ(L0sk;*x_a}698%GX`bDLs|GUbhyBQ1zeY6QW z0IvA4z&6h&T4lix7W4QG5$5qagnCZbep|Pi0cak$JqS|3sb>el<#ZAq*$@j6dRjIF z0lrym@*k`1kL5WVIB$`yL+;wt4rMc_g68M#33mLJO{1ef(O zd9cJ3@<|;TQ^@%!(h%r>oCJ9(Fo@S51UDbJ1}Y(5=WF0qE4cVml~C+-*_c&!9*s-X803|8%P&HR(s=tGOwXYGe)0p{|<2dJTQ^}il~ozyr!uL%fx z`MM^^r8c%U(Vs?VDM#RSB84X)Q;&KByrzIKgr7JLqsaZ%asRHMX1WcRp43cVXkb?w zzxo!GQFgR7%uF*S*{uq=g}_gCL-fjmEE5h?_Q>o=IGI#aFTvHz5NOlh}5ZY zzOoC3>JzU)qA?;RU9iR_ePVnS1~MMC2ZDb46MPGSet9?zRXfb)R{@8@Y~74_#zZv) z`D-v4HK1~eu-2&Isu>qk`r|BU%oIsO^i~V@LP$$BonT;dkMSAlXM-`B6;}Tjgc!k% zvgJ`Z(yRPLX(bDO5Mu_2^*t&Rh~0fu?ylh@L+~kT)bbEqCgOuyy)z7-F{+4j;(93J z2b}03a?Xh}rSpL{qH;y>SIqwwjEVZxfmoc(FF%djjK#s*$D>tmQg8(D_yh-z~>je!Lii)l*{&_4al60Q8$nFv($g zT5vm+95?FDwU|4A@7aI{Ayua=w%93~v(;EfWLgcD6PaF%3B0!k7mx?>r)B3pu*F$r zi*y0#)$JiHvq<}NcMD!M!G3W0qfKiEQecHu%SH1#}du?zk6Zvnz9%8 zQXlj1&Jvc%x36H=VTA5o$*MvjlYd*m=ET1Rf?yW}Vd#^Ru#o8G$K)S@`zqNoN~W`t zeTua0jZLg0Ix~Iss>SKcN=jF*DqEelYPIlAoFo*{exF{ynLPoaK@=y9ALBfK A@&Et; delta 3076 zcmZuydstOf7C&q4d*N~)+yh-f@B-(;MNt%dB9NjdK(sXSH9i=z(o`;7R6yrbQ=v4_ z;&D0Z_K~lw#t|x-GkToVPp5qQO+lYJX5%<~Ici_(fSFm=H0#`peoWu|v)5y zrcz-@o&0j<8mNZ!&2SYy#i{FI9lQo>p$10mf}M~xZtUxjm!rVS%~;1CBnQ?*8o;ScoErr(YVq79 zKtlUV=V?7KZyLm^q4Uo&aH?N;h8sy2w&(}aSr!+vUN;)ZL(hOaF-{WnTO)u%QoGi9HBqSdGeDS9M>1mZ;HM|nR(H1G*U=u{JPzYn4tV#d2@ z9W`FRCu2gTQFK{B_j(gNl2M8fUCNnBGs(g|xf$Y>w#lu;zcpnBS^qTUITre`o}!Y- z{xo>RICbXq1x#HORbqx1@4DoZz&IxsPwN}x{ey_3qK ze%r4T#Kb@Z`XQqfA||T$`cFiMqsAN%vA6-IC< zvCDd^-j@deZfj8AT=|KWcAj5+9gcFRMf~_pgViIO3iX7YTb?F`bIVY5+m=ZNV()C9LFE{`V*_HSVKhwy$VM zj*$$qM6aVn9NLXv)v13zWCxc+kc1>8hdMDNp*2hpEY?R#@hB*#4#(ggP#zxc#ox}u z93}3ILtSxXWh6cQ59deet&wptpVoC373$oWzugCjR~=vE8Pwli4Mw%#3ZOctJxL$A ztQ&5n<+=qXDTlA;b;(ILdiXiLyY&4xyJWX=@i8af4A{8Ur*9_fHc_3Ncb>4n|e z?q3Hh?YD}%xYf72I5p?mUx6s;oKSH^3e>J5v>-%Mfz-R^R!^KI;wTB}~MKJVOrKbK=ZG=nw=^`w*PPZB? zlHiAi>HNbWn8_QB;KL7)KU0LoJOSZ2T-Qy@_@*FOqTN7f1I-c)K%K#DA&?AqEh7Xj zq>^aQfLQ3MrDQ+|U}c?_kqHxMptb5Oc+U{)l*~5KiWVt^05M3uL~v;+lh0MsgA*q5 zN!dWq$Mez{!VH zL7~HGWfsYvOK>d8^*Y#^MW^;o6`TU{?0preXgW#Oa@N4VSs%MZeUxNl)NV-xkMaWw z>6_Q-Sg;gKF$J~_qj_@;#PHwMz`wAiRx4ZwubAk&wU(T@2xAVSCtjco)^m8mNEvjVhd%tooAh%@+SKjv48SzLdj}PBn)cTn z@CFr)&)fqpA}{ZOY%1ZgJ@lo~J@Py77Lok-VVD;6E_jRqp&x(03DU{@Mw95|1fYWg_WiV3 z2VjH<3EI|^aNaDQ3=Ap#I>ta+tJ036==~HVLxHF z)_Mu@3{<5EzOWtoYh$iJZ@oRd?XV<9tkgdd9Uu4F0#5J#2kt_kR&GuW)e1BCWx)P0 zLkmVcVx$~G{5cr)98f+;h^yytIT+_q_*o{@`-!A}+A$M$Lg;b*HFSjT(7!3|s2TgR z{Ew-{x}b^?=*Wk<%RN1^+Fd3nYw9i&l4 zFq=-Ka9=hK#Er;1axsSgn2n#nK)xsshiZ3nu?k?IMnXlLmgvDGyGb7D!lwk6Lz}t` zvx87!IzGhmrb0Ap|CoG9CIk8U z^fMe6Abq*qiZze;Z(C7%#E)$A^M!3Vh*S-2m`vnw8$KD3T$Yy8#|UP7QknevA=%;R)n28T9WiFoOWn*|`DU0DQFN=vTd!gc`*(F8ZqKcQwGBds9 z^D{FiFPXb=Liv3Dyq87t(h}z3cS~3*pIXX>@k?ITpTFQ`5&A|7KjUR~zP^-QrD66g zWYuAi!S7bG>G3KEf=v*F{=G!ud7@wbN@mDQs#p;Pd9jLphIH)RHLNW?Xz7he!+hMp@V+K