diff --git a/.github/workflows/docker-push.yml b/.github/workflows/docker-push.yml index 4bc91fcd015..785325d4553 100644 --- a/.github/workflows/docker-push.yml +++ b/.github/workflows/docker-push.yml @@ -16,7 +16,7 @@ jobs: build-and-push-image: runs-on: ubuntu-latest permissions: - contents: read + contents: write packages: write steps: @@ -54,3 +54,14 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} if: ${{ env.NEW_COMMIT_COUNT > 0 }} + + - name: Dispatch Interchain test + uses: peter-evans/repository-dispatch@v3 + with: + event-type: image-pushed + client-payload: | + { + "tag_name": "${{ fromJson(steps.meta.outputs.json)['labels']['org.opencontainers.image.version'] }}", + "ref_name": "${{ fromJson(steps.meta.outputs.json)['labels']['org.opencontainers.image.revision'] }}" + } + if: ${{ env.NEW_COMMIT_COUNT > 0 }} diff --git a/.github/workflows/interchain-test.yml b/.github/workflows/interchain-test.yml new file mode 100644 index 00000000000..73ba214a17c --- /dev/null +++ b/.github/workflows/interchain-test.yml @@ -0,0 +1,62 @@ +name: Interchain Test +on: + repository_dispatch: + types: [image-pushed] + workflow_dispatch: + +jobs: + prepare-matrix: + runs-on: ubuntu-latest + steps: + # We need to figure out a) a ref to clone based on a docker image, and b) which tag to test + # If the event is a registry_package, this comes from the pushed image; for a workflow_dispatch, it's the branch/tag that the user supplied + - name: Get metadata + id: get-metadata + run: | + if [[ "${{ github.event_name }}" == 'repository_dispatch' ]]; then + echo "ref_name=${{ github.event.client_payload.ref_name }}" | tee -a $GITHUB_OUTPUT + echo "tag_name=${{ github.event.client_payload.tag_name }}" | tee -a $GITHUB_OUTPUT + else + echo "ref_name=${{ github.ref_name }}" | tee -a $GITHUB_OUTPUT + echo "tag_name=${{ github.ref_name }}" | tee -a $GITHUB_OUTPUT + fi + - name: Check out repository code + uses: actions/checkout@v3 + with: + ref: ${{ steps.get-metadata.outputs.ref_name }} + - name: Setup go + uses: actions/setup-go@v5 + - name: Prepare matrix + id: generate-matrix + run: | + echo "matrix=$(go run ./tests/interchain/matrix_tool/main.go ${{ steps.get-metadata.outputs.tag_name }})" | tee -a $GITHUB_OUTPUT + outputs: + matrix: ${{ steps.generate-matrix.outputs.matrix }} + ref_name: ${{ steps.get-metadata.outputs.ref_name }} + test: + needs: prepare-matrix + runs-on: ubuntu-latest + name: "${{ matrix.previous_version }} -> ${{ matrix.test_version }} test ${{ matrix.test_name }}" + strategy: + matrix: + ${{fromJson(needs.prepare-matrix.outputs.matrix)}} + fail-fast: false + max-parallel: 10 + steps: + - name: Check out repository code + uses: actions/checkout@v3 + with: + ref: ${{ needs.prepare-matrix.outputs.ref_name }} + - name: Setup go + uses: actions/setup-go@v5 + - name: Run test + env: + TEST_DOCKER_REGISTRY: "ghcr.io/${{ github.repository_owner }}" + TEST_OLD_GAIA_IMAGE_VERSION: "${{ matrix.previous_version }}" + TEST_NEW_GAIA_IMAGE_VERSION: "${{ matrix.test_version }}" + TEST_UPGRADE_NAME: "${{ matrix.upgrade_name }}" + run: | + # This docker pull/tag is a quick hack only necessary for v19, since there were no official v18 images built. + # Once we're testing 19 -> 20 this can be removed + docker pull "ghcr.io/hyphacoop/gaia:v18.1.0" && docker tag "ghcr.io/hyphacoop/gaia:v18.1.0" "ghcr.io/${{ github.repository_owner }}/gaia:v18.1.0" + go test -v ./tests/interchain/... -failfast -p 1 -timeout 5h -run="^${{ matrix.test_name }}" diff --git a/go.mod b/go.mod index b54701ec544..2d8f2729859 100644 --- a/go.mod +++ b/go.mod @@ -18,8 +18,11 @@ require ( github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 github.com/cosmos/ibc-go/v7 v7.6.0 github.com/cosmos/interchain-security/v4 v4.3.0 + github.com/docker/docker v24.0.9+incompatible + github.com/google/go-github/v62 v62.0.0 github.com/google/gofuzz v1.2.0 github.com/gorilla/mux v1.8.1 + github.com/kelseyhightower/envconfig v1.4.0 github.com/ory/dockertest/v3 v3.10.0 github.com/prometheus/client_golang v1.17.0 github.com/rakyll/statik v0.1.7 @@ -28,7 +31,12 @@ require ( github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 + github.com/strangelove-ventures/interchaintest/v7 v7.0.0-00010101000000-000000000000 github.com/stretchr/testify v1.9.0 + github.com/tidwall/gjson v1.17.1 + github.com/tidwall/sjson v1.2.4 + go.uber.org/zap v1.26.0 + golang.org/x/sync v0.7.0 ) require ( @@ -46,19 +54,24 @@ require ( require ( cloud.google.com/go/auth v0.5.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect - cosmossdk.io/core v0.5.1 // indirect + cosmossdk.io/core v0.6.1 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect cosmossdk.io/log v1.3.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.2 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/CosmWasm/wasmvm v1.5.0 // indirect - github.com/DataDog/zstd v1.5.0 // indirect + github.com/DataDog/zstd v1.5.2 // indirect + github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect + github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect + github.com/StirlingMarketingGroup/go-namecase v1.0.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect + github.com/avast/retry-go/v4 v4.5.0 // indirect github.com/aws/aws-sdk-go v1.44.224 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect @@ -81,12 +94,17 @@ require ( github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.0.0 // indirect + github.com/cosmos/ibc-go/modules/capability v1.0.0-rc1 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect github.com/creachadair/taskgroup v0.4.2 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/base58 v1.0.4 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect @@ -94,11 +112,11 @@ require ( github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/docker/cli v20.10.17+incompatible // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.9+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.7.0 // indirect + github.com/ethereum/go-ethereum v1.10.20 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/getsentry/sentry-go v0.25.0 // indirect @@ -107,17 +125,19 @@ require ( github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-stack/stack v1.8.1 // indirect github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect - github.com/gogo/protobuf v1.3.2 // indirect + github.com/gogo/protobuf v1.3.3 // indirect github.com/golang/glog v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/orderedcode v0.0.1 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect @@ -140,41 +160,59 @@ require ( github.com/hdevalence/ed25519consensus v0.1.0 // indirect github.com/huandu/skiplist v1.2.0 // indirect github.com/iancoleman/orderedmap v0.2.0 // indirect + github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/ipfs/go-cid v0.4.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/libp2p/go-libp2p v0.27.8 // indirect github.com/linxGnu/grocksdb v1.8.12 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect - github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect + github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b // indirect github.com/minio/highwayhash v1.0.2 // indirect + github.com/minio/sha256-simd v1.0.0 // indirect + github.com/misko9/go-substrate-rpc-client/v4 v4.0.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect + github.com/mr-tron/base58 v1.2.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr v0.9.0 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.8.1 // indirect + github.com/multiformats/go-multihash v0.2.1 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc2 // indirect github.com/opencontainers/runc v1.1.12 // indirect github.com/oxyno-zeta/gomock-extra-matcher v1.2.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect + github.com/pierrec/xxHash v0.1.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/cors v1.8.3 // indirect github.com/rs/zerolog v1.32.0 // indirect @@ -183,12 +221,18 @@ require ( github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/tidwall/btree v1.7.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/tyler-smith/go-bip32 v1.0.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/ulikunitz/xz v0.5.11 // indirect + github.com/vedhavyas/go-subkey/v2 v2.0.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -202,13 +246,12 @@ require ( go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/mock v0.2.0 // indirect - go.uber.org/multierr v1.10.0 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.24.0 // indirect golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect golang.org/x/mod v0.18.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect - golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/term v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect @@ -219,9 +262,21 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - nhooyr.io/websocket v1.8.6 // indirect + lukechampine.com/blake3 v1.1.7 // indirect + lukechampine.com/uint128 v1.2.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.24.1 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.6.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/sqlite v1.25.0 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.0.1 // indirect + nhooyr.io/websocket v1.8.7 // indirect pgregory.net/rapid v1.1.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) @@ -245,6 +300,11 @@ replace ( // TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.8.1 + github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 + github.com/misko9/go-substrate-rpc-client/v4 => github.com/faddat/go-substrate-rpc-client/v4 v4.0.1-0.20240402155230-48db8c110afe + + github.com/strangelove-ventures/interchaintest/v7 => github.com/hyphacoop/interchaintest/v7 v7.0.1-0.20240610153824-9ccc5551034a + // following versions might cause unexpected behavior github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/go.sum b/go.sum index 9b1de1fd0fb..7c94c47ce0d 100644 --- a/go.sum +++ b/go.sum @@ -526,8 +526,8 @@ cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcP collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= cosmossdk.io/api v0.3.1 h1:NNiOclKRR0AOlO4KIqeaG6PS6kswOMhHD0ir0SscNXE= cosmossdk.io/api v0.3.1/go.mod h1:DfHfMkiNA2Uhy8fj0JJlOCYOBp4eWUUJ1te5zBGNyIw= -cosmossdk.io/core v0.5.1 h1:vQVtFrIYOQJDV3f7rw4pjjVqc1id4+mE0L9hHP66pyI= -cosmossdk.io/core v0.5.1/go.mod h1:KZtwHCLjcFuo0nmDc24Xy6CRNEL9Vl/MeimQ2aC7NLE= +cosmossdk.io/core v0.6.1 h1:OBy7TI2W+/gyn2z40vVvruK3di+cAluinA6cybFbE7s= +cosmossdk.io/core v0.6.1/go.mod h1:g3MMBCBXtxbDWBURDVnJE7XML4BG5qENhs0gzkcpuFA= cosmossdk.io/depinject v1.0.0-alpha.4 h1:PLNp8ZYAMPTUKyG9IK2hsbciDWqna2z1Wsl98okJopc= cosmossdk.io/depinject v1.0.0-alpha.4/go.mod h1:HeDk7IkR5ckZ3lMGs/o91AVUc7E596vMaOmslGFM3yU= cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0= @@ -555,14 +555,21 @@ github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/CosmWasm/wasmvm v1.5.0 h1:3hKeT9SfwfLhxTGKH3vXaKFzBz1yuvP8SlfwfQXbQfw= github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/zstd v1.5.0 h1:+K/VEwIAaPcHiMtQvpLD4lqW7f0Gk3xdYZmI1hD+CXo= github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= +github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc= +github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= @@ -573,7 +580,10 @@ 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 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StirlingMarketingGroup/go-namecase v1.0.0 h1:2CzaNtCzc4iNHirR+5ru9OzGg8rQp860gqLBFqRI02Y= +github.com/StirlingMarketingGroup/go-namecase v1.0.0/go.mod h1:ZsoSKcafcAzuBx+sndbxHu/RjDcDTrEdT4UvhniHfio= github.com/Stride-Labs/ibc-rate-limiting v1.0.1 h1:MT80/HAZ+sCVqmfill5dJ7aIY/p5evGF3MslbU0PRas= github.com/Stride-Labs/ibc-rate-limiting v1.0.1/go.mod h1:EBulHz7dKsjbydj7bHiykqraA4Vn7wRkoTXZ7tydRZM= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= @@ -609,6 +619,8 @@ github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJ github.com/armon/go-metrics v0.4.1/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/avast/retry-go/v4 v4.5.0 h1:QoRAZZ90cj5oni2Lsgl2GW8mNTnUCnmpx/iKpwVisHg= +github.com/avast/retry-go/v4 v4.5.0/go.mod h1:7hLEXp0oku2Nir2xBAsg0PTphp9z71bN5Aq1fboC3+I= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= @@ -655,6 +667,7 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufo 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/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= 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= @@ -697,6 +710,8 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp 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.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e h1:0XBUw73chJ1VYSsfvcPvVT7auykAJce9FpRr10L6Qhw= +github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA= 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= @@ -764,6 +779,8 @@ github.com/cosmos/iavl v0.20.1 h1:rM1kqeG3/HBT85vsZdoSNsehciqUQPWrR4BYmqE2+zg= github.com/cosmos/iavl v0.20.1/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3 h1:MZGDMETv72suFpTAD6VPGqSIm1FJcChtk2HmVh9D+Bo= github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7 v7.1.3/go.mod h1:UvDmcGIWJPIytq+Q78/ff5NTOsuX/7IrNgEugTW5i0s= +github.com/cosmos/ibc-go/modules/capability v1.0.0-rc1 h1:BvSKnPFKxL+TTSLxGKwJN4x0ndCZj0yfXhSvmsQztSA= +github.com/cosmos/ibc-go/modules/capability v1.0.0-rc1/go.mod h1:A+CxAQdn2j6ihDTbClpEEBdHthWgAUAcHbRAQPY8sl4= github.com/cosmos/ibc-go/v7 v7.6.0 h1:S1G5hcIVe9go+jQV6F9+I9yy+hylbJeLiVHUmktQNrM= github.com/cosmos/ibc-go/v7 v7.6.0/go.mod h1:LifBA7JHRHl95ujjHIaBEHmUqy2qCGyqDCXB7qmAsZk= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= @@ -794,10 +811,17 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/base58 v1.0.4 h1:QJC6B0E0rXOPA8U/kw2rP+qiRJsUaE2Er+pYb3siUeA= +github.com/decred/base58 v1.0.4/go.mod h1:jJswKPEdvpFpvf7dsDvFZyLT22xZ9lWqEByX38oGd9E= +github.com/decred/dcrd/chaincfg/chainhash v1.0.2 h1:rt5Vlq/jM3ZawwiacWjPa+smINyLRN07EO0cNBV6DGU= +github.com/decred/dcrd/chaincfg/chainhash v1.0.2/go.mod h1:BpbrGgrPTr3YJYRN3Bm+D9NuaFd+zGyNeIKgrhCXK60= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.1 h1:18HurQ6DfHeNvwIjvOmrgr44bPdtVaQAe/WWwHg9goM= +github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.1/go.mod h1:XmyzkaXBy7ZvHdrTAlXAjpog8qKSAWa3ze7yqzWmgmc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= @@ -862,6 +886,10 @@ github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/ethereum/go-ethereum v1.10.17/go.mod h1:Lt5WzjM07XlXc95YzrhosmR4J9Ahd6X2wyEV2SvGhk0= +github.com/ethereum/go-ethereum v1.10.20 h1:75IW830ClSS40yrQC1ZCMZCt5I+zU16oqId2SiQwdQ4= +github.com/ethereum/go-ethereum v1.10.20/go.mod h1:LWUN82TCHGpxB3En5HVmLLzPD7YSrEUFmFfN1nKkVN0= +github.com/faddat/go-substrate-rpc-client/v4 v4.0.1-0.20240402155230-48db8c110afe h1:63rMpjrCwbJVYoz1XFOzRXCZd8frLSuChg5XSo3tKg4= +github.com/faddat/go-substrate-rpc-client/v4 v4.0.1-0.20240402155230-48db8c110afe/go.mod h1:enTNfc1aCsOpHnOqlDEDAGr3SzacyTh/VX/nL+5YBs4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= @@ -921,6 +949,8 @@ github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= @@ -939,14 +969,17 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= +github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= @@ -958,12 +991,6 @@ github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFG github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= @@ -1039,6 +1066,10 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github/v62 v62.0.0 h1:/6mGCaRywZz9MuHyw9gD1CwsbmBX8GWsbFkwMmHdhl4= +github.com/google/go-github/v62 v62.0.0/go.mod h1:EMxeUqGJq2xRu9DYBMwel/mr7kZrzUOfQmmpYrZn2a4= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= 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= @@ -1069,6 +1100,8 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe 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/pprof v0.0.0-20230405160723-4a4c7d95572b h1:Qcx5LM0fSiks9uCyFZwDBUasd3lxd1RM0GYpL+Li5o4= +github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= @@ -1157,8 +1190,8 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX 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/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -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/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= @@ -1187,11 +1220,15 @@ github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXM github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/huin/goupnp v1.0.3-0.20220313090229-ca81a64b4204/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/hyphacoop/interchaintest/v7 v7.0.1-0.20240610153824-9ccc5551034a h1:qVs0ol0izqypo52cFdzKeKbMAZbsoSJYL5CoxNVeWO0= +github.com/hyphacoop/interchaintest/v7 v7.0.1-0.20240610153824-9ccc5551034a/go.mod h1:TClMrgabgG2e6wjuK1e0xP0wrLM+yQ70jc4T97YS23Q= github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= 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/icza/dyno v0.0.0-20220812133438-f0b6f8a18845 h1:H+uM0Bv88eur3ZSsd2NGKg3YIiuXxwxtlN7HjE66UTU= +github.com/icza/dyno v0.0.0-20220812133438-f0b6f8a18845/go.mod h1:c1tRKs5Tx7E2+uHGSyyncziFjvGpgv4H2HrqXeUQ/Uk= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= @@ -1213,6 +1250,8 @@ github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mq github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= github.com/informalsystems/wasmd v0.45.0-lsm h1:sRldfkkUjZRIOV9+nNw34dS+wrTX6ShhQZd9WqcI+IQ= github.com/informalsystems/wasmd v0.45.0-lsm/go.mod h1:m0eKqxW2caVw1CJKEcEDaCiLXuo7+BflIlUOwiQU55c= +github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= +github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/jackpal/go-nat-pmp v1.0.2/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= @@ -1246,9 +1285,10 @@ github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+ github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= 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= @@ -1262,7 +1302,10 @@ github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrD github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1289,6 +1332,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-libp2p v0.27.8 h1:IX5x/4yKwyPQeVS2AXHZ3J4YATM9oHBGH1gBc23jBAI= +github.com/libp2p/go-libp2p v0.27.8/go.mod h1:eCFFtd0s5i/EVKR7+5Ki8bM7qwkNW3TPTTSSW9sz8NE= 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/linxGnu/grocksdb v1.8.12 h1:1/pCztQUOa3BX/1gR3jSZDoaKFpeHFvQ1XrqZpSvZVo= @@ -1329,18 +1374,22 @@ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= 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/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b h1:QrHweqAtyJ9EwCaGHBu1fghwxIPiopAHV06JlXrMHjk= +github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b/go.mod h1:xxLb2ip6sSUts3g1irPVHyk/DGslwQsNOo9I7smJfNU= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= 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/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= 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 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -1367,9 +1416,27 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb 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/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= 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/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= +github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.8.1 h1:ycepHwavHafh3grIbR1jIXnKCsFm0fqsfEOsJ8NtKE8= +github.com/multiformats/go-multicodec v0.8.1/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= +github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= +github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= 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= @@ -1397,14 +1464,14 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W 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/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= 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/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= -github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= 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= @@ -1434,6 +1501,8 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= 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.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= @@ -1450,6 +1519,8 @@ github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk 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/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/xxHash v0.1.5 h1:n/jBpwTHiER4xYvK3/CdPVnLDPchj8eTJFFLUb4QHBo= +github.com/pierrec/xxHash v0.1.5/go.mod h1:w2waW5Zoa/Wc4Yqe0wgrIYAGKqRMf7czn2HNKXmuL+I= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -1506,7 +1577,11 @@ github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Ung 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/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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -1541,6 +1616,7 @@ github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KR github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+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= @@ -1593,6 +1669,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1616,16 +1693,29 @@ github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= +github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc= github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE= +github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE= 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/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -1640,6 +1730,8 @@ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/X github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/vedhavyas/go-subkey/v2 v2.0.0 h1:LemDIsrVtRSOkp0FA8HxP6ynfKjeOj3BY2U9UNfeDMA= +github.com/vedhavyas/go-subkey/v2 v2.0.0/go.mod h1:95aZ+XDCWAUUynjlmi7BtPExjXgXxByE0WfBwbmIRH4= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= @@ -1701,18 +1793,23 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU= go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 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= @@ -2007,6 +2104,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc 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-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2063,11 +2161,9 @@ golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -2247,6 +2343,7 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfG 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= @@ -2442,6 +2539,7 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy 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 h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= 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= @@ -2478,18 +2576,29 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt 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= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087 h1:Izowp2XBH6Ya6rv+hqbceQyw/gSGoXfH/UPoTGduL54= +launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= +lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= +lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= @@ -2498,22 +2607,38 @@ modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= +modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM= +modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak= modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/memory v1.6.0 h1:i6mzavxrE9a30whzMfwf7XWVODx2r5OYXvU46cirX7o= +modernc.org/memory v1.6.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= +modernc.org/sqlite v1.25.0 h1:AFweiwPNd/b3BoKnBOfFm+Y260guGMF+0UFk0savqeA= +modernc.org/sqlite v1.25.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU= modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= +modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= -nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= +modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= +modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/tests/interchain/README.md b/tests/interchain/README.md index e69de29bb2d..90ae60ee125 100644 --- a/tests/interchain/README.md +++ b/tests/interchain/README.md @@ -0,0 +1,139 @@ +# Interchain tests for gaia. + + +These tests use [interchaintest](https://github.com/strangelove-ventures/interchaintest/) to +create, upgrade, and test chains. + +They dockerize the validators, so they depend on a `gaia` docker image being built. +You can build a docker image using the [docker-push](../../.github/workflows/docker-push.yml) workflow. +`docker-push` runs nightly on the `main` branch, and for all new releases, but you can also +[run it manually on any branch](https://github.com/cosmos/gaia/actions/workflows/docker-push.yml) + +Once the `gaia` image is built, the `docker-push` action workflow automatically invoke the +[interchain-test](../../.github/workflows/interchain-test.yml) workflow. + +Read on to learn how these tests work. + +## Upgrade testing + +The tests will make sure it's possible to upgrade from a previous version of +`gaia` to the current version being tested. It does so by starting a chain from genesis +on the previous version, then upgrading it to the current version. + +## Version selection + +The `interchain-test` workflow will start by selecting versions to test upgrading from. + +The [`matrix_tool`](./matrix_tool/main.go) tool will take the tag of the image +being tested (e.g. `v18.0.0`, or `main`, or `some-feature-branch`), and figure +out a corresponding semver. If the tag is already a valid semver, that's the +version. Otherwise, it will take the major version from the module line in `go.mod`, +and append `.999.0`. Given that semver, it'll figure out: + +* The previous rc (if the current version is itself an rc) +* The previous minor version (if applicable) +* The previous major version + +For instance, for `v15.1.0-rc1`, we'll test upgrading from: +* `v15.1.0-rc0` +* `v15.0.0` +* `v14.2.0` + +The workflow will then test upgrading from each of those three to the current +version. When it's a major upgrade, it will do so via governance proposal, +otherwise it'll simply stop the old image and start the new one. + +## Test Suites + +Each of the *_test.go files in this directory contains a test suite. These +share some common scaffolding (a `SetupSuite`) to create and upgrade a chain, +and then run a set of tests on that chain. + +So, for instance, a transactions suite: + +```go +type TxSuite struct { + *chainsuite.Suite +} +``` + +It extends `chainsuite.Suite,` so its SetupSuite will create and upgrade a +chain (more on this later). The individual `Test*` methods then run the gaia +version being tested: + +```go +func (s *TxSuite) TestBankSend() { + balanceBefore, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[1].Address, chainsuite.Uatom) + s.Require().NoError(err) + + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "bank", "send", + s.Chain.ValidatorWallets[0].Address, s.Chain.ValidatorWallets[1].Address, txAmountUatom(), + ) + s.Require().NoError(err) + + balanceAfter, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[1].Address, chainsuite.Uatom) + s.Require().NoError(err) + s.Require().Equal(balanceBefore.Add(sdkmath.NewInt(txAmount)), balanceAfter) +} +``` + +Because of how testify works, we have to instantiate each suite to run it. +This is also where we tell the suite to run an upgrade on Setup: + +```go +func TestTransactions(t *testing.T) { + txSuite := TxSuite{chainsuite.NewSuite(chainsuite.SuiteConfig{UpgradeOnSetup: true})} + suite.Run(t, &txSuite) +} +``` + +Of course, we can also parameterize the test suites themselves. This enables us +to write tests once and run them a bunch of times on different configurations: + +```go +type ConsumerLaunchSuite struct { + *chainsuite.Suite + OtherChain string + OtherChainVersion string + ShouldCopyProviderKey [chainsuite.ValidatorCount]bool +} + +func TestICS40ChainLaunch(t *testing.T) { + s := &ConsumerLaunchSuite{ + Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{}), + OtherChain: "ics-consumer", + OtherChainVersion: "v4.0.0", + ShouldCopyProviderKey: noProviderKeysCopied(), + } + suite.Run(t, s) +} + +func TestICS33ConsumerAllKeysChainLaunch(t *testing.T) { + s := &ConsumerLaunchSuite{ + Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{}), + OtherChain: "ics-consumer", + OtherChainVersion: "v3.3.0", + ShouldCopyProviderKey: allProviderKeysCopied(), + } + suite.Run(t, s) +} +``` + +Notice also how `UpgradeOnSetup` isn't set here: the ConsumerLaunchSuite needs +to be handed a pre-upgrade chain so it can make sure that a consumer chain that +launched before the upgrade keeps working after the upgrade. + + +## Writing new tests + +All you need to start writing new tests is a test suite as described above. +The suite will have an `s.Chain` that you can test. Check out utilities in +[`chainsuite/chain.go`](./chainsuite/chain.go) and +[`chain_ics.go`](./chainsuite/chain_ics.go) for some convenience methods. + +In addition, the s.Chain object extends the `interchaintest` chain object, so +check out [the docs](https://pkg.go.dev/github.com/strangelove-ventures/interchaintest/v7) to +see what else is available. diff --git a/tests/interchain/chainsuite/chain.go b/tests/interchain/chainsuite/chain.go new file mode 100644 index 00000000000..dd62e6a081b --- /dev/null +++ b/tests/interchain/chainsuite/chain.go @@ -0,0 +1,268 @@ +package chainsuite + +import ( + "context" + "fmt" + "strconv" + "sync" + "time" + + sdkmath "cosmossdk.io/math" + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testutil" + "github.com/tidwall/gjson" + "golang.org/x/sync/errgroup" + + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" +) + +// This moniker is hardcoded into interchaintest +const validatorMoniker = "validator" + +type Chain struct { + *cosmos.CosmosChain + ValidatorWallets []ValidatorWallet + RelayerWallet ibc.Wallet +} + +type ValidatorWallet struct { + Moniker string + Address string + ValoperAddress string +} + +func chainFromCosmosChain(cosmos *cosmos.CosmosChain, relayerWallet ibc.Wallet) (*Chain, error) { + c := &Chain{CosmosChain: cosmos} + wallets, err := getValidatorWallets(context.Background(), c) + if err != nil { + return nil, err + } + c.ValidatorWallets = wallets + c.RelayerWallet = relayerWallet + return c, nil +} + +// CreateChain creates a single new chain with the given version and returns the chain object. +func CreateChain(ctx context.Context, testName interchaintest.TestName, spec *interchaintest.ChainSpec) (*Chain, error) { + cf := interchaintest.NewBuiltinChainFactory( + GetLogger(ctx), + []*interchaintest.ChainSpec{spec}, + ) + + chains, err := cf.Chains(testName.Name()) + if err != nil { + return nil, err + } + cosmosChain := chains[0].(*cosmos.CosmosChain) + relayerWallet, err := cosmosChain.BuildRelayerWallet(ctx, "relayer-"+cosmosChain.Config().ChainID) + if err != nil { + return nil, err + } + + ic := interchaintest.NewInterchain().AddChain(cosmosChain, ibc.WalletAmount{ + Address: relayerWallet.FormattedAddress(), + Denom: cosmosChain.Config().Denom, + Amount: sdkmath.NewInt(ValidatorFunds), + }) + + dockerClient, dockerNetwork := GetDockerContext(ctx) + + if err := ic.Build(ctx, GetRelayerExecReporter(ctx), interchaintest.InterchainBuildOptions{ + Client: dockerClient, + NetworkID: dockerNetwork, + TestName: testName.Name(), + }); err != nil { + return nil, err + } + // t.Cleanup(func() { + // _ = ic.Close() + // }) + + chain, err := chainFromCosmosChain(cosmosChain, relayerWallet) + if err != nil { + return nil, err + } + return chain, nil +} + +func (c *Chain) GenerateTx(ctx context.Context, valIdx int, command ...string) (string, error) { + command = append([]string{"tx"}, command...) + command = append(command, "--generate-only", "--keyring-backend", "test", "--chain-id", c.Config().ChainID) + command = c.Validators[valIdx].NodeCommand(command...) + stdout, _, err := c.Validators[valIdx].Exec(ctx, command, nil) + if err != nil { + return "", err + } + return string(stdout), nil +} + +func (c *Chain) WaitForProposalStatus(ctx context.Context, proposalID string, status govv1beta1.ProposalStatus) error { + propID, err := strconv.ParseInt(proposalID, 10, 64) + if err != nil { + return err + } + chainHeight, err := c.Height(ctx) + if err != nil { + return err + } + maxHeight := chainHeight + UpgradeDelta + _, err = cosmos.PollForProposalStatus(ctx, c.CosmosChain, chainHeight, maxHeight, propID, status) + return err +} + +func (c *Chain) PassProposal(ctx context.Context, proposalID string) error { + propID, err := strconv.ParseInt(proposalID, 10, 64) + if err != nil { + return err + } + err = c.VoteOnProposalAllValidators(ctx, propID, cosmos.ProposalVoteYes) + if err != nil { + return err + } + return c.WaitForProposalStatus(ctx, proposalID, govv1beta1.StatusPassed) +} + +func (c *Chain) ReplaceImagesAndRestart(ctx context.Context, version string) error { + // bring down nodes to prepare for upgrade + err := c.StopAllNodes(ctx) + if err != nil { + return err + } + + // upgrade version on all nodes + c.UpgradeVersion(ctx, c.GetNode().DockerClient, c.GetNode().Image.Repository, version) + + // start all nodes back up. + // validators reach consensus on first block after upgrade height + // and block production resumes. + err = c.StartAllNodes(ctx) + if err != nil { + return err + } + + timeoutCtx, timeoutCancel := context.WithTimeout(ctx, 60*time.Second) + defer timeoutCancel() + err = testutil.WaitForBlocks(timeoutCtx, 5, c) + if err != nil { + return fmt.Errorf("failed to wait for blocks after upgrade: %w", err) + } + + // Flush "successfully migrated key info" messages + for _, val := range c.Validators { + _, _, err := val.ExecBin(ctx, "keys", "list", "--keyring-backend", "test") + if err != nil { + return err + } + } + return nil +} + +func (c *Chain) Upgrade(ctx context.Context, upgradeName, version string) error { + height, err := c.Height(ctx) + if err != nil { + return err + } + + haltHeight := height + UpgradeDelta + + proposal := cosmos.SoftwareUpgradeProposal{ + Deposit: GovDepositAmount, // greater than min deposit + Title: "Upgrade to " + upgradeName, + Name: upgradeName, + Description: "Upgrade to " + upgradeName, + Height: haltHeight, + } + upgradeTx, err := c.UpgradeProposal(ctx, interchaintest.FaucetAccountKeyName, proposal) + if err != nil { + return err + } + if err := c.PassProposal(ctx, upgradeTx.ProposalID); err != nil { + return err + } + + height, err = c.Height(ctx) + if err != nil { + return err + } + + // wait for the chain to halt. We're asking for blocks after the halt height, so we should time out. + timeoutCtx, timeoutCtxCancel := context.WithTimeout(ctx, (time.Duration(haltHeight-height)+10)*CommitTimeout) + defer timeoutCtxCancel() + err = testutil.WaitForBlocks(timeoutCtx, int(haltHeight-height)+3, c) + if err == nil { + return fmt.Errorf("chain should not produce blocks after halt height") + } else if timeoutCtx.Err() == nil { + return fmt.Errorf("chain should not produce blocks after halt height") + } + + height, err = c.Height(ctx) + if err != nil { + return err + } + + // make sure that chain is halted; some chains may produce one more block after halt height + if height-haltHeight > 1 { + return fmt.Errorf("height %d is not within one block of halt height %d; chain isn't halted", height, haltHeight) + } + + return c.ReplaceImagesAndRestart(ctx, version) +} + +func (c *Chain) GetValidatorPower(ctx context.Context, hexaddr string) (int64, error) { + var power int64 + err := CheckEndpoint(ctx, c.GetHostRPCAddress()+"/validators", func(b []byte) error { + power = gjson.GetBytes(b, fmt.Sprintf("result.validators.#(address==\"%s\").voting_power", hexaddr)).Int() + if power == 0 { + return fmt.Errorf("validator %s power not found; validators are: %s", hexaddr, string(b)) + } + return nil + }) + if err != nil { + return 0, err + } + return power, nil +} + +func (c *Chain) GetValidatorHex(ctx context.Context, val int) (string, error) { + json, err := c.Validators[val].ReadFile(ctx, "config/priv_validator_key.json") + if err != nil { + return "", err + } + providerHex := gjson.GetBytes(json, "address").String() + return providerHex, nil +} + +func getValidatorWallets(ctx context.Context, chain *Chain) ([]ValidatorWallet, error) { + wallets := make([]ValidatorWallet, ValidatorCount) + lock := new(sync.Mutex) + eg := new(errgroup.Group) + for i := 0; i < ValidatorCount; i++ { + i := i + eg.Go(func() error { + // This moniker is hardcoded into the chain's genesis process. + moniker := validatorMoniker + address, err := chain.Validators[i].KeyBech32(ctx, moniker, "acc") + if err != nil { + return err + } + valoperAddress, err := chain.Validators[i].KeyBech32(ctx, moniker, "val") + if err != nil { + return err + } + lock.Lock() + defer lock.Unlock() + wallets[i] = ValidatorWallet{ + Moniker: moniker, + Address: address, + ValoperAddress: valoperAddress, + } + return nil + }) + } + if err := eg.Wait(); err != nil { + return nil, err + } + return wallets, nil +} diff --git a/tests/interchain/chainsuite/chain_ics.go b/tests/interchain/chainsuite/chain_ics.go new file mode 100644 index 00000000000..9a912353d56 --- /dev/null +++ b/tests/interchain/chainsuite/chain_ics.go @@ -0,0 +1,518 @@ +package chainsuite + +import ( + "context" + "fmt" + "strconv" + "time" + + sdkmath "cosmossdk.io/math" + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testutil" + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" + "golang.org/x/mod/semver" + + govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" + ccvclient "github.com/cosmos/interchain-security/v4/x/ccv/provider/client" +) + +type ConsumerBootstrapCb func(ctx context.Context, consumer *cosmos.CosmosChain) + +type ConsumerConfig struct { + ChainName string + Version string + Denom string + ShouldCopyProviderKey [ValidatorCount]bool + TopN int + ValidatorSetCap int + ValidatorPowerCap int + spec *interchaintest.ChainSpec + + DuringDepositPeriod ConsumerBootstrapCb + DuringVotingPeriod ConsumerBootstrapCb + BeforeSpawnTime ConsumerBootstrapCb + AfterSpawnTime ConsumerBootstrapCb +} + +type proposalWaiter struct { + canDeposit chan struct{} + isInVoting chan struct{} + canVote chan struct{} + isPassed chan struct{} +} + +func (pw *proposalWaiter) waitForDepositAllowed() { + <-pw.canDeposit +} + +func (pw *proposalWaiter) allowDeposit() { + close(pw.canDeposit) +} + +func (pw *proposalWaiter) waitForVotingPeriod() { + <-pw.isInVoting +} + +func (pw *proposalWaiter) startVotingPeriod() { + close(pw.isInVoting) +} + +func (pw *proposalWaiter) waitForVoteAllowed() { + <-pw.canVote +} + +func (pw *proposalWaiter) allowVote() { + close(pw.canVote) +} + +func (pw *proposalWaiter) waitForPassed() { + <-pw.isPassed +} + +func (pw *proposalWaiter) pass() { + close(pw.isPassed) +} + +func newProposalWaiter() *proposalWaiter { + return &proposalWaiter{ + canDeposit: make(chan struct{}), + isInVoting: make(chan struct{}), + canVote: make(chan struct{}), + isPassed: make(chan struct{}), + } +} + +func (p *Chain) AddConsumerChain(ctx context.Context, relayer *Relayer, config ConsumerConfig) (*Chain, error) { + dockerClient, dockerNetwork := GetDockerContext(ctx) + + if len(config.ShouldCopyProviderKey) != ValidatorCount { + return nil, fmt.Errorf("shouldCopyProviderKey must be the same length as the number of validators") + } + + spawnTime := time.Now().Add(CHAIN_SPAWN_WAIT) + chainID := fmt.Sprintf("%s-%d", config.ChainName, len(p.Consumers)+1) + + proposalWaiter, errCh, err := p.consumerAdditionProposal(ctx, chainID, config, spawnTime) + if err != nil { + return nil, err + } + + if config.spec == nil { + config.spec = p.DefaultConsumerChainSpec(ctx, chainID, config, spawnTime, proposalWaiter) + } + if semver.Compare(p.GetNode().ICSVersion(ctx), "v4.1.0") > 0 && + semver.Major(p.GetNode().ICSVersion(ctx)) == "v4" && + config.spec.InterchainSecurityConfig.ProviderVerOverride == "" { + config.spec.InterchainSecurityConfig.ProviderVerOverride = "v4.1.0" + } + cf := interchaintest.NewBuiltinChainFactory( + GetLogger(ctx), + []*interchaintest.ChainSpec{config.spec}, + ) + chains, err := cf.Chains(p.GetNode().TestName) + if err != nil { + return nil, err + } + cosmosConsumer := chains[0].(*cosmos.CosmosChain) + + // We can't use AddProviderConsumerLink here because the provider chain is already built; we'll have to do everything by hand. + p.Consumers = append(p.Consumers, cosmosConsumer) + cosmosConsumer.Provider = p.CosmosChain + + relayerWallet, err := cosmosConsumer.BuildRelayerWallet(ctx, "relayer-"+cosmosConsumer.Config().ChainID) + if err != nil { + return nil, err + } + wallets := make([]ibc.Wallet, len(p.Validators)+1) + wallets[0] = relayerWallet + // This is a hack, but we need to create wallets for the validators that have the right moniker. + for i := 1; i <= len(p.Validators); i++ { + wallets[i], err = cosmosConsumer.BuildRelayerWallet(ctx, validatorMoniker) + if err != nil { + return nil, err + } + } + walletAmounts := make([]ibc.WalletAmount, len(wallets)) + for i, wallet := range wallets { + walletAmounts[i] = ibc.WalletAmount{ + Address: wallet.FormattedAddress(), + Denom: cosmosConsumer.Config().Denom, + Amount: sdkmath.NewInt(ValidatorFunds), + } + } + ic := interchaintest.NewInterchain(). + AddChain(cosmosConsumer, walletAmounts...). + AddRelayer(relayer, "relayer") + + if err := ic.Build(ctx, GetRelayerExecReporter(ctx), interchaintest.InterchainBuildOptions{ + Client: dockerClient, + NetworkID: dockerNetwork, + TestName: p.GetNode().TestName, + }); err != nil { + return nil, err + } + + // The chain should be built now, so we gotta check for errors in passing the proposal. + if err := <-errCh; err != nil { + return nil, err + } + + for i, val := range cosmosConsumer.Validators { + if err := val.RecoverKey(ctx, validatorMoniker, wallets[i+1].Mnemonic()); err != nil { + return nil, err + } + } + consumer, err := chainFromCosmosChain(cosmosConsumer, relayerWallet) + if err != nil { + return nil, err + } + + err = relayer.SetupChainKeys(ctx, consumer) + if err != nil { + return nil, err + } + rep := GetRelayerExecReporter(ctx) + if err := relayer.StopRelayer(ctx, rep); err != nil { + return nil, err + } + if err := relayer.StartRelayer(ctx, rep); err != nil { + return nil, err + } + err = connectProviderConsumer(ctx, p, consumer, relayer) + if err != nil { + return nil, err + } + + return consumer, nil +} + +func (p *Chain) DefaultConsumerChainSpec(ctx context.Context, chainID string, config ConsumerConfig, spawnTime time.Time, proposalWaiter *proposalWaiter) *interchaintest.ChainSpec { + fullNodes := len(p.FullNodes) + validators := len(p.Validators) + + chainType := config.ChainName + version := config.Version + denom := config.Denom + shouldCopyProviderKey := config.ShouldCopyProviderKey + + bechPrefix := "" + if chainType == "ics-consumer" { + majorVersion, err := strconv.Atoi(version[1:2]) + if err != nil { + // this really shouldn't happen unless someone misconfigured something + panic(fmt.Sprintf("failed to parse major version from %s: %v", version, err)) + } + if majorVersion >= 4 { + bechPrefix = "consumer" + } + } else if chainType == "stride" { + bechPrefix = "stride" + } + genesisOverrides := []cosmos.GenesisKV{ + cosmos.NewGenesisKV("app_state.slashing.params.signed_blocks_window", strconv.Itoa(SLASHING_WINDOW_CONSUMER)), + cosmos.NewGenesisKV("consensus_params.block.max_gas", "50000000"), + } + if config.TopN >= 0 { + genesisOverrides = append(genesisOverrides, cosmos.NewGenesisKV("app_state.ccvconsumer.params.soft_opt_out_threshold", "0.0")) + } + if chainType == "neutron" { + genesisOverrides = append(genesisOverrides, + cosmos.NewGenesisKV("app_state.globalfee.params.minimum_gas_prices", []interface{}{ + map[string]interface{}{ + "amount": "0.005", + "denom": denom, + }, + }), + ) + } + + modifyGenesis := cosmos.ModifyGenesis(genesisOverrides) + if chainType == "stride" { + genesisOverrides = append(genesisOverrides, + cosmos.NewGenesisKV("app_state.gov.params.voting_period", GovVotingPeriod.String()), + ) + modifyGenesis = func(cc ibc.ChainConfig, b []byte) ([]byte, error) { + b, err := cosmos.ModifyGenesis(genesisOverrides)(cc, b) + if err != nil { + return nil, err + } + b, err = sjson.SetBytes(b, "app_state.epochs.epochs.#(identifier==\"day\").duration", "120s") + if err != nil { + return nil, err + } + return sjson.SetBytes(b, "app_state.epochs.epochs.#(identifier==\"stride_epoch\").duration", "30s") + } + } + + return &interchaintest.ChainSpec{ + Name: chainType, + Version: version, + ChainName: chainID, + NumFullNodes: &fullNodes, + NumValidators: &validators, + ChainConfig: ibc.ChainConfig{ + Denom: denom, + GasPrices: "0.005" + denom, + GasAdjustment: 2.0, + ChainID: chainID, + ConfigFileOverrides: map[string]any{ + "config/config.toml": DefaultConfigToml(), + }, + PreGenesis: func(consumer ibc.Chain) error { + if config.DuringDepositPeriod != nil { + config.DuringDepositPeriod(ctx, consumer.(*cosmos.CosmosChain)) + } + proposalWaiter.allowDeposit() + proposalWaiter.waitForVotingPeriod() + if config.DuringVotingPeriod != nil { + config.DuringVotingPeriod(ctx, consumer.(*cosmos.CosmosChain)) + } + proposalWaiter.allowVote() + proposalWaiter.waitForPassed() + tCtx, tCancel := context.WithDeadline(ctx, spawnTime) + defer tCancel() + if config.BeforeSpawnTime != nil { + config.BeforeSpawnTime(tCtx, consumer.(*cosmos.CosmosChain)) + } + // interchaintest will set up the validator keys right before PreGenesis. + // Now we just need to wait for the chain to spawn before interchaintest can get the ccv file. + // This wait is here and not there because of changes we've made to interchaintest that need to be upstreamed in an orderly way. + GetLogger(ctx).Sugar().Infof("waiting for chain %s to spawn at %s", chainID, spawnTime) + <-tCtx.Done() + if err := testutil.WaitForBlocks(ctx, 2, p); err != nil { + return err + } + if config.AfterSpawnTime != nil { + config.AfterSpawnTime(ctx, consumer.(*cosmos.CosmosChain)) + } + return nil + }, + Bech32Prefix: bechPrefix, + ModifyGenesisAmounts: DefaultGenesisAmounts(denom), + ModifyGenesis: modifyGenesis, + ConsumerCopyProviderKey: func(i int) bool { + return shouldCopyProviderKey[i] + }, + }, + } +} + +func connectProviderConsumer(ctx context.Context, provider *Chain, consumer *Chain, relayer *Relayer) error { + icsPath := relayerICSPathFor(provider, consumer) + rep := GetRelayerExecReporter(ctx) + if err := relayer.GeneratePath(ctx, rep, consumer.Config().ChainID, provider.Config().ChainID, icsPath); err != nil { + return err + } + + consumerClients, err := relayer.GetClients(ctx, rep, consumer.Config().ChainID) + if err != nil { + return err + } + + var consumerClient *ibc.ClientOutput + for _, client := range consumerClients { + if client.ClientState.ChainID == provider.Config().ChainID { + consumerClient = client + break + } + } + if consumerClient == nil { + return fmt.Errorf("consumer chain %s does not have a client tracking the provider chain %s", consumer.Config().ChainID, provider.Config().ChainID) + } + consumerClientID := consumerClient.ClientID + + providerClients, err := relayer.GetClients(ctx, rep, provider.Config().ChainID) + if err != nil { + return err + } + + var providerClient *ibc.ClientOutput + for _, client := range providerClients { + if client.ClientState.ChainID == consumer.Config().ChainID { + providerClient = client + break + } + } + if providerClient == nil { + return fmt.Errorf("provider chain %s does not have a client tracking the consumer chain %s for path %s on relayer %s", + provider.Config().ChainID, consumer.Config().ChainID, icsPath, relayer) + } + providerClientID := providerClient.ClientID + + if err := relayer.UpdatePath(ctx, rep, icsPath, ibc.PathUpdateOptions{ + SrcClientID: &consumerClientID, + DstClientID: &providerClientID, + }); err != nil { + return err + } + + if err := relayer.CreateConnections(ctx, rep, icsPath); err != nil { + return err + } + + if err := relayer.CreateChannel(ctx, rep, icsPath, ibc.CreateChannelOptions{ + SourcePortName: "consumer", + DestPortName: "provider", + Order: ibc.Ordered, + Version: "1", + }); err != nil { + return err + } + + tCtx, tCancel := context.WithTimeout(ctx, 30*CommitTimeout) + defer tCancel() + for tCtx.Err() == nil { + var ch *ibc.ChannelOutput + ch, err = relayer.GetTransferChannel(ctx, provider, consumer) + if err == nil && ch != nil { + break + } else if err == nil { + err = fmt.Errorf("channel not found") + } + time.Sleep(CommitTimeout) + } + return err +} + +func (p *Chain) consumerAdditionProposal(ctx context.Context, chainID string, config ConsumerConfig, spawnTime time.Time) (*proposalWaiter, chan error, error) { + propWaiter := newProposalWaiter() + prop := ccvclient.ConsumerAdditionProposalJSON{ + Title: fmt.Sprintf("Addition of %s consumer chain", chainID), + Summary: "Proposal to add new consumer chain", + ChainId: chainID, + InitialHeight: clienttypes.Height{RevisionNumber: clienttypes.ParseChainID(chainID), RevisionHeight: 1}, + GenesisHash: []byte("gen_hash"), + BinaryHash: []byte("bin_hash"), + SpawnTime: spawnTime, + + BlocksPerDistributionTransmission: 1000, + CcvTimeoutPeriod: 2419200000000000, + TransferTimeoutPeriod: 3600000000000, + ConsumerRedistributionFraction: "0.75", + HistoricalEntries: 10000, + UnbondingPeriod: 1728000000000000, + Deposit: strconv.Itoa(GovMinDepositAmount/2) + p.Config().Denom, + } + if config.TopN >= 0 { + prop.TopN = uint32(config.TopN) + } + if config.ValidatorSetCap > 0 { + prop.ValidatorSetCap = uint32(config.ValidatorSetCap) + } + if config.ValidatorPowerCap > 0 { + prop.ValidatorsPowerCap = uint32(config.ValidatorPowerCap) + } + propTx, err := p.ConsumerAdditionProposal(ctx, interchaintest.FaucetAccountKeyName, prop) + if err != nil { + return nil, nil, err + } + errCh := make(chan error) + go func() { + defer close(errCh) + if err := p.WaitForProposalStatus(ctx, propTx.ProposalID, govv1beta1.StatusDepositPeriod); err != nil { + errCh <- err + return + } + propWaiter.waitForDepositAllowed() + + if _, err := p.GetNode().ExecTx(ctx, interchaintest.FaucetAccountKeyName, "gov", "deposit", propTx.ProposalID, prop.Deposit); err != nil { + errCh <- err + return + } + + if err := p.WaitForProposalStatus(ctx, propTx.ProposalID, govv1beta1.StatusVotingPeriod); err != nil { + errCh <- err + return + } + propWaiter.startVotingPeriod() + propWaiter.waitForVoteAllowed() + + if err := p.PassProposal(ctx, propTx.ProposalID); err != nil { + errCh <- err + return + } + propWaiter.pass() + }() + return propWaiter, errCh, nil +} + +func (p *Chain) CheckCCV(ctx context.Context, consumer *Chain, relayer *Relayer, amount, valIdx, blocksPerEpoch int) error { + providerAddress := p.ValidatorWallets[valIdx] + + json, err := p.Validators[valIdx].ReadFile(ctx, "config/priv_validator_key.json") + if err != nil { + return err + } + providerHex := gjson.GetBytes(json, "address").String() + json, err = consumer.Validators[valIdx].ReadFile(ctx, "config/priv_validator_key.json") + if err != nil { + return err + } + consumerHex := gjson.GetBytes(json, "address").String() + + providerPowerBefore, err := p.GetValidatorPower(ctx, providerHex) + if err != nil { + return err + } + + _, err = p.Validators[valIdx].ExecTx(ctx, providerAddress.Moniker, + "staking", "delegate", + providerAddress.ValoperAddress, fmt.Sprintf("%d%s", amount, p.Config().Denom), + ) + if err != nil { + return err + } + + if blocksPerEpoch > 1 { + providerPower, err := p.GetValidatorPower(ctx, providerHex) + if err != nil { + return err + } + if providerPowerBefore >= providerPower { + return fmt.Errorf("provider power did not increase after delegation") + } + consumerPower, err := consumer.GetValidatorPower(ctx, consumerHex) + if err != nil { + return err + } + if providerPower == consumerPower { + return fmt.Errorf("consumer power updated too soon") + } + if err := testutil.WaitForBlocks(ctx, blocksPerEpoch, p); err != nil { + return err + } + } + + tCtx, tCancel := context.WithTimeout(ctx, 15*time.Minute) + defer tCancel() + var retErr error + for tCtx.Err() == nil { + retErr = nil + providerPower, err := p.GetValidatorPower(ctx, providerHex) + if err != nil { + return err + } + consumerPower, err := consumer.GetValidatorPower(ctx, consumerHex) + if err != nil { + return err + } + if providerPowerBefore >= providerPower { + retErr = fmt.Errorf("provider power did not increase after delegation") + } else if providerPower != consumerPower { + retErr = fmt.Errorf("consumer power did not update after provider delegation") + } + if retErr == nil { + break + } + time.Sleep(CommitTimeout) + } + return retErr +} + +func relayerICSPathFor(chainA, chainB *Chain) string { + return fmt.Sprintf("ics-%s-%s", chainA.Config().ChainID, chainB.Config().ChainID) +} diff --git a/tests/interchain/chainsuite/config.go b/tests/interchain/chainsuite/config.go new file mode 100644 index 00000000000..7700d5b0fa1 --- /dev/null +++ b/tests/interchain/chainsuite/config.go @@ -0,0 +1,147 @@ +package chainsuite + +import ( + "fmt" + "strconv" + "strings" + "time" + + sdkmath "cosmossdk.io/math" + "github.com/cosmos/cosmos-sdk/types" + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testutil" +) + +type SuiteConfig struct { + ChainSpec *interchaintest.ChainSpec + UpgradeOnSetup bool +} + +const ( + CommitTimeout = 4 * time.Second + Uatom = "uatom" + Ucon = "ucon" + NeutronDenom = "untn" + StrideDenom = "ustr" + GovMinDepositAmount = 1000 + GovDepositAmount = "5000000" + Uatom + GovDepositPeriod = 60 * time.Second + GovVotingPeriod = 80 * time.Second + DowntimeJailDuration = 10 * time.Second + ProviderSlashingWindow = 10 + GasPrices = "0.005" + Uatom + ValidatorCount = 6 + UpgradeDelta = 30 + ValidatorFunds = 11_000_000_000 + CHAIN_SPAWN_WAIT = 155 * time.Second + SLASHING_WINDOW_CONSUMER = 20 +) + +func (c SuiteConfig) Merge(other SuiteConfig) SuiteConfig { + if c.ChainSpec == nil { + c.ChainSpec = other.ChainSpec + } else if other.ChainSpec != nil { + c.ChainSpec.ChainConfig = c.ChainSpec.MergeChainSpecConfig(other.ChainSpec.ChainConfig) + if other.ChainSpec.Name != "" { + c.ChainSpec.Name = other.ChainSpec.Name + } + if other.ChainSpec.ChainName != "" { + c.ChainSpec.ChainName = other.ChainSpec.ChainName + } + if other.ChainSpec.Version != "" { + c.ChainSpec.Version = other.ChainSpec.Version + } + if other.ChainSpec.NoHostMount != nil { + c.ChainSpec.NoHostMount = other.ChainSpec.NoHostMount + } + if other.ChainSpec.NumValidators != nil { + c.ChainSpec.NumValidators = other.ChainSpec.NumValidators + } + if other.ChainSpec.NumFullNodes != nil { + c.ChainSpec.NumFullNodes = other.ChainSpec.NumFullNodes + } + } + c.UpgradeOnSetup = other.UpgradeOnSetup + return c +} + +func DefaultGenesisAmounts(denom string) func(i int) (types.Coin, types.Coin) { + return func(i int) (types.Coin, types.Coin) { + return types.Coin{ + Denom: denom, + Amount: sdkmath.NewInt(ValidatorFunds), + }, types.Coin{ + Denom: denom, + Amount: sdkmath.NewInt([ValidatorCount]int64{ + 30_000_000, + 29_000_000, + 20_000_000, + 10_000_000, + 7_000_000, + 4_000_000, + }[i]), + } + } +} + +func DefaultSuiteConfig(env Environment) SuiteConfig { + fullNodes := 0 + validators := ValidatorCount + var repository string + if env.DockerRegistry == "" { + repository = env.GaiaImageName + } else { + repository = fmt.Sprintf("%s/%s", env.DockerRegistry, env.GaiaImageName) + } + return SuiteConfig{ + ChainSpec: &interchaintest.ChainSpec{ + Name: "gaia", + NumFullNodes: &fullNodes, + NumValidators: &validators, + Version: env.OldGaiaImageVersion, + ChainConfig: ibc.ChainConfig{ + Denom: Uatom, + GasPrices: GasPrices, + GasAdjustment: 2.0, + ConfigFileOverrides: map[string]any{ + "config/config.toml": DefaultConfigToml(), + }, + Images: []ibc.DockerImage{{ + Repository: repository, + UidGid: "1025:1025", // this is the user in heighliner docker images + }}, + ModifyGenesis: cosmos.ModifyGenesis(DefaultGenesis()), + ModifyGenesisAmounts: DefaultGenesisAmounts(Uatom), + }, + }, + } +} + +func DefaultConfigToml() testutil.Toml { + configToml := make(testutil.Toml) + consensusToml := make(testutil.Toml) + consensusToml["timeout_commit"] = CommitTimeout + configToml["consensus"] = consensusToml + configToml["block_sync"] = false + configToml["fast_sync"] = false + return configToml +} + +func DefaultGenesis() []cosmos.GenesisKV { + return []cosmos.GenesisKV{ + cosmos.NewGenesisKV("app_state.gov.params.voting_period", GovVotingPeriod.String()), + cosmos.NewGenesisKV("app_state.gov.params.max_deposit_period", GovDepositPeriod.String()), + cosmos.NewGenesisKV("app_state.gov.params.min_deposit.0.denom", Uatom), + cosmos.NewGenesisKV("app_state.gov.params.min_deposit.0.amount", strconv.Itoa(GovMinDepositAmount)), + cosmos.NewGenesisKV("app_state.slashing.params.signed_blocks_window", strconv.Itoa(ProviderSlashingWindow)), + cosmos.NewGenesisKV("app_state.slashing.params.downtime_jail_duration", DowntimeJailDuration.String()), + cosmos.NewGenesisKV("app_state.provider.params.slash_meter_replenish_period", "2s"), + cosmos.NewGenesisKV("app_state.provider.params.slash_meter_replenish_fraction", "1.00"), + cosmos.NewGenesisKV("app_state.provider.params.blocks_per_epoch", "1"), + cosmos.NewGenesisKV("app_state.feemarket.params.min_base_gas_price", strings.TrimSuffix(GasPrices, Uatom)), + cosmos.NewGenesisKV("app_state.feemarket.state.base_gas_price", strings.TrimSuffix(GasPrices, Uatom)), + cosmos.NewGenesisKV("app_state.feemarket.params.fee_denom", Uatom), + } +} diff --git a/tests/interchain/chainsuite/context.go b/tests/interchain/chainsuite/context.go new file mode 100644 index 00000000000..83483f22936 --- /dev/null +++ b/tests/interchain/chainsuite/context.go @@ -0,0 +1,86 @@ +package chainsuite + +import ( + "context" + "fmt" + "time" + + "github.com/docker/docker/client" + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/testreporter" + "github.com/stretchr/testify/suite" + "go.uber.org/zap" + "go.uber.org/zap/zaptest" +) + +type testReporterKey struct{} + +type relayerExecReporterKey struct{} + +type loggerKey struct{} + +type dockerKey struct{} + +type dockerContext struct { + NetworkID string + Client *client.Client +} + +func WithDockerContext(ctx context.Context, d *dockerContext) context.Context { + return context.WithValue(ctx, dockerKey{}, d) +} + +func GetDockerContext(ctx context.Context) (*client.Client, string) { + d, _ := ctx.Value(dockerKey{}).(*dockerContext) + return d.Client, d.NetworkID +} + +func WithTestReporter(ctx context.Context, r *testreporter.Reporter) context.Context { + return context.WithValue(ctx, testReporterKey{}, r) +} + +func GetTestReporter(ctx context.Context) *testreporter.Reporter { + r, _ := ctx.Value(testReporterKey{}).(*testreporter.Reporter) + return r +} + +func WithRelayerExecReporter(ctx context.Context, r *testreporter.RelayerExecReporter) context.Context { + return context.WithValue(ctx, relayerExecReporterKey{}, r) +} + +func GetRelayerExecReporter(ctx context.Context) *testreporter.RelayerExecReporter { + r, _ := ctx.Value(relayerExecReporterKey{}).(*testreporter.RelayerExecReporter) + return r +} + +func WithLogger(ctx context.Context, l *zap.Logger) context.Context { + return context.WithValue(ctx, loggerKey{}, l) +} + +func GetLogger(ctx context.Context) *zap.Logger { + l, _ := ctx.Value(loggerKey{}).(*zap.Logger) + return l +} + +func NewSuiteContext(s *suite.Suite) (context.Context, error) { + ctx := context.Background() + + dockerClient, dockerNetwork := interchaintest.DockerSetup(s.T()) + dockerContext := &dockerContext{ + NetworkID: dockerNetwork, + Client: dockerClient, + } + ctx = WithDockerContext(ctx, dockerContext) + logger := zaptest.NewLogger(s.T()) + ctx = WithLogger(ctx, logger) + + f, err := interchaintest.CreateLogFile(fmt.Sprintf("%d.json", time.Now().Unix())) + if err != nil { + return nil, err + } + testReporter := testreporter.NewReporter(f) + ctx = WithTestReporter(ctx, testReporter) + relayerExecReporter := testReporter.RelayerExecReporter(s.T()) + ctx = WithRelayerExecReporter(ctx, relayerExecReporter) + return ctx, nil +} diff --git a/tests/interchain/chainsuite/envconfig.go b/tests/interchain/chainsuite/envconfig.go new file mode 100644 index 00000000000..7c837979baa --- /dev/null +++ b/tests/interchain/chainsuite/envconfig.go @@ -0,0 +1,21 @@ +package chainsuite + +import ( + "github.com/kelseyhightower/envconfig" +) + +const prefix = "TEST" + +type Environment struct { + DockerRegistry string `envconfig:"DOCKER_REGISTRY"` + GaiaImageName string `envconfig:"GAIA_IMAGE_NAME" default:"gaia"` + OldGaiaImageVersion string `envconfig:"OLD_GAIA_IMAGE_VERSION"` + NewGaiaImageVersion string `envconfig:"NEW_GAIA_IMAGE_VERSION"` + UpgradeName string `envconfig:"UPGRADE_NAME"` +} + +func GetEnvironment() Environment { + var env Environment + envconfig.MustProcess(prefix, &env) + return env +} diff --git a/tests/interchain/chainsuite/http.go b/tests/interchain/chainsuite/http.go new file mode 100644 index 00000000000..b1f6d47e696 --- /dev/null +++ b/tests/interchain/chainsuite/http.go @@ -0,0 +1,20 @@ +package chainsuite + +import ( + "context" + "io" + "net/http" +) + +func CheckEndpoint(ctx context.Context, url string, f func([]byte) error) error { + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + bts, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + return f(bts) +} diff --git a/tests/interchain/chainsuite/relayer.go b/tests/interchain/chainsuite/relayer.go new file mode 100644 index 00000000000..9721ef2537d --- /dev/null +++ b/tests/interchain/chainsuite/relayer.go @@ -0,0 +1,89 @@ +package chainsuite + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/relayer" + "github.com/tidwall/gjson" +) + +type Relayer struct { + ibc.Relayer +} + +func NewRelayer(ctx context.Context, testName interchaintest.TestName) (*Relayer, error) { + dockerClient, dockerNetwork := GetDockerContext(ctx) + rly := interchaintest.NewBuiltinRelayerFactory( + ibc.Hermes, + GetLogger(ctx), + relayer.CustomDockerImage("ghcr.io/informalsystems/hermes", "v1.8.0", "1000:1000"), + ).Build(testName, dockerClient, dockerNetwork) + return &Relayer{Relayer: rly}, nil +} + +func (r *Relayer) SetupChainKeys(ctx context.Context, chain *Chain) error { + rep := GetRelayerExecReporter(ctx) + rpcAddr, grpcAddr := chain.GetRPCAddress(), chain.GetGRPCAddress() + if !r.UseDockerNetwork() { + rpcAddr, grpcAddr = chain.GetHostRPCAddress(), chain.GetHostGRPCAddress() + } + + chainName := chain.Config().ChainID + if err := r.AddChainConfiguration(ctx, rep, chain.Config(), chainName, rpcAddr, grpcAddr); err != nil { + return err + } + + if err := r.RestoreKey(ctx, rep, chain.Config(), chainName, chain.RelayerWallet.Mnemonic()); err != nil { + return err + } + return nil +} + +func (r *Relayer) GetTransferChannel(ctx context.Context, chain, counterparty *Chain) (*ibc.ChannelOutput, error) { + return r.GetChannelWithPort(ctx, chain, counterparty, "transfer") +} + +func (r *Relayer) GetChannelWithPort(ctx context.Context, chain, counterparty *Chain, portID string) (*ibc.ChannelOutput, error) { + clients, err := r.GetClients(ctx, GetRelayerExecReporter(ctx), chain.Config().ChainID) + if err != nil { + return nil, err + } + var client *ibc.ClientOutput + for _, c := range clients { + if c.ClientState.ChainID == counterparty.Config().ChainID { + client = c + break + } + } + if client == nil { + return nil, fmt.Errorf("no client found for chain %s", counterparty.Config().ChainID) + } + + stdout, _, err := chain.GetNode().ExecQuery(ctx, "ibc", "connection", "connections") + if err != nil { + return nil, fmt.Errorf("error querying connections: %w", err) + } + connections := gjson.GetBytes(stdout, fmt.Sprintf("connections.#(client_id==\"%s\")#.id", client.ClientID)).Array() + if len(connections) == 0 { + return nil, fmt.Errorf("no connections found for client %s", client.ClientID) + } + for _, connID := range connections { + stdout, _, err := chain.GetNode().ExecQuery(ctx, "ibc", "channel", "connections", connID.String()) + if err != nil { + return nil, err + } + channelJson := gjson.GetBytes(stdout, fmt.Sprintf("channels.#(port_id==\"%s\")", portID)).String() + if channelJson != "" { + channelOutput := &ibc.ChannelOutput{} + if err := json.Unmarshal([]byte(channelJson), channelOutput); err != nil { + return nil, fmt.Errorf("error unmarshalling channel output %s: %w", channelJson, err) + } + return channelOutput, nil + } + } + return nil, fmt.Errorf("no channel found for port %s", portID) +} diff --git a/tests/interchain/chainsuite/suite.go b/tests/interchain/chainsuite/suite.go new file mode 100644 index 00000000000..603b1dbd54c --- /dev/null +++ b/tests/interchain/chainsuite/suite.go @@ -0,0 +1,56 @@ +package chainsuite + +import ( + "context" + "os" + "path" + + "github.com/stretchr/testify/suite" + "golang.org/x/mod/semver" +) + +type Suite struct { + suite.Suite + Config SuiteConfig + Env Environment + Chain *Chain + ctx context.Context +} + +func NewSuite(config SuiteConfig) *Suite { + env := GetEnvironment() + defaultConfig := DefaultSuiteConfig(env) + newCfg := defaultConfig.Merge(config) + return &Suite{Config: newCfg, Env: env} +} + +func (s *Suite) SetupSuite() { + cwd, err := os.Getwd() + s.Require().NoError(err) + err = os.Setenv("IBCTEST_CONFIGURED_CHAINS", path.Join(cwd, "configuredChains.yaml")) + s.Require().NoError(err) + + ctx, err := NewSuiteContext(&s.Suite) + s.Require().NoError(err) + s.ctx = ctx + s.Chain, err = CreateChain(s.GetContext(), s.T(), s.Config.ChainSpec) + s.Require().NoError(err) + if s.Config.UpgradeOnSetup { + s.UpgradeChain() + } +} + +func (s *Suite) GetContext() context.Context { + s.Require().NotNil(s.ctx, "Tried to GetContext before it was set. SetupSuite must run first") + return s.ctx +} + +func (s *Suite) UpgradeChain() { + GetLogger(s.GetContext()).Sugar().Infof("Upgrade %s from %s to %s", s.Env.UpgradeName, s.Env.OldGaiaImageVersion, s.Env.NewGaiaImageVersion) + if s.Env.UpgradeName == semver.Major(s.Env.OldGaiaImageVersion) { + // Not an on-chain upgrade, just replace the image. + s.Require().NoError(s.Chain.ReplaceImagesAndRestart(s.GetContext(), s.Env.NewGaiaImageVersion)) + } else { + s.Require().NoError(s.Chain.Upgrade(s.GetContext(), s.Env.UpgradeName, s.Env.NewGaiaImageVersion)) + } +} diff --git a/tests/interchain/configuredChains.yaml b/tests/interchain/configuredChains.yaml new file mode 100644 index 00000000000..a3dc930b16e --- /dev/null +++ b/tests/interchain/configuredChains.yaml @@ -0,0 +1,55 @@ +gaia: + name: gaia + type: cosmos + bin: gaiad + bech32-prefix: cosmos + denom: uatom + gas-prices: 0.005uatom + gas-adjustment: 2.0 + trusting-period: 504h + images: + - repository: ghcr.io/hyphacoop/gaia + uid-gid: 1025:1025 + no-host-mount: false + +stride: + name: stride + type: cosmos + bin: strided + bech32-prefix: stride + denom: ustrd + gas-prices: 0.005ustrd + gas-adjustment: 2.0 + trusting-period: "336h" + images: + - repository: ghcr.io/strangelove-ventures/heighliner/stride + uid-gid: 1025:1025 + no-host-mount: false + +neutron: + name: neutron + type: cosmos + bin: neutrond + bech32-prefix: neutron + denom: untrn + gas-prices: 0.005untrn + gas-adjustment: 2.0 + trusting-period: "336h" + images: + - repository: ghcr.io/strangelove-ventures/heighliner/neutron + uid-gid: 1025:1025 + no-host-mount: false + +ics-consumer: + name: ics-consumer + type: cosmos + bin: interchain-security-cd + bech32-prefix: cosmos + denom: stake + gas-prices: 0.0stake + gas-adjustment: 2.0 + trusting-period: 96h + images: + - repository: ghcr.io/hyphacoop/ics + uid-gid: 1025:1025 + no-host-mount: false diff --git a/tests/interchain/consumer_launch_test.go b/tests/interchain/consumer_launch_test.go new file mode 100644 index 00000000000..5dd1cae1a1b --- /dev/null +++ b/tests/interchain/consumer_launch_test.go @@ -0,0 +1,147 @@ +package interchain_test + +import ( + "testing" + + "github.com/cosmos/gaia/v19/tests/interchain/chainsuite" + "github.com/stretchr/testify/suite" +) + +type ConsumerLaunchSuite struct { + *chainsuite.Suite + OtherChain string + OtherChainVersion string + ShouldCopyProviderKey [chainsuite.ValidatorCount]bool +} + +func noProviderKeysCopied() [chainsuite.ValidatorCount]bool { + return [chainsuite.ValidatorCount]bool{false, false, false, false, false, false} +} + +func allProviderKeysCopied() [chainsuite.ValidatorCount]bool { + return [chainsuite.ValidatorCount]bool{true, true, true, true, true, true} +} + +func someProviderKeysCopied() [chainsuite.ValidatorCount]bool { + return [chainsuite.ValidatorCount]bool{true, false, true, false, true, false} +} + +func (s *ConsumerLaunchSuite) TestChainLaunch() { + relayer, err := chainsuite.NewRelayer(s.GetContext(), s.T()) + s.Require().NoError(err) + err = relayer.SetupChainKeys(s.GetContext(), s.Chain) + s.Require().NoError(err) + + cfg := chainsuite.ConsumerConfig{ + ChainName: s.OtherChain, + Version: s.OtherChainVersion, + ShouldCopyProviderKey: s.ShouldCopyProviderKey, + Denom: chainsuite.Ucon, + TopN: 95, + } + consumer, err := s.Chain.AddConsumerChain(s.GetContext(), relayer, cfg) + s.Require().NoError(err) + err = s.Chain.CheckCCV(s.GetContext(), consumer, relayer, 1_000_000, 0, 1) + s.Require().NoError(err) + + s.UpgradeChain() + + s.Require().NoError(relayer.StopRelayer(s.GetContext(), chainsuite.GetRelayerExecReporter(s.GetContext()))) + s.Require().NoError(relayer.StartRelayer(s.GetContext(), chainsuite.GetRelayerExecReporter(s.GetContext()))) + + err = s.Chain.CheckCCV(s.GetContext(), consumer, relayer, 1_000_000, 0, 1) + s.Require().NoError(err) + consumer2, err := s.Chain.AddConsumerChain(s.GetContext(), relayer, cfg) + s.Require().NoError(err) + err = s.Chain.CheckCCV(s.GetContext(), consumer2, relayer, 1_000_000, 0, 1) + s.Require().NoError(err) +} + +func TestICS40ChainLaunch(t *testing.T) { + s := &ConsumerLaunchSuite{ + Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{}), + OtherChain: "ics-consumer", + OtherChainVersion: "v4.0.0", + ShouldCopyProviderKey: noProviderKeysCopied(), + } + suite.Run(t, s) +} + +func TestICS33ConsumerAllKeysChainLaunch(t *testing.T) { + s := &ConsumerLaunchSuite{ + Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{}), + OtherChain: "ics-consumer", + OtherChainVersion: "v3.3.0", + ShouldCopyProviderKey: allProviderKeysCopied(), + } + suite.Run(t, s) +} + +func TestICS33ConsumerSomeKeysChainLaunch(t *testing.T) { + s := &ConsumerLaunchSuite{ + Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{}), + OtherChain: "ics-consumer", + OtherChainVersion: "v3.3.0", + ShouldCopyProviderKey: someProviderKeysCopied(), + } + suite.Run(t, s) +} + +func TestICS33ConsumerNoKeysChainLaunch(t *testing.T) { + s := &ConsumerLaunchSuite{ + Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{}), + OtherChain: "ics-consumer", + OtherChainVersion: "v3.3.0", + ShouldCopyProviderKey: noProviderKeysCopied(), + } + suite.Run(t, s) +} + +type MainnetConsumerChainsSuite struct { + *chainsuite.Suite +} + +func (s *MainnetConsumerChainsSuite) TestMainnetConsumerChainsAfterUpgrade() { + const neutronVersion = "v3.0.2" + const strideVersion = "v22.0.0" + + relayer, err := chainsuite.NewRelayer(s.GetContext(), s.T()) + s.Require().NoError(err) + err = relayer.SetupChainKeys(s.GetContext(), s.Chain) + s.Require().NoError(err) + + neutron, err := s.Chain.AddConsumerChain(s.GetContext(), relayer, chainsuite.ConsumerConfig{ + ChainName: "neutron", + Version: neutronVersion, + ShouldCopyProviderKey: allProviderKeysCopied(), + Denom: chainsuite.NeutronDenom, + TopN: 95, + }) + s.Require().NoError(err) + stride, err := s.Chain.AddConsumerChain(s.GetContext(), relayer, chainsuite.ConsumerConfig{ + ChainName: "stride", + Version: strideVersion, + ShouldCopyProviderKey: allProviderKeysCopied(), + Denom: chainsuite.StrideDenom, + TopN: 95, + }) + s.Require().NoError(err) + + s.Require().NoError(s.Chain.CheckCCV(s.GetContext(), neutron, relayer, 1_000_000, 0, 1)) + s.Require().NoError(s.Chain.CheckCCV(s.GetContext(), stride, relayer, 1_000_000, 0, 1)) + + s.UpgradeChain() + + s.Require().NoError(relayer.StopRelayer(s.GetContext(), chainsuite.GetRelayerExecReporter(s.GetContext()))) + s.Require().NoError(relayer.StartRelayer(s.GetContext(), chainsuite.GetRelayerExecReporter(s.GetContext()))) + + s.Require().NoError(s.Chain.CheckCCV(s.GetContext(), neutron, relayer, 1_000_000, 0, 1)) + s.Require().NoError(s.Chain.CheckCCV(s.GetContext(), stride, relayer, 1_000_000, 0, 1)) +} + +func TestMainnetConsumerChainsAfterUpgrade(t *testing.T) { + s := &MainnetConsumerChainsSuite{ + Suite: chainsuite.NewSuite(chainsuite.SuiteConfig{}), + } + suite.Run(t, s) +} diff --git a/tests/interchain/matrix_tool/main.go b/tests/interchain/matrix_tool/main.go new file mode 100644 index 00000000000..c396dcf3fd7 --- /dev/null +++ b/tests/interchain/matrix_tool/main.go @@ -0,0 +1,145 @@ +//go:build version_tool +// +build version_tool + +package main + +import ( + "context" + "encoding/json" + "fmt" + "os" + "os/exec" + "slices" + "strconv" + "strings" + + "github.com/google/go-github/v62/github" + "github.com/tidwall/gjson" + "golang.org/x/mod/semver" +) + +func GetPreviousMajorMinor(ctx context.Context, testVersion string) (previousVersions []string, upgradeName string, err error) { + org, ok := os.LookupEnv("GITHUB_REPOSITORY_OWNER") + if !ok { + org = "cosmos" + } + client := github.NewClient(nil) + releaes, _, err := client.Repositories.ListReleases(ctx, org, "gaia", nil) + if err != nil { + err = fmt.Errorf("ListReleases failed: %w", err) + return + } + upgradeName = semver.Major(testVersion) + testMajor, err := strconv.Atoi(upgradeName[1:]) + if err != nil { + err = fmt.Errorf("failed to parse major version: %w", err) + return + } + semvers := make([]string, 0, len(releaes)) + for _, release := range releaes { + semvers = append(semvers, release.GetTagName()) + } + var previousMinor, previousRc bool + slices.SortFunc(semvers, + func(i, j string) int { + // Sort in descending order + return semver.Compare(j, i) + }) + for _, v := range semvers { + if !semver.IsValid(v) { + continue + } + var major int + major, err = strconv.Atoi(semver.Major(v)[1:]) + if err != nil { + err = fmt.Errorf("failed to parse major version: %w", err) + return + } + if major == testMajor && semver.Compare(v, testVersion) < 0 { + if !previousRc && semver.Prerelease(v) != "" && semver.Prerelease(testVersion) != "" && (semver.MajorMinor(v) == semver.MajorMinor(testVersion) || semver.Prerelease(testVersion) == "-ref") { + previousRc = true + previousVersions = append(previousVersions, v) + } else if !previousMinor && semver.Prerelease(v) == "" { + previousMinor = true + previousVersions = append(previousVersions, v) + } + continue + } else if major == testMajor-1 { + previousVersions = append(previousVersions, v) + return + } + } + err = fmt.Errorf("failed to find previous major version") + return +} + +func GetSemverForBranch() (string, error) { + mod, err := exec.Command("go", "mod", "edit", "-json").Output() + if err != nil { + return "", fmt.Errorf("go mod edit -json failed: %w\n", err) + } + module := gjson.GetBytes(mod, "Module.Path").String() + parts := strings.Split(module, "/") + major := parts[len(parts)-1] + return fmt.Sprintf("%s.999.0-ref", major), nil +} + +func GetTestList() ([]string, error) { + retval := []string{} + out, err := exec.Command("go", "test", "-list=.", "./tests/interchain/...").Output() + if err != nil { + return nil, fmt.Errorf("go test -list failed: %w\n", err) + } + lines := strings.Split(string(out), "\n") + for _, line := range lines { + if strings.HasPrefix(line, "Test") { + retval = append(retval, line) + } + } + return retval, nil +} + +func main() { + ctx := context.Background() + if len(os.Args) != 2 { + fmt.Fprintf(os.Stderr, "Usage: %s \n", os.Args[0]) + return + } + if _, err := os.Stat("go.mod"); err != nil { + fmt.Fprintf(os.Stderr, "go.mod not found: %v\nRun me from the root of the gaia repo!\n", err) + return + } + testTag := os.Args[1] + testVersion := testTag + if !semver.IsValid(testVersion) { + var err error + testVersion, err = GetSemverForBranch() + if err != nil { + fmt.Fprint(os.Stderr, err) + return + } + } + previous, upgradeName, err := GetPreviousMajorMinor(ctx, testVersion) + if err != nil { + fmt.Fprint(os.Stderr, err) + return + } + tests, err := GetTestList() + if err != nil { + fmt.Fprint(os.Stderr, err) + return + } + matrix := map[string][]string{ + // It needs to be versionOrBranch so it matches the docker image that was pushed + "test_version": {testTag}, + "previous_version": previous, + "test_name": tests, + "upgrade_name": {upgradeName}, + } + marshaled, err := json.Marshal(matrix) + if err != nil { + fmt.Fprint(os.Stderr, err) + return + } + fmt.Println(string(marshaled)) +} diff --git a/tests/interchain/txs_test.go b/tests/interchain/txs_test.go new file mode 100644 index 00000000000..ca177ac963a --- /dev/null +++ b/tests/interchain/txs_test.go @@ -0,0 +1,471 @@ +package interchain_test + +import ( + "context" + "encoding/json" + "fmt" + "path" + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/x/params/client/utils" + "github.com/cosmos/gaia/v19/tests/interchain/chainsuite" + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + + sdkmath "cosmossdk.io/math" +) + +const txAmount = 1_000_000_000 + +type TxSuite struct { + *chainsuite.Suite +} + +func txAmountUatom() string { + return fmt.Sprintf("%d%s", txAmount, chainsuite.Uatom) +} + +func (s *TxSuite) TestBankSend() { + balanceBefore, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[1].Address, chainsuite.Uatom) + s.Require().NoError(err) + + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "bank", "send", + s.Chain.ValidatorWallets[0].Address, s.Chain.ValidatorWallets[1].Address, txAmountUatom(), + ) + s.Require().NoError(err) + + balanceAfter, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[1].Address, chainsuite.Uatom) + s.Require().NoError(err) + s.Require().Equal(balanceBefore.Add(sdkmath.NewInt(txAmount)), balanceAfter) +} + +func (s TxSuite) TestDelegateWithdrawUnbond() { + // delegate tokens + _, err := s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "staking", "delegate", s.Chain.ValidatorWallets[0].ValoperAddress, txAmountUatom(), + ) + s.Require().NoError(err) + + startingBalance, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[0].Address, chainsuite.Uatom) + s.Require().NoError(err) + time.Sleep(20 * time.Second) + // Withdraw rewards + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "distribution", "withdraw-rewards", s.Chain.ValidatorWallets[0].ValoperAddress, + ) + s.Require().NoError(err) + endingBalance, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[0].Address, chainsuite.Uatom) + s.Require().NoError(err) + s.Require().Truef(endingBalance.GT(startingBalance), "endingBalance: %s, startingBalance: %s", endingBalance, startingBalance) + + // Unbond tokens + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "staking", "unbond", s.Chain.ValidatorWallets[0].ValoperAddress, txAmountUatom(), + ) + s.Require().NoError(err) +} + +func (s TxSuite) TestAuthz() { + s.Run("send", func() { + balanceBefore, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[2].Address, chainsuite.Uatom) + s.Require().NoError(err) + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "authz", "grant", s.Chain.ValidatorWallets[1].Address, "send", + "--spend-limit", fmt.Sprintf("%d%s", txAmount*2, chainsuite.Uatom), + "--allow-list", s.Chain.ValidatorWallets[2].Address, + ) + s.Require().NoError(err) + + s.Require().Error(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "bank", "send", s.Chain.ValidatorWallets[0].Address, s.Chain.ValidatorWallets[3].Address, txAmountUatom())) + + s.Require().NoError(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "bank", "send", s.Chain.ValidatorWallets[0].Address, s.Chain.ValidatorWallets[2].Address, txAmountUatom())) + balanceAfter, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[2].Address, chainsuite.Uatom) + s.Require().NoError(err) + s.Require().Equal(balanceBefore.Add(sdkmath.NewInt(int64(txAmount))), balanceAfter) + + s.Require().Error(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "bank", "send", s.Chain.ValidatorWallets[0].Address, s.Chain.ValidatorWallets[2].Address, fmt.Sprintf("%d%s", txAmount+200, chainsuite.Uatom))) + + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "authz", "revoke", s.Chain.ValidatorWallets[1].Address, "/cosmos.bank.v1beta1.MsgSend", + ) + s.Require().NoError(err) + + s.Require().Error(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "bank", "send", s.Chain.ValidatorWallets[0].Address, s.Chain.ValidatorWallets[2].Address, txAmountUatom())) + }) + + s.Run("delegate", func() { + _, err := s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "authz", "grant", s.Chain.ValidatorWallets[1].Address, "delegate", + "--allowed-validators", s.Chain.ValidatorWallets[2].ValoperAddress, + ) + s.Require().NoError(err) + + s.Require().NoError(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "staking", "delegate", s.Chain.ValidatorWallets[2].ValoperAddress, txAmountUatom(), "--from", s.Chain.ValidatorWallets[0].Address)) + + s.Require().Error(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "staking", "delegate", s.Chain.ValidatorWallets[0].ValoperAddress, txAmountUatom(), "--from", s.Chain.ValidatorWallets[0].Address)) + + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "authz", "revoke", s.Chain.ValidatorWallets[1].Address, "/cosmos.staking.v1beta1.MsgDelegate", + ) + s.Require().NoError(err) + s.Require().Error(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "staking", "delegate", s.Chain.ValidatorWallets[2].ValoperAddress, txAmountUatom(), "--from", s.Chain.ValidatorWallets[0].Address)) + }) + + s.Run("unbond", func() { + valHex, err := s.Chain.GetValidatorHex(s.GetContext(), 2) + s.Require().NoError(err) + powerBefore, err := s.Chain.GetValidatorPower(s.GetContext(), valHex) + s.Require().NoError(err) + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "staking", "delegate", s.Chain.ValidatorWallets[2].ValoperAddress, txAmountUatom(), + ) + s.Require().NoError(err) + s.Require().EventuallyWithT(func(c *assert.CollectT) { + powerAfter, err := s.Chain.GetValidatorPower(s.GetContext(), valHex) + s.Require().NoError(err) + assert.NoError(c, err) + assert.Greater(c, powerAfter, powerBefore) + }, 15*chainsuite.CommitTimeout, chainsuite.CommitTimeout) + + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "authz", "grant", s.Chain.ValidatorWallets[1].Address, "unbond", + "--allowed-validators", s.Chain.ValidatorWallets[2].ValoperAddress, + ) + s.Require().NoError(err) + + s.Require().NoError(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "staking", "unbond", s.Chain.ValidatorWallets[2].ValoperAddress, txAmountUatom(), "--from", s.Chain.ValidatorWallets[0].Address)) + s.Require().Error(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "staking", "unbond", s.Chain.ValidatorWallets[0].ValoperAddress, txAmountUatom(), "--from", s.Chain.ValidatorWallets[0].Address)) + + s.Require().EventuallyWithT(func(c *assert.CollectT) { + powerAfter, err := s.Chain.GetValidatorPower(s.GetContext(), valHex) + s.Require().NoError(err) + assert.NoError(c, err) + assert.Equal(c, powerAfter, powerBefore) + }, 15*chainsuite.CommitTimeout, chainsuite.CommitTimeout) + + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "authz", "revoke", s.Chain.ValidatorWallets[1].Address, "/cosmos.staking.v1beta1.MsgUndelegate", + ) + s.Require().NoError(err) + s.Require().Error(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "staking", "unbond", s.Chain.ValidatorWallets[2].ValoperAddress, txAmountUatom(), "--from", s.Chain.ValidatorWallets[0].Address)) + }) + + s.Run("redelegate", func() { + val0Hex, err := s.Chain.GetValidatorHex(s.GetContext(), 0) + s.Require().NoError(err) + val2Hex, err := s.Chain.GetValidatorHex(s.GetContext(), 2) + s.Require().NoError(err) + val0PowerBefore, err := s.Chain.GetValidatorPower(s.GetContext(), val0Hex) + s.Require().NoError(err) + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "staking", "delegate", s.Chain.ValidatorWallets[0].ValoperAddress, txAmountUatom(), + ) + s.Require().NoError(err) + s.Require().EventuallyWithT(func(c *assert.CollectT) { + val0PowerAfter, err := s.Chain.GetValidatorPower(s.GetContext(), val0Hex) + s.Require().NoError(err) + s.Require().NoError(err) + s.Require().Greater(val0PowerAfter, val0PowerBefore) + }, 15*chainsuite.CommitTimeout, chainsuite.CommitTimeout) + + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "authz", "grant", s.Chain.ValidatorWallets[1].Address, "redelegate", + "--allowed-validators", s.Chain.ValidatorWallets[2].ValoperAddress, + ) + s.Require().NoError(err) + + s.Require().Error(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "staking", "redelegate", s.Chain.ValidatorWallets[0].ValoperAddress, s.Chain.ValidatorWallets[1].ValoperAddress, txAmountUatom(), "--from", s.Chain.ValidatorWallets[0].Address)) + + val2PowerBefore, err := s.Chain.GetValidatorPower(s.GetContext(), val2Hex) + s.Require().NoError(err) + s.Require().NoError(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "staking", "redelegate", s.Chain.ValidatorWallets[0].ValoperAddress, s.Chain.ValidatorWallets[2].ValoperAddress, txAmountUatom(), "--from", s.Chain.ValidatorWallets[0].Address)) + s.Require().EventuallyWithT(func(c *assert.CollectT) { + val2PowerAfter, err := s.Chain.GetValidatorPower(s.GetContext(), val2Hex) + s.Require().NoError(err) + s.Require().Greater(val2PowerAfter, val2PowerBefore) + }, 15*chainsuite.CommitTimeout, chainsuite.CommitTimeout) + + _, err = s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "authz", "revoke", s.Chain.ValidatorWallets[1].Address, "/cosmos.staking.v1beta1.MsgBeginRedelegate", + ) + s.Require().NoError(err) + + s.Require().Error(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "staking", "redelegate", s.Chain.ValidatorWallets[0].ValoperAddress, s.Chain.ValidatorWallets[2].ValoperAddress, txAmountUatom(), "--from", s.Chain.ValidatorWallets[0].Address)) + }) + + s.Run("generic", func() { + _, err := s.Chain.Validators[0].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[0].Moniker, + "authz", "grant", s.Chain.ValidatorWallets[1].Address, "generic", + "--msg-type", "/cosmos.gov.v1.MsgVote", + ) + s.Require().NoError(err) + + prop, err := s.Chain.ParamChangeProposal(s.GetContext(), s.Chain.ValidatorWallets[0].Moniker, &utils.ParamChangeProposalJSON{ + Title: "Test Proposal", + Description: "Test Proposal", + Changes: utils.ParamChangesJSON{ + { + Subspace: "staking", + Key: "MaxValidators", + Value: json.RawMessage(`100`), + }, + }, + Deposit: chainsuite.GovDepositAmount, + }) + s.Require().NoError(err) + s.Require().NoError(s.authzGenExec(s.GetContext(), s.Chain.ValidatorWallets[1], "gov", "vote", prop.ProposalID, "yes", "--from", s.Chain.ValidatorWallets[0].Address)) + }) +} + +func (s TxSuite) TestFeegrant() { + const ( + granter = 5 + grantee = 1 + fundsReceiver = 2 + ) + + tests := []struct { + name string + revoke func(expireTime time.Time) + }{ + { + name: "revoke", + revoke: func(_ time.Time) { + _, err := s.Chain.Validators[granter].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[granter].Moniker, + "feegrant", "revoke", s.Chain.ValidatorWallets[granter].Address, s.Chain.ValidatorWallets[grantee].Address, + ) + s.Require().NoError(err) + }, + }, + { + name: "expire", + revoke: func(expire time.Time) { + <-time.After(time.Until(expire)) + err := testutil.WaitForBlocks(s.GetContext(), 1, s.Chain) + s.Require().NoError(err) + }, + }, + } + + for _, tt := range tests { + tt := tt + s.Run(tt.name, func() { + expire := time.Now().Add(20 * chainsuite.CommitTimeout) + _, err := s.Chain.Validators[granter].ExecTx( + s.GetContext(), + s.Chain.ValidatorWallets[granter].Moniker, + "feegrant", "grant", s.Chain.ValidatorWallets[granter].Address, s.Chain.ValidatorWallets[grantee].Address, + "--expiration", expire.Format(time.RFC3339), + ) + s.Require().NoError(err) + + granterBalanceBefore, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[granter].Address, chainsuite.Uatom) + s.Require().NoError(err) + granteeBalanceBefore, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[grantee].Address, chainsuite.Uatom) + s.Require().NoError(err) + + _, err = s.Chain.Validators[grantee].ExecTx(s.GetContext(), s.Chain.ValidatorWallets[grantee].Moniker, + "bank", "send", s.Chain.ValidatorWallets[grantee].Address, s.Chain.ValidatorWallets[fundsReceiver].Address, txAmountUatom(), + "--fee-granter", s.Chain.ValidatorWallets[granter].Address, + ) + s.Require().NoError(err) + + granteeBalanceAfter, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[grantee].Address, chainsuite.Uatom) + s.Require().NoError(err) + granterBalanceAfter, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[granter].Address, chainsuite.Uatom) + s.Require().NoError(err) + + s.Require().True(granterBalanceAfter.LT(granterBalanceBefore), "granterBalanceBefore: %s, granterBalanceAfter: %s", granterBalanceBefore, granterBalanceAfter) + s.Require().True(granteeBalanceAfter.Equal(granteeBalanceBefore.Sub(sdkmath.NewInt(txAmount))), "granteeBalanceBefore: %s, granteeBalanceAfter: %s", granteeBalanceBefore, granteeBalanceAfter) + + tt.revoke(expire) + + _, err = s.Chain.Validators[1].ExecTx(s.GetContext(), s.Chain.ValidatorWallets[grantee].Moniker, + "bank", "send", s.Chain.ValidatorWallets[1].Address, s.Chain.ValidatorWallets[fundsReceiver].Address, txAmountUatom(), + "--fee-granter", s.Chain.ValidatorWallets[0].Address, + ) + s.Require().Error(err) + }) + } +} + +func (s *TxSuite) TestMultisig() { + pubkey1, _, err := s.Chain.Validators[1].ExecBin(s.GetContext(), "keys", "show", s.Chain.ValidatorWallets[1].Moniker, "--pubkey", "--keyring-backend", "test") + s.Require().NoError(err) + + pubkey2, _, err := s.Chain.Validators[2].ExecBin(s.GetContext(), "keys", "show", s.Chain.ValidatorWallets[2].Moniker, "--pubkey", "--keyring-backend", "test") + s.Require().NoError(err) + + _, _, err = s.Chain.Validators[0].ExecBin(s.GetContext(), "keys", "add", "val1", "--pubkey", string(pubkey1), "--keyring-backend", "test") + s.Require().NoError(err) + + _, _, err = s.Chain.Validators[0].ExecBin(s.GetContext(), "keys", "add", "val2", "--pubkey", string(pubkey2), "--keyring-backend", "test") + s.Require().NoError(err) + + multisigName := "multisig" + _, _, err = s.Chain.Validators[0].ExecBin(s.GetContext(), "keys", "add", multisigName, "--multisig", fmt.Sprintf("%s,val1,val2", s.Chain.ValidatorWallets[0].Moniker), "--multisig-threshold", "2", "--keyring-backend", "test") + s.Require().NoError(err) + + pubkeyMulti, _, err := s.Chain.Validators[0].ExecBin(s.GetContext(), "keys", "show", multisigName, "--pubkey", "--keyring-backend", "test") + s.Require().NoError(err) + + _, _, err = s.Chain.Validators[1].ExecBin(s.GetContext(), "keys", "add", multisigName, "--pubkey", string(pubkeyMulti), "--keyring-backend", "test") + s.Require().NoError(err) + _, _, err = s.Chain.Validators[2].ExecBin(s.GetContext(), "keys", "add", multisigName, "--pubkey", string(pubkeyMulti), "--keyring-backend", "test") + s.Require().NoError(err) + // bogus validator, not in the multisig + _, _, err = s.Chain.Validators[4].ExecBin(s.GetContext(), "keys", "add", multisigName, "--pubkey", string(pubkeyMulti), "--keyring-backend", "test") + s.Require().NoError(err) + + defer func() { + _, _, err = s.Chain.Validators[0].ExecBin(s.GetContext(), "keys", "delete", "val1", "--keyring-backend", "test", "-y") + s.Require().NoError(err) + _, _, err = s.Chain.Validators[0].ExecBin(s.GetContext(), "keys", "delete", "val2", "--keyring-backend", "test", "-y") + s.Require().NoError(err) + for i := 0; i < 3; i++ { + _, _, err = s.Chain.Validators[i].ExecBin(s.GetContext(), "keys", "delete", multisigName, "--keyring-backend", "test", "-y") + s.Require().NoError(err) + } + _, _, err = s.Chain.Validators[4].ExecBin(s.GetContext(), "keys", "delete", multisigName, "--keyring-backend", "test", "-y") + s.Require().NoError(err) + }() + + multisigAddr, err := s.Chain.Validators[0].KeyBech32(s.GetContext(), multisigName, "") + s.Require().NoError(err) + + err = s.Chain.SendFunds(s.GetContext(), interchaintest.FaucetAccountKeyName, ibc.WalletAmount{ + Denom: chainsuite.Uatom, + Amount: sdkmath.NewInt(chainsuite.ValidatorFunds), + Address: multisigAddr, + }) + s.Require().NoError(err) + + balanceBefore, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[3].Address, chainsuite.Uatom) + s.Require().NoError(err) + + txjson, err := s.Chain.GenerateTx( + s.GetContext(), 0, "bank", "send", multisigName, s.Chain.ValidatorWallets[3].Address, txAmountUatom(), + "--gas", "auto", "--gas-adjustment", fmt.Sprint(s.Chain.Config().GasAdjustment), "--gas-prices", s.Chain.Config().GasPrices, + ) + s.Require().NoError(err) + + err = s.Chain.Validators[0].WriteFile(s.GetContext(), []byte(txjson), "tx.json") + s.Require().NoError(err) + + signed0, _, err := s.Chain.Validators[0].Exec(s.GetContext(), + s.Chain.Validators[0].TxCommand(s.Chain.ValidatorWallets[0].Moniker, "sign", + path.Join(s.Chain.Validators[0].HomeDir(), "tx.json"), + "--multisig", multisigAddr, + ), nil) + s.Require().NoError(err) + + err = s.Chain.Validators[1].WriteFile(s.GetContext(), []byte(txjson), "tx.json") + s.Require().NoError(err) + + signed1, _, err := s.Chain.Validators[1].Exec(s.GetContext(), + s.Chain.Validators[1].TxCommand(s.Chain.ValidatorWallets[1].Moniker, "sign", + path.Join(s.Chain.Validators[1].HomeDir(), "tx.json"), + "--multisig", multisigAddr, + ), nil) + s.Require().NoError(err) + + err = s.Chain.Validators[4].WriteFile(s.GetContext(), []byte(txjson), "tx.json") + s.Require().NoError(err) + _, _, err = s.Chain.Validators[4].Exec(s.GetContext(), + s.Chain.Validators[4].TxCommand(s.Chain.ValidatorWallets[4].Moniker, "sign", + path.Join(s.Chain.Validators[4].HomeDir(), "tx.json"), + "--multisig", multisigAddr, + ), nil) + s.Require().Error(err) + + err = s.Chain.Validators[0].WriteFile(s.GetContext(), signed0, "signed0.json") + s.Require().NoError(err) + + _, _, err = s.Chain.Validators[0].Exec(s.GetContext(), s.Chain.Validators[0].TxCommand( + multisigName, + "multisign", + path.Join(s.Chain.Validators[0].HomeDir(), "tx.json"), + multisigName, + path.Join(s.Chain.Validators[0].HomeDir(), "signed0.json"), + ), nil) + s.Require().NoError(err) + + err = s.Chain.Validators[0].WriteFile(s.GetContext(), signed1, "signed1.json") + s.Require().NoError(err) + + multisign, _, err := s.Chain.Validators[0].Exec(s.GetContext(), s.Chain.Validators[0].TxCommand( + multisigName, + "multisign", + path.Join(s.Chain.Validators[0].HomeDir(), "tx.json"), + multisigName, + path.Join(s.Chain.Validators[0].HomeDir(), "signed0.json"), + path.Join(s.Chain.Validators[0].HomeDir(), "signed1.json"), + ), nil) + s.Require().NoError(err) + + err = s.Chain.Validators[0].WriteFile(s.GetContext(), multisign, "multisign.json") + s.Require().NoError(err) + + _, err = s.Chain.Validators[0].ExecTx(s.GetContext(), multisigName, "broadcast", path.Join(s.Chain.Validators[0].HomeDir(), "multisign.json")) + s.Require().NoError(err) + balanceAfter, err := s.Chain.GetBalance(s.GetContext(), s.Chain.ValidatorWallets[3].Address, chainsuite.Uatom) + s.Require().NoError(err) + s.Require().Equal(balanceBefore.Add(sdkmath.NewInt(txAmount)), balanceAfter) +} + +func TestTransactions(t *testing.T) { + txSuite := TxSuite{chainsuite.NewSuite(chainsuite.SuiteConfig{UpgradeOnSetup: true})} + suite.Run(t, &txSuite) +} + +func (s TxSuite) authzGenExec(ctx context.Context, grantee chainsuite.ValidatorWallet, command ...string) error { + txjson, err := s.Chain.GenerateTx(ctx, 1, command...) + s.Require().NoError(err) + + err = s.Chain.Validators[1].WriteFile(ctx, []byte(txjson), "tx.json") + s.Require().NoError(err) + + _, err = s.Chain.Validators[1].ExecTx( + ctx, + grantee.Moniker, + "authz", "exec", path.Join(s.Chain.Validators[1].HomeDir(), "tx.json"), + ) + return err +}