From 74609cfda938175f3dee0d381f133589f6ac4a55 Mon Sep 17 00:00:00 2001 From: Roman Date: Sun, 24 Apr 2022 14:42:50 -0400 Subject: [PATCH 1/9] Setup e2e tests on a single chain; add balances query test (#1193) * create e2e image and a makefile step to build * progress * e2e tests in ci * use root distroless image and correct volume path * remove chain b references * implement query balances * implement TestQueryBalances * trigger worflow * trigger * test-e2e Makefile step * fmt and sleep if service unavailable * README * restore branches * add changelog entry * exclude e2e from regular tests * -E flag for grep exclusion * grep * go mod tidy --compat=1.17 * manually tidy go.mod --- .github/workflows/test.yml | 2 +- CHANGELOG.md | 1 + Makefile | 5 + e2e.Dockerfile | 26 +++ go.mod | 23 ++- go.sum | 118 +++----------- tests/e2e/README.md | 13 ++ tests/e2e/chain.go | 126 +++++++++++++++ tests/e2e/e2e_setup_test.go | 315 ++++++++++++++++++++++++++++++++++++ tests/e2e/e2e_test.go | 76 +++++++++ tests/e2e/genesis.go | 110 +++++++++++++ tests/e2e/io.go | 43 +++++ tests/e2e/keys.go | 56 +++++++ tests/e2e/util.go | 45 ++++++ tests/e2e/validator.go | 267 ++++++++++++++++++++++++++++++ 15 files changed, 1128 insertions(+), 98 deletions(-) create mode 100644 e2e.Dockerfile create mode 100644 tests/e2e/README.md create mode 100644 tests/e2e/chain.go create mode 100644 tests/e2e/e2e_setup_test.go create mode 100644 tests/e2e/e2e_test.go create mode 100644 tests/e2e/genesis.go create mode 100644 tests/e2e/io.go create mode 100644 tests/e2e/keys.go create mode 100644 tests/e2e/util.go create mode 100644 tests/e2e/validator.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2ad4abcc0f1..6086098d5d1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,6 +17,6 @@ jobs: - name: Display go version run: go version - name: Run all tests - run: go test -mod=readonly -timeout 30m -coverprofile=coverage.txt -tags='norace' -covermode=atomic `go list ./... | grep -v simapp` + run: go test -mod=readonly -timeout 30m -coverprofile=coverage.txt -tags='norace' -covermode=atomic `go list ./... | grep -E -v 'simapp|e2e'` - name: Codecov uses: codecov/codecov-action@v1.5.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1587e0bf65a..84e2c57fe2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Minor improvements & Bug Fixes * [#1177](https://github.com/osmosis-labs/osmosis/pull/1177) upgrade to go 1.18 +* [#1193](https://github.com/osmosis-labs/osmosis/pull/1193) Setup e2e tests on a single chain; add balances query test * [#1061](https://github.com/osmosis-labs/osmosis/pull/1061) upgrade iavl to v0.17.3-osmo-v5 with concurrent map write fix * [#1071](https://github.com/osmosis-labs/osmosis/pull/1071) improve Dockerfile diff --git a/Makefile b/Makefile index 25009f2b6ef..780fbadbbf6 100644 --- a/Makefile +++ b/Makefile @@ -222,9 +222,14 @@ test-race: test-cover: @go test -mod=readonly -timeout 30m -coverprofile=coverage.txt -covermode=atomic -tags='ledger test_ledger_mock' ./... +test-e2e: + @VERSION=$(VERSION) go test -mod=readonly -timeout=25m -v ./tests/e2e + benchmark: @go test -mod=readonly -bench=. ./... +docker-build-debug: + @docker build -t cosmos/osmosisd-e2e --build-arg IMG_TAG=debug -f e2e.Dockerfile . ############################################################################### ### Linting ### diff --git a/e2e.Dockerfile b/e2e.Dockerfile new file mode 100644 index 00000000000..f0bfd24d8f4 --- /dev/null +++ b/e2e.Dockerfile @@ -0,0 +1,26 @@ +# syntax=docker/dockerfile:1 +ARG IMG_TAG=latest + +## Build Image +FROM golang:1.17-bullseye as build + +WORKDIR /osmosis +COPY . /osmosis + +# From https://github.com/CosmWasm/wasmd/blob/master/Dockerfile +# For more details see https://github.com/CosmWasm/wasmvm#builds-of-libwasmvm +ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.0.0-beta7/libwasmvm_muslc.a /lib/libwasmvm_muslc.a +RUN sha256sum /lib/libwasmvm_muslc.a | grep d0152067a5609bfdfb3f0d5d6c0f2760f79d5f2cd7fd8513cafa9932d22eb350 +RUN BUILD_TAGS=muslc make build + +## Deploy image +FROM gcr.io/distroless/cc:$IMG_TAG +ARG IMG_TAG +COPY --from=build /osmosis/build/osmosisd /bin/osmosisd + +ENV HOME /osmosis +WORKDIR $HOME + +EXPOSE 26656 26657 1317 9090 + +ENTRYPOINT ["osmosisd", "start"] diff --git a/go.mod b/go.mod index a3f0c57cfa9..c7478a90f75 100644 --- a/go.mod +++ b/go.mod @@ -35,12 +35,15 @@ require ( github.com/99designs/keyring v1.1.6 // indirect github.com/Antonboom/errname v0.1.5 // indirect github.com/Antonboom/nilnil v0.1.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/BurntSushi/toml v1.1.0 // indirect github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect github.com/CosmWasm/wasmvm v1.0.0-beta5 // indirect github.com/DataDog/zstd v1.4.5 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/Masterminds/semver v1.5.0 // indirect + github.com/Microsoft/go-winio v0.5.1 // indirect + github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/OpenPeeDeeP/depguard v1.1.0 // indirect github.com/Workiva/go-datastructures v1.0.53 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect @@ -56,12 +59,14 @@ require ( github.com/breml/errchkjson v0.2.3 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect github.com/butuzov/ireturn v0.1.1 // indirect + github.com/cenkalti/backoff/v4 v4.1.2 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/charithe/durationcheck v0.0.9 // indirect github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af // indirect github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect github.com/confio/ics23/go v0.6.6 // indirect + github.com/containerd/continuity v0.2.1 // indirect github.com/cosmos/btcutil v1.0.4 // indirect github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect github.com/cosmos/ledger-go v0.9.2 // indirect @@ -73,6 +78,10 @@ require ( github.com/dgraph-io/badger/v2 v2.2007.3 // indirect github.com/dgraph-io/ristretto v0.0.3 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/docker/cli v20.10.11+incompatible // indirect + github.com/docker/docker v20.10.7+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.4.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect github.com/esimonov/ifshort v1.0.4 // indirect @@ -113,6 +122,7 @@ require ( github.com/google/go-cmp v0.5.7 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/orderedcode v0.0.1 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect @@ -132,6 +142,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect + github.com/imdario/mergo v0.3.12 // indirect github.com/improbable-eng/grpc-web v0.14.1 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jgautheron/goconst v1.5.1 // indirect @@ -164,6 +175,7 @@ require ( github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect github.com/moricho/tparallel v0.2.1 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/nakabonne/nestif v0.3.1 // indirect @@ -171,6 +183,10 @@ require ( github.com/nishanths/exhaustive v0.7.11 // indirect github.com/nishanths/predeclared v0.2.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/runc v1.0.3 // indirect + github.com/ory/dockertest/v3 v3.8.1 github.com/pelletier/go-toml v1.9.4 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d // indirect @@ -199,12 +215,12 @@ require ( github.com/sourcegraph/go-diff v0.6.1 // indirect github.com/spf13/afero v1.6.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/viper v1.10.1 // indirect + github.com/spf13/viper v1.10.1 github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stretchr/objx v0.3.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/sylvia7788/contextcheck v1.0.4 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect + github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca github.com/tdakkota/asciicheck v0.1.1 // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tendermint/btcd v0.1.1 // indirect @@ -217,6 +233,9 @@ require ( github.com/ultraware/funlen v0.0.3 // indirect github.com/ultraware/whitespace v0.0.5 // indirect github.com/uudashr/gocognit v1.0.5 // 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 github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.1.1-0.20210918184747-d757024714a1 // indirect github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 // indirect diff --git a/go.sum b/go.sum index 259edcc0815..a7cb1233107 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,5 @@ 4d63.com/gochecknoglobals v0.1.0 h1:zeZSRqj5yCg28tCkIV/z/lWbwvNm5qnKVS15PI8nhD0= 4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -30,7 +29,6 @@ cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aD cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= @@ -84,7 +82,6 @@ github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -110,7 +107,6 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0 github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= @@ -120,7 +116,6 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.1.0 h1:pjK9nLPS1FwQYGGpPxoMYpe7qACHOhAWQMQzV71i49o= github.com/OpenPeeDeeP/depguard v1.1.0/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= @@ -131,9 +126,7 @@ github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3 github.com/Workiva/go-datastructures v1.0.53 h1:J6Y/52yX10Xc5JjXmGtWoSSxs3mZnGSaq37xZZh7Yig= github.com/Workiva/go-datastructures v1.0.53/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6/go.mod h1:eSYp2T6f0apnuW8TzhV3f6Aff2SE8Dwio++U4ha4yEM= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/adlio/schema v1.1.13/go.mod h1:L5Z7tw+7lRK1Fnpi/LT/ooCP1elkXn0krMWBQHUhEDE= -github.com/adlio/schema v1.1.14/go.mod h1:hQveFEMiDlG/M9yz9RAajnH5DzT6nAfqOG9YkEQU2pg= github.com/adlio/schema v1.3.0 h1:eSVYLxYWbm/6ReZBCkLw4Fz7uqC+ZNoPvA39bOwi52A= github.com/adlio/schema v1.3.0/go.mod h1:51QzxkpeFs6lRY11kPye26IaFPOV+HqEj01t5aXXKfs= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -147,9 +140,6 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= @@ -164,13 +154,11 @@ github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8 github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/ashanbrown/forbidigo v1.3.0 h1:VkYIwb/xxdireGAdJNZoo24O4lmnEWkactplBlWTShc= github.com/ashanbrown/forbidigo v1.3.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= -github.com/avast/retry-go v2.6.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -194,7 +182,6 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= -github.com/blizzy78/varnamelen v0.6.1/go.mod h1:zy2Eic4qWqjrxa60jG34cfL0VXcSwzUrIx68eJPb4Q8= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM= @@ -230,9 +217,9 @@ github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= -github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= @@ -262,15 +249,12 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coinbase/rosetta-sdk-go v0.6.10/go.mod h1:J/JFMsfcePrjJZkwQFLh+hJErkAmdm9Iyy3D5Y0LfXo= github.com/coinbase/rosetta-sdk-go v0.7.0 h1:lmTO/JEpCvZgpbkOITL95rA80CPKb5CtMzLaqF2mCNg= github.com/coinbase/rosetta-sdk-go v0.7.0/go.mod h1:7nD3oBPIiHqhRprqvMgPoGxe/nyq3yftRmpsy29coWE= github.com/confio/ics23/go v0.6.6 h1:pkOy18YxxJ/r0XFDCnrl4Bjv6h4LkBSpLS6F38mrKL8= github.com/confio/ics23/go v0.6.6/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/continuity v0.2.0/go.mod h1:wCYX+dRqZdImhGucXOqTQn05AhX6EUDaGEMUzTFFpLg= github.com/containerd/continuity v0.2.1 h1:/EeEo2EtN3umhbbgCveyjifoMYg0pS+nMMEemaYw634= github.com/containerd/continuity v0.2.1/go.mod h1:wCYX+dRqZdImhGucXOqTQn05AhX6EUDaGEMUzTFFpLg= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -296,13 +280,13 @@ github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6 github.com/cosmos/ledger-cosmos-go v0.11.1/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY= github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI= github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI= -github.com/cosmos/relayer v1.0.0/go.mod h1:jIFz7lytxGMCC3mcI9pQ0/IBMMaaNEyTP0OMmzzq0p4= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/daixiang0/gci v0.3.3 h1:55xJKH7Gl9Vk6oQ1cMkwrDWjAkT1D+D1G9kNmRcAIY4= @@ -334,7 +318,11 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUn github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/docker/cli v20.10.11+incompatible h1:tXU1ezXcruZQRrMP8RN2z9N91h+6egZTS1gsPsKantc= +github.com/docker/cli v20.10.11+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ= +github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= @@ -351,8 +339,6 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -383,7 +369,6 @@ github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4 github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= @@ -404,18 +389,11 @@ github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU= github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-critic/go-critic v0.6.2 h1:L5SDut1N4ZfsWZY0sH4DCrsHLHnhuuWak2wa165t9gs= github.com/go-critic/go-critic v0.6.2/go.mod h1:td1s27kfmLpe5G/DPjlnFI7o1UCzePptwU7Az0V5iCM= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -433,12 +411,9 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= @@ -598,6 +573,8 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe 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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -644,7 +621,6 @@ github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3 github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= -github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -670,7 +646,6 @@ github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIv github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= -github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -737,6 +712,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/improbable-eng/grpc-web v0.14.1 h1:NrN4PY71A6tAz2sKDvC5JCauENWp0ykG8Oq1H3cpFvw= github.com/improbable-eng/grpc-web v0.14.1/go.mod h1:zEjGHa8DAlkoOXmswrNvhUGEYQA9UI7DhrGeHR1DMGU= @@ -746,11 +722,9 @@ github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZ github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= @@ -768,7 +742,6 @@ github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+ github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a/go.mod h1:izVPOvVRsHiKkeGCT6tYBNWyDVuzj9wAaBb5R9qamfw= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -791,7 +764,6 @@ github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSX github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -800,11 +772,9 @@ github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -832,7 +802,6 @@ github.com/ldez/gomoddirectives v0.2.2 h1:p9/sXuNFArS2RLc+UpYZSI4KQwGMEDWC/LbtF5 github.com/ldez/gomoddirectives v0.2.2/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/tagliatelle v0.3.1 h1:3BqVVlReVUZwafJUwQ+oxbx2BEX2vUG4Yu/NOfMiKiM= github.com/ldez/tagliatelle v0.3.1/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= -github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leonklingele/grouper v1.1.0 h1:tC2y/ygPbMFSBOs3DcyaEMKnnwH7eYKzohOtRrf0SAg= @@ -843,8 +812,6 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= @@ -853,7 +820,6 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -864,7 +830,6 @@ github.com/maratori/testpackage v1.0.1 h1:QtJ5ZjqapShm0w5DosRjg0PRlSdAdlx+W6cCKo github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -881,7 +846,6 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= @@ -920,7 +884,6 @@ github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFW github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= @@ -934,8 +897,8 @@ github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/term v0.0.0-20200915141129-7f0af18e79f2/go.mod h1:TjQg8pa4iejrUrjiz0MCtMV38jdMNW4doKSiBrEvCQQ= -github.com/moby/term v0.0.0-20201101162038-25d840ce174a/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -1024,7 +987,6 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k= github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= @@ -1042,7 +1004,8 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= -github.com/ory/dockertest/v3 v3.6.2/go.mod h1:EFLcVUOl8qCwp9NyDAcCDtq/QviLtYswW/VbWzUnTNE= +github.com/ory/dockertest/v3 v3.8.1 h1:vU/8d1We4qIad2YM0kOwRVtnyue7ExvacPiw1yDm17g= +github.com/ory/dockertest/v3 v3.8.1/go.mod h1:wSRQ3wmkz+uSARYMk7kVJFDBGm8x5gSxIhI7NDc+BAQ= github.com/osmosis-labs/bech32-ibc v0.2.0-rc2 h1:7xy1pLtNiF2KaRSkolayZf4z3OfCJsO3eqBtEAXg2VA= github.com/osmosis-labs/bech32-ibc v0.2.0-rc2/go.mod h1:0JCaioRNOVUiw7c3MngmKACnumaQ2sjPenXCnwxCttI= github.com/osmosis-labs/cosmos-sdk v0.45.1-0.20220412153824-b375ea016dae h1:PQaRkOpENB7WBDD8fV+z/8KOsiznQxrztnrCjkMBeEc= @@ -1097,7 +1060,6 @@ github.com/polyfloyd/go-errorlint v0.0.0-20211125173453-6d6d39c5bb8b h1:/BDyEJWL github.com/polyfloyd/go-errorlint v0.0.0-20211125173453-6d6d39c5bb8b/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -1107,7 +1069,6 @@ github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -1127,7 +1088,6 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8 github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.33.0 h1:rHgav/0a6+uYgGdNt3jwz8FNSesO/Hsang3O0T9A5SE= @@ -1153,7 +1113,6 @@ github.com/quasilyte/go-ruleguard v0.3.15/go.mod h1:NhuWhnlVEM1gT1A4VJHYfy9MuYSx github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/go-ruleguard/dsl v0.3.12-0.20220101150716-969a394a9451/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/go-ruleguard/dsl v0.3.12/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/dsl v0.3.17/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= github.com/quasilyte/gogrep v0.0.0-20220103110004-ffaa07af02e3 h1:P4QPNn+TK49zJjXKERt/vyPbv/mCHB/zQ4flDYOMN+M= @@ -1178,7 +1137,6 @@ github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XF github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= @@ -1196,7 +1154,6 @@ github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8 github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= -github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= @@ -1212,7 +1169,6 @@ github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -1252,7 +1208,6 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= @@ -1268,7 +1223,6 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= -github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= @@ -1312,7 +1266,6 @@ github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/tendermint v0.34.14/go.mod h1:FrwVm3TvsVicI9Z7FlucHV6Znfd5KBc/Lpp69cCwtk0= -github.com/tendermint/tendermint v0.34.15/go.mod h1:/7EDAw02rD7GT8syC317cX9ZhZTCdaFVvYjU8W+yJSs= github.com/tendermint/tendermint v0.34.19 h1:y0P1qI5wSa9IRuhKnTDA6IUcOrLi1hXJuALR+R7HFEk= github.com/tendermint/tendermint v0.34.19/go.mod h1:R5+wgIwSxMdKQcmOaeudL0Cjkr3HDkhpcdum6VeU3R4= github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= @@ -1331,8 +1284,6 @@ github.com/tidwall/sjson v1.1.4/go.mod h1:wXpKXu8CtDjKAZ+3DrKY5ROCorDFahq8l0tey/ github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 h1:kl4KhGNsJIbDHS9/4U9yQo1UcPQM0kOMJHn29EoH/Ro= github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= -github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= -github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -1360,17 +1311,18 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/uudashr/gocognit v1.0.5 h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4= github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= -github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= -github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI= github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -1389,8 +1341,6 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 h1:O9XLFXGkVswDFmH9LaYpqu+r/AAFWqr0DL6V00KEVFg= github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= @@ -1443,7 +1393,6 @@ golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1458,16 +1407,12 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -1544,7 +1489,6 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1571,12 +1515,10 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1584,7 +1526,6 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211005001312-d4b1ae081e3b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211208012354-db4efeb81f4b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1645,10 +1586,8 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1691,7 +1630,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1701,12 +1639,10 @@ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1716,15 +1652,12 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211004093028-2c5d950f24ef/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1733,7 +1666,6 @@ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1839,7 +1771,6 @@ golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4X golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201028025901-8cd080b735b3/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201114224030-61ea331ec02b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1905,7 +1836,6 @@ google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqiv google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1985,8 +1915,6 @@ google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e h1:fNKDNuUyC4WH+inqDMpfXDdfvwfYILbsX+oskGZ8hxg= @@ -2022,8 +1950,6 @@ gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qS gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= -gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -2043,7 +1969,6 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -2051,8 +1976,11 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/tests/e2e/README.md b/tests/e2e/README.md new file mode 100644 index 00000000000..846d854bdd4 --- /dev/null +++ b/tests/e2e/README.md @@ -0,0 +1,13 @@ +# End-to-end Tests + +The package e2e defines an integration testing suite used for full end-to-end +testing functionality. + +The file e2e_suite_test.go defines the testing suite and contains the core +bootstrapping logic that creates a testing environment via Docker containers. +A testing network is created dynamically with 2 test validators. + +The file e2e_test.go contains the actual end-to-end integration tests that +utilize the testing suite. + +Currently, there is a single test in `e2e_test.go` to query the balances of a validator. diff --git a/tests/e2e/chain.go b/tests/e2e/chain.go new file mode 100644 index 00000000000..a5ce93561ad --- /dev/null +++ b/tests/e2e/chain.go @@ -0,0 +1,126 @@ +package e2e + +import ( + "fmt" + "io/ioutil" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + tmrand "github.com/tendermint/tendermint/libs/rand" + + osmosisApp "github.com/osmosis-labs/osmosis/v7/app" + "github.com/osmosis-labs/osmosis/v7/app/params" +) + +const ( + keyringPassphrase = "testpassphrase" + keyringAppName = "testnet" +) + +var ( + encodingConfig params.EncodingConfig + cdc codec.Codec +) + +func init() { + encodingConfig = osmosisApp.MakeEncodingConfig() + + encodingConfig.InterfaceRegistry.RegisterImplementations( + (*sdk.Msg)(nil), + &stakingtypes.MsgCreateValidator{}, + ) + encodingConfig.InterfaceRegistry.RegisterImplementations( + (*cryptotypes.PubKey)(nil), + &secp256k1.PubKey{}, + &ed25519.PubKey{}, + ) + + cdc = encodingConfig.Marshaler +} + +type chain struct { + dataDir string + id string + validators []*validator +} + +func newChain() (*chain, error) { + tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-") + if err != nil { + return nil, err + } + + return &chain{ + id: "chain-" + tmrand.NewRand().Str(6), + dataDir: tmpDir, + }, nil +} + +func (c *chain) configDir() string { + return fmt.Sprintf("%s/%s", c.dataDir, c.id) +} + +func (c *chain) createAndInitValidators(count int) error { + for i := 0; i < count; i++ { + node := c.createValidator(i) + + // generate genesis files + if err := node.init(); err != nil { + return err + } + + c.validators = append(c.validators, node) + + // create keys + if err := node.createKey("val"); err != nil { + return err + } + if err := node.createNodeKey(); err != nil { + return err + } + if err := node.createConsensusKey(); err != nil { + return err + } + } + + return nil +} + +func (c *chain) createAndInitValidatorsWithMnemonics(count int, mnemonics []string) error { + for i := 0; i < count; i++ { + // create node + node := c.createValidator(i) + + // generate genesis files + if err := node.init(); err != nil { + return err + } + + c.validators = append(c.validators, node) + + // create keys + if err := node.createKeyFromMnemonic("val", mnemonics[i]); err != nil { + return err + } + if err := node.createNodeKey(); err != nil { + return err + } + if err := node.createConsensusKey(); err != nil { + return err + } + } + + return nil +} + +func (c *chain) createValidator(index int) *validator { + return &validator{ + chain: c, + index: index, + moniker: fmt.Sprintf("%s-osmosis-%d", c.id, index), + } +} diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go new file mode 100644 index 00000000000..f88d265e073 --- /dev/null +++ b/tests/e2e/e2e_setup_test.go @@ -0,0 +1,315 @@ +package e2e + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/server" + srvconfig "github.com/cosmos/cosmos-sdk/server/config" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + "github.com/ory/dockertest/v3" + "github.com/ory/dockertest/v3/docker" + "github.com/spf13/viper" + "github.com/stretchr/testify/suite" + tmconfig "github.com/tendermint/tendermint/config" + tmjson "github.com/tendermint/tendermint/libs/json" + rpchttp "github.com/tendermint/tendermint/rpc/client/http" +) + +const ( + osmoBalance = 200000000000 + osmoDenom = "uosmo" + stakeBalance = 110000000000 + stakeAmount = 100000000000 + stakeDenom = "stake" + minGasPrice = "0.00001" +) + +var ( + initBalanceStr = fmt.Sprintf("%d%s,%d%s", osmoBalance, osmoDenom, stakeBalance, stakeDenom) + stakeAmountInt, _ = sdk.NewIntFromString(fmt.Sprintf("%d", stakeAmount)) + stakeAmountCoin = sdk.NewCoin(stakeDenom, stakeAmountInt) +) + +type IntegrationTestSuite struct { + suite.Suite + + tmpDirs []string + chain *chain + dkrPool *dockertest.Pool + dkrNet *dockertest.Network + valResources map[string][]*dockertest.Resource +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up e2e integration test suite...") + + var err error + s.chain, err = newChain() + s.Require().NoError(err) + + s.dkrPool, err = dockertest.NewPool("") + s.Require().NoError(err) + + s.dkrNet, err = s.dkrPool.CreateNetwork(fmt.Sprintf("%s-testnet", s.chain.id)) + s.Require().NoError(err) + + s.valResources = make(map[string][]*dockertest.Resource) + + // The boostrapping phase is as follows: + // + // 1. Initialize Osmosis validator nodes. + // 2. Create and initialize Osmosis validator genesis files (one chain) + + s.T().Logf("starting e2e infrastructure for chain A; chain-id: %s; datadir: %s", s.chain.id, s.chain.dataDir) + s.initNodes(s.chain) + s.initGenesis(s.chain) + s.initValidatorConfigs(s.chain) + s.runValidators(s.chain, 0) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + if str := os.Getenv("OSMOSIS_E2E_SKIP_CLEANUP"); len(str) > 0 { + skipCleanup, err := strconv.ParseBool(str) + s.Require().NoError(err) + + if skipCleanup { + return + } + } + + s.T().Log("tearing down e2e integration test suite...") + + for _, vr := range s.valResources { + for _, r := range vr { + s.Require().NoError(s.dkrPool.Purge(r)) + } + } + + s.Require().NoError(s.dkrPool.RemoveNetwork(s.dkrNet)) + + os.RemoveAll(s.chain.dataDir) + + for _, td := range s.tmpDirs { + os.RemoveAll(td) + } +} + +func (s *IntegrationTestSuite) initNodes(c *chain) { + s.Require().NoError(c.createAndInitValidators(2)) + + // initialize a genesis file for the first validator + val0ConfigDir := c.validators[0].configDir() + for _, val := range c.validators { + s.Require().NoError( + addGenesisAccount(val0ConfigDir, "", initBalanceStr, val.keyInfo.GetAddress()), + ) + } + + // copy the genesis file to the remaining validators + for _, val := range c.validators[1:] { + _, err := copyFile( + filepath.Join(val0ConfigDir, "config", "genesis.json"), + filepath.Join(val.configDir(), "config", "genesis.json"), + ) + s.Require().NoError(err) + } +} + +func (s *IntegrationTestSuite) initGenesis(c *chain) { + serverCtx := server.NewDefaultContext() + config := serverCtx.Config + + config.SetRoot(c.validators[0].configDir()) + config.Moniker = c.validators[0].moniker + + genFilePath := config.GenesisFile() + appGenState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFilePath) + s.Require().NoError(err) + + var bankGenState banktypes.GenesisState + s.Require().NoError(cdc.UnmarshalJSON(appGenState[banktypes.ModuleName], &bankGenState)) + + bankGenState.DenomMetadata = append(bankGenState.DenomMetadata, banktypes.Metadata{ + Description: "An example stable token", + Display: osmoDenom, + Base: osmoDenom, + Symbol: osmoDenom, + Name: osmoDenom, + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: osmoDenom, + Exponent: 0, + }, + }, + }) + + bz, err := cdc.MarshalJSON(&bankGenState) + s.Require().NoError(err) + appGenState[banktypes.ModuleName] = bz + + var genUtilGenState genutiltypes.GenesisState + s.Require().NoError(cdc.UnmarshalJSON(appGenState[genutiltypes.ModuleName], &genUtilGenState)) + + // generate genesis txs + genTxs := make([]json.RawMessage, len(c.validators)) + for i, val := range c.validators { + createValmsg, err := val.buildCreateValidatorMsg(stakeAmountCoin) + s.Require().NoError(err) + + signedTx, err := val.signMsg(createValmsg) + s.Require().NoError(err) + + txRaw, err := cdc.MarshalJSON(signedTx) + s.Require().NoError(err) + + genTxs[i] = txRaw + } + + genUtilGenState.GenTxs = genTxs + + bz, err = cdc.MarshalJSON(&genUtilGenState) + s.Require().NoError(err) + appGenState[genutiltypes.ModuleName] = bz + + bz, err = json.MarshalIndent(appGenState, "", " ") + s.Require().NoError(err) + + genDoc.AppState = bz + + bz, err = tmjson.MarshalIndent(genDoc, "", " ") + s.Require().NoError(err) + + // write the updated genesis file to each validator + for _, val := range c.validators { + writeFile(filepath.Join(val.configDir(), "config", "genesis.json"), bz) + } +} + +func (s *IntegrationTestSuite) initValidatorConfigs(c *chain) { + for i, val := range c.validators { + tmCfgPath := filepath.Join(val.configDir(), "config", "config.toml") + + vpr := viper.New() + vpr.SetConfigFile(tmCfgPath) + s.Require().NoError(vpr.ReadInConfig()) + + valConfig := &tmconfig.Config{} + s.Require().NoError(vpr.Unmarshal(valConfig)) + + valConfig.P2P.ListenAddress = "tcp://0.0.0.0:26656" + valConfig.P2P.AddrBookStrict = false + valConfig.P2P.ExternalAddress = fmt.Sprintf("%s:%d", val.instanceName(), 26656) + valConfig.RPC.ListenAddress = "tcp://0.0.0.0:26657" + valConfig.StateSync.Enable = false + valConfig.LogLevel = "info" + + var peers []string + + for j := 0; j < len(c.validators); j++ { + if i == j { + continue + } + + peer := c.validators[j] + peerID := fmt.Sprintf("%s@%s%d:26656", peer.nodeKey.ID(), peer.moniker, j) + peers = append(peers, peerID) + } + + valConfig.P2P.PersistentPeers = strings.Join(peers, ",") + + tmconfig.WriteConfigFile(tmCfgPath, valConfig) + + // set application configuration + appCfgPath := filepath.Join(val.configDir(), "config", "app.toml") + + appConfig := srvconfig.DefaultConfig() + appConfig.API.Enable = true + appConfig.MinGasPrices = fmt.Sprintf("%s%s", minGasPrice, osmoDenom) + + srvconfig.WriteConfigFile(appCfgPath, appConfig) + } +} + +func (s *IntegrationTestSuite) runValidators(c *chain, portOffset int) { + s.T().Logf("starting Osmosis %s validator containers...", c.id) + + s.valResources[c.id] = make([]*dockertest.Resource, len(c.validators)) + for i, val := range c.validators { + runOpts := &dockertest.RunOptions{ + Name: val.instanceName(), + NetworkID: s.dkrNet.Network.ID, + Mounts: []string{ + fmt.Sprintf("%s/:/osmosis/.osmosisd", val.configDir()), + }, + Repository: "cosmos/osmosisd-e2e", + } + + // expose the first validator for debugging and communication + if val.index == 0 { + runOpts.PortBindings = map[docker.Port][]docker.PortBinding{ + "1317/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 1317+portOffset)}}, + "6060/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 6060+portOffset)}}, + "6061/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 6061+portOffset)}}, + "6062/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 6062+portOffset)}}, + "6063/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 6063+portOffset)}}, + "6064/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 6064+portOffset)}}, + "6065/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 6065+portOffset)}}, + "9090/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 9090+portOffset)}}, + "26656/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 26656+portOffset)}}, + "26657/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 26657+portOffset)}}, + } + } + + resource, err := s.dkrPool.RunWithOptions(runOpts, noRestart) + s.Require().NoError(err) + + s.valResources[c.id][i] = resource + s.T().Logf("started Osmosis %s validator container: %s", c.id, resource.Container.ID) + } + + rpcClient, err := rpchttp.New("tcp://localhost:26657", "/websocket") + s.Require().NoError(err) + + s.Require().Eventually( + func() bool { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + + status, err := rpcClient.Status(ctx) + if err != nil { + return false + } + + // let the node produce a few blocks + if status.SyncInfo.CatchingUp || status.SyncInfo.LatestBlockHeight < 3 { + return false + } + + return true + }, + 5*time.Minute, + time.Second, + "Osmosis node failed to produce blocks", + ) +} + +func noRestart(config *docker.HostConfig) { + // in this case we don't want the nodes to restart on failure + config.RestartPolicy = docker.RestartPolicy{ + Name: "no", + } +} diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go new file mode 100644 index 00000000000..5495a4efecd --- /dev/null +++ b/tests/e2e/e2e_test.go @@ -0,0 +1,76 @@ +package e2e + +import ( + "errors" + "fmt" + "io" + "net/http" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func (s *IntegrationTestSuite) TestQueryBalances() { + var ( + expectedDenoms = []string{osmoDenom, stakeDenom} + expectedBalances = []uint64{osmoBalance, stakeBalance - stakeAmount} + ) + + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chain.id][0].GetHostPort("1317/tcp")) + balances, err := queryBalances(chainAAPIEndpoint, s.chain.validators[0].keyInfo.GetAddress().String()) + s.Require().NoError(err) + s.Require().NotNil(balances) + s.Require().Equal(2, len(balances)) + + actualDenoms := make([]string, 0, 2) + actualBalances := make([]uint64, 0, 2) + + for _, balance := range balances { + actualDenoms = append(actualDenoms, balance.GetDenom()) + actualBalances = append(actualBalances, balance.Amount.Uint64()) + } + + s.Require().ElementsMatch(expectedDenoms, actualDenoms) + s.Require().ElementsMatch(expectedBalances, actualBalances) +} + +func queryBalances(endpoint, addr string) (sdk.Coins, error) { + path := fmt.Sprintf( + "%s/cosmos/bank/v1beta1/balances/%s", + endpoint, addr, + ) + resp, err := http.Get(path) + retriesLeft := 5 + for { + resp, err = http.Get(path) + + if resp.StatusCode == http.StatusServiceUnavailable { + retriesLeft-- + if retriesLeft == 0 { + return nil, errors.New(fmt.Sprintf("exceeded retry limit of %d with %d", retriesLeft, http.StatusServiceUnavailable)) + } + time.Sleep(10 * time.Second) + } else { + break + } + } + + if err != nil { + return nil, fmt.Errorf("failed to execute HTTP request: %w", err) + } + + defer resp.Body.Close() + + bz, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var balancesResp banktypes.QueryAllBalancesResponse + if err := cdc.UnmarshalJSON(bz, &balancesResp); err != nil { + return nil, err + } + + return balancesResp.GetBalances(), nil +} diff --git a/tests/e2e/genesis.go b/tests/e2e/genesis.go new file mode 100644 index 00000000000..8ef24b81173 --- /dev/null +++ b/tests/e2e/genesis.go @@ -0,0 +1,110 @@ +package e2e + +import ( + "encoding/json" + "fmt" + "os" + + "github.com/cosmos/cosmos-sdk/server" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + tmtypes "github.com/tendermint/tendermint/types" +) + +func getGenDoc(path string) (*tmtypes.GenesisDoc, error) { + serverCtx := server.NewDefaultContext() + config := serverCtx.Config + config.SetRoot(path) + + genFile := config.GenesisFile() + doc := &tmtypes.GenesisDoc{} + + if _, err := os.Stat(genFile); err != nil { + if !os.IsNotExist(err) { + return nil, err + } + } else { + var err error + + doc, err = tmtypes.GenesisDocFromFile(genFile) + if err != nil { + return nil, fmt.Errorf("failed to read genesis doc from file: %w", err) + } + } + + return doc, nil +} + +func addGenesisAccount(path, moniker, amountStr string, accAddr sdk.AccAddress) error { + serverCtx := server.NewDefaultContext() + config := serverCtx.Config + + config.SetRoot(path) + config.Moniker = moniker + + coins, err := sdk.ParseCoinsNormalized(amountStr) + if err != nil { + return fmt.Errorf("failed to parse coins: %w", err) + } + + balances := banktypes.Balance{Address: accAddr.String(), Coins: coins.Sort()} + genAccount := authtypes.NewBaseAccount(accAddr, nil, 0, 0) + + genFile := config.GenesisFile() + appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile) + if err != nil { + return fmt.Errorf("failed to unmarshal genesis state: %w", err) + } + + authGenState := authtypes.GetGenesisStateFromAppState(cdc, appState) + + accs, err := authtypes.UnpackAccounts(authGenState.Accounts) + if err != nil { + return fmt.Errorf("failed to get accounts from any: %w", err) + } + + if accs.Contains(accAddr) { + return fmt.Errorf("failed to add account to genesis state; account already exists: %s", accAddr) + } + + // Add the new account to the set of genesis accounts and sanitize the + // accounts afterwards. + accs = append(accs, genAccount) + accs = authtypes.SanitizeGenesisAccounts(accs) + + genAccs, err := authtypes.PackAccounts(accs) + if err != nil { + return fmt.Errorf("failed to convert accounts into any's: %w", err) + } + + authGenState.Accounts = genAccs + + authGenStateBz, err := cdc.MarshalJSON(&authGenState) + if err != nil { + return fmt.Errorf("failed to marshal auth genesis state: %w", err) + } + + appState[authtypes.ModuleName] = authGenStateBz + + bankGenState := banktypes.GetGenesisStateFromAppState(cdc, appState) + bankGenState.Balances = append(bankGenState.Balances, balances) + bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances) + + bankGenStateBz, err := cdc.MarshalJSON(bankGenState) + if err != nil { + return fmt.Errorf("failed to marshal bank genesis state: %w", err) + } + + appState[banktypes.ModuleName] = bankGenStateBz + + appStateJSON, err := json.Marshal(appState) + if err != nil { + return fmt.Errorf("failed to marshal application genesis state: %w", err) + } + + genDoc.AppState = appStateJSON + return genutil.ExportGenesisFile(genDoc, genFile) +} diff --git a/tests/e2e/io.go b/tests/e2e/io.go new file mode 100644 index 00000000000..97bfac75dce --- /dev/null +++ b/tests/e2e/io.go @@ -0,0 +1,43 @@ +package e2e + +import ( + "fmt" + "io" + "io/ioutil" + "os" +) + +func copyFile(src, dst string) (int64, error) { + sourceFileStat, err := os.Stat(src) + if err != nil { + return 0, err + } + + if !sourceFileStat.Mode().IsRegular() { + return 0, fmt.Errorf("%s is not a regular file", src) + } + + source, err := os.Open(src) + if err != nil { + return 0, err + } + defer source.Close() + + destination, err := os.Create(dst) + if err != nil { + return 0, err + } + defer destination.Close() + + nBytes, err := io.Copy(destination, source) + return nBytes, err +} + +func writeFile(path string, body []byte) error { + _, err := os.Create(path) + if err != nil { + return err + } + + return ioutil.WriteFile(path, body, 0600) +} diff --git a/tests/e2e/keys.go b/tests/e2e/keys.go new file mode 100644 index 00000000000..55074ef30b6 --- /dev/null +++ b/tests/e2e/keys.go @@ -0,0 +1,56 @@ +package e2e + +import ( + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/go-bip39" +) + +func createMnemonic() (string, error) { + entropySeed, err := bip39.NewEntropy(256) + if err != nil { + return "", err + } + + mnemonic, err := bip39.NewMnemonic(entropySeed) + if err != nil { + return "", err + } + + return mnemonic, nil +} + +func createMemoryKey() (mnemonic string, info *keyring.Info, err error) { + mnemonic, err = createMnemonic() + if err != nil { + return "", nil, err + } + + account, err := createMemoryKeyFromMnemonic(mnemonic) + if err != nil { + return "", nil, err + } + + return mnemonic, account, nil +} + +func createMemoryKeyFromMnemonic(mnemonic string) (*keyring.Info, error) { + kb, err := keyring.New("testnet", keyring.BackendMemory, "", nil) + if err != nil { + return nil, err + } + + keyringAlgos, _ := kb.SupportedAlgorithms() + algo, err := keyring.NewSigningAlgoFromString(string(hd.Secp256k1Type), keyringAlgos) + if err != nil { + return nil, err + } + + account, err := kb.NewAccount("", mnemonic, "", sdk.FullFundraiserPath, algo) + if err != nil { + return nil, err + } + + return &account, nil +} diff --git a/tests/e2e/util.go b/tests/e2e/util.go new file mode 100644 index 00000000000..5ee776d0c02 --- /dev/null +++ b/tests/e2e/util.go @@ -0,0 +1,45 @@ +package e2e + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/codec/unknownproto" + sdktx "github.com/cosmos/cosmos-sdk/types/tx" +) + +func decodeTx(txBytes []byte) (*sdktx.Tx, error) { + var raw sdktx.TxRaw + + // reject all unknown proto fields in the root TxRaw + err := unknownproto.RejectUnknownFieldsStrict(txBytes, &raw, encodingConfig.InterfaceRegistry) + if err != nil { + return nil, fmt.Errorf("failed to reject unknown fields: %w", err) + } + + if err := cdc.Unmarshal(txBytes, &raw); err != nil { + return nil, err + } + + var body sdktx.TxBody + if err := cdc.Unmarshal(raw.BodyBytes, &body); err != nil { + return nil, fmt.Errorf("failed to decode tx: %w", err) + } + + var authInfo sdktx.AuthInfo + + // reject all unknown proto fields in AuthInfo + err = unknownproto.RejectUnknownFieldsStrict(raw.AuthInfoBytes, &authInfo, encodingConfig.InterfaceRegistry) + if err != nil { + return nil, fmt.Errorf("failed to reject unknown fields: %w", err) + } + + if err := cdc.Unmarshal(raw.AuthInfoBytes, &authInfo); err != nil { + return nil, fmt.Errorf("failed to decode auth info: %w", err) + } + + return &sdktx.Tx{ + Body: &body, + AuthInfo: &authInfo, + Signatures: raw.Signatures, + }, nil +} diff --git a/tests/e2e/validator.go b/tests/e2e/validator.go new file mode 100644 index 00000000000..6c7941614c6 --- /dev/null +++ b/tests/e2e/validator.go @@ -0,0 +1,267 @@ +package e2e + +import ( + "encoding/json" + "fmt" + "os" + "path" + "path/filepath" + + sdkcrypto "github.com/cosmos/cosmos-sdk/crypto" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/server" + sdk "github.com/cosmos/cosmos-sdk/types" + sdktx "github.com/cosmos/cosmos-sdk/types/tx" + txsigning "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + "github.com/cosmos/cosmos-sdk/x/genutil" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + tmcfg "github.com/tendermint/tendermint/config" + tmos "github.com/tendermint/tendermint/libs/os" + "github.com/tendermint/tendermint/p2p" + "github.com/tendermint/tendermint/privval" + + osmosisApp "github.com/osmosis-labs/osmosis/v7/app" +) + +type validator struct { + chain *chain + index int + moniker string + mnemonic string + keyInfo keyring.Info + privateKey cryptotypes.PrivKey + consensusKey privval.FilePVKey + consensusPrivKey cryptotypes.PrivKey + nodeKey p2p.NodeKey +} + +func (v *validator) instanceName() string { + return fmt.Sprintf("%s%d", v.moniker, v.index) +} + +func (v *validator) configDir() string { + return fmt.Sprintf("%s/%s", v.chain.configDir(), v.instanceName()) +} + +func (v *validator) createConfig() error { + p := path.Join(v.configDir(), "config") + return os.MkdirAll(p, 0755) +} + +func (v *validator) init() error { + if err := v.createConfig(); err != nil { + return err + } + + serverCtx := server.NewDefaultContext() + config := serverCtx.Config + + config.SetRoot(v.configDir()) + config.Moniker = v.moniker + + genDoc, err := getGenDoc(v.configDir()) + if err != nil { + return err + } + + appState, err := json.MarshalIndent(osmosisApp.ModuleBasics.DefaultGenesis(cdc), "", " ") + if err != nil { + return fmt.Errorf("failed to JSON encode app genesis state: %w", err) + } + + genDoc.ChainID = v.chain.id + genDoc.Validators = nil + genDoc.AppState = appState + + if err = genutil.ExportGenesisFile(genDoc, config.GenesisFile()); err != nil { + return fmt.Errorf("failed to export app genesis state: %w", err) + } + + tmcfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) + return nil +} + +func (v *validator) createNodeKey() error { + serverCtx := server.NewDefaultContext() + config := serverCtx.Config + + config.SetRoot(v.configDir()) + config.Moniker = v.moniker + + nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) + if err != nil { + return err + } + + v.nodeKey = *nodeKey + return nil +} + +func (v *validator) createConsensusKey() error { + serverCtx := server.NewDefaultContext() + config := serverCtx.Config + + config.SetRoot(v.configDir()) + config.Moniker = v.moniker + + pvKeyFile := config.PrivValidatorKeyFile() + if err := tmos.EnsureDir(filepath.Dir(pvKeyFile), 0777); err != nil { + return err + } + + pvStateFile := config.PrivValidatorStateFile() + if err := tmos.EnsureDir(filepath.Dir(pvStateFile), 0777); err != nil { + return err + } + + filePV := privval.LoadOrGenFilePV(pvKeyFile, pvStateFile) + v.consensusKey = filePV.Key + + return nil +} + +func (v *validator) createKeyFromMnemonic(name, mnemonic string) error { + kb, err := keyring.New(keyringAppName, keyring.BackendTest, v.configDir(), nil) + if err != nil { + return err + } + + keyringAlgos, _ := kb.SupportedAlgorithms() + algo, err := keyring.NewSigningAlgoFromString(string(hd.Secp256k1Type), keyringAlgos) + if err != nil { + return err + } + + info, err := kb.NewAccount(name, mnemonic, "", sdk.FullFundraiserPath, algo) + if err != nil { + return err + } + + privKeyArmor, err := kb.ExportPrivKeyArmor(name, keyringPassphrase) + if err != nil { + return err + } + + privKey, _, err := sdkcrypto.UnarmorDecryptPrivKey(privKeyArmor, keyringPassphrase) + if err != nil { + return err + } + + v.keyInfo = info + v.mnemonic = mnemonic + v.privateKey = privKey + + return nil +} + +func (v *validator) createKey(name string) error { + mnemonic, err := createMnemonic() + if err != nil { + return err + } + + return v.createKeyFromMnemonic(name, mnemonic) +} + +func (v *validator) buildCreateValidatorMsg(amount sdk.Coin) (sdk.Msg, error) { + description := stakingtypes.NewDescription(v.moniker, "", "", "", "") + commissionRates := stakingtypes.CommissionRates{ + Rate: sdk.MustNewDecFromStr("0.1"), + MaxRate: sdk.MustNewDecFromStr("0.2"), + MaxChangeRate: sdk.MustNewDecFromStr("0.01"), + } + + // get the initial validator min self delegation + minSelfDelegation, _ := sdk.NewIntFromString("1") + + valPubKey, err := cryptocodec.FromTmPubKeyInterface(v.consensusKey.PubKey) + if err != nil { + return nil, err + } + + return stakingtypes.NewMsgCreateValidator( + sdk.ValAddress(v.keyInfo.GetAddress()), + valPubKey, + amount, + description, + commissionRates, + minSelfDelegation, + ) +} + +func (v *validator) signMsg(msgs ...sdk.Msg) (*sdktx.Tx, error) { + txBuilder := encodingConfig.TxConfig.NewTxBuilder() + + if err := txBuilder.SetMsgs(msgs...); err != nil { + return nil, err + } + + txBuilder.SetMemo(fmt.Sprintf("%s@%s:26656", v.nodeKey.ID(), v.instanceName())) + txBuilder.SetFeeAmount(sdk.NewCoins()) + txBuilder.SetGasLimit(200000) + + signerData := authsigning.SignerData{ + ChainID: v.chain.id, + AccountNumber: 0, + Sequence: 0, + } + + // For SIGN_MODE_DIRECT, calling SetSignatures calls setSignerInfos on + // TxBuilder under the hood, and SignerInfos is needed to generate the sign + // bytes. This is the reason for setting SetSignatures here, with a nil + // signature. + // + // Note: This line is not needed for SIGN_MODE_LEGACY_AMINO, but putting it + // also doesn't affect its generated sign bytes, so for code's simplicity + // sake, we put it here. + sig := txsigning.SignatureV2{ + PubKey: v.keyInfo.GetPubKey(), + Data: &txsigning.SingleSignatureData{ + SignMode: txsigning.SignMode_SIGN_MODE_DIRECT, + Signature: nil, + }, + Sequence: 0, + } + + if err := txBuilder.SetSignatures(sig); err != nil { + return nil, err + } + + bytesToSign, err := encodingConfig.TxConfig.SignModeHandler().GetSignBytes( + txsigning.SignMode_SIGN_MODE_DIRECT, + signerData, + txBuilder.GetTx(), + ) + if err != nil { + return nil, err + } + + sigBytes, err := v.privateKey.Sign(bytesToSign) + if err != nil { + return nil, err + } + + sig = txsigning.SignatureV2{ + PubKey: v.keyInfo.GetPubKey(), + Data: &txsigning.SingleSignatureData{ + SignMode: txsigning.SignMode_SIGN_MODE_DIRECT, + Signature: sigBytes, + }, + Sequence: 0, + } + if err := txBuilder.SetSignatures(sig); err != nil { + return nil, err + } + + signedTx := txBuilder.GetTx() + bz, err := encodingConfig.TxConfig.TxEncoder()(signedTx) + if err != nil { + return nil, err + } + + return decodeTx(bz) +} From b80433c66818e910401161d7e4551438548ca9a8 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Wed, 6 Apr 2022 12:19:43 -0500 Subject: [PATCH 2/9] second e2e chain with expanded test (#1206) --- tests/e2e/chain.go | 5 +-- tests/e2e/e2e_setup_test.go | 79 ++++++++++++++++++++++++++----------- tests/e2e/e2e_test.go | 42 ++++++++++++++------ 3 files changed, 87 insertions(+), 39 deletions(-) diff --git a/tests/e2e/chain.go b/tests/e2e/chain.go index a5ce93561ad..24cea7e9f3b 100644 --- a/tests/e2e/chain.go +++ b/tests/e2e/chain.go @@ -10,7 +10,6 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - tmrand "github.com/tendermint/tendermint/libs/rand" osmosisApp "github.com/osmosis-labs/osmosis/v7/app" "github.com/osmosis-labs/osmosis/v7/app/params" @@ -48,14 +47,14 @@ type chain struct { validators []*validator } -func newChain() (*chain, error) { +func newChain(name string) (*chain, error) { tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-") if err != nil { return nil, err } return &chain{ - id: "chain-" + tmrand.NewRand().Str(6), + id: name, dataDir: tmpDir, }, nil } diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index f88d265e073..43cb0740b4d 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -26,25 +26,37 @@ import ( ) const ( - osmoBalance = 200000000000 - osmoDenom = "uosmo" - stakeBalance = 110000000000 - stakeAmount = 100000000000 - stakeDenom = "stake" - minGasPrice = "0.00001" + // common + osmoDenom = "uosmo" + stakeDenom = "stake" + minGasPrice = "0.00001" + // chainA + chainAName = "osmo-test-a" + osmoBalanceA = 200000000000 + stakeBalanceA = 110000000000 + stakeAmountA = 100000000000 + // chainB + chainBName = "osmo-test-b" + osmoBalanceB = 500000000000 + stakeBalanceB = 440000000000 + stakeAmountB = 400000000000 ) var ( - initBalanceStr = fmt.Sprintf("%d%s,%d%s", osmoBalance, osmoDenom, stakeBalance, stakeDenom) - stakeAmountInt, _ = sdk.NewIntFromString(fmt.Sprintf("%d", stakeAmount)) - stakeAmountCoin = sdk.NewCoin(stakeDenom, stakeAmountInt) + initBalanceStrA = fmt.Sprintf("%d%s,%d%s", osmoBalanceA, osmoDenom, stakeBalanceA, stakeDenom) + initBalanceStrB = fmt.Sprintf("%d%s,%d%s", osmoBalanceB, osmoDenom, stakeBalanceB, stakeDenom) + stakeAmountIntA = sdk.NewInt(stakeAmountA) + stakeAmountCoinA = sdk.NewCoin(stakeDenom, stakeAmountIntA) + stakeAmountIntB = sdk.NewInt(stakeAmountB) + stakeAmountCoinB = sdk.NewCoin(stakeDenom, stakeAmountIntB) ) type IntegrationTestSuite struct { suite.Suite tmpDirs []string - chain *chain + chainA *chain + chainB *chain dkrPool *dockertest.Pool dkrNet *dockertest.Network valResources map[string][]*dockertest.Resource @@ -58,13 +70,16 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up e2e integration test suite...") var err error - s.chain, err = newChain() + s.chainA, err = newChain(chainAName) + s.Require().NoError(err) + + s.chainB, err = newChain(chainBName) s.Require().NoError(err) s.dkrPool, err = dockertest.NewPool("") s.Require().NoError(err) - s.dkrNet, err = s.dkrPool.CreateNetwork(fmt.Sprintf("%s-testnet", s.chain.id)) + s.dkrNet, err = s.dkrPool.CreateNetwork(fmt.Sprintf("%s-%s-testnet", s.chainA.id, s.chainB.id)) s.Require().NoError(err) s.valResources = make(map[string][]*dockertest.Resource) @@ -72,13 +87,20 @@ func (s *IntegrationTestSuite) SetupSuite() { // The boostrapping phase is as follows: // // 1. Initialize Osmosis validator nodes. - // 2. Create and initialize Osmosis validator genesis files (one chain) - - s.T().Logf("starting e2e infrastructure for chain A; chain-id: %s; datadir: %s", s.chain.id, s.chain.dataDir) - s.initNodes(s.chain) - s.initGenesis(s.chain) - s.initValidatorConfigs(s.chain) - s.runValidators(s.chain, 0) + // 2. Create and initialize Osmosis validator genesis files (both chains) + // 3. Start both networks. + + s.T().Logf("starting e2e infrastructure for chain A; chain-id: %s; datadir: %s", s.chainA.id, s.chainA.dataDir) + s.initNodes(s.chainA) + s.initGenesis(s.chainA) + s.initValidatorConfigs(s.chainA) + s.runValidators(s.chainA, 0) + + s.T().Logf("starting e2e infrastructure for chain B; chain-id: %s; datadir: %s", s.chainB.id, s.chainB.dataDir) + s.initNodes(s.chainB) + s.initGenesis(s.chainB) + s.initValidatorConfigs(s.chainB) + s.runValidators(s.chainB, 10) } func (s *IntegrationTestSuite) TearDownSuite() { @@ -101,7 +123,8 @@ func (s *IntegrationTestSuite) TearDownSuite() { s.Require().NoError(s.dkrPool.RemoveNetwork(s.dkrNet)) - os.RemoveAll(s.chain.dataDir) + os.RemoveAll(s.chainA.dataDir) + os.RemoveAll(s.chainB.dataDir) for _, td := range s.tmpDirs { os.RemoveAll(td) @@ -114,9 +137,15 @@ func (s *IntegrationTestSuite) initNodes(c *chain) { // initialize a genesis file for the first validator val0ConfigDir := c.validators[0].configDir() for _, val := range c.validators { - s.Require().NoError( - addGenesisAccount(val0ConfigDir, "", initBalanceStr, val.keyInfo.GetAddress()), - ) + if c.id == chainAName { + s.Require().NoError( + addGenesisAccount(val0ConfigDir, "", initBalanceStrA, val.keyInfo.GetAddress()), + ) + } else if c.id == chainBName { + s.Require().NoError( + addGenesisAccount(val0ConfigDir, "", initBalanceStrB, val.keyInfo.GetAddress()), + ) + } } // copy the genesis file to the remaining validators @@ -167,6 +196,10 @@ func (s *IntegrationTestSuite) initGenesis(c *chain) { // generate genesis txs genTxs := make([]json.RawMessage, len(c.validators)) for i, val := range c.validators { + stakeAmountCoin := stakeAmountCoinA + if c.id != chainAName { + stakeAmountCoin = stakeAmountCoinB + } createValmsg, err := val.buildCreateValidatorMsg(stakeAmountCoin) s.Require().NoError(err) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 5495a4efecd..2cc226a7854 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -13,26 +13,42 @@ import ( func (s *IntegrationTestSuite) TestQueryBalances() { var ( - expectedDenoms = []string{osmoDenom, stakeDenom} - expectedBalances = []uint64{osmoBalance, stakeBalance - stakeAmount} + expectedDenoms = []string{osmoDenom, stakeDenom} + expectedBalancesA = []uint64{osmoBalanceA, stakeBalanceA - stakeAmountA} + expectedBalancesB = []uint64{osmoBalanceB, stakeBalanceB - stakeAmountB} ) - chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chain.id][0].GetHostPort("1317/tcp")) - balances, err := queryBalances(chainAAPIEndpoint, s.chain.validators[0].keyInfo.GetAddress().String()) + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) + balancesA, err := queryBalances(chainAAPIEndpoint, s.chainA.validators[0].keyInfo.GetAddress().String()) s.Require().NoError(err) - s.Require().NotNil(balances) - s.Require().Equal(2, len(balances)) + s.Require().NotNil(balancesA) + s.Require().Equal(2, len(balancesA)) - actualDenoms := make([]string, 0, 2) - actualBalances := make([]uint64, 0, 2) + chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) + balancesB, err := queryBalances(chainBAPIEndpoint, s.chainB.validators[0].keyInfo.GetAddress().String()) + s.Require().NoError(err) + s.Require().NotNil(balancesB) + s.Require().Equal(2, len(balancesB)) + + actualDenomsA := make([]string, 0, 2) + actualBalancesA := make([]uint64, 0, 2) + actualDenomsB := make([]string, 0, 2) + actualBalancesB := make([]uint64, 0, 2) + + for _, balanceA := range balancesA { + actualDenomsA = append(actualDenomsA, balanceA.GetDenom()) + actualBalancesA = append(actualBalancesA, balanceA.Amount.Uint64()) + } - for _, balance := range balances { - actualDenoms = append(actualDenoms, balance.GetDenom()) - actualBalances = append(actualBalances, balance.Amount.Uint64()) + for _, balanceB := range balancesB { + actualDenomsB = append(actualDenomsB, balanceB.GetDenom()) + actualBalancesB = append(actualBalancesB, balanceB.Amount.Uint64()) } - s.Require().ElementsMatch(expectedDenoms, actualDenoms) - s.Require().ElementsMatch(expectedBalances, actualBalances) + s.Require().ElementsMatch(expectedDenoms, actualDenomsA) + s.Require().ElementsMatch(expectedBalancesA, actualBalancesA) + s.Require().ElementsMatch(expectedDenoms, actualDenomsB) + s.Require().ElementsMatch(expectedBalancesB, actualBalancesB) } func queryBalances(endpoint, addr string) (sdk.Coins, error) { From 4c248b1ffe19169498733db4ef249c99ed315f79 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Fri, 8 Apr 2022 12:43:53 -0500 Subject: [PATCH 3/9] e2e with IBC tx and test (#1216) * second chain with tests * add hermes, comment out balance query for now * eventually * Update Makefile Co-authored-by: Roman <34196718+p0mvn@users.noreply.github.com> * remove gas fees and unused functions * readded check * Nicco changes to own hermes image * Remove unused hermes.Dockerfile * Use a single Dockerfile for both debug and official image * readd build hermes in makefile * remove hermes * Set correct golang image and use correct debug image tag Co-authored-by: Adam Tucker Co-authored-by: Roman <34196718+p0mvn@users.noreply.github.com> Co-authored-by: Niccolo Raspa --- Dockerfile | 7 +- Makefile | 2 +- e2e.Dockerfile | 26 ----- tests/e2e/chain.go | 4 +- tests/e2e/e2e_setup_test.go | 141 ++++++++++++++++++++++---- tests/e2e/e2e_test.go | 59 +++++++++-- tests/e2e/e2e_util_test.go | 108 ++++++++++++++++++++ tests/e2e/scripts/hermes_bootstrap.sh | 72 +++++++++++++ 8 files changed, 362 insertions(+), 57 deletions(-) delete mode 100644 e2e.Dockerfile create mode 100644 tests/e2e/e2e_util_test.go create mode 100644 tests/e2e/scripts/hermes_bootstrap.sh diff --git a/Dockerfile b/Dockerfile index 022e5105bef..2a01c6639ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ # syntax=docker/dockerfile:1 +ARG BASE_IMG_TAG=nonroot + ## Build Image FROM golang:1.18-bullseye as build @@ -13,7 +15,7 @@ RUN sha256sum /lib/libwasmvm_muslc.a | grep d0152067a5609bfdfb3f0d5d6c0f2760f79d RUN BUILD_TAGS=muslc make build ## Deploy image -FROM gcr.io/distroless/base-debian11:nonroot +FROM gcr.io/distroless/base-debian11:${BASE_IMG_TAG} COPY --from=build /osmosis/build/osmosisd /bin/osmosisd @@ -22,6 +24,7 @@ WORKDIR $HOME EXPOSE 26656 EXPOSE 26657 -EXPOSE 1317 +EXPOSE 1317 ENTRYPOINT ["osmosisd"] +CMD [ "start" ] diff --git a/Makefile b/Makefile index 780fbadbbf6..737f32c6c4e 100644 --- a/Makefile +++ b/Makefile @@ -229,7 +229,7 @@ benchmark: @go test -mod=readonly -bench=. ./... docker-build-debug: - @docker build -t cosmos/osmosisd-e2e --build-arg IMG_TAG=debug -f e2e.Dockerfile . + @docker build -t osmosis:debug --build-arg BASE_IMG_TAG=debug -f Dockerfile . ############################################################################### ### Linting ### diff --git a/e2e.Dockerfile b/e2e.Dockerfile deleted file mode 100644 index f0bfd24d8f4..00000000000 --- a/e2e.Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -# syntax=docker/dockerfile:1 -ARG IMG_TAG=latest - -## Build Image -FROM golang:1.17-bullseye as build - -WORKDIR /osmosis -COPY . /osmosis - -# From https://github.com/CosmWasm/wasmd/blob/master/Dockerfile -# For more details see https://github.com/CosmWasm/wasmvm#builds-of-libwasmvm -ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.0.0-beta7/libwasmvm_muslc.a /lib/libwasmvm_muslc.a -RUN sha256sum /lib/libwasmvm_muslc.a | grep d0152067a5609bfdfb3f0d5d6c0f2760f79d5f2cd7fd8513cafa9932d22eb350 -RUN BUILD_TAGS=muslc make build - -## Deploy image -FROM gcr.io/distroless/cc:$IMG_TAG -ARG IMG_TAG -COPY --from=build /osmosis/build/osmosisd /bin/osmosisd - -ENV HOME /osmosis -WORKDIR $HOME - -EXPOSE 26656 26657 1317 9090 - -ENTRYPOINT ["osmosisd", "start"] diff --git a/tests/e2e/chain.go b/tests/e2e/chain.go index 24cea7e9f3b..a5eadfe4230 100644 --- a/tests/e2e/chain.go +++ b/tests/e2e/chain.go @@ -47,14 +47,14 @@ type chain struct { validators []*validator } -func newChain(name string) (*chain, error) { +func newChain(id string) (*chain, error) { tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-") if err != nil { return nil, err } return &chain{ - id: name, + id: id, dataDir: tmpDir, }, nil } diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 43cb0740b4d..53bf8cbd67c 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -4,7 +4,11 @@ import ( "context" "encoding/json" "fmt" + "io" + "io/ioutil" + "net/http" "os" + "path" "path/filepath" "strconv" "strings" @@ -27,16 +31,18 @@ import ( const ( // common - osmoDenom = "uosmo" - stakeDenom = "stake" - minGasPrice = "0.00001" + osmoDenom = "uosmo" + stakeDenom = "stake" + ibcDenom = "ibc/ED07A3391A112B175915CD8FAF43A2DA8E4790EDE12566649D0C2F97716B8518" + minGasPrice = "0.000" + ibcSendAmount = 3300000000 // chainA - chainAName = "osmo-test-a" + chainAID = "osmo-test-a" osmoBalanceA = 200000000000 stakeBalanceA = 110000000000 stakeAmountA = 100000000000 // chainB - chainBName = "osmo-test-b" + chainBID = "osmo-test-b" osmoBalanceB = 500000000000 stakeBalanceB = 440000000000 stakeAmountB = 400000000000 @@ -54,12 +60,13 @@ var ( type IntegrationTestSuite struct { suite.Suite - tmpDirs []string - chainA *chain - chainB *chain - dkrPool *dockertest.Pool - dkrNet *dockertest.Network - valResources map[string][]*dockertest.Resource + tmpDirs []string + chainA *chain + chainB *chain + dkrPool *dockertest.Pool + dkrNet *dockertest.Network + hermesResource *dockertest.Resource + valResources map[string][]*dockertest.Resource } func TestIntegrationTestSuite(t *testing.T) { @@ -70,10 +77,10 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up e2e integration test suite...") var err error - s.chainA, err = newChain(chainAName) + s.chainA, err = newChain(chainAID) s.Require().NoError(err) - s.chainB, err = newChain(chainBName) + s.chainB, err = newChain(chainBID) s.Require().NoError(err) s.dkrPool, err = dockertest.NewPool("") @@ -101,6 +108,8 @@ func (s *IntegrationTestSuite) SetupSuite() { s.initGenesis(s.chainB) s.initValidatorConfigs(s.chainB) s.runValidators(s.chainB, 10) + + s.runIBCRelayer() } func (s *IntegrationTestSuite) TearDownSuite() { @@ -115,6 +124,8 @@ func (s *IntegrationTestSuite) TearDownSuite() { s.T().Log("tearing down e2e integration test suite...") + s.Require().NoError(s.dkrPool.Purge(s.hermesResource)) + for _, vr := range s.valResources { for _, r := range vr { s.Require().NoError(s.dkrPool.Purge(r)) @@ -137,11 +148,11 @@ func (s *IntegrationTestSuite) initNodes(c *chain) { // initialize a genesis file for the first validator val0ConfigDir := c.validators[0].configDir() for _, val := range c.validators { - if c.id == chainAName { + if c.id == chainAID { s.Require().NoError( addGenesisAccount(val0ConfigDir, "", initBalanceStrA, val.keyInfo.GetAddress()), ) - } else if c.id == chainBName { + } else if c.id == chainBID { s.Require().NoError( addGenesisAccount(val0ConfigDir, "", initBalanceStrB, val.keyInfo.GetAddress()), ) @@ -197,7 +208,7 @@ func (s *IntegrationTestSuite) initGenesis(c *chain) { genTxs := make([]json.RawMessage, len(c.validators)) for i, val := range c.validators { stakeAmountCoin := stakeAmountCoinA - if c.id != chainAName { + if c.id != chainAID { stakeAmountCoin = stakeAmountCoinB } createValmsg, err := val.buildCreateValidatorMsg(stakeAmountCoin) @@ -288,7 +299,8 @@ func (s *IntegrationTestSuite) runValidators(c *chain, portOffset int) { Mounts: []string{ fmt.Sprintf("%s/:/osmosis/.osmosisd", val.configDir()), }, - Repository: "cosmos/osmosisd-e2e", + Repository: "osmosis", + Tag: "debug", } // expose the first validator for debugging and communication @@ -340,6 +352,101 @@ func (s *IntegrationTestSuite) runValidators(c *chain, portOffset int) { ) } +func (s *IntegrationTestSuite) runIBCRelayer() { + s.T().Log("starting Hermes relayer container...") + + tmpDir, err := ioutil.TempDir("", "gaia-e2e-testnet-hermes-") + s.Require().NoError(err) + s.tmpDirs = append(s.tmpDirs, tmpDir) + + gaiaAVal := s.chainA.validators[0] + gaiaBVal := s.chainB.validators[0] + hermesCfgPath := path.Join(tmpDir, "hermes") + + s.Require().NoError(os.MkdirAll(hermesCfgPath, 0755)) + _, err = copyFile( + filepath.Join("./scripts/", "hermes_bootstrap.sh"), + filepath.Join(hermesCfgPath, "hermes_bootstrap.sh"), + ) + s.Require().NoError(err) + + s.hermesResource, err = s.dkrPool.RunWithOptions( + &dockertest.RunOptions{ + Name: fmt.Sprintf("%s-%s-relayer", s.chainA.id, s.chainB.id), + Repository: "osmolabs/hermes", + Tag: "0.13.0", + NetworkID: s.dkrNet.Network.ID, + Cmd: []string{ + "start", + }, + User: "root:root", + Mounts: []string{ + fmt.Sprintf("%s/:/root/hermes", hermesCfgPath), + }, + ExposedPorts: []string{ + "3031", + }, + PortBindings: map[docker.Port][]docker.PortBinding{ + "3031/tcp": {{HostIP: "", HostPort: "3031"}}, + }, + Env: []string{ + fmt.Sprintf("OSMO_A_E2E_CHAIN_ID=%s", s.chainA.id), + fmt.Sprintf("OSMO_B_E2E_CHAIN_ID=%s", s.chainB.id), + fmt.Sprintf("OSMO_A_E2E_VAL_MNEMONIC=%s", gaiaAVal.mnemonic), + fmt.Sprintf("OSMO_B_E2E_VAL_MNEMONIC=%s", gaiaBVal.mnemonic), + fmt.Sprintf("OSMO_A_E2E_VAL_HOST=%s", s.valResources[s.chainA.id][0].Container.Name[1:]), + fmt.Sprintf("OSMO_B_E2E_VAL_HOST=%s", s.valResources[s.chainB.id][0].Container.Name[1:]), + }, + Entrypoint: []string{ + "sh", + "-c", + "chmod +x /root/hermes/hermes_bootstrap.sh && /root/hermes/hermes_bootstrap.sh", + }, + }, + noRestart, + ) + s.Require().NoError(err) + + endpoint := fmt.Sprintf("http://%s/state", s.hermesResource.GetHostPort("3031/tcp")) + s.Require().Eventually( + func() bool { + resp, err := http.Get(endpoint) + if err != nil { + return false + } + + defer resp.Body.Close() + + bz, err := io.ReadAll(resp.Body) + if err != nil { + return false + } + + var respBody map[string]interface{} + if err := json.Unmarshal(bz, &respBody); err != nil { + return false + } + + status := respBody["status"].(string) + result := respBody["result"].(map[string]interface{}) + + return status == "success" && len(result["chains"].([]interface{})) == 2 + }, + 5*time.Minute, + time.Second, + "hermes relayer not healthy", + ) + + s.T().Logf("started Hermes relayer container: %s", s.hermesResource.Container.ID) + + // XXX: Give time to both networks to start, otherwise we might see gRPC + // transport errors. + time.Sleep(10 * time.Second) + + // create the client, connection and channel between the two Gaia chains + s.connectIBCChains() +} + func noRestart(config *docker.HostConfig) { // in this case we don't want the nodes to restart on failure config.RestartPolicy = docker.RestartPolicy{ diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 2cc226a7854..8be7b7dd446 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1,10 +1,10 @@ package e2e import ( - "errors" "fmt" "io" "net/http" + "strings" "time" sdk "github.com/cosmos/cosmos-sdk/types" @@ -13,9 +13,10 @@ import ( func (s *IntegrationTestSuite) TestQueryBalances() { var ( - expectedDenoms = []string{osmoDenom, stakeDenom} - expectedBalancesA = []uint64{osmoBalanceA, stakeBalanceA - stakeAmountA} - expectedBalancesB = []uint64{osmoBalanceB, stakeBalanceB - stakeAmountB} + expectedDenomsA = []string{osmoDenom, stakeDenom} + expectedDenomsB = []string{osmoDenom, stakeDenom, ibcDenom} + expectedBalancesA = []uint64{osmoBalanceA - ibcSendAmount, stakeBalanceA - stakeAmountA} + expectedBalancesB = []uint64{osmoBalanceB, stakeBalanceB - stakeAmountB, ibcSendAmount} ) chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) @@ -28,7 +29,7 @@ func (s *IntegrationTestSuite) TestQueryBalances() { balancesB, err := queryBalances(chainBAPIEndpoint, s.chainB.validators[0].keyInfo.GetAddress().String()) s.Require().NoError(err) s.Require().NotNil(balancesB) - s.Require().Equal(2, len(balancesB)) + s.Require().Equal(3, len(balancesB)) actualDenomsA := make([]string, 0, 2) actualBalancesA := make([]uint64, 0, 2) @@ -45,10 +46,11 @@ func (s *IntegrationTestSuite) TestQueryBalances() { actualBalancesB = append(actualBalancesB, balanceB.Amount.Uint64()) } - s.Require().ElementsMatch(expectedDenoms, actualDenomsA) + s.Require().ElementsMatch(expectedDenomsA, actualDenomsA) s.Require().ElementsMatch(expectedBalancesA, actualBalancesA) - s.Require().ElementsMatch(expectedDenoms, actualDenomsB) + s.Require().ElementsMatch(expectedDenomsB, actualDenomsB) s.Require().ElementsMatch(expectedBalancesB, actualBalancesB) + } func queryBalances(endpoint, addr string) (sdk.Coins, error) { @@ -56,7 +58,8 @@ func queryBalances(endpoint, addr string) (sdk.Coins, error) { "%s/cosmos/bank/v1beta1/balances/%s", endpoint, addr, ) - resp, err := http.Get(path) + var err error + var resp *http.Response retriesLeft := 5 for { resp, err = http.Get(path) @@ -64,7 +67,7 @@ func queryBalances(endpoint, addr string) (sdk.Coins, error) { if resp.StatusCode == http.StatusServiceUnavailable { retriesLeft-- if retriesLeft == 0 { - return nil, errors.New(fmt.Sprintf("exceeded retry limit of %d with %d", retriesLeft, http.StatusServiceUnavailable)) + return nil, fmt.Errorf("exceeded retry limit of %d with %d", retriesLeft, http.StatusServiceUnavailable) } time.Sleep(10 * time.Second) } else { @@ -90,3 +93,41 @@ func queryBalances(endpoint, addr string) (sdk.Coins, error) { return balancesResp.GetBalances(), nil } + +func (s *IntegrationTestSuite) TestIBCTokenTransfer() { + var ibcStakeDenom string + + s.Run("send_uosmo_to_chainB", func() { + recipient := s.chainB.validators[0].keyInfo.GetAddress().String() + token := sdk.NewInt64Coin(osmoDenom, ibcSendAmount) // 3,300uosmo + s.sendIBC(s.chainA.id, s.chainB.id, recipient, token) + + chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) + + // require the recipient account receives the IBC tokens (IBC packets ACKd) + var ( + balances sdk.Coins + err error + ) + s.Require().Eventually( + func() bool { + balances, err = queryBalances(chainBAPIEndpoint, recipient) + s.Require().NoError(err) + + return balances.Len() == 3 + }, + time.Minute, + 5*time.Second, + ) + + for _, c := range balances { + if strings.Contains(c.Denom, "ibc/") { + ibcStakeDenom = c.Denom + s.Require().Equal(token.Amount.Int64(), c.Amount.Int64()) + break + } + } + + s.Require().NotEmpty(ibcStakeDenom) + }) +} diff --git a/tests/e2e/e2e_util_test.go b/tests/e2e/e2e_util_test.go new file mode 100644 index 00000000000..efd7cbffed9 --- /dev/null +++ b/tests/e2e/e2e_util_test.go @@ -0,0 +1,108 @@ +package e2e + +import ( + "bytes" + "context" + "fmt" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ory/dockertest/v3/docker" +) + +func (s *IntegrationTestSuite) connectIBCChains() { + s.T().Logf("connecting %s and %s chains via IBC", s.chainA.id, s.chainB.id) + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + exec, err := s.dkrPool.Client.CreateExec(docker.CreateExecOptions{ + Context: ctx, + AttachStdout: true, + AttachStderr: true, + Container: s.hermesResource.Container.ID, + User: "root", + Cmd: []string{ + "hermes", + "create", + "channel", + s.chainA.id, + s.chainB.id, + "--port-a=transfer", + "--port-b=transfer", + }, + }) + s.Require().NoError(err) + + var ( + outBuf bytes.Buffer + errBuf bytes.Buffer + ) + + err = s.dkrPool.Client.StartExec(exec.ID, docker.StartExecOptions{ + Context: ctx, + Detach: false, + OutputStream: &outBuf, + ErrorStream: &errBuf, + }) + s.Require().NoErrorf( + err, + "failed connect chains; stdout: %s, stderr: %s", outBuf.String(), errBuf.String(), + ) + + s.Require().Containsf( + errBuf.String(), + "successfully opened init channel", + "failed to connect chains via IBC: %s", errBuf.String(), + ) + + s.T().Logf("connected %s and %s chains via IBC", s.chainA.id, s.chainB.id) +} + +func (s *IntegrationTestSuite) sendIBC(srcChainID, dstChainID, recipient string, token sdk.Coin) { + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + s.T().Logf("sending %s from %s to %s (%s)", token, srcChainID, dstChainID, recipient) + + exec, err := s.dkrPool.Client.CreateExec(docker.CreateExecOptions{ + Context: ctx, + AttachStdout: true, + AttachStderr: true, + Container: s.hermesResource.Container.ID, + User: "root", + Cmd: []string{ + "hermes", + "tx", + "raw", + "ft-transfer", + dstChainID, + srcChainID, + "transfer", // source chain port ID + "channel-0", // since only one connection/channel exists, assume 0 + token.Amount.String(), + fmt.Sprintf("--denom=%s", token.Denom), + fmt.Sprintf("--receiver=%s", recipient), + "--timeout-height-offset=1000", + }, + }) + s.Require().NoError(err) + + var ( + outBuf bytes.Buffer + errBuf bytes.Buffer + ) + + err = s.dkrPool.Client.StartExec(exec.ID, docker.StartExecOptions{ + Context: ctx, + Detach: false, + OutputStream: &outBuf, + ErrorStream: &errBuf, + }) + s.Require().NoErrorf( + err, + "failed to send IBC tokens; stdout: %s, stderr: %s", outBuf.String(), errBuf.String(), + ) + + s.T().Log("successfully sent IBC tokens") +} diff --git a/tests/e2e/scripts/hermes_bootstrap.sh b/tests/e2e/scripts/hermes_bootstrap.sh new file mode 100644 index 00000000000..7295a8e14ec --- /dev/null +++ b/tests/e2e/scripts/hermes_bootstrap.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +set -ex + +# initialize Hermes relayer configuration +mkdir -p /root/.hermes/ +touch /root/.hermes/config.toml + +# setup Hermes relayer configuration +tee /root/.hermes/config.toml < Date: Sun, 24 Apr 2022 15:13:20 -0400 Subject: [PATCH 4/9] missing e2e ci job --- .github/workflows/test.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6086098d5d1..358b567039c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,3 +20,25 @@ jobs: run: go test -mod=readonly -timeout 30m -coverprofile=coverage.txt -tags='norace' -covermode=atomic `go list ./... | grep -E -v 'simapp|e2e'` - name: Codecov uses: codecov/codecov-action@v1.5.2 + test-e2e: + runs-on: ubuntu-latest + timeout-minutes: 25 + steps: + - uses: actions/setup-go@v2.2.0 + with: + go-version: 1.17 + - uses: actions/checkout@v2 + - uses: technote-space/get-diff-action@v6.0.1 + with: + PATTERNS: | + **/**.go + go.mod + go.sum + - name: Build Docker Image + run: | + make docker-build-debug + if: env.GIT_DIFF + - name: Test E2E + run: | + make test-e2e + if: env.GIT_DIFF From 1b94ed6a4b0683ff82b1e27d3979bb97a06be093 Mon Sep 17 00:00:00 2001 From: Roman <34196718+p0mvn@users.noreply.github.com> Date: Wed, 6 Apr 2022 09:45:14 -0700 Subject: [PATCH 5/9] cleanup Makefile and ci workflows (#1203) * cleanup makefile and ci workflows * update changelog * fix sim test * fix makefile and rename docker repo --- .github/workflows/sim.yml | 3 ++- .github/workflows/test.yml | 3 ++- Makefile | 18 +++++++++++++----- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/workflows/sim.yml b/.github/workflows/sim.yml index 04616183fa8..cf2b59c99dd 100644 --- a/.github/workflows/sim.yml +++ b/.github/workflows/sim.yml @@ -17,4 +17,5 @@ jobs: - name: Display go version run: go version - name: Run simulation - run: go test ./simapp + run: | + make test-sim diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 358b567039c..f91f4bd472d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,8 @@ jobs: - name: Display go version run: go version - name: Run all tests - run: go test -mod=readonly -timeout 30m -coverprofile=coverage.txt -tags='norace' -covermode=atomic `go list ./... | grep -E -v 'simapp|e2e'` + run: | + make test-cover - name: Codecov uses: codecov/codecov-action@v1.5.2 test-e2e: diff --git a/Makefile b/Makefile index 737f32c6c4e..f35ae653863 100644 --- a/Makefile +++ b/Makefile @@ -207,6 +207,11 @@ sync-docs: ### Tests & Simulation ### ############################################################################### +PACKAGES_UNIT=$(shell go list ./... | grep -E -v 'simapp|e2e') +PACKAGES_E2E=$(shell go list ./... | grep '/e2e') +PACKAGES_SIM=$(shell go list ./... | grep '/simapp') +TEST_PACKAGES=./... + include sims.mk test: test-unit test-build @@ -214,19 +219,22 @@ test: test-unit test-build test-all: check test-race test-cover test-unit: - @VERSION=$(VERSION) go test -mod=readonly -tags='ledger test_ledger_mock norace' ./... + @VERSION=$(VERSION) go test -mod=readonly -tags='ledger test_ledger_mock norace' $(PACKAGES_UNIT) test-race: - @VERSION=$(VERSION) go test -mod=readonly -race -tags='ledger test_ledger_mock' ./... + @VERSION=$(VERSION) go test -mod=readonly -race -tags='ledger test_ledger_mock' $(PACKAGES_UNIT) test-cover: - @go test -mod=readonly -timeout 30m -coverprofile=coverage.txt -covermode=atomic -tags='ledger test_ledger_mock' ./... + @VERSION=$(VERSION) go test -mod=readonly -timeout 30m -coverprofile=coverage.txt -tags='norace' -covermode=atomic $(PACKAGES_UNIT) + +test-sim: + @VERSION=$(VERSION) go test -mod=readonly $(PACKAGES_SIM) test-e2e: - @VERSION=$(VERSION) go test -mod=readonly -timeout=25m -v ./tests/e2e + @VERSION=$(VERSION) go test -mod=readonly -timeout=25m -v $(PACKAGES_E2E) benchmark: - @go test -mod=readonly -bench=. ./... + @go test -mod=readonly -bench=. $(PACKAGES_UNIT) docker-build-debug: @docker build -t osmosis:debug --build-arg BASE_IMG_TAG=debug -f Dockerfile . From c44854976b3dff503da55d651567a8812bbd8394 Mon Sep 17 00:00:00 2001 From: Roman <34196718+p0mvn@users.noreply.github.com> Date: Thu, 7 Apr 2022 14:16:54 -0700 Subject: [PATCH 6/9] fix make test-cover (#1219) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f35ae653863..bb5ef93ab72 100644 --- a/Makefile +++ b/Makefile @@ -225,7 +225,7 @@ test-race: @VERSION=$(VERSION) go test -mod=readonly -race -tags='ledger test_ledger_mock' $(PACKAGES_UNIT) test-cover: - @VERSION=$(VERSION) go test -mod=readonly -timeout 30m -coverprofile=coverage.txt -tags='norace' -covermode=atomic $(PACKAGES_UNIT) + @VERSION=$(VERSION) go test -mod=readonly -timeout 30m -coverprofile=coverage.txt -tags='norace' -covermode=atomic $(PACKAGES_UNIT) test-sim: @VERSION=$(VERSION) go test -mod=readonly $(PACKAGES_SIM) From 6b6d5b544f5fc7d35ec003ef5af465f0888c4f30 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 22 Apr 2022 21:24:16 -0400 Subject: [PATCH 7/9] refactor: begin modularizing e2e tests in preparation for upgrade (#1293) * begin modularizing e2e test in preparation for upgrade * rename common package to util * move chain related constants from util to chain package * fix genesis.go * exctract initNodes into the genesis package * remove genesis package, move all logic to chain * continue cleaning up chain package and refactoring e2e * store chains in a slice * reuse common cdc from util package * lexicographical reorder of functions in config.go of chain package * clean up names --- tests/e2e/chain.go | 125 --------- tests/e2e/chain/chain.go | 94 +++++++ tests/e2e/{util.go => chain/chain_util.go} | 14 +- tests/e2e/chain/config.go | 300 ++++++++++++++++++++ tests/e2e/chain/main.go | 18 ++ tests/e2e/{ => chain}/validator.go | 185 ++++++++----- tests/e2e/e2e_setup_test.go | 301 +++++---------------- tests/e2e/e2e_test.go | 29 +- tests/e2e/e2e_util_test.go | 8 +- tests/e2e/genesis.go | 110 -------- tests/e2e/keys.go | 56 ---- tests/e2e/scripts/hermes_bootstrap.sh | 8 +- tests/e2e/util/codec.go | 40 +++ tests/e2e/{ => util}/io.go | 6 +- 14 files changed, 672 insertions(+), 622 deletions(-) delete mode 100644 tests/e2e/chain.go create mode 100644 tests/e2e/chain/chain.go rename tests/e2e/{util.go => chain/chain_util.go} (66%) create mode 100644 tests/e2e/chain/config.go create mode 100644 tests/e2e/chain/main.go rename tests/e2e/{ => chain}/validator.go (69%) delete mode 100644 tests/e2e/genesis.go delete mode 100644 tests/e2e/keys.go create mode 100644 tests/e2e/util/codec.go rename tests/e2e/{ => util}/io.go (84%) diff --git a/tests/e2e/chain.go b/tests/e2e/chain.go deleted file mode 100644 index a5eadfe4230..00000000000 --- a/tests/e2e/chain.go +++ /dev/null @@ -1,125 +0,0 @@ -package e2e - -import ( - "fmt" - "io/ioutil" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - - osmosisApp "github.com/osmosis-labs/osmosis/v7/app" - "github.com/osmosis-labs/osmosis/v7/app/params" -) - -const ( - keyringPassphrase = "testpassphrase" - keyringAppName = "testnet" -) - -var ( - encodingConfig params.EncodingConfig - cdc codec.Codec -) - -func init() { - encodingConfig = osmosisApp.MakeEncodingConfig() - - encodingConfig.InterfaceRegistry.RegisterImplementations( - (*sdk.Msg)(nil), - &stakingtypes.MsgCreateValidator{}, - ) - encodingConfig.InterfaceRegistry.RegisterImplementations( - (*cryptotypes.PubKey)(nil), - &secp256k1.PubKey{}, - &ed25519.PubKey{}, - ) - - cdc = encodingConfig.Marshaler -} - -type chain struct { - dataDir string - id string - validators []*validator -} - -func newChain(id string) (*chain, error) { - tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-") - if err != nil { - return nil, err - } - - return &chain{ - id: id, - dataDir: tmpDir, - }, nil -} - -func (c *chain) configDir() string { - return fmt.Sprintf("%s/%s", c.dataDir, c.id) -} - -func (c *chain) createAndInitValidators(count int) error { - for i := 0; i < count; i++ { - node := c.createValidator(i) - - // generate genesis files - if err := node.init(); err != nil { - return err - } - - c.validators = append(c.validators, node) - - // create keys - if err := node.createKey("val"); err != nil { - return err - } - if err := node.createNodeKey(); err != nil { - return err - } - if err := node.createConsensusKey(); err != nil { - return err - } - } - - return nil -} - -func (c *chain) createAndInitValidatorsWithMnemonics(count int, mnemonics []string) error { - for i := 0; i < count; i++ { - // create node - node := c.createValidator(i) - - // generate genesis files - if err := node.init(); err != nil { - return err - } - - c.validators = append(c.validators, node) - - // create keys - if err := node.createKeyFromMnemonic("val", mnemonics[i]); err != nil { - return err - } - if err := node.createNodeKey(); err != nil { - return err - } - if err := node.createConsensusKey(); err != nil { - return err - } - } - - return nil -} - -func (c *chain) createValidator(index int) *validator { - return &validator{ - chain: c, - index: index, - moniker: fmt.Sprintf("%s-osmosis-%d", c.id, index), - } -} diff --git a/tests/e2e/chain/chain.go b/tests/e2e/chain/chain.go new file mode 100644 index 00000000000..b43bbbf5ce9 --- /dev/null +++ b/tests/e2e/chain/chain.go @@ -0,0 +1,94 @@ +package chain + +import ( + "fmt" + "io/ioutil" +) + +const ( + keyringPassphrase = "testpassphrase" + keyringAppName = "testnet" +) + +type Chain struct { + DataDir string + Id string + Validators []*Validator +} + +func new(id string) (*Chain, error) { + tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-") + if err != nil { + return nil, err + } + + return &Chain{ + Id: id, + DataDir: tmpDir, + }, nil +} + +func (c *Chain) configDir() string { + return fmt.Sprintf("%s/%s", c.DataDir, c.Id) +} + +func (c *Chain) createAndInitValidators(count int) error { + for i := 0; i < count; i++ { + node := c.createValidator(i) + + // generate genesis files + if err := node.init(); err != nil { + return err + } + + c.Validators = append(c.Validators, node) + + // create keys + if err := node.createKey("val"); err != nil { + return err + } + if err := node.createNodeKey(); err != nil { + return err + } + if err := node.createConsensusKey(); err != nil { + return err + } + } + + return nil +} + +func (c *Chain) createAndInitValidatorsWithMnemonics(count int, mnemonics []string) error { + for i := 0; i < count; i++ { + // create node + node := c.createValidator(i) + + // generate genesis files + if err := node.init(); err != nil { + return err + } + + c.Validators = append(c.Validators, node) + + // create keys + if err := node.createKeyFromMnemonic("val", mnemonics[i]); err != nil { + return err + } + if err := node.createNodeKey(); err != nil { + return err + } + if err := node.createConsensusKey(); err != nil { + return err + } + } + + return nil +} + +func (c *Chain) createValidator(index int) *Validator { + return &Validator{ + chain: c, + index: index, + moniker: fmt.Sprintf("%s-osmosis-%d", c.Id, index), + } +} diff --git a/tests/e2e/util.go b/tests/e2e/chain/chain_util.go similarity index 66% rename from tests/e2e/util.go rename to tests/e2e/chain/chain_util.go index 5ee776d0c02..f780976e312 100644 --- a/tests/e2e/util.go +++ b/tests/e2e/chain/chain_util.go @@ -1,39 +1,41 @@ -package e2e +package chain import ( "fmt" "github.com/cosmos/cosmos-sdk/codec/unknownproto" sdktx "github.com/cosmos/cosmos-sdk/types/tx" + + "github.com/osmosis-labs/osmosis/v7/tests/e2e/util" ) func decodeTx(txBytes []byte) (*sdktx.Tx, error) { var raw sdktx.TxRaw // reject all unknown proto fields in the root TxRaw - err := unknownproto.RejectUnknownFieldsStrict(txBytes, &raw, encodingConfig.InterfaceRegistry) + err := unknownproto.RejectUnknownFieldsStrict(txBytes, &raw, util.EncodingConfig.InterfaceRegistry) if err != nil { return nil, fmt.Errorf("failed to reject unknown fields: %w", err) } - if err := cdc.Unmarshal(txBytes, &raw); err != nil { + if err := util.Cdc.Unmarshal(txBytes, &raw); err != nil { return nil, err } var body sdktx.TxBody - if err := cdc.Unmarshal(raw.BodyBytes, &body); err != nil { + if err := util.Cdc.Unmarshal(raw.BodyBytes, &body); err != nil { return nil, fmt.Errorf("failed to decode tx: %w", err) } var authInfo sdktx.AuthInfo // reject all unknown proto fields in AuthInfo - err = unknownproto.RejectUnknownFieldsStrict(raw.AuthInfoBytes, &authInfo, encodingConfig.InterfaceRegistry) + err = unknownproto.RejectUnknownFieldsStrict(raw.AuthInfoBytes, &authInfo, util.EncodingConfig.InterfaceRegistry) if err != nil { return nil, fmt.Errorf("failed to reject unknown fields: %w", err) } - if err := cdc.Unmarshal(raw.AuthInfoBytes, &authInfo); err != nil { + if err := util.Cdc.Unmarshal(raw.AuthInfoBytes, &authInfo); err != nil { return nil, fmt.Errorf("failed to decode auth info: %w", err) } diff --git a/tests/e2e/chain/config.go b/tests/e2e/chain/config.go new file mode 100644 index 00000000000..a5abf60041e --- /dev/null +++ b/tests/e2e/chain/config.go @@ -0,0 +1,300 @@ +package chain + +import ( + "encoding/json" + "fmt" + "path/filepath" + "strings" + + "github.com/cosmos/cosmos-sdk/server" + srvconfig "github.com/cosmos/cosmos-sdk/server/config" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + "github.com/spf13/viper" + tmconfig "github.com/tendermint/tendermint/config" + tmjson "github.com/tendermint/tendermint/libs/json" + + "github.com/osmosis-labs/osmosis/v7/tests/e2e/util" +) + +const ( + // common + OsmoDenom = "uosmo" + StakeDenom = "stake" + IbcDenom = "ibc/ED07A3391A112B175915CD8FAF43A2DA8E4790EDE12566649D0C2F97716B8518" + MinGasPrice = "0.000" + IbcSendAmount = 3300000000 + // chainA + ChainAID = "osmo-test-a" + OsmoBalanceA = 200000000000 + StakeBalanceA = 110000000000 + StakeAmountA = 100000000000 + // chainB + ChainBID = "osmo-test-b" + OsmoBalanceB = 500000000000 + StakeBalanceB = 440000000000 + StakeAmountB = 400000000000 +) + +var ( + StakeAmountIntA = sdk.NewInt(StakeAmountA) + StakeAmountCoinA = sdk.NewCoin(StakeDenom, StakeAmountIntA) + StakeAmountIntB = sdk.NewInt(StakeAmountB) + StakeAmountCoinB = sdk.NewCoin(StakeDenom, StakeAmountIntB) + + InitBalanceStrA = fmt.Sprintf("%d%s,%d%s", OsmoBalanceA, OsmoDenom, StakeBalanceA, StakeDenom) + InitBalanceStrB = fmt.Sprintf("%d%s,%d%s", OsmoBalanceB, OsmoDenom, StakeBalanceB, StakeDenom) +) + +func addAccount(path, moniker, amountStr string, accAddr sdk.AccAddress) error { + serverCtx := server.NewDefaultContext() + config := serverCtx.Config + + config.SetRoot(path) + config.Moniker = moniker + + coins, err := sdk.ParseCoinsNormalized(amountStr) + if err != nil { + return fmt.Errorf("failed to parse coins: %w", err) + } + + balances := banktypes.Balance{Address: accAddr.String(), Coins: coins.Sort()} + genAccount := authtypes.NewBaseAccount(accAddr, nil, 0, 0) + + genFile := config.GenesisFile() + appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile) + if err != nil { + return fmt.Errorf("failed to unmarshal genesis state: %w", err) + } + + authGenState := authtypes.GetGenesisStateFromAppState(util.Cdc, appState) + + accs, err := authtypes.UnpackAccounts(authGenState.Accounts) + if err != nil { + return fmt.Errorf("failed to get accounts from any: %w", err) + } + + if accs.Contains(accAddr) { + return fmt.Errorf("failed to add account to genesis state; account already exists: %s", accAddr) + } + + // Add the new account to the set of genesis accounts and sanitize the + // accounts afterwards. + accs = append(accs, genAccount) + accs = authtypes.SanitizeGenesisAccounts(accs) + + genAccs, err := authtypes.PackAccounts(accs) + if err != nil { + return fmt.Errorf("failed to convert accounts into any's: %w", err) + } + + authGenState.Accounts = genAccs + + authGenStateBz, err := util.Cdc.MarshalJSON(&authGenState) + if err != nil { + return fmt.Errorf("failed to marshal auth genesis state: %w", err) + } + + appState[authtypes.ModuleName] = authGenStateBz + + bankGenState := banktypes.GetGenesisStateFromAppState(util.Cdc, appState) + bankGenState.Balances = append(bankGenState.Balances, balances) + bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances) + + bankGenStateBz, err := util.Cdc.MarshalJSON(bankGenState) + if err != nil { + return fmt.Errorf("failed to marshal bank genesis state: %w", err) + } + + appState[banktypes.ModuleName] = bankGenStateBz + + appStateJSON, err := json.Marshal(appState) + if err != nil { + return fmt.Errorf("failed to marshal application genesis state: %w", err) + } + + genDoc.AppState = appStateJSON + return genutil.ExportGenesisFile(genDoc, genFile) +} + +func initGenesis(c *Chain) error { + serverCtx := server.NewDefaultContext() + config := serverCtx.Config + + config.SetRoot(c.Validators[0].ConfigDir()) + config.Moniker = c.Validators[0].GetMoniker() + + genFilePath := config.GenesisFile() + appGenState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFilePath) + if err != nil { + return err + } + + var bankGenState banktypes.GenesisState + if err := util.Cdc.UnmarshalJSON(appGenState[banktypes.ModuleName], &bankGenState); err != nil { + return err + } + + bankGenState.DenomMetadata = append(bankGenState.DenomMetadata, banktypes.Metadata{ + Description: "An example stable token", + Display: OsmoDenom, + Base: OsmoDenom, + Symbol: OsmoDenom, + Name: OsmoDenom, + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: OsmoDenom, + Exponent: 0, + }, + }, + }) + + bz, err := util.Cdc.MarshalJSON(&bankGenState) + if err != nil { + return err + } + appGenState[banktypes.ModuleName] = bz + + var genUtilGenState genutiltypes.GenesisState + if err := util.Cdc.UnmarshalJSON(appGenState[genutiltypes.ModuleName], &genUtilGenState); err != nil { + return err + } + + // generate genesis txs + genTxs := make([]json.RawMessage, len(c.Validators)) + for i, val := range c.Validators { + stakeAmountCoin := StakeAmountCoinA + if c.Id != ChainAID { + stakeAmountCoin = StakeAmountCoinB + } + createValmsg, err := val.buildCreateValidatorMsg(stakeAmountCoin) + if err != nil { + return err + } + + signedTx, err := val.signMsg(createValmsg) + if err != nil { + return err + } + + txRaw, err := util.Cdc.MarshalJSON(signedTx) + if err != nil { + return err + } + + genTxs[i] = txRaw + } + + genUtilGenState.GenTxs = genTxs + + bz, err = util.Cdc.MarshalJSON(&genUtilGenState) + if err != nil { + return err + } + appGenState[genutiltypes.ModuleName] = bz + + bz, err = json.MarshalIndent(appGenState, "", " ") + if err != nil { + return err + } + + genDoc.AppState = bz + + bz, err = tmjson.MarshalIndent(genDoc, "", " ") + if err != nil { + return err + } + + // write the updated genesis file to each validator + for _, val := range c.Validators { + if err := util.WriteFile(filepath.Join(val.ConfigDir(), "config", "genesis.json"), bz); err != nil { + return err + } + } + return nil +} + +func initNodes(c *Chain) error { + if err := c.createAndInitValidators(2); err != nil { + return err + } + + // initialize a genesis file for the first validator + val0ConfigDir := c.Validators[0].ConfigDir() + for _, val := range c.Validators { + if c.Id == ChainAID { + if err := addAccount(val0ConfigDir, "", InitBalanceStrA, val.GetKeyInfo().GetAddress()); err != nil { + return err + } + } else if c.Id == ChainBID { + if err := addAccount(val0ConfigDir, "", InitBalanceStrB, val.GetKeyInfo().GetAddress()); err != nil { + return err + } + } + } + + // copy the genesis file to the remaining validators + for _, val := range c.Validators[1:] { + _, err := util.CopyFile( + filepath.Join(val0ConfigDir, "config", "genesis.json"), + filepath.Join(val.ConfigDir(), "config", "genesis.json"), + ) + if err != nil { + return err + } + } + return nil +} + +func initValidatorConfigs(c *Chain) error { + for i, val := range c.Validators { + tmCfgPath := filepath.Join(val.ConfigDir(), "config", "config.toml") + + vpr := viper.New() + vpr.SetConfigFile(tmCfgPath) + if err := vpr.ReadInConfig(); err != nil { + return err + } + + valConfig := &tmconfig.Config{} + if err := vpr.Unmarshal(valConfig); err != nil { + return err + } + + valConfig.P2P.ListenAddress = "tcp://0.0.0.0:26656" + valConfig.P2P.AddrBookStrict = false + valConfig.P2P.ExternalAddress = fmt.Sprintf("%s:%d", val.InstanceName(), 26656) + valConfig.RPC.ListenAddress = "tcp://0.0.0.0:26657" + valConfig.StateSync.Enable = false + valConfig.LogLevel = "info" + + var peers []string + + for j := 0; j < len(c.Validators); j++ { + if i == j { + continue + } + + peer := c.Validators[j] + peerID := fmt.Sprintf("%s@%s%d:26656", peer.getNodeKey().ID(), peer.GetMoniker(), j) + peers = append(peers, peerID) + } + + valConfig.P2P.PersistentPeers = strings.Join(peers, ",") + + tmconfig.WriteConfigFile(tmCfgPath, valConfig) + + // set application configuration + appCfgPath := filepath.Join(val.ConfigDir(), "config", "app.toml") + + appConfig := srvconfig.DefaultConfig() + appConfig.API.Enable = true + appConfig.MinGasPrices = fmt.Sprintf("%s%s", MinGasPrice, OsmoDenom) + + srvconfig.WriteConfigFile(appCfgPath, appConfig) + } + return nil +} diff --git a/tests/e2e/chain/main.go b/tests/e2e/chain/main.go new file mode 100644 index 00000000000..3f9a341d638 --- /dev/null +++ b/tests/e2e/chain/main.go @@ -0,0 +1,18 @@ +package chain + +func Init(id string) (*Chain, error) { + chain, err := new(id) + if err != nil { + return nil, err + } + if err := initNodes(chain); err != nil { + return nil, err + } + if err := initGenesis(chain); err != nil { + return nil, err + } + if err := initValidatorConfigs(chain); err != nil { + return nil, err + } + return chain, nil +} diff --git a/tests/e2e/validator.go b/tests/e2e/chain/validator.go similarity index 69% rename from tests/e2e/validator.go rename to tests/e2e/chain/validator.go index 6c7941614c6..570463a66cd 100644 --- a/tests/e2e/validator.go +++ b/tests/e2e/chain/validator.go @@ -1,4 +1,4 @@ -package e2e +package chain import ( "encoding/json" @@ -19,16 +19,19 @@ import ( authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/genutil" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/cosmos/go-bip39" tmcfg "github.com/tendermint/tendermint/config" tmos "github.com/tendermint/tendermint/libs/os" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/privval" + tmtypes "github.com/tendermint/tendermint/types" osmosisApp "github.com/osmosis-labs/osmosis/v7/app" + "github.com/osmosis-labs/osmosis/v7/tests/e2e/util" ) -type validator struct { - chain *chain +type Validator struct { + chain *Chain index int moniker string mnemonic string @@ -39,57 +42,66 @@ type validator struct { nodeKey p2p.NodeKey } -func (v *validator) instanceName() string { +func (v *Validator) InstanceName() string { return fmt.Sprintf("%s%d", v.moniker, v.index) } -func (v *validator) configDir() string { - return fmt.Sprintf("%s/%s", v.chain.configDir(), v.instanceName()) +func (v *Validator) ConfigDir() string { + return fmt.Sprintf("%s/%s", v.chain.configDir(), v.InstanceName()) } -func (v *validator) createConfig() error { - p := path.Join(v.configDir(), "config") - return os.MkdirAll(p, 0755) +func (v *Validator) GetKeyInfo() keyring.Info { + return v.keyInfo } -func (v *validator) init() error { - if err := v.createConfig(); err != nil { - return err - } +func (v *Validator) GetMoniker() string { + return v.moniker +} - serverCtx := server.NewDefaultContext() - config := serverCtx.Config +func (v *Validator) GetMnemonic() string { + return v.mnemonic +} - config.SetRoot(v.configDir()) - config.Moniker = v.moniker +func (v *Validator) GetIndex() int { + return v.index +} - genDoc, err := getGenDoc(v.configDir()) - if err != nil { - return err +func (v *Validator) buildCreateValidatorMsg(amount sdk.Coin) (sdk.Msg, error) { + description := stakingtypes.NewDescription(v.moniker, "", "", "", "") + commissionRates := stakingtypes.CommissionRates{ + Rate: sdk.MustNewDecFromStr("0.1"), + MaxRate: sdk.MustNewDecFromStr("0.2"), + MaxChangeRate: sdk.MustNewDecFromStr("0.01"), } - appState, err := json.MarshalIndent(osmosisApp.ModuleBasics.DefaultGenesis(cdc), "", " ") + // get the initial validator min self delegation + minSelfDelegation, _ := sdk.NewIntFromString("1") + + valPubKey, err := cryptocodec.FromTmPubKeyInterface(v.consensusKey.PubKey) if err != nil { - return fmt.Errorf("failed to JSON encode app genesis state: %w", err) + return nil, err } - genDoc.ChainID = v.chain.id - genDoc.Validators = nil - genDoc.AppState = appState - - if err = genutil.ExportGenesisFile(genDoc, config.GenesisFile()); err != nil { - return fmt.Errorf("failed to export app genesis state: %w", err) - } + return stakingtypes.NewMsgCreateValidator( + sdk.ValAddress(v.keyInfo.GetAddress()), + valPubKey, + amount, + description, + commissionRates, + minSelfDelegation, + ) +} - tmcfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) - return nil +func (v *Validator) createConfig() error { + p := path.Join(v.ConfigDir(), "config") + return os.MkdirAll(p, 0o755) } -func (v *validator) createNodeKey() error { +func (v *Validator) createNodeKey() error { serverCtx := server.NewDefaultContext() config := serverCtx.Config - config.SetRoot(v.configDir()) + config.SetRoot(v.ConfigDir()) config.Moniker = v.moniker nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) @@ -101,11 +113,11 @@ func (v *validator) createNodeKey() error { return nil } -func (v *validator) createConsensusKey() error { +func (v *Validator) createConsensusKey() error { serverCtx := server.NewDefaultContext() config := serverCtx.Config - config.SetRoot(v.configDir()) + config.SetRoot(v.ConfigDir()) config.Moniker = v.moniker pvKeyFile := config.PrivValidatorKeyFile() @@ -124,8 +136,8 @@ func (v *validator) createConsensusKey() error { return nil } -func (v *validator) createKeyFromMnemonic(name, mnemonic string) error { - kb, err := keyring.New(keyringAppName, keyring.BackendTest, v.configDir(), nil) +func (v *Validator) createKeyFromMnemonic(name, mnemonic string) error { + kb, err := keyring.New(keyringAppName, keyring.BackendTest, v.ConfigDir(), nil) if err != nil { return err } @@ -158,7 +170,7 @@ func (v *validator) createKeyFromMnemonic(name, mnemonic string) error { return nil } -func (v *validator) createKey(name string) error { +func (v *Validator) createKey(name string) error { mnemonic, err := createMnemonic() if err != nil { return err @@ -167,45 +179,94 @@ func (v *validator) createKey(name string) error { return v.createKeyFromMnemonic(name, mnemonic) } -func (v *validator) buildCreateValidatorMsg(amount sdk.Coin) (sdk.Msg, error) { - description := stakingtypes.NewDescription(v.moniker, "", "", "", "") - commissionRates := stakingtypes.CommissionRates{ - Rate: sdk.MustNewDecFromStr("0.1"), - MaxRate: sdk.MustNewDecFromStr("0.2"), - MaxChangeRate: sdk.MustNewDecFromStr("0.01"), +func (v *Validator) getNodeKey() *p2p.NodeKey { + return &v.nodeKey +} + +func (v *Validator) getGenesisDoc() (*tmtypes.GenesisDoc, error) { + serverCtx := server.NewDefaultContext() + config := serverCtx.Config + config.SetRoot(v.ConfigDir()) + + genFile := config.GenesisFile() + doc := &tmtypes.GenesisDoc{} + + if _, err := os.Stat(genFile); err != nil { + if !os.IsNotExist(err) { + return nil, err + } + } else { + var err error + + doc, err = tmtypes.GenesisDocFromFile(genFile) + if err != nil { + return nil, fmt.Errorf("failed to read genesis doc from file: %w", err) + } } - // get the initial validator min self delegation - minSelfDelegation, _ := sdk.NewIntFromString("1") + return doc, nil +} - valPubKey, err := cryptocodec.FromTmPubKeyInterface(v.consensusKey.PubKey) +func (v *Validator) init() error { + if err := v.createConfig(); err != nil { + return err + } + + serverCtx := server.NewDefaultContext() + config := serverCtx.Config + + config.SetRoot(v.ConfigDir()) + config.Moniker = v.moniker + + genDoc, err := v.getGenesisDoc() if err != nil { - return nil, err + return err } - return stakingtypes.NewMsgCreateValidator( - sdk.ValAddress(v.keyInfo.GetAddress()), - valPubKey, - amount, - description, - commissionRates, - minSelfDelegation, - ) + appState, err := json.MarshalIndent(osmosisApp.ModuleBasics.DefaultGenesis(util.Cdc), "", " ") + if err != nil { + return fmt.Errorf("failed to JSON encode app genesis state: %w", err) + } + + genDoc.ChainID = v.chain.Id + genDoc.Validators = nil + genDoc.AppState = appState + + if err = genutil.ExportGenesisFile(genDoc, config.GenesisFile()); err != nil { + return fmt.Errorf("failed to export app genesis state: %w", err) + } + + tmcfg.WriteConfigFile(filepath.Join(config.RootDir, "config", "config.toml"), config) + return nil +} + +func createMnemonic() (string, error) { + entropySeed, err := bip39.NewEntropy(256) + if err != nil { + return "", err + } + + mnemonic, err := bip39.NewMnemonic(entropySeed) + if err != nil { + return "", err + } + + return mnemonic, nil } -func (v *validator) signMsg(msgs ...sdk.Msg) (*sdktx.Tx, error) { - txBuilder := encodingConfig.TxConfig.NewTxBuilder() +func (v *Validator) signMsg(msgs ...sdk.Msg) (*sdktx.Tx, error) { + txBuilder := util.EncodingConfig.TxConfig.NewTxBuilder() if err := txBuilder.SetMsgs(msgs...); err != nil { return nil, err } - txBuilder.SetMemo(fmt.Sprintf("%s@%s:26656", v.nodeKey.ID(), v.instanceName())) + txBuilder.SetMemo(fmt.Sprintf("%s@%s:26656", v.nodeKey.ID(), v.InstanceName())) txBuilder.SetFeeAmount(sdk.NewCoins()) txBuilder.SetGasLimit(200000) signerData := authsigning.SignerData{ - ChainID: v.chain.id, + ChainID: v.chain.Id, AccountNumber: 0, Sequence: 0, } @@ -231,7 +292,7 @@ func (v *validator) signMsg(msgs ...sdk.Msg) (*sdktx.Tx, error) { return nil, err } - bytesToSign, err := encodingConfig.TxConfig.SignModeHandler().GetSignBytes( + bytesToSign, err := util.EncodingConfig.TxConfig.SignModeHandler().GetSignBytes( txsigning.SignMode_SIGN_MODE_DIRECT, signerData, txBuilder.GetTx(), @@ -258,7 +319,7 @@ func (v *validator) signMsg(msgs ...sdk.Msg) (*sdktx.Tx, error) { } signedTx := txBuilder.GetTx() - bz, err := encodingConfig.TxConfig.TxEncoder()(signedTx) + bz, err := util.EncodingConfig.TxConfig.TxEncoder()(signedTx) if err != nil { return nil, err } diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 53bf8cbd67c..2885c31a330 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -11,58 +11,24 @@ import ( "path" "path/filepath" "strconv" - "strings" "testing" "time" - "github.com/cosmos/cosmos-sdk/server" - srvconfig "github.com/cosmos/cosmos-sdk/server/config" - sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/ory/dockertest/v3" "github.com/ory/dockertest/v3/docker" - "github.com/spf13/viper" "github.com/stretchr/testify/suite" - tmconfig "github.com/tendermint/tendermint/config" - tmjson "github.com/tendermint/tendermint/libs/json" - rpchttp "github.com/tendermint/tendermint/rpc/client/http" -) -const ( - // common - osmoDenom = "uosmo" - stakeDenom = "stake" - ibcDenom = "ibc/ED07A3391A112B175915CD8FAF43A2DA8E4790EDE12566649D0C2F97716B8518" - minGasPrice = "0.000" - ibcSendAmount = 3300000000 - // chainA - chainAID = "osmo-test-a" - osmoBalanceA = 200000000000 - stakeBalanceA = 110000000000 - stakeAmountA = 100000000000 - // chainB - chainBID = "osmo-test-b" - osmoBalanceB = 500000000000 - stakeBalanceB = 440000000000 - stakeAmountB = 400000000000 -) + rpchttp "github.com/tendermint/tendermint/rpc/client/http" -var ( - initBalanceStrA = fmt.Sprintf("%d%s,%d%s", osmoBalanceA, osmoDenom, stakeBalanceA, stakeDenom) - initBalanceStrB = fmt.Sprintf("%d%s,%d%s", osmoBalanceB, osmoDenom, stakeBalanceB, stakeDenom) - stakeAmountIntA = sdk.NewInt(stakeAmountA) - stakeAmountCoinA = sdk.NewCoin(stakeDenom, stakeAmountIntA) - stakeAmountIntB = sdk.NewInt(stakeAmountB) - stakeAmountCoinB = sdk.NewCoin(stakeDenom, stakeAmountIntB) + "github.com/osmosis-labs/osmosis/v7/tests/e2e/chain" + "github.com/osmosis-labs/osmosis/v7/tests/e2e/util" ) type IntegrationTestSuite struct { suite.Suite tmpDirs []string - chainA *chain - chainB *chain + chains []*chain.Chain dkrPool *dockertest.Pool dkrNet *dockertest.Network hermesResource *dockertest.Resource @@ -76,39 +42,23 @@ func TestIntegrationTestSuite(t *testing.T) { func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up e2e integration test suite...") - var err error - s.chainA, err = newChain(chainAID) - s.Require().NoError(err) - - s.chainB, err = newChain(chainBID) - s.Require().NoError(err) - - s.dkrPool, err = dockertest.NewPool("") - s.Require().NoError(err) + s.chains = make([]*chain.Chain, 0, 2) - s.dkrNet, err = s.dkrPool.CreateNetwork(fmt.Sprintf("%s-%s-testnet", s.chainA.id, s.chainB.id)) - s.Require().NoError(err) - - s.valResources = make(map[string][]*dockertest.Resource) - - // The boostrapping phase is as follows: + // The e2e test flow is as follows: // - // 1. Initialize Osmosis validator nodes. - // 2. Create and initialize Osmosis validator genesis files (both chains) - // 3. Start both networks. - - s.T().Logf("starting e2e infrastructure for chain A; chain-id: %s; datadir: %s", s.chainA.id, s.chainA.dataDir) - s.initNodes(s.chainA) - s.initGenesis(s.chainA) - s.initValidatorConfigs(s.chainA) - s.runValidators(s.chainA, 0) - - s.T().Logf("starting e2e infrastructure for chain B; chain-id: %s; datadir: %s", s.chainB.id, s.chainB.dataDir) - s.initNodes(s.chainB) - s.initGenesis(s.chainB) - s.initValidatorConfigs(s.chainB) - s.runValidators(s.chainB, 10) - + // 1. Configure two chains - chan A and chain B. + // * For each chain, set up two validators + // * Initialize configs and genesis for all validators. + // 2. Start both networks. + // 3. Run IBC relayer betweeen the two chains. + // 4. Execute various e2e tests, including IBC. + s.configureChain(chain.ChainAID) + s.configureChain(chain.ChainBID) + + s.configureDockerResources() + + s.runValidators(s.chains[0], 0) + s.runValidators(s.chains[1], 10) s.runIBCRelayer() } @@ -134,177 +84,32 @@ func (s *IntegrationTestSuite) TearDownSuite() { s.Require().NoError(s.dkrPool.RemoveNetwork(s.dkrNet)) - os.RemoveAll(s.chainA.dataDir) - os.RemoveAll(s.chainB.dataDir) + for _, chain := range s.chains { + os.RemoveAll(chain.DataDir) + } for _, td := range s.tmpDirs { os.RemoveAll(td) } } -func (s *IntegrationTestSuite) initNodes(c *chain) { - s.Require().NoError(c.createAndInitValidators(2)) - - // initialize a genesis file for the first validator - val0ConfigDir := c.validators[0].configDir() - for _, val := range c.validators { - if c.id == chainAID { - s.Require().NoError( - addGenesisAccount(val0ConfigDir, "", initBalanceStrA, val.keyInfo.GetAddress()), - ) - } else if c.id == chainBID { - s.Require().NoError( - addGenesisAccount(val0ConfigDir, "", initBalanceStrB, val.keyInfo.GetAddress()), - ) - } - } - - // copy the genesis file to the remaining validators - for _, val := range c.validators[1:] { - _, err := copyFile( - filepath.Join(val0ConfigDir, "config", "genesis.json"), - filepath.Join(val.configDir(), "config", "genesis.json"), - ) - s.Require().NoError(err) - } -} - -func (s *IntegrationTestSuite) initGenesis(c *chain) { - serverCtx := server.NewDefaultContext() - config := serverCtx.Config - - config.SetRoot(c.validators[0].configDir()) - config.Moniker = c.validators[0].moniker - - genFilePath := config.GenesisFile() - appGenState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFilePath) - s.Require().NoError(err) - - var bankGenState banktypes.GenesisState - s.Require().NoError(cdc.UnmarshalJSON(appGenState[banktypes.ModuleName], &bankGenState)) - - bankGenState.DenomMetadata = append(bankGenState.DenomMetadata, banktypes.Metadata{ - Description: "An example stable token", - Display: osmoDenom, - Base: osmoDenom, - Symbol: osmoDenom, - Name: osmoDenom, - DenomUnits: []*banktypes.DenomUnit{ - { - Denom: osmoDenom, - Exponent: 0, - }, - }, - }) - - bz, err := cdc.MarshalJSON(&bankGenState) - s.Require().NoError(err) - appGenState[banktypes.ModuleName] = bz - - var genUtilGenState genutiltypes.GenesisState - s.Require().NoError(cdc.UnmarshalJSON(appGenState[genutiltypes.ModuleName], &genUtilGenState)) - - // generate genesis txs - genTxs := make([]json.RawMessage, len(c.validators)) - for i, val := range c.validators { - stakeAmountCoin := stakeAmountCoinA - if c.id != chainAID { - stakeAmountCoin = stakeAmountCoinB - } - createValmsg, err := val.buildCreateValidatorMsg(stakeAmountCoin) - s.Require().NoError(err) - - signedTx, err := val.signMsg(createValmsg) - s.Require().NoError(err) - - txRaw, err := cdc.MarshalJSON(signedTx) - s.Require().NoError(err) - - genTxs[i] = txRaw - } - - genUtilGenState.GenTxs = genTxs - - bz, err = cdc.MarshalJSON(&genUtilGenState) - s.Require().NoError(err) - appGenState[genutiltypes.ModuleName] = bz - - bz, err = json.MarshalIndent(appGenState, "", " ") - s.Require().NoError(err) - - genDoc.AppState = bz - - bz, err = tmjson.MarshalIndent(genDoc, "", " ") - s.Require().NoError(err) - - // write the updated genesis file to each validator - for _, val := range c.validators { - writeFile(filepath.Join(val.configDir(), "config", "genesis.json"), bz) - } -} - -func (s *IntegrationTestSuite) initValidatorConfigs(c *chain) { - for i, val := range c.validators { - tmCfgPath := filepath.Join(val.configDir(), "config", "config.toml") - - vpr := viper.New() - vpr.SetConfigFile(tmCfgPath) - s.Require().NoError(vpr.ReadInConfig()) - - valConfig := &tmconfig.Config{} - s.Require().NoError(vpr.Unmarshal(valConfig)) - - valConfig.P2P.ListenAddress = "tcp://0.0.0.0:26656" - valConfig.P2P.AddrBookStrict = false - valConfig.P2P.ExternalAddress = fmt.Sprintf("%s:%d", val.instanceName(), 26656) - valConfig.RPC.ListenAddress = "tcp://0.0.0.0:26657" - valConfig.StateSync.Enable = false - valConfig.LogLevel = "info" - - var peers []string - - for j := 0; j < len(c.validators); j++ { - if i == j { - continue - } - - peer := c.validators[j] - peerID := fmt.Sprintf("%s@%s%d:26656", peer.nodeKey.ID(), peer.moniker, j) - peers = append(peers, peerID) - } +func (s *IntegrationTestSuite) runValidators(c *chain.Chain, portOffset int) { + s.T().Logf("starting Osmosis %s validator containers...", c.Id) - valConfig.P2P.PersistentPeers = strings.Join(peers, ",") - - tmconfig.WriteConfigFile(tmCfgPath, valConfig) - - // set application configuration - appCfgPath := filepath.Join(val.configDir(), "config", "app.toml") - - appConfig := srvconfig.DefaultConfig() - appConfig.API.Enable = true - appConfig.MinGasPrices = fmt.Sprintf("%s%s", minGasPrice, osmoDenom) - - srvconfig.WriteConfigFile(appCfgPath, appConfig) - } -} - -func (s *IntegrationTestSuite) runValidators(c *chain, portOffset int) { - s.T().Logf("starting Osmosis %s validator containers...", c.id) - - s.valResources[c.id] = make([]*dockertest.Resource, len(c.validators)) - for i, val := range c.validators { + s.valResources[c.Id] = make([]*dockertest.Resource, len(c.Validators)) + for i, val := range c.Validators { runOpts := &dockertest.RunOptions{ - Name: val.instanceName(), + Name: val.InstanceName(), NetworkID: s.dkrNet.Network.ID, Mounts: []string{ - fmt.Sprintf("%s/:/osmosis/.osmosisd", val.configDir()), + fmt.Sprintf("%s/:/osmosis/.osmosisd", val.ConfigDir()), }, Repository: "osmosis", Tag: "debug", } // expose the first validator for debugging and communication - if val.index == 0 { + if val.GetIndex() == 0 { runOpts.PortBindings = map[docker.Port][]docker.PortBinding{ "1317/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 1317+portOffset)}}, "6060/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 6060+portOffset)}}, @@ -322,8 +127,8 @@ func (s *IntegrationTestSuite) runValidators(c *chain, portOffset int) { resource, err := s.dkrPool.RunWithOptions(runOpts, noRestart) s.Require().NoError(err) - s.valResources[c.id][i] = resource - s.T().Logf("started Osmosis %s validator container: %s", c.id, resource.Container.ID) + s.valResources[c.Id][i] = resource + s.T().Logf("started Osmosis %s validator container: %s", c.Id, resource.Container.ID) } rpcClient, err := rpchttp.New("tcp://localhost:26657", "/websocket") @@ -355,16 +160,16 @@ func (s *IntegrationTestSuite) runValidators(c *chain, portOffset int) { func (s *IntegrationTestSuite) runIBCRelayer() { s.T().Log("starting Hermes relayer container...") - tmpDir, err := ioutil.TempDir("", "gaia-e2e-testnet-hermes-") + tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-hermes-") s.Require().NoError(err) s.tmpDirs = append(s.tmpDirs, tmpDir) - gaiaAVal := s.chainA.validators[0] - gaiaBVal := s.chainB.validators[0] + osmoAVal := s.chains[0].Validators[0] + osmoBVal := s.chains[1].Validators[0] hermesCfgPath := path.Join(tmpDir, "hermes") - s.Require().NoError(os.MkdirAll(hermesCfgPath, 0755)) - _, err = copyFile( + s.Require().NoError(os.MkdirAll(hermesCfgPath, 0o755)) + _, err = util.CopyFile( filepath.Join("./scripts/", "hermes_bootstrap.sh"), filepath.Join(hermesCfgPath, "hermes_bootstrap.sh"), ) @@ -372,7 +177,7 @@ func (s *IntegrationTestSuite) runIBCRelayer() { s.hermesResource, err = s.dkrPool.RunWithOptions( &dockertest.RunOptions{ - Name: fmt.Sprintf("%s-%s-relayer", s.chainA.id, s.chainB.id), + Name: fmt.Sprintf("%s-%s-relayer", s.chains[0].Id, s.chains[1].Id), Repository: "osmolabs/hermes", Tag: "0.13.0", NetworkID: s.dkrNet.Network.ID, @@ -390,12 +195,12 @@ func (s *IntegrationTestSuite) runIBCRelayer() { "3031/tcp": {{HostIP: "", HostPort: "3031"}}, }, Env: []string{ - fmt.Sprintf("OSMO_A_E2E_CHAIN_ID=%s", s.chainA.id), - fmt.Sprintf("OSMO_B_E2E_CHAIN_ID=%s", s.chainB.id), - fmt.Sprintf("OSMO_A_E2E_VAL_MNEMONIC=%s", gaiaAVal.mnemonic), - fmt.Sprintf("OSMO_B_E2E_VAL_MNEMONIC=%s", gaiaBVal.mnemonic), - fmt.Sprintf("OSMO_A_E2E_VAL_HOST=%s", s.valResources[s.chainA.id][0].Container.Name[1:]), - fmt.Sprintf("OSMO_B_E2E_VAL_HOST=%s", s.valResources[s.chainB.id][0].Container.Name[1:]), + fmt.Sprintf("OSMO_A_E2E_CHAIN_ID=%s", s.chains[0].Id), + fmt.Sprintf("OSMO_B_E2E_CHAIN_ID=%s", s.chains[1].Id), + fmt.Sprintf("OSMO_A_E2E_VAL_MNEMONIC=%s", osmoAVal.GetMnemonic()), + fmt.Sprintf("OSMO_B_E2E_VAL_MNEMONIC=%s", osmoBVal.GetMnemonic()), + fmt.Sprintf("OSMO_A_E2E_VAL_HOST=%s", s.valResources[s.chains[0].Id][0].Container.Name[1:]), + fmt.Sprintf("OSMO_B_E2E_VAL_HOST=%s", s.valResources[s.chains[1].Id][0].Container.Name[1:]), }, Entrypoint: []string{ "sh", @@ -443,10 +248,28 @@ func (s *IntegrationTestSuite) runIBCRelayer() { // transport errors. time.Sleep(10 * time.Second) - // create the client, connection and channel between the two Gaia chains + // create the client, connection and channel between the two Osmosis chains s.connectIBCChains() } +func (s *IntegrationTestSuite) configureChain(chainId string) { + s.T().Logf("starting e2e infrastructure for chain-id: %s", chainId) + newChain, err := chain.Init(chainId) + s.chains = append(s.chains, newChain) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) configureDockerResources() { + var err error + s.dkrPool, err = dockertest.NewPool("") + s.Require().NoError(err) + + s.dkrNet, err = s.dkrPool.CreateNetwork(fmt.Sprintf("%s-%s-testnet", s.chains[0].Id, s.chains[1].Id)) + s.Require().NoError(err) + + s.valResources = make(map[string][]*dockertest.Resource) +} + func noRestart(config *docker.HostConfig) { // in this case we don't want the nodes to restart on failure config.RestartPolicy = docker.RestartPolicy{ diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index 8be7b7dd446..dc011b0a80b 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -9,24 +9,27 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + "github.com/osmosis-labs/osmosis/v7/tests/e2e/chain" + "github.com/osmosis-labs/osmosis/v7/tests/e2e/util" ) func (s *IntegrationTestSuite) TestQueryBalances() { var ( - expectedDenomsA = []string{osmoDenom, stakeDenom} - expectedDenomsB = []string{osmoDenom, stakeDenom, ibcDenom} - expectedBalancesA = []uint64{osmoBalanceA - ibcSendAmount, stakeBalanceA - stakeAmountA} - expectedBalancesB = []uint64{osmoBalanceB, stakeBalanceB - stakeAmountB, ibcSendAmount} + expectedDenomsA = []string{chain.OsmoDenom, chain.StakeDenom} + expectedDenomsB = []string{chain.OsmoDenom, chain.StakeDenom, chain.IbcDenom} + expectedBalancesA = []uint64{chain.OsmoBalanceA - chain.IbcSendAmount, chain.StakeBalanceA - chain.StakeAmountA} + expectedBalancesB = []uint64{chain.OsmoBalanceB, chain.StakeBalanceB - chain.StakeAmountB, chain.IbcSendAmount} ) - chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainA.id][0].GetHostPort("1317/tcp")) - balancesA, err := queryBalances(chainAAPIEndpoint, s.chainA.validators[0].keyInfo.GetAddress().String()) + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chains[0].Id][0].GetHostPort("1317/tcp")) + balancesA, err := queryBalances(chainAAPIEndpoint, s.chains[0].Validators[0].GetKeyInfo().GetAddress().String()) s.Require().NoError(err) s.Require().NotNil(balancesA) s.Require().Equal(2, len(balancesA)) - chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) - balancesB, err := queryBalances(chainBAPIEndpoint, s.chainB.validators[0].keyInfo.GetAddress().String()) + chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chains[1].Id][0].GetHostPort("1317/tcp")) + balancesB, err := queryBalances(chainBAPIEndpoint, s.chains[1].Validators[0].GetKeyInfo().GetAddress().String()) s.Require().NoError(err) s.Require().NotNil(balancesB) s.Require().Equal(3, len(balancesB)) @@ -87,7 +90,7 @@ func queryBalances(endpoint, addr string) (sdk.Coins, error) { } var balancesResp banktypes.QueryAllBalancesResponse - if err := cdc.UnmarshalJSON(bz, &balancesResp); err != nil { + if err := util.Cdc.UnmarshalJSON(bz, &balancesResp); err != nil { return nil, err } @@ -98,11 +101,11 @@ func (s *IntegrationTestSuite) TestIBCTokenTransfer() { var ibcStakeDenom string s.Run("send_uosmo_to_chainB", func() { - recipient := s.chainB.validators[0].keyInfo.GetAddress().String() - token := sdk.NewInt64Coin(osmoDenom, ibcSendAmount) // 3,300uosmo - s.sendIBC(s.chainA.id, s.chainB.id, recipient, token) + recipient := s.chains[1].Validators[0].GetKeyInfo().GetAddress().String() + token := sdk.NewInt64Coin(chain.OsmoDenom, chain.IbcSendAmount) // 3,300uosmo + s.sendIBC(s.chains[0].Id, s.chains[1].Id, recipient, token) - chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chainB.id][0].GetHostPort("1317/tcp")) + chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chains[1].Id][0].GetHostPort("1317/tcp")) // require the recipient account receives the IBC tokens (IBC packets ACKd) var ( diff --git a/tests/e2e/e2e_util_test.go b/tests/e2e/e2e_util_test.go index efd7cbffed9..fb6d7de3727 100644 --- a/tests/e2e/e2e_util_test.go +++ b/tests/e2e/e2e_util_test.go @@ -11,7 +11,7 @@ import ( ) func (s *IntegrationTestSuite) connectIBCChains() { - s.T().Logf("connecting %s and %s chains via IBC", s.chainA.id, s.chainB.id) + s.T().Logf("connecting %s and %s chains via IBC", s.chains[0].Id, s.chains[1].Id) ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() @@ -26,8 +26,8 @@ func (s *IntegrationTestSuite) connectIBCChains() { "hermes", "create", "channel", - s.chainA.id, - s.chainB.id, + s.chains[0].Id, + s.chains[1].Id, "--port-a=transfer", "--port-b=transfer", }, @@ -56,7 +56,7 @@ func (s *IntegrationTestSuite) connectIBCChains() { "failed to connect chains via IBC: %s", errBuf.String(), ) - s.T().Logf("connected %s and %s chains via IBC", s.chainA.id, s.chainB.id) + s.T().Logf("connected %s and %s chains via IBC", s.chains[0].Id, s.chains[1].Id) } func (s *IntegrationTestSuite) sendIBC(srcChainID, dstChainID, recipient string, token sdk.Coin) { diff --git a/tests/e2e/genesis.go b/tests/e2e/genesis.go deleted file mode 100644 index 8ef24b81173..00000000000 --- a/tests/e2e/genesis.go +++ /dev/null @@ -1,110 +0,0 @@ -package e2e - -import ( - "encoding/json" - "fmt" - "os" - - "github.com/cosmos/cosmos-sdk/server" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/cosmos/cosmos-sdk/x/genutil" - genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" - tmtypes "github.com/tendermint/tendermint/types" -) - -func getGenDoc(path string) (*tmtypes.GenesisDoc, error) { - serverCtx := server.NewDefaultContext() - config := serverCtx.Config - config.SetRoot(path) - - genFile := config.GenesisFile() - doc := &tmtypes.GenesisDoc{} - - if _, err := os.Stat(genFile); err != nil { - if !os.IsNotExist(err) { - return nil, err - } - } else { - var err error - - doc, err = tmtypes.GenesisDocFromFile(genFile) - if err != nil { - return nil, fmt.Errorf("failed to read genesis doc from file: %w", err) - } - } - - return doc, nil -} - -func addGenesisAccount(path, moniker, amountStr string, accAddr sdk.AccAddress) error { - serverCtx := server.NewDefaultContext() - config := serverCtx.Config - - config.SetRoot(path) - config.Moniker = moniker - - coins, err := sdk.ParseCoinsNormalized(amountStr) - if err != nil { - return fmt.Errorf("failed to parse coins: %w", err) - } - - balances := banktypes.Balance{Address: accAddr.String(), Coins: coins.Sort()} - genAccount := authtypes.NewBaseAccount(accAddr, nil, 0, 0) - - genFile := config.GenesisFile() - appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile) - if err != nil { - return fmt.Errorf("failed to unmarshal genesis state: %w", err) - } - - authGenState := authtypes.GetGenesisStateFromAppState(cdc, appState) - - accs, err := authtypes.UnpackAccounts(authGenState.Accounts) - if err != nil { - return fmt.Errorf("failed to get accounts from any: %w", err) - } - - if accs.Contains(accAddr) { - return fmt.Errorf("failed to add account to genesis state; account already exists: %s", accAddr) - } - - // Add the new account to the set of genesis accounts and sanitize the - // accounts afterwards. - accs = append(accs, genAccount) - accs = authtypes.SanitizeGenesisAccounts(accs) - - genAccs, err := authtypes.PackAccounts(accs) - if err != nil { - return fmt.Errorf("failed to convert accounts into any's: %w", err) - } - - authGenState.Accounts = genAccs - - authGenStateBz, err := cdc.MarshalJSON(&authGenState) - if err != nil { - return fmt.Errorf("failed to marshal auth genesis state: %w", err) - } - - appState[authtypes.ModuleName] = authGenStateBz - - bankGenState := banktypes.GetGenesisStateFromAppState(cdc, appState) - bankGenState.Balances = append(bankGenState.Balances, balances) - bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances) - - bankGenStateBz, err := cdc.MarshalJSON(bankGenState) - if err != nil { - return fmt.Errorf("failed to marshal bank genesis state: %w", err) - } - - appState[banktypes.ModuleName] = bankGenStateBz - - appStateJSON, err := json.Marshal(appState) - if err != nil { - return fmt.Errorf("failed to marshal application genesis state: %w", err) - } - - genDoc.AppState = appStateJSON - return genutil.ExportGenesisFile(genDoc, genFile) -} diff --git a/tests/e2e/keys.go b/tests/e2e/keys.go deleted file mode 100644 index 55074ef30b6..00000000000 --- a/tests/e2e/keys.go +++ /dev/null @@ -1,56 +0,0 @@ -package e2e - -import ( - "github.com/cosmos/cosmos-sdk/crypto/hd" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/go-bip39" -) - -func createMnemonic() (string, error) { - entropySeed, err := bip39.NewEntropy(256) - if err != nil { - return "", err - } - - mnemonic, err := bip39.NewMnemonic(entropySeed) - if err != nil { - return "", err - } - - return mnemonic, nil -} - -func createMemoryKey() (mnemonic string, info *keyring.Info, err error) { - mnemonic, err = createMnemonic() - if err != nil { - return "", nil, err - } - - account, err := createMemoryKeyFromMnemonic(mnemonic) - if err != nil { - return "", nil, err - } - - return mnemonic, account, nil -} - -func createMemoryKeyFromMnemonic(mnemonic string) (*keyring.Info, error) { - kb, err := keyring.New("testnet", keyring.BackendMemory, "", nil) - if err != nil { - return nil, err - } - - keyringAlgos, _ := kb.SupportedAlgorithms() - algo, err := keyring.NewSigningAlgoFromString(string(hd.Secp256k1Type), keyringAlgos) - if err != nil { - return nil, err - } - - account, err := kb.NewAccount("", mnemonic, "", sdk.FullFundraiserPath, algo) - if err != nil { - return nil, err - } - - return &account, nil -} diff --git a/tests/e2e/scripts/hermes_bootstrap.sh b/tests/e2e/scripts/hermes_bootstrap.sh index 7295a8e14ec..4a438c1f9ff 100644 --- a/tests/e2e/scripts/hermes_bootstrap.sh +++ b/tests/e2e/scripts/hermes_bootstrap.sh @@ -39,7 +39,7 @@ grpc_addr = 'http://$OSMO_A_E2E_VAL_HOST:9090' websocket_addr = 'ws://$OSMO_A_E2E_VAL_HOST:26657/websocket' rpc_timeout = '10s' account_prefix = 'osmo' -key_name = 'val01-gaia-a' +key_name = 'val01-osmosis-a' store_prefix = 'ibc' max_gas = 6000000 gas_price = { price = 0.000, denom = 'stake' } @@ -54,7 +54,7 @@ grpc_addr = 'http://$OSMO_B_E2E_VAL_HOST:9090' websocket_addr = 'ws://$OSMO_B_E2E_VAL_HOST:26657/websocket' rpc_timeout = '10s' account_prefix = 'osmo' -key_name = 'val01-gaia-b' +key_name = 'val01-osmosis-b' store_prefix = 'ibc' max_gas = 6000000 gas_price = { price = 0.000, denom = 'stake' } @@ -65,8 +65,8 @@ trust_threshold = { numerator = '1', denominator = '3' } EOF # import keys -hermes keys restore ${OSMO_B_E2E_CHAIN_ID} -n "val01-gaia-b" -m "${OSMO_B_E2E_VAL_MNEMONIC}" -hermes keys restore ${OSMO_A_E2E_CHAIN_ID} -n "val01-gaia-a" -m "${OSMO_A_E2E_VAL_MNEMONIC}" +hermes keys restore ${OSMO_B_E2E_CHAIN_ID} -n "val01-osmosis-b" -m "${OSMO_B_E2E_VAL_MNEMONIC}" +hermes keys restore ${OSMO_A_E2E_CHAIN_ID} -n "val01-osmosis-a" -m "${OSMO_A_E2E_VAL_MNEMONIC}" # start Hermes relayer hermes start diff --git a/tests/e2e/util/codec.go b/tests/e2e/util/codec.go new file mode 100644 index 00000000000..fc1d0ea1ab5 --- /dev/null +++ b/tests/e2e/util/codec.go @@ -0,0 +1,40 @@ +package util + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + osmosisApp "github.com/osmosis-labs/osmosis/v7/app" + "github.com/osmosis-labs/osmosis/v7/app/params" +) + +var ( + EncodingConfig params.EncodingConfig + Cdc codec.Codec +) + +func init() { + EncodingConfig, Cdc = initEncodingConfigAndCdc() +} + +func initEncodingConfigAndCdc() (params.EncodingConfig, codec.Codec) { + encodingConfig := osmosisApp.MakeEncodingConfig() + + encodingConfig.InterfaceRegistry.RegisterImplementations( + (*sdk.Msg)(nil), + &stakingtypes.MsgCreateValidator{}, + ) + encodingConfig.InterfaceRegistry.RegisterImplementations( + (*cryptotypes.PubKey)(nil), + &secp256k1.PubKey{}, + &ed25519.PubKey{}, + ) + + cdc := encodingConfig.Marshaler + + return encodingConfig, cdc +} diff --git a/tests/e2e/io.go b/tests/e2e/util/io.go similarity index 84% rename from tests/e2e/io.go rename to tests/e2e/util/io.go index 97bfac75dce..31b534f640c 100644 --- a/tests/e2e/io.go +++ b/tests/e2e/util/io.go @@ -1,4 +1,4 @@ -package e2e +package util import ( "fmt" @@ -7,7 +7,7 @@ import ( "os" ) -func copyFile(src, dst string) (int64, error) { +func CopyFile(src, dst string) (int64, error) { sourceFileStat, err := os.Stat(src) if err != nil { return 0, err @@ -33,7 +33,7 @@ func copyFile(src, dst string) (int64, error) { return nBytes, err } -func writeFile(path string, body []byte) error { +func WriteFile(path string, body []byte) error { _, err := os.Create(path) if err != nil { return err From c71f077bc131800c07e7d35f6fc47146d4aa7e81 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 22 Apr 2022 21:52:36 -0400 Subject: [PATCH 8/9] refactor: implement Dockerized chain initialization in e2e tests (#1330) Closes: #XXX ## What is the purpose of the change This is a follow-up PR to #1293 and builds upon its work. It is part of the e2e test chain upgrade epic #1235 This PR introduces the ability to run chain initialization in a Docker container by running the following: ``` docker run -v < path >:/tmp/osmo-test osmosis-e2e-chain-init:debug --data-dir=/tmp/osmo-test ``` All chain data is placed at the given `< path >` that is mounted as a volume on the container. In addition, this PR introduces documentation about the current state of the e2e tests. ## Brief change log - [pull chain temp folder creation our of chain to e2e package](https://github.com/osmosis-labs/osmosis/pull/1330/commits/c175289ba8c09bc178eafcfcca36a053fade961e) - [create image and makefile steps to initialize chain state](https://github.com/osmosis-labs/osmosis/pull/1330/commits/de89119bde788b03de15eaef855f40dacb38c780) - [allow for running the upgrade initialization in Docker by providing a data dir](https://github.com/osmosis-labs/osmosis/pull/1330/commits/dabb683955b0645c61462089af89bf022072eca9) - [improve abstractions for chain initialization and add README](https://github.com/osmosis-labs/osmosis/pull/1330/commits/cf0d8a33053638553a228e3467ad5b439b83bafe) - improve README ## Testing and Verifying - ran e2e tests locally a few times - `make build-e2e-chain-init` - `make docker-build-e2e-chain-init` - `docker run -v /home/roman/cosmos/osmosis/tmp:/tmp/osmo-test osmosis-e2e-chain-init:debug --data-dir=/tmp/osmo-test` All steps worked as desired ## Documentation and Release Note - Does this pull request introduce a new feature or user-facing behavior changes? no - Is a relevant changelog entry added to the `Unreleased` section in `CHANGELOG.md`? no - How is the feature or change documented? improved `tests/e2e/README.md` ## Next Steps The next step is to switch our chain initialization logic in `func (s *IntegrationTestSuite) configureChain(chainId string)` to use Dockertest and the newly introduced container. Then, mount the genesis and configs on the Osmosis containers, against which the e2e tests are executed --- Makefile | 7 +++ tests/e2e/README.md | 62 +++++++++++++++++++++- tests/e2e/chain/chain.go | 10 +--- tests/e2e/chain/main.go | 4 +- tests/e2e/chain_init/chain-init.Dockerfile | 23 ++++++++ tests/e2e/chain_init/main.go | 29 ++++++++++ tests/e2e/e2e_setup_test.go | 4 +- 7 files changed, 126 insertions(+), 13 deletions(-) create mode 100644 tests/e2e/chain_init/chain-init.Dockerfile create mode 100644 tests/e2e/chain_init/main.go diff --git a/Makefile b/Makefile index bb5ef93ab72..6f040b23f66 100644 --- a/Makefile +++ b/Makefile @@ -112,6 +112,10 @@ build-contract-tests-hooks: mkdir -p $(BUILDDIR) go build -mod=readonly $(BUILD_FLAGS) -o $(BUILDDIR)/ ./cmd/contract_tests +build-e2e-chain-init: + mkdir -p $(BUILDDIR) + go build -mod=readonly $(BUILD_FLAGS) -o $(BUILDDIR)/ ./tests/e2e/chain_init + go-mod-cache: go.sum @echo "--> Download go modules to local cache" @go mod download @@ -239,6 +243,9 @@ benchmark: docker-build-debug: @docker build -t osmosis:debug --build-arg BASE_IMG_TAG=debug -f Dockerfile . +docker-build-e2e-chain-init: + @docker build -t osmosis-e2e-chain-init:debug -f tests/e2e/chain_init/chain-init.Dockerfile . + ############################################################################### ### Linting ### ############################################################################### diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 846d854bdd4..a3de35e60dd 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -1,7 +1,15 @@ # End-to-end Tests -The package e2e defines an integration testing suite used for full end-to-end -testing functionality. +# Structure + +## `e2e` Package + +The `e2e` package defines an integration testing suite used for full end-to-end +testing functionality. This package is decoupled from depending on the Osmosis codebase. +It initializes the chains for testing via Docker files. As a result, the test suite may +provide the desired Osmosis version to Docker containers during the initialization. +This design allows for the opportunity of testing chain upgrades in the future by providing +an older Osmosis version to the container, performing the chain upgrade, and running the latest test suite. The file e2e_suite_test.go defines the testing suite and contains the core bootstrapping logic that creates a testing environment via Docker containers. @@ -11,3 +19,53 @@ The file e2e_test.go contains the actual end-to-end integration tests that utilize the testing suite. Currently, there is a single test in `e2e_test.go` to query the balances of a validator. + +## `chain` Package + +The `chain` package introduces the logic necessary for initializing a chain by creating a genesis +file and all required configuration files such as the `app.toml`. This package directly depends on the Osmosis codebase. + +## `upgrade` Package + +The `upgrade` package starts chain initialization. In addition, there is a Dockerfile `init-e2e.Dockerfile`. +When executed, its container produces all files necessary for starting up a new chain. +These resulting files can be mounted on a volume and propagated to our production osmosis container to start the `osmosisd` service. + +The decoupling between chain initialization and start-up allows to minimize the differences between our test suite and the production environment. + +# Running Locally + +##### To build the binary that initializes the chain: + +``` +make build-e2e-chain-init +``` +- The produced binary is an entrypoint to the `osmosis-e2e-chain-init:debug` image. + +##### To build the image for initializing the chain (`osmosis-e2e-chain-init:debug`): + +``` +make docker-build-e2e-chain-init +``` + +##### To run the chain initialization container locally: + +``` +mkdir < path > +docker run -v < path >:/tmp/osmo-test osmosis-e2e-chain-init:debug --data-dir=/tmp/osmo-test +sudo rm -r < path > # must be root to clean up +``` +- runs a container with a volume mounted at < path > where all chain initialization files are placed. +- < path > must be absolute. +- `--data-dir` flag is needed for outputting the files into a directory inside the container + +Example: +``` +docker run -v /home/roman/cosmos/osmosis/tmp:/tmp/osmo-test osmosis-e2e-chain-init:debug --data-dir=/tmp/osmo-test +``` + +##### To build the debug Osmosis image: + +``` +make docker-build-e2e-debug +``` diff --git a/tests/e2e/chain/chain.go b/tests/e2e/chain/chain.go index b43bbbf5ce9..0a4e0d3f4f3 100644 --- a/tests/e2e/chain/chain.go +++ b/tests/e2e/chain/chain.go @@ -2,7 +2,6 @@ package chain import ( "fmt" - "io/ioutil" ) const ( @@ -16,15 +15,10 @@ type Chain struct { Validators []*Validator } -func new(id string) (*Chain, error) { - tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-") - if err != nil { - return nil, err - } - +func new(id, dataDir string) (*Chain, error) { return &Chain{ Id: id, - DataDir: tmpDir, + DataDir: dataDir, }, nil } diff --git a/tests/e2e/chain/main.go b/tests/e2e/chain/main.go index 3f9a341d638..20453d7186d 100644 --- a/tests/e2e/chain/main.go +++ b/tests/e2e/chain/main.go @@ -1,7 +1,7 @@ package chain -func Init(id string) (*Chain, error) { - chain, err := new(id) +func Init(id, dataDir string) (*Chain, error) { + chain, err := new(id, dataDir) if err != nil { return nil, err } diff --git a/tests/e2e/chain_init/chain-init.Dockerfile b/tests/e2e/chain_init/chain-init.Dockerfile new file mode 100644 index 00000000000..91e5346b0df --- /dev/null +++ b/tests/e2e/chain_init/chain-init.Dockerfile @@ -0,0 +1,23 @@ +# syntax=docker/dockerfile:1 + +## Build Image +FROM golang:1.18-bullseye as build + +WORKDIR /osmosis +COPY . /osmosis + +# From https://github.com/CosmWasm/wasmd/blob/master/Dockerfile +# For more details see https://github.com/CosmWasm/wasmvm#builds-of-libwasmvm +ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.0.0-beta7/libwasmvm_muslc.a /lib/libwasmvm_muslc.a +RUN sha256sum /lib/libwasmvm_muslc.a | grep d0152067a5609bfdfb3f0d5d6c0f2760f79d5f2cd7fd8513cafa9932d22eb350 +RUN BUILD_TAGS=muslc make build-e2e-chain-init + +## Deploy image +FROM ubuntu + +COPY --from=build /osmosis/build/chain_init /bin/chain_init + +ENV HOME /osmosis +WORKDIR $HOME + +ENTRYPOINT [ "chain_init" ] diff --git a/tests/e2e/chain_init/main.go b/tests/e2e/chain_init/main.go new file mode 100644 index 00000000000..edb26b0c199 --- /dev/null +++ b/tests/e2e/chain_init/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/osmosis-labs/osmosis/v7/tests/e2e/chain" +) + +func main() { + var dataDir string + flag.StringVar(&dataDir, "data-dir", "", "chain data directory") + flag.Parse() + + if len(dataDir) == 0 { + panic("data-dir is required") + } + + if err := os.MkdirAll(dataDir, 0o755); err != nil { + panic(err) + } + + chain, err := chain.Init(chain.ChainAID, dataDir) + if err != nil { + panic(err) + } + fmt.Println(chain) +} diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 2885c31a330..b3f8988df21 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -254,7 +254,9 @@ func (s *IntegrationTestSuite) runIBCRelayer() { func (s *IntegrationTestSuite) configureChain(chainId string) { s.T().Logf("starting e2e infrastructure for chain-id: %s", chainId) - newChain, err := chain.Init(chainId) + tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-") + s.Require().NoError(err) + newChain, err := chain.Init(chainId, tmpDir) s.chains = append(s.chains, newChain) s.Require().NoError(err) } From c32c5b319a3e171adb40a74b74c58dcadeb89c40 Mon Sep 17 00:00:00 2001 From: Adam Tucker Date: Thu, 28 Apr 2022 16:55:59 -0500 Subject: [PATCH 9/9] Setup e2e tests on a single chain; add balances query test (#1193) * create e2e image and a makefile step to build * progress * e2e tests in ci * use root distroless image and correct volume path * remove chain b references * implement query balances * implement TestQueryBalances * trigger worflow * trigger * test-e2e Makefile step * fmt and sleep if service unavailable * README * restore branches * add changelog entry * exclude e2e from regular tests * -E flag for grep exclusion * grep * go mod tidy --compat=1.17 * manually tidy go.mod --- .github/workflows/test.yml | 1 + tests/e2e/chain/chain.go | 46 +++++++++++------- tests/e2e/chain/config.go | 50 ++++++++++---------- tests/e2e/chain/export.go | 25 ++++++++++ tests/e2e/chain/main.go | 2 +- tests/e2e/chain/validator.go | 68 ++++++++++++++------------- tests/e2e/chain_init/main.go | 17 +++++-- tests/e2e/e2e_setup_test.go | 90 +++++++++++++++++++++++++++--------- tests/e2e/e2e_test.go | 14 +++--- tests/e2e/e2e_util_test.go | 8 ++-- 10 files changed, 212 insertions(+), 109 deletions(-) create mode 100644 tests/e2e/chain/export.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f91f4bd472d..15d47fc63ad 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,6 +38,7 @@ jobs: - name: Build Docker Image run: | make docker-build-debug + make docker-build-e2e-chain-init if: env.GIT_DIFF - name: Test E2E run: | diff --git a/tests/e2e/chain/chain.go b/tests/e2e/chain/chain.go index 0a4e0d3f4f3..a746bcc7440 100644 --- a/tests/e2e/chain/chain.go +++ b/tests/e2e/chain/chain.go @@ -9,24 +9,24 @@ const ( keyringAppName = "testnet" ) -type Chain struct { - DataDir string - Id string - Validators []*Validator +// internalChain contains the same info as chain, but with the validator structs instead using the internal validator +// representation, with more derived data +type internalChain struct { + chainMeta ChainMeta + validators []*internalValidator } -func new(id, dataDir string) (*Chain, error) { - return &Chain{ +func new(id, dataDir string) (*internalChain, error) { + chainMeta := ChainMeta{ Id: id, DataDir: dataDir, + } + return &internalChain{ + chainMeta: chainMeta, }, nil } -func (c *Chain) configDir() string { - return fmt.Sprintf("%s/%s", c.DataDir, c.Id) -} - -func (c *Chain) createAndInitValidators(count int) error { +func (c *internalChain) createAndInitValidators(count int) error { for i := 0; i < count; i++ { node := c.createValidator(i) @@ -35,7 +35,7 @@ func (c *Chain) createAndInitValidators(count int) error { return err } - c.Validators = append(c.Validators, node) + c.validators = append(c.validators, node) // create keys if err := node.createKey("val"); err != nil { @@ -52,7 +52,7 @@ func (c *Chain) createAndInitValidators(count int) error { return nil } -func (c *Chain) createAndInitValidatorsWithMnemonics(count int, mnemonics []string) error { +func (c *internalChain) createAndInitValidatorsWithMnemonics(count int, mnemonics []string) error { for i := 0; i < count; i++ { // create node node := c.createValidator(i) @@ -62,7 +62,7 @@ func (c *Chain) createAndInitValidatorsWithMnemonics(count int, mnemonics []stri return err } - c.Validators = append(c.Validators, node) + c.validators = append(c.validators, node) // create keys if err := node.createKeyFromMnemonic("val", mnemonics[i]); err != nil { @@ -79,10 +79,22 @@ func (c *Chain) createAndInitValidatorsWithMnemonics(count int, mnemonics []stri return nil } -func (c *Chain) createValidator(index int) *Validator { - return &Validator{ +func (c *internalChain) createValidator(index int) *internalValidator { + return &internalValidator{ chain: c, index: index, - moniker: fmt.Sprintf("%s-osmosis-%d", c.Id, index), + moniker: fmt.Sprintf("%s-osmosis-%d", c.chainMeta.Id, index), + } +} + +func (c *internalChain) export() *Chain { + exportValidators := make([]*Validator, 0, len(c.validators)) + for _, v := range c.validators { + exportValidators = append(exportValidators, v.export()) + } + + return &Chain{ + ChainMeta: c.chainMeta, + Validators: exportValidators, } } diff --git a/tests/e2e/chain/config.go b/tests/e2e/chain/config.go index a5abf60041e..28bc3ba3016 100644 --- a/tests/e2e/chain/config.go +++ b/tests/e2e/chain/config.go @@ -120,12 +120,12 @@ func addAccount(path, moniker, amountStr string, accAddr sdk.AccAddress) error { return genutil.ExportGenesisFile(genDoc, genFile) } -func initGenesis(c *Chain) error { +func initGenesis(c *internalChain) error { serverCtx := server.NewDefaultContext() config := serverCtx.Config - config.SetRoot(c.Validators[0].ConfigDir()) - config.Moniker = c.Validators[0].GetMoniker() + config.SetRoot(c.validators[0].configDir()) + config.Moniker = c.validators[0].getMoniker() genFilePath := config.GenesisFile() appGenState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFilePath) @@ -164,10 +164,10 @@ func initGenesis(c *Chain) error { } // generate genesis txs - genTxs := make([]json.RawMessage, len(c.Validators)) - for i, val := range c.Validators { + genTxs := make([]json.RawMessage, len(c.validators)) + for i, val := range c.validators { stakeAmountCoin := StakeAmountCoinA - if c.Id != ChainAID { + if c.chainMeta.Id != ChainAID { stakeAmountCoin = StakeAmountCoinB } createValmsg, err := val.buildCreateValidatorMsg(stakeAmountCoin) @@ -209,38 +209,38 @@ func initGenesis(c *Chain) error { } // write the updated genesis file to each validator - for _, val := range c.Validators { - if err := util.WriteFile(filepath.Join(val.ConfigDir(), "config", "genesis.json"), bz); err != nil { + for _, val := range c.validators { + if err := util.WriteFile(filepath.Join(val.configDir(), "config", "genesis.json"), bz); err != nil { return err } } return nil } -func initNodes(c *Chain) error { +func initNodes(c *internalChain) error { if err := c.createAndInitValidators(2); err != nil { return err } // initialize a genesis file for the first validator - val0ConfigDir := c.Validators[0].ConfigDir() - for _, val := range c.Validators { - if c.Id == ChainAID { - if err := addAccount(val0ConfigDir, "", InitBalanceStrA, val.GetKeyInfo().GetAddress()); err != nil { + val0ConfigDir := c.validators[0].configDir() + for _, val := range c.validators { + if c.chainMeta.Id == ChainAID { + if err := addAccount(val0ConfigDir, "", InitBalanceStrA, val.getKeyInfo().GetAddress()); err != nil { return err } - } else if c.Id == ChainBID { - if err := addAccount(val0ConfigDir, "", InitBalanceStrB, val.GetKeyInfo().GetAddress()); err != nil { + } else if c.chainMeta.Id == ChainBID { + if err := addAccount(val0ConfigDir, "", InitBalanceStrB, val.getKeyInfo().GetAddress()); err != nil { return err } } } // copy the genesis file to the remaining validators - for _, val := range c.Validators[1:] { + for _, val := range c.validators[1:] { _, err := util.CopyFile( filepath.Join(val0ConfigDir, "config", "genesis.json"), - filepath.Join(val.ConfigDir(), "config", "genesis.json"), + filepath.Join(val.configDir(), "config", "genesis.json"), ) if err != nil { return err @@ -249,9 +249,9 @@ func initNodes(c *Chain) error { return nil } -func initValidatorConfigs(c *Chain) error { - for i, val := range c.Validators { - tmCfgPath := filepath.Join(val.ConfigDir(), "config", "config.toml") +func initValidatorConfigs(c *internalChain) error { + for i, val := range c.validators { + tmCfgPath := filepath.Join(val.configDir(), "config", "config.toml") vpr := viper.New() vpr.SetConfigFile(tmCfgPath) @@ -266,20 +266,20 @@ func initValidatorConfigs(c *Chain) error { valConfig.P2P.ListenAddress = "tcp://0.0.0.0:26656" valConfig.P2P.AddrBookStrict = false - valConfig.P2P.ExternalAddress = fmt.Sprintf("%s:%d", val.InstanceName(), 26656) + valConfig.P2P.ExternalAddress = fmt.Sprintf("%s:%d", val.instanceName(), 26656) valConfig.RPC.ListenAddress = "tcp://0.0.0.0:26657" valConfig.StateSync.Enable = false valConfig.LogLevel = "info" var peers []string - for j := 0; j < len(c.Validators); j++ { + for j := 0; j < len(c.validators); j++ { if i == j { continue } - peer := c.Validators[j] - peerID := fmt.Sprintf("%s@%s%d:26656", peer.getNodeKey().ID(), peer.GetMoniker(), j) + peer := c.validators[j] + peerID := fmt.Sprintf("%s@%s%d:26656", peer.getNodeKey().ID(), peer.getMoniker(), j) peers = append(peers, peerID) } @@ -288,7 +288,7 @@ func initValidatorConfigs(c *Chain) error { tmconfig.WriteConfigFile(tmCfgPath, valConfig) // set application configuration - appCfgPath := filepath.Join(val.ConfigDir(), "config", "app.toml") + appCfgPath := filepath.Join(val.configDir(), "config", "app.toml") appConfig := srvconfig.DefaultConfig() appConfig.API.Enable = true diff --git a/tests/e2e/chain/export.go b/tests/e2e/chain/export.go new file mode 100644 index 00000000000..d2b7922dbaa --- /dev/null +++ b/tests/e2e/chain/export.go @@ -0,0 +1,25 @@ +package chain + +import "fmt" + +type ChainMeta struct { + DataDir string `json:"dataDir"` + Id string `json:"id"` +} + +type Validator struct { + Name string `json:"name"` + ConfigDir string `json:"configDir"` + Index int `json:"index"` + Mnemonic string `json:"mnemonic"` + PublicAddress string `json:"publicAddress"` +} + +type Chain struct { + ChainMeta ChainMeta `json:"chainMeta"` + Validators []*Validator `json:"validators"` +} + +func (c *ChainMeta) configDir() string { + return fmt.Sprintf("%s/%s", c.DataDir, c.Id) +} diff --git a/tests/e2e/chain/main.go b/tests/e2e/chain/main.go index 20453d7186d..56cfc89b329 100644 --- a/tests/e2e/chain/main.go +++ b/tests/e2e/chain/main.go @@ -14,5 +14,5 @@ func Init(id, dataDir string) (*Chain, error) { if err := initValidatorConfigs(chain); err != nil { return nil, err } - return chain, nil + return chain.export(), nil } diff --git a/tests/e2e/chain/validator.go b/tests/e2e/chain/validator.go index 570463a66cd..2cc66e85f9c 100644 --- a/tests/e2e/chain/validator.go +++ b/tests/e2e/chain/validator.go @@ -30,8 +30,8 @@ import ( "github.com/osmosis-labs/osmosis/v7/tests/e2e/util" ) -type Validator struct { - chain *Chain +type internalValidator struct { + chain *internalChain index int moniker string mnemonic string @@ -42,31 +42,27 @@ type Validator struct { nodeKey p2p.NodeKey } -func (v *Validator) InstanceName() string { +func (v *internalValidator) instanceName() string { return fmt.Sprintf("%s%d", v.moniker, v.index) } -func (v *Validator) ConfigDir() string { - return fmt.Sprintf("%s/%s", v.chain.configDir(), v.InstanceName()) +func (v *internalValidator) configDir() string { + return fmt.Sprintf("%s/%s", v.chain.chainMeta.configDir(), v.instanceName()) } -func (v *Validator) GetKeyInfo() keyring.Info { +func (v *internalValidator) getKeyInfo() keyring.Info { return v.keyInfo } -func (v *Validator) GetMoniker() string { +func (v *internalValidator) getMoniker() string { return v.moniker } -func (v *Validator) GetMnemonic() string { +func (v *internalValidator) getMnemonic() string { return v.mnemonic } -func (v *Validator) GetIndex() int { - return v.index -} - -func (v *Validator) buildCreateValidatorMsg(amount sdk.Coin) (sdk.Msg, error) { +func (v *internalValidator) buildCreateValidatorMsg(amount sdk.Coin) (sdk.Msg, error) { description := stakingtypes.NewDescription(v.moniker, "", "", "", "") commissionRates := stakingtypes.CommissionRates{ Rate: sdk.MustNewDecFromStr("0.1"), @@ -92,16 +88,16 @@ func (v *Validator) buildCreateValidatorMsg(amount sdk.Coin) (sdk.Msg, error) { ) } -func (v *Validator) createConfig() error { - p := path.Join(v.ConfigDir(), "config") +func (v *internalValidator) createConfig() error { + p := path.Join(v.configDir(), "config") return os.MkdirAll(p, 0o755) } -func (v *Validator) createNodeKey() error { +func (v *internalValidator) createNodeKey() error { serverCtx := server.NewDefaultContext() config := serverCtx.Config - config.SetRoot(v.ConfigDir()) + config.SetRoot(v.configDir()) config.Moniker = v.moniker nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) @@ -113,11 +109,11 @@ func (v *Validator) createNodeKey() error { return nil } -func (v *Validator) createConsensusKey() error { +func (v *internalValidator) createConsensusKey() error { serverCtx := server.NewDefaultContext() config := serverCtx.Config - config.SetRoot(v.ConfigDir()) + config.SetRoot(v.configDir()) config.Moniker = v.moniker pvKeyFile := config.PrivValidatorKeyFile() @@ -136,8 +132,8 @@ func (v *Validator) createConsensusKey() error { return nil } -func (v *Validator) createKeyFromMnemonic(name, mnemonic string) error { - kb, err := keyring.New(keyringAppName, keyring.BackendTest, v.ConfigDir(), nil) +func (v *internalValidator) createKeyFromMnemonic(name, mnemonic string) error { + kb, err := keyring.New(keyringAppName, keyring.BackendTest, v.configDir(), nil) if err != nil { return err } @@ -170,7 +166,7 @@ func (v *Validator) createKeyFromMnemonic(name, mnemonic string) error { return nil } -func (v *Validator) createKey(name string) error { +func (v *internalValidator) createKey(name string) error { mnemonic, err := createMnemonic() if err != nil { return err @@ -179,14 +175,24 @@ func (v *Validator) createKey(name string) error { return v.createKeyFromMnemonic(name, mnemonic) } -func (v *Validator) getNodeKey() *p2p.NodeKey { +func (v *internalValidator) export() *Validator { + return &Validator{ + Name: v.instanceName(), + ConfigDir: v.configDir(), + Index: v.index, + Mnemonic: v.mnemonic, + PublicAddress: v.keyInfo.GetAddress().String(), + } +} + +func (v *internalValidator) getNodeKey() *p2p.NodeKey { return &v.nodeKey } -func (v *Validator) getGenesisDoc() (*tmtypes.GenesisDoc, error) { +func (v *internalValidator) getGenesisDoc() (*tmtypes.GenesisDoc, error) { serverCtx := server.NewDefaultContext() config := serverCtx.Config - config.SetRoot(v.ConfigDir()) + config.SetRoot(v.configDir()) genFile := config.GenesisFile() doc := &tmtypes.GenesisDoc{} @@ -207,7 +213,7 @@ func (v *Validator) getGenesisDoc() (*tmtypes.GenesisDoc, error) { return doc, nil } -func (v *Validator) init() error { +func (v *internalValidator) init() error { if err := v.createConfig(); err != nil { return err } @@ -215,7 +221,7 @@ func (v *Validator) init() error { serverCtx := server.NewDefaultContext() config := serverCtx.Config - config.SetRoot(v.ConfigDir()) + config.SetRoot(v.configDir()) config.Moniker = v.moniker genDoc, err := v.getGenesisDoc() @@ -228,7 +234,7 @@ func (v *Validator) init() error { return fmt.Errorf("failed to JSON encode app genesis state: %w", err) } - genDoc.ChainID = v.chain.Id + genDoc.ChainID = v.chain.chainMeta.Id genDoc.Validators = nil genDoc.AppState = appState @@ -254,19 +260,19 @@ func createMnemonic() (string, error) { return mnemonic, nil } -func (v *Validator) signMsg(msgs ...sdk.Msg) (*sdktx.Tx, error) { +func (v *internalValidator) signMsg(msgs ...sdk.Msg) (*sdktx.Tx, error) { txBuilder := util.EncodingConfig.TxConfig.NewTxBuilder() if err := txBuilder.SetMsgs(msgs...); err != nil { return nil, err } - txBuilder.SetMemo(fmt.Sprintf("%s@%s:26656", v.nodeKey.ID(), v.InstanceName())) + txBuilder.SetMemo(fmt.Sprintf("%s@%s:26656", v.nodeKey.ID(), v.instanceName())) txBuilder.SetFeeAmount(sdk.NewCoins()) txBuilder.SetGasLimit(200000) signerData := authsigning.SignerData{ - ChainID: v.chain.Id, + ChainID: v.chain.chainMeta.Id, AccountNumber: 0, Sequence: 0, } diff --git a/tests/e2e/chain_init/main.go b/tests/e2e/chain_init/main.go index edb26b0c199..12275a56baa 100644 --- a/tests/e2e/chain_init/main.go +++ b/tests/e2e/chain_init/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "flag" "fmt" "os" @@ -9,8 +10,13 @@ import ( ) func main() { - var dataDir string + var ( + dataDir string + chainId string + ) + flag.StringVar(&dataDir, "data-dir", "", "chain data directory") + flag.StringVar(&chainId, "chain-id", "", "chain ID") flag.Parse() if len(dataDir) == 0 { @@ -21,9 +27,14 @@ func main() { panic(err) } - chain, err := chain.Init(chain.ChainAID, dataDir) + createdChain, err := chain.Init(chainId, dataDir) if err != nil { panic(err) } - fmt.Println(chain) + + b, _ := json.Marshal(createdChain) + fileName := fmt.Sprintf("%v/%v-encode", dataDir, chainId) + if err = os.WriteFile(fileName, b, 0777); err != nil { + panic(err) + } } diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index b3f8988df21..7e2ac86197e 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -24,6 +24,8 @@ import ( "github.com/osmosis-labs/osmosis/v7/tests/e2e/util" ) +const maxRetries = 10 // max retries for json unmarshalling + type IntegrationTestSuite struct { suite.Suite @@ -32,6 +34,7 @@ type IntegrationTestSuite struct { dkrPool *dockertest.Pool dkrNet *dockertest.Network hermesResource *dockertest.Resource + initResource *dockertest.Resource valResources map[string][]*dockertest.Resource } @@ -52,10 +55,12 @@ func (s *IntegrationTestSuite) SetupSuite() { // 2. Start both networks. // 3. Run IBC relayer betweeen the two chains. // 4. Execute various e2e tests, including IBC. + s.configureDockerResources(chain.ChainAID, chain.ChainBID) + s.configureChain(chain.ChainAID) + s.Require().NoError(s.dkrPool.Purge(s.initResource)) s.configureChain(chain.ChainBID) - - s.configureDockerResources() + s.Require().NoError(s.dkrPool.Purge(s.initResource)) s.runValidators(s.chains[0], 0) s.runValidators(s.chains[1], 10) @@ -85,7 +90,7 @@ func (s *IntegrationTestSuite) TearDownSuite() { s.Require().NoError(s.dkrPool.RemoveNetwork(s.dkrNet)) for _, chain := range s.chains { - os.RemoveAll(chain.DataDir) + os.RemoveAll(chain.ChainMeta.DataDir) } for _, td := range s.tmpDirs { @@ -94,22 +99,22 @@ func (s *IntegrationTestSuite) TearDownSuite() { } func (s *IntegrationTestSuite) runValidators(c *chain.Chain, portOffset int) { - s.T().Logf("starting Osmosis %s validator containers...", c.Id) + s.T().Logf("starting Osmosis %s validator containers...", c.ChainMeta.Id) - s.valResources[c.Id] = make([]*dockertest.Resource, len(c.Validators)) + s.valResources[c.ChainMeta.Id] = make([]*dockertest.Resource, len(c.Validators)) for i, val := range c.Validators { runOpts := &dockertest.RunOptions{ - Name: val.InstanceName(), + Name: val.Name, NetworkID: s.dkrNet.Network.ID, Mounts: []string{ - fmt.Sprintf("%s/:/osmosis/.osmosisd", val.ConfigDir()), + fmt.Sprintf("%s/:/osmosis/.osmosisd", val.ConfigDir), }, Repository: "osmosis", Tag: "debug", } // expose the first validator for debugging and communication - if val.GetIndex() == 0 { + if val.Index == 0 { runOpts.PortBindings = map[docker.Port][]docker.PortBinding{ "1317/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 1317+portOffset)}}, "6060/tcp": {{HostIP: "", HostPort: fmt.Sprintf("%d", 6060+portOffset)}}, @@ -127,8 +132,8 @@ func (s *IntegrationTestSuite) runValidators(c *chain.Chain, portOffset int) { resource, err := s.dkrPool.RunWithOptions(runOpts, noRestart) s.Require().NoError(err) - s.valResources[c.Id][i] = resource - s.T().Logf("started Osmosis %s validator container: %s", c.Id, resource.Container.ID) + s.valResources[c.ChainMeta.Id][i] = resource + s.T().Logf("started Osmosis %s validator container: %s", c.ChainMeta.Id, resource.Container.ID) } rpcClient, err := rpchttp.New("tcp://localhost:26657", "/websocket") @@ -177,7 +182,7 @@ func (s *IntegrationTestSuite) runIBCRelayer() { s.hermesResource, err = s.dkrPool.RunWithOptions( &dockertest.RunOptions{ - Name: fmt.Sprintf("%s-%s-relayer", s.chains[0].Id, s.chains[1].Id), + Name: fmt.Sprintf("%s-%s-relayer", s.chains[0].ChainMeta.Id, s.chains[1].ChainMeta.Id), Repository: "osmolabs/hermes", Tag: "0.13.0", NetworkID: s.dkrNet.Network.ID, @@ -195,12 +200,12 @@ func (s *IntegrationTestSuite) runIBCRelayer() { "3031/tcp": {{HostIP: "", HostPort: "3031"}}, }, Env: []string{ - fmt.Sprintf("OSMO_A_E2E_CHAIN_ID=%s", s.chains[0].Id), - fmt.Sprintf("OSMO_B_E2E_CHAIN_ID=%s", s.chains[1].Id), - fmt.Sprintf("OSMO_A_E2E_VAL_MNEMONIC=%s", osmoAVal.GetMnemonic()), - fmt.Sprintf("OSMO_B_E2E_VAL_MNEMONIC=%s", osmoBVal.GetMnemonic()), - fmt.Sprintf("OSMO_A_E2E_VAL_HOST=%s", s.valResources[s.chains[0].Id][0].Container.Name[1:]), - fmt.Sprintf("OSMO_B_E2E_VAL_HOST=%s", s.valResources[s.chains[1].Id][0].Container.Name[1:]), + fmt.Sprintf("OSMO_A_E2E_CHAIN_ID=%s", s.chains[0].ChainMeta.Id), + fmt.Sprintf("OSMO_B_E2E_CHAIN_ID=%s", s.chains[1].ChainMeta.Id), + fmt.Sprintf("OSMO_A_E2E_VAL_MNEMONIC=%s", osmoAVal.Mnemonic), + fmt.Sprintf("OSMO_B_E2E_VAL_MNEMONIC=%s", osmoBVal.Mnemonic), + fmt.Sprintf("OSMO_A_E2E_VAL_HOST=%s", s.valResources[s.chains[0].ChainMeta.Id][0].Container.Name[1:]), + fmt.Sprintf("OSMO_B_E2E_VAL_HOST=%s", s.valResources[s.chains[1].ChainMeta.Id][0].Container.Name[1:]), }, Entrypoint: []string{ "sh", @@ -255,18 +260,61 @@ func (s *IntegrationTestSuite) runIBCRelayer() { func (s *IntegrationTestSuite) configureChain(chainId string) { s.T().Logf("starting e2e infrastructure for chain-id: %s", chainId) tmpDir, err := ioutil.TempDir("", "osmosis-e2e-testnet-") + + s.T().Logf("temp directory for chain-id %v: %v", chainId, tmpDir) s.Require().NoError(err) - newChain, err := chain.Init(chainId, tmpDir) - s.chains = append(s.chains, newChain) + + s.initResource, err = s.dkrPool.RunWithOptions( + &dockertest.RunOptions{ + Name: fmt.Sprintf("%s", chainId), + Repository: "osmosis-e2e-chain-init", + Tag: "debug", + NetworkID: s.dkrNet.Network.ID, + Cmd: []string{ + fmt.Sprintf("--data-dir=%s", tmpDir), + fmt.Sprintf("--chain-id=%s", chainId), + }, + User: "root:root", + Mounts: []string{ + fmt.Sprintf("%s:%s", tmpDir, tmpDir), + }, + }, + noRestart, + ) s.Require().NoError(err) + + var newChain chain.Chain + + fileName := fmt.Sprintf("%v/%v-encode", tmpDir, chainId) + s.T().Logf("serialized init file for chain-id %v: %v", chainId, fileName) + + // loop through the reading and unmarshaling of the init file a total of maxRetries or until error is nil + // without this, test attempts to unmarshal file before docker container is finished writing + for i := 0; i < maxRetries; i++ { + encJson, _ := os.ReadFile(fileName) + err = json.Unmarshal(encJson, &newChain) + if err == nil { + break + } + + if i == maxRetries-1 { + s.Require().NoError(err) + } + + if i > 0 { + time.Sleep(1 * time.Second) + } + } + s.chains = append(s.chains, &newChain) + } -func (s *IntegrationTestSuite) configureDockerResources() { +func (s *IntegrationTestSuite) configureDockerResources(chainIDOne, chainIDTwo string) { var err error s.dkrPool, err = dockertest.NewPool("") s.Require().NoError(err) - s.dkrNet, err = s.dkrPool.CreateNetwork(fmt.Sprintf("%s-%s-testnet", s.chains[0].Id, s.chains[1].Id)) + s.dkrNet, err = s.dkrPool.CreateNetwork(fmt.Sprintf("%s-%s-testnet", chainIDOne, chainIDTwo)) s.Require().NoError(err) s.valResources = make(map[string][]*dockertest.Resource) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index dc011b0a80b..e93d8e10db7 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -22,14 +22,14 @@ func (s *IntegrationTestSuite) TestQueryBalances() { expectedBalancesB = []uint64{chain.OsmoBalanceB, chain.StakeBalanceB - chain.StakeAmountB, chain.IbcSendAmount} ) - chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chains[0].Id][0].GetHostPort("1317/tcp")) - balancesA, err := queryBalances(chainAAPIEndpoint, s.chains[0].Validators[0].GetKeyInfo().GetAddress().String()) + chainAAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chains[0].ChainMeta.Id][0].GetHostPort("1317/tcp")) + balancesA, err := queryBalances(chainAAPIEndpoint, s.chains[0].Validators[0].PublicAddress) s.Require().NoError(err) s.Require().NotNil(balancesA) s.Require().Equal(2, len(balancesA)) - chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chains[1].Id][0].GetHostPort("1317/tcp")) - balancesB, err := queryBalances(chainBAPIEndpoint, s.chains[1].Validators[0].GetKeyInfo().GetAddress().String()) + chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chains[1].ChainMeta.Id][0].GetHostPort("1317/tcp")) + balancesB, err := queryBalances(chainBAPIEndpoint, s.chains[1].Validators[0].PublicAddress) s.Require().NoError(err) s.Require().NotNil(balancesB) s.Require().Equal(3, len(balancesB)) @@ -101,11 +101,11 @@ func (s *IntegrationTestSuite) TestIBCTokenTransfer() { var ibcStakeDenom string s.Run("send_uosmo_to_chainB", func() { - recipient := s.chains[1].Validators[0].GetKeyInfo().GetAddress().String() + recipient := s.chains[1].Validators[0].PublicAddress token := sdk.NewInt64Coin(chain.OsmoDenom, chain.IbcSendAmount) // 3,300uosmo - s.sendIBC(s.chains[0].Id, s.chains[1].Id, recipient, token) + s.sendIBC(s.chains[0].ChainMeta.Id, s.chains[1].ChainMeta.Id, recipient, token) - chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chains[1].Id][0].GetHostPort("1317/tcp")) + chainBAPIEndpoint := fmt.Sprintf("http://%s", s.valResources[s.chains[1].ChainMeta.Id][0].GetHostPort("1317/tcp")) // require the recipient account receives the IBC tokens (IBC packets ACKd) var ( diff --git a/tests/e2e/e2e_util_test.go b/tests/e2e/e2e_util_test.go index fb6d7de3727..83976442b76 100644 --- a/tests/e2e/e2e_util_test.go +++ b/tests/e2e/e2e_util_test.go @@ -11,7 +11,7 @@ import ( ) func (s *IntegrationTestSuite) connectIBCChains() { - s.T().Logf("connecting %s and %s chains via IBC", s.chains[0].Id, s.chains[1].Id) + s.T().Logf("connecting %s and %s chains via IBC", s.chains[0].ChainMeta.Id, s.chains[1].ChainMeta.Id) ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() @@ -26,8 +26,8 @@ func (s *IntegrationTestSuite) connectIBCChains() { "hermes", "create", "channel", - s.chains[0].Id, - s.chains[1].Id, + s.chains[0].ChainMeta.Id, + s.chains[1].ChainMeta.Id, "--port-a=transfer", "--port-b=transfer", }, @@ -56,7 +56,7 @@ func (s *IntegrationTestSuite) connectIBCChains() { "failed to connect chains via IBC: %s", errBuf.String(), ) - s.T().Logf("connected %s and %s chains via IBC", s.chains[0].Id, s.chains[1].Id) + s.T().Logf("connected %s and %s chains via IBC", s.chains[0].ChainMeta.Id, s.chains[1].ChainMeta.Id) } func (s *IntegrationTestSuite) sendIBC(srcChainID, dstChainID, recipient string, token sdk.Coin) {