diff --git a/.gitattributes b/.gitattributes index eb6e897296..6a47cb6e75 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,4 +5,5 @@ client/docs/* linguist-documentation docs/* linguist-documentation x/**/spec/* linguist-documentation **/*.pb.go linguist-generated -**/*.pb.gw.go linguist-generated \ No newline at end of file +**/*.pb.gw.go linguist-generated +.tgz filter=lfs diff=lfs merge=lfs -text diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 0000000000..d3d9d402a4 --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,39 @@ +name: "docker-build" + +on: + push: + branches: + - "main" + workflow_dispatch: + +jobs: + docker-build: + runs-on: "ubuntu-latest" + permissions: + contents: write + packages: write + steps: + - name: "Checkout source code" + uses: "actions/checkout@v2" + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.17 + - name: "Build" + run: "make build" + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Login to GHCR + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push + uses: docker/build-push-action@v2 + with: + push: true + tags: ghcr.io/celestiaorg/celestia-node:latest + file: docker/Dockerfile diff --git a/.github/workflows/docker-push.yml b/.github/workflows/docker-push.yml new file mode 100644 index 0000000000..ce07797233 --- /dev/null +++ b/.github/workflows/docker-push.yml @@ -0,0 +1,43 @@ +name: Push to Docker Hub + +on: + push: + tags: + - "v*.*.*" + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v2 + - + name: Git fetch everything + run: git fetch --prune --unshallow + - + name: Get Github tag + id: meta + run: | + echo "::set-output name=tag::$(git describe --always --tags --match='v*')" + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - + name: Login to DockerHub + uses: docker/login-action@v1 + with: + registry: docker.io + username: tharsishq + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + push: true + platforms: linux/amd64, linux/386, linux/arm64 + tags: tharsishq/evmos:latest, tharsishq/evmos:${{ steps.meta.outputs.tag }} diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 2b947dcd9a..a7d878ed4e 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -1,20 +1,34 @@ name: Run Gosec on: + pull_request: push: branches: - main - pull_request: - branches: - - '**' + jobs: - tests: + Gosec: runs-on: ubuntu-latest env: GO111MODULE: on steps: - name: Checkout Source - uses: actions/checkout@v2 + uses: actions/checkout@v2.4.0 + - name: Get Diff + uses: technote-space/get-diff-action@v5 + with: + PATTERNS: | + **/*.go + go.mod + go.sum - name: Run Gosec Security Scanner uses: informalsystems/gosec@master with: - args: ./... \ No newline at end of file + # we let the report trigger content trigger a failure using the GitHub Security features. + args: '-no-fail -fmt sarif -out results.sarif ./...' + if: "env.GIT_DIFF_FILTERED != ''" + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v1 + with: + # Path to SARIF file relative to the root of the repository + sarif_file: results.sarif + if: "env.GIT_DIFF_FILTERED != ''" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0645fd5e5d..e8579c6071 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: - name: Install tparse run: | export GO111MODULE="on" && go get github.com/mfridman/tparse@latest - - uses: actions/cache@v2.1.6 + - uses: actions/cache@v2.1.7 with: path: ~/go/bin key: ${{ runner.os }}-go-tparse-binary diff --git a/.markdownlint.yml b/.markdownlint.yml new file mode 100644 index 0000000000..0978bcb3d6 --- /dev/null +++ b/.markdownlint.yml @@ -0,0 +1,18 @@ +"default": true +"MD001": false +"MD004": false +"MD007": + "indent": 4 +"MD013": false +"MD024": + "siblings_only": true +"MD025": false +"MD026": + "punctuation": ".;:" +"MD029": false +"MD033": false +"MD034": false +"MD036": false +"MD040": false +"MD041": false +"no-hard-tabs": false diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 0000000000..f3a830d7c1 --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,3 @@ +CHANGELOG.md +docs/api/proto-docs.md +docs/node_modules diff --git a/.mergify.yml b/.mergify.yml index 69eb476cc7..338f0f186f 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -1,10 +1,26 @@ +queue_rules: + - name: default + conditions: + - "#approved-reviews-by>1" + pull_request_rules: - - name: automerge to base branch with label automerge and branch protection passing + - name: automerge to the base branch with label automerge and branch protection passing conditions: - "#approved-reviews-by>1" - base=main - label=automerge actions: + queue: + name: default merge: method: squash strict: true + commit_message: title+body + - name: backport patches to v0.3.x branch + conditions: + - base=main + - label=backport/0.3.x + actions: + backport: + branches: + - release/v0.3.x diff --git a/CHANGELOG.md b/CHANGELOG.md index d6dda7d065..68e2db7db1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,40 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Unreleased +## State Machine Breaking + +* (intrarelayer) [\#119](https://github.com/tharsis/evmos/issues/119) Register `x/intrarelayer` proposal types on governance module. + +### Improvements + +* (app) [\#128](https://github.com/tharsis/evmos/pull/128) Add ibc-go `TestingApp` interface. +* (ci) [\#117](https://github.com/tharsis/evmos/pull/117) Enable automatic backport of PRs. +* (deps) [\#135](https://github.com/tharsis/evmos/pull/135) Bump Ethermint version to [`v0.9.0`](https://github.com/tharsis/ethermint/releases/tag/v0.9.0) +* (ci) [\#136](https://github.com/tharsis/evmos/pull/136) Deploy `evmos` docker container to [docker hub](https://hub.docker.com/u/tharsishq) for every versioned releases + +### Bug Fixes + +* (build) [\#116](https://github.com/tharsis/evmos/pull/116) Fix `build-docker` command + +## [v0.3.0] - 2021-11-24 + +### API Breaking + +* (intrarelayer) [\#99](https://github.com/tharsis/evmos/pull/99) Rename `enable_e_v_m_hook` json parameter to `enable_evm_hook`. + +### Improvements + +* (deps) [\#110](https://github.com/tharsis/evmos/pull/110) Bump Ethermint version to [`v0.8.1`](https://github.com/tharsis/ethermint/releases/tag/v0.8.1) +* (intrarelayer) [\#107](https://github.com/tharsis/evmos/pull/107) Add IBC validation +* (cmd) [\#105](https://github.com/tharsis/evmos/pull/105) Improve testnet command to include JSON-RPC client. + +## Bug Fixes + +* (intrarelayer) [\#109](https://github.com/tharsis/evmos/pull/109) Fix hardcoded intrarelayer nonce and `UpdateTokenPairERC20` proposal to support ERC20s with 0 decimals. +* (intrarelayer) [\#102](https://github.com/tharsis/evmos/pull/102) Add `convert-erc20` cmd + +## [v0.2.0] - 2021-11-17 + ### Features * (intrarelayer) [\#82](https://github.com/tharsis/evmos/pull/82) Intrarelayer module @@ -53,7 +87,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (deps) [\#64](https://github.com/tharsis/evmos/pull/64) Bump Ethermint version to `v0.7.2` -## Bug Fixes +### Bug Fixes * (cmd) [\#41](https://github.com/tharsis/evmos/pull/41) Fix `debug` command. @@ -65,13 +99,13 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [v0.1.1] - 2021-10-07 -## Bug Fixes +### Bug Fixes * (build) [\#30](https://github.com/tharsis/evmos/pull/30) Fix `version` command. ## [v0.1.0] - 2021-10-07 -## Improvements +### Improvements * (cmd) [\#26](https://github.com/tharsis/evmos/pull/26) Use config on genesis accounts. * (deps) [\#28](https://github.com/tharsis/evmos/pull/28) Bump Ethermint version to `v0.7.0` diff --git a/Dockerfile b/Dockerfile index 9f6e109ce4..a3189d3fcd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,30 +1,23 @@ -FROM golang:alpine AS build-env +FROM golang:stretch AS build-env -# Set up dependencies -ENV PACKAGES git build-base - -# Set working directory for the build WORKDIR /go/src/github.com/tharsis/evmos -# Install dependencies -RUN apk add --update $PACKAGES -RUN apk add linux-headers +RUN apt update +RUN apt install git -y -# Add source files COPY . . -# Make the binary RUN make build -# Final image -FROM alpine +FROM golang:stretch + +RUN apt update +RUN apt install ca-certificates jq -y -# Install ca-certificates -RUN apk add --update ca-certificates jq WORKDIR /root -# Copy over binaries from the build-env COPY --from=build-env /go/src/github.com/tharsis/evmos/build/evmosd /usr/bin/evmosd -# Run evmosd by default -CMD ["evmosd"] +EXPOSE 26656 26657 1317 9090 + +CMD ["evmosd"] \ No newline at end of file diff --git a/Makefile b/Makefile index f039083650..98e41eb7eb 100755 --- a/Makefile +++ b/Makefile @@ -14,6 +14,11 @@ SIMAPP = ./app HTTPS_GIT := https://github.com/tharsis/evmos.git DOCKER := $(shell which docker) DOCKER_BUF := $(DOCKER) run --rm -v $(CURDIR):/workspace --workdir /workspace bufbuild/buf +NAMESPACE := tharsishq +PROJECT := evmos +DOCKER_IMAGE := $(NAMESPACE)/$(PROJECT) +COMMIT_HASH := $(shell git rev-parse --short=7 HEAD) +DOCKER_TAG := $(COMMIT_HASH) export GO111MODULE = on @@ -118,7 +123,7 @@ $(BUILD_TARGETS): go.sum $(BUILDDIR)/ $(BUILDDIR)/: mkdir -p $(BUILDDIR)/ -docker-build: +build-docker: # TODO replace with kaniko docker build -t ${DOCKER_IMAGE}:${DOCKER_TAG} . docker tag ${DOCKER_IMAGE}:${DOCKER_TAG} ${DOCKER_IMAGE}:latest @@ -126,11 +131,15 @@ docker-build: # update old container docker rm evmos || true # create a new container from the latest image - docker create --name evmos -t -i tharsis/evmos:latest evmos + docker create --name evmos -t -i ${DOCKER_IMAGE}:latest evmos # move the binaries to the ./build directory mkdir -p ./build/ docker cp evmos:/usr/bin/evmosd ./build/ +push-docker: build-docker + docker push ${DOCKER_IMAGE}:${DOCKER_TAG} + docker push ${DOCKER_IMAGE}:latest + $(MOCKS_DIR): mkdir -p $(MOCKS_DIR) @@ -245,7 +254,7 @@ docs-tools-stamp: docs-tools go.sum: go.mod echo "Ensure dependencies have not been modified ..." >&2 go mod verify - go mod tidy + go mod tidy -e ############################################################################### ### Documentation ### diff --git a/app/app.go b/app/app.go index bba2f8032d..764ddcd7c7 100644 --- a/app/app.go +++ b/app/app.go @@ -92,9 +92,11 @@ import ( porttypes "github.com/cosmos/ibc-go/v2/modules/core/05-port/types" ibchost "github.com/cosmos/ibc-go/v2/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v2/modules/core/keeper" + ibctesting "github.com/cosmos/ibc-go/v2/testing" // unnamed import of statik for swagger UI support _ "github.com/tharsis/ethermint/client/docs/statik" + "github.com/tharsis/ethermint/encoding" "github.com/tharsis/ethermint/app/ante" srvflags "github.com/tharsis/ethermint/server/flags" @@ -108,6 +110,7 @@ import ( feemarketkeeper "github.com/tharsis/ethermint/x/feemarket/keeper" feemarkettypes "github.com/tharsis/ethermint/x/feemarket/types" "github.com/tharsis/evmos/x/intrarelayer" + irclient "github.com/tharsis/evmos/x/intrarelayer/client" irk "github.com/tharsis/evmos/x/intrarelayer/keeper" irt "github.com/tharsis/evmos/x/intrarelayer/types" ) @@ -142,6 +145,9 @@ var ( gov.NewAppModuleBasic( paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler, + // Evmos proposal types + irclient.RegisterCoinProposalHandler, irclient.RegisterERC20ProposalHandler, + irclient.ToggleTokenRelayProposalHandler, irclient.UpdateTokenPairERC20ProposalHandler, ), params.AppModuleBasic{}, crisis.AppModuleBasic{}, @@ -177,9 +183,11 @@ var ( } ) -var _ simapp.App = (*Evmos)(nil) - -// var _ server.Application (*Evmos)(nil) +var ( + _ servertypes.Application = (*Evmos)(nil) + _ simapp.App = (*Evmos)(nil) + _ ibctesting.TestingApp = (*Evmos)(nil) +) // Evmos implements an extended ABCI application. It is an application // that may process transactions through Ethereum's EVM running atop of @@ -375,7 +383,7 @@ func NewEvmos( AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). AddRoute(ibchost.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)). - AddRoute(irt.RouterKey, intrarelayer.NewIntrarelayerProposalHandler(app.IntrarelayerKeeper)) + AddRoute(irt.RouterKey, intrarelayer.NewIntrarelayerProposalHandler(&app.IntrarelayerKeeper)) govKeeper := govkeeper.NewKeeper( appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper, @@ -395,6 +403,8 @@ func NewEvmos( ), ) + app.EvmKeeper = app.EvmKeeper.SetHooks(app.IntrarelayerKeeper) + // Create Transfer Keepers app.TransferKeeper = ibctransferkeeper.NewKeeper( appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), @@ -717,6 +727,34 @@ func (app *Evmos) RegisterTendermintService(clientCtx client.Context) { tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry) } +// IBC Go TestingApp functions + +// GetBaseApp implements the TestingApp interface. +func (app *Evmos) GetBaseApp() *baseapp.BaseApp { + return app.BaseApp +} + +// GetStakingKeeper implements the TestingApp interface. +func (app *Evmos) GetStakingKeeper() stakingkeeper.Keeper { + return app.StakingKeeper +} + +// GetIBCKeeper implements the TestingApp interface. +func (app *Evmos) GetIBCKeeper() *ibckeeper.Keeper { + return app.IBCKeeper +} + +// GetScopedIBCKeeper implements the TestingApp interface. +func (app *Evmos) GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper { + return app.ScopedIBCKeeper +} + +// GetTxConfig implements the TestingApp interface. +func (app *Evmos) GetTxConfig() client.TxConfig { + cfg := encoding.MakeConfig(ModuleBasics) + return cfg.TxConfig +} + // RegisterSwaggerAPI registers swagger route with API Server func RegisterSwaggerAPI(_ client.Context, rtr *mux.Router) { statikFS, err := fs.New() diff --git a/app/export.go b/app/export.go index 54d5ce55db..dcad0fd0f8 100644 --- a/app/export.go +++ b/app/export.go @@ -188,7 +188,9 @@ func (app *Evmos) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs []s counter++ } - iter.Close() + if err := iter.Close(); err != nil { + return err + } if _, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx); err != nil { return err diff --git a/app/test_helpers.go b/app/test_helpers.go index 15c257dcad..810b515ad6 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -5,6 +5,7 @@ import ( "time" "github.com/cosmos/cosmos-sdk/simapp" + ibctesting "github.com/cosmos/ibc-go/v2/testing" "github.com/tharsis/ethermint/encoding" abci "github.com/tendermint/tendermint/abci/types" @@ -69,3 +70,11 @@ func Setup(isCheckTx bool, feemarketGenesis *feemarkettypes.GenesisState) *Evmos return app } + +// SetupTestingApp initializes the IBC-go testing application +func SetupTestingApp() (ibctesting.TestingApp, map[string]json.RawMessage) { + db := dbm.NewMemDB() + cfg := encoding.MakeConfig(ModuleBasics) + app := NewEvmos(log.NewNopLogger(), db, nil, true, map[int64]bool{}, DefaultNodeHome, 5, cfg, simapp.EmptyAppOptions{}) + return app, NewDefaultGenesisState() +} diff --git a/app/tps_counter.go b/app/tps_counter.go index b36c5b36e9..82324b4b6d 100644 --- a/app/tps_counter.go +++ b/app/tps_counter.go @@ -83,9 +83,11 @@ func (tpc *tpsCounter) start(ctx context.Context) error { panic(err) } - // Record to our logger for easy examination in the logs. - secs := float64(tpsReportPeriod) / float64(time.Second) - tpc.logger.Info("Transactions per second", "tps", float64(nTxn)/secs) + if nTxn != 0 { + // Record to our logger for easy examination in the logs. + secs := float64(tpsReportPeriod) / float64(time.Second) + tpc.logger.Info("Transactions per second", "tps", float64(nTxn)/secs) + } lastNFailed = latestNFailed lastNSuccessful = latestNSuccessful diff --git a/app/tps_counter_test.go b/app/tps_counter_test.go index d00999cd13..71a19abb7c 100644 --- a/app/tps_counter_test.go +++ b/app/tps_counter_test.go @@ -16,6 +16,8 @@ import ( ) func TestTPSCounter(t *testing.T) { + t.Skip("FIXME: non deterministic") + buf := new(bytes.Buffer) wlog := &writerLogger{w: buf} tpc := newTPSCounter(wlog) diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000..3531563812 --- /dev/null +++ b/build.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +DOCKER_TAG=$1 + +WORKDIR=$PWD +rm -rf optimint ethermint + +# Get Optimint +git clone git@github.com:celestiaorg/optimint.git -q +echo "cloned optimint" +cd optimint +git checkout 939aa77 -q +echo "checked out 939aa77 commit" +rm -rf .git +go mod tidy -compat=1.17 -e +echo "finished tidying optimint" +cd $WORKDIR + +# Get ethermint +git clone git@github.com:jbowen93/ethermint.git -q +echo "cloned ethermint" +cd ethermint +git checkout jbowen93-optimint -q +echo "checked out jbowen93-optimint branch" +rm -rf .git +go mod edit -replace=github.com/celestiaorg/optimint=../optimint +go mod tidy -compat=1.17 -e +echo "finished tidying ethermint" +cd $WORKDIR + +# Cleanup +go mod edit -replace=github.com/celestiaorg/optimint=./optimint +go mod edit -replace=github.com/tharsis/ethermint=./ethermint +go mod tidy -compat=1.17 -e +echo "finished tidying evmos" + +# Docker build +docker buildx build --platform linux/arm64 -f docker/debug.Dockerfile -t ghcr.io/jbowen93/evmos:$DOCKER_TAG . diff --git a/cmd/evmosd/root.go b/cmd/evmosd/root.go index fe8c1ebf21..df7e4d6aa3 100644 --- a/cmd/evmosd/root.go +++ b/cmd/evmosd/root.go @@ -122,7 +122,10 @@ func NewRootCmd() (*cobra.Command, params.EncodingConfig) { txCommand(), ethermintclient.KeyCommands(app.DefaultNodeHome), ) - rootCmd = srvflags.AddTxFlags(rootCmd) + rootCmd, err := srvflags.AddTxFlags(rootCmd) + if err != nil { + panic(err) + } // add rosetta rootCmd.AddCommand(sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler)) diff --git a/cmd/evmosd/testnet.go b/cmd/evmosd/testnet.go index 1fec932023..8b47b5906b 100644 --- a/cmd/evmosd/testnet.go +++ b/cmd/evmosd/testnet.go @@ -42,7 +42,8 @@ import ( ethermint "github.com/tharsis/ethermint/types" evmtypes "github.com/tharsis/ethermint/x/evm/types" - "github.com/tharsis/evmos/testutil/network" + "github.com/tharsis/ethermint/testutil/network" + evmosnetwork "github.com/tharsis/evmos/testutil/network" ) var ( @@ -519,7 +520,7 @@ func calculateIP(ip string, i int) (string, error) { // startTestnet starts an in-process testnet func startTestnet(cmd *cobra.Command, args startArgs) error { - networkConfig := network.DefaultConfig() + networkConfig := evmosnetwork.DefaultConfig() // Default networkConfig.ChainID is random, and we should only override it if chainID provided // is non-empty @@ -555,7 +556,10 @@ func startTestnet(cmd *cobra.Command, args startArgs) error { } cmd.Println("press the Enter Key to terminate") - fmt.Scanln() // wait for Enter Key + _, err = fmt.Scanln() // wait for Enter Key + if err != nil { + return err + } testnet.Cleanup() return nil diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000000..0c070378cc --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,36 @@ +FROM golang:alpine AS build-env + +# Set up dependencies +ENV PACKAGES git build-base + +# Set working directory for the build +WORKDIR /go/src/github.com/tharsis/evmos + +# Install dependencies +RUN apk add --update $PACKAGES +RUN apk add linux-headers + +# Add source files +COPY . . + +# Make the binary +RUN make build + +# Final image +FROM alpine + +# Install ca-certificates +RUN apk add --update ca-certificates jq + +WORKDIR /root + +COPY docker/entrypoint.sh . +COPY init.sh . + +# Copy over binaries from the build-env +COPY --from=build-env /go/src/github.com/tharsis/evmos/build/evmosd /usr/bin/evmosd + +EXPOSE 26656 26657 + +ENTRYPOINT ["./entrypoint.sh"] +CMD ["evmosd"] diff --git a/docker/debug.Dockerfile b/docker/debug.Dockerfile new file mode 100644 index 0000000000..1850d0f594 --- /dev/null +++ b/docker/debug.Dockerfile @@ -0,0 +1,42 @@ +FROM golang:1.17 AS build-env + +# Set up dependencies +ENV COSMOS_BUILD_OPTIONS nostrip + +# Set working directory for the build +WORKDIR /go/src/github.com/tharsis/evmos + +# Install dependencies +RUN apt update +RUN apt install git + +# Build Delve +RUN go install github.com/go-delve/delve/cmd/dlv@latest + +# Add source files +COPY . . + +# Make the binary +RUN make build + +# Final image +FROM debian + +# Install ca-certificates +RUN apt-get update +RUN apt-get install -y jq procps + +WORKDIR /root + +COPY docker/entrypoint-debug.sh . +COPY init.sh . + +# Copy over binaries from the build-env +COPY --from=build-env /go/src/github.com/tharsis/evmos/build/evmosd /usr/bin/evmosd +COPY --from=build-env /go/bin/dlv /usr/bin/dlv + +EXPOSE 26656 26657 + +ENTRYPOINT ["./entrypoint-debug.sh"] +CMD ["evmosd"] + diff --git a/docker/entrypoint-debug.sh b/docker/entrypoint-debug.sh new file mode 100755 index 0000000000..bdd8a52e5f --- /dev/null +++ b/docker/entrypoint-debug.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e + +if [ "$1" = 'dlv' ]; then + ./init.sh + + exec "$@" "--" +fi + +exec "$@" diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100755 index 0000000000..9fa7aa8948 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e + +if [ "$1" = 'evmosd' ]; then + ./init.sh + + exec "$@" "--" +fi + +exec "$@" diff --git a/docker/evmos-docker-compose-debug.yml b/docker/evmos-docker-compose-debug.yml new file mode 100644 index 0000000000..f039db7d13 --- /dev/null +++ b/docker/evmos-docker-compose-debug.yml @@ -0,0 +1,40 @@ +version: '3' + +services: + evmos0: + container_name: evmos0 + image: "ghcr.io/jbowen93/evmos:testing-debug" + command: [ + "dlv", "--listen=:40000", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", + "/usr/bin/evmosd", "--", "start", + "--optimint.aggregator", "true", + "--optimint.block_time", "30s", + "--optimint.namespace_id", "0000DEADBEEF0000", + "--optimint.da_layer", "grpc", + "--optimint.da_config", '{"host":"192.167.10.14", "port":4200}', + "--rpc.laddr", "tcp://0.0.0.0:26657", + "--json-rpc.enable", "true", + "--json-rpc.api", "eth,txpool,personal,net,web3,miner", + "--json-rpc.address", "0.0.0.0:8545", + ] + ports: + # Expose the EVM json-rpc server + - 8545:8545 + # Debug port + - 40000:40000 + security_opt: + - "seccomp:unconfined" + cap_add: + - SYS_PTRACE + networks: + localnet: + ipv4_address: 192.167.10.15 + +networks: + localnet: + driver: bridge + ipam: + driver: default + config: + - + subnet: 192.167.10.0/16 diff --git a/docker/evmos-docker-compose.yml b/docker/evmos-docker-compose.yml new file mode 100644 index 0000000000..cc565d0c19 --- /dev/null +++ b/docker/evmos-docker-compose.yml @@ -0,0 +1,33 @@ +version: '3' + +services: + evmos0: + container_name: evmos0 + image: "ghcr.io/jbowen93/evmos:testing" + command: [ + "evmosd", "start", + "--optimint.aggregator", "true", + "--optimint.block_time", "30s", + "--optimint.namespace_id", "0000DEADBEEF0000", + "--optimint.da_layer", "grpc", + "--optimint.da_config", '{"host":"192.167.10.14", "port":4200}', + "--rpc.laddr", "tcp://0.0.0.0:26657", + "--json-rpc.enable", "true", + "--json-rpc.api", "eth,txpool,personal,net,web3,miner", + "--json-rpc.address", "0.0.0.0:8545", + ] + ports: + # Expose the EVM json-rpc server + - 8545:8545 + networks: + localnet: + ipv4_address: 192.167.10.15 + +networks: + localnet: + driver: bridge + ipam: + driver: default + config: + - + subnet: 192.167.10.0/16 diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 0640a9c83a..ee53062d17 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -62,7 +62,7 @@ module.exports = { rpc_url_local: 'http://localhost:8545/', chain_id: '9001', testnet_chain_id: '9000', - latest_version: 'v0.2.0', + latest_version: 'v0.4.0', version_number: '1', testnet_version_number: '2', block_explorer_url: 'https://evm.evmos.org', diff --git a/docs/api/proto-docs.md b/docs/api/proto-docs.md index dd5accbc8e..f6653faa49 100644 --- a/docs/api/proto-docs.md +++ b/docs/api/proto-docs.md @@ -191,7 +191,7 @@ Params defines the intrarelayer module params | ----- | ---- | ----- | ----------- | | `enable_intrarelayer` | [bool](#bool) | | parameter to enable the intrarelaying of Cosmos coins <--> ERC20 tokens. | | `token_pair_voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | overrides the governance voting period for token pairs proposals | -| `enable_e_v_m_hook` | [bool](#bool) | | parameter to enable the EVM hook to convert an ERC20 token to a Cosmos Coin by transferring the Tokens through a MsgEthereumTx to the ModuleAddress Ethereum address. | +| `enable_evm_hook` | [bool](#bool) | | parameter to enable the EVM hook to convert an ERC20 token to a Cosmos Coin by transferring the Tokens through a MsgEthereumTx to the ModuleAddress Ethereum address. | diff --git a/docs/guides/img/reset_account.png b/docs/guides/img/reset_account.png new file mode 100644 index 0000000000..51dce6a96e Binary files /dev/null and b/docs/guides/img/reset_account.png differ diff --git a/docs/guides/keys-wallets/metamask.md b/docs/guides/keys-wallets/metamask.md index 436d8e3ddf..f7c5daf699 100644 --- a/docs/guides/keys-wallets/metamask.md +++ b/docs/guides/keys-wallets/metamask.md @@ -75,6 +75,18 @@ Your account balance should show up as `1 {{ $themeConfig.project.testnet_ticker If it takes some time to load the balance of the account, change the network to `Main Ethereum Network` (or any other than `Localhost 8545` or `{{ $themeConfig.project.name }}`) and then switch back to `{{ $themeConfig.project.name }}`. ::: -## Downloading State +## Reset Account -To see your Metamask logs, click the top right circle and go to `Settings` > `Advanced` > `Download State Logs`. If you search through the JSON file for the account address you'll find the transaction history. +If you used your Metamask account for a legacy testnet/mainnet upgrade, you will need to reset your account in order to use it with the new network. This will clear your account's transaction history, but it won't change the balances in your accounts or require you to re-enter your `Secret Recovery Phrase`. + +::: warning +Make sure you download your [account state](#download-account-state) to persist public account addresses and transactions before clearing your wallet accounts. +::: + +Go to `Settings` > `Advanced` and click the `Reset Account` button as shown below: + +![Metamask Account Reset](./../img/reset_account.png) + +## Download Account State + +To see your Metamask logs, click the top right circle and go to `Settings` > `Advanced` > `State Logs`. If you search through the JSON file for the account address you'll find the transaction history. diff --git a/docs/quickstart/binary.md b/docs/quickstart/binary.md index 843ff656d1..302d499138 100644 --- a/docs/quickstart/binary.md +++ b/docs/quickstart/binary.md @@ -62,7 +62,7 @@ The Cosmos SDK automatically generates two configuration files inside `~/.evmosd Both files are heavily commented, please refer to them directly to tweak your node. -One example config to tweak is the `minimum-gas-prices` field inside `app.toml`, which defines the minimum amount the validator node is willing to accept for processing a transaction. It is am anti spam mechanism and it will reject incoming transactions with less than the minimum gas prices. +One example config to tweak is the `minimum-gas-prices` field inside `app.toml`, which defines the minimum amount the validator node is willing to accept for processing a transaction. It is an anti spam mechanism and it will reject incoming transactions with less than the minimum gas prices. If it's empty, make sure to edit the field with some value, for example `10token`, or else the node will halt on startup. diff --git a/docs/quickstart/installation.md b/docs/quickstart/installation.md index 1502810e19..9cc32d0ec3 100644 --- a/docs/quickstart/installation.md +++ b/docs/quickstart/installation.md @@ -57,14 +57,19 @@ evmosd version You can build {{ $themeConfig.project.name }} using Docker by running: ```bash -make docker-build +make build-docker ``` -This will install the binaries on the `./build` directory. Now, check that the binaries have been -successfully installed: +The command above will create a docker container: `tharsishq/evmos:latest`. Now you can run `evmosd` in the container. ```bash -evmosd version +docker run -it -p 26657:26657 -p 26656:26656 -v ~/.evmosd/:/root/.evmosd tharsishq/evmos:latest evmosd version + +# To initialize +# docker run -it -p 26657:26657 -p 26656:26656 -v ~/.evmosd/:/root/.evmosd tharsishq/evmos:latest evmosd init test-chain --chain-id test_9000-2 + +# To run +# docker run -it -p 26657:26657 -p 26656:26656 -v ~/.evmosd/:/root/.evmosd tharsishq/evmos:latest evmosd start ``` ### Releases diff --git a/docs/testnet/join.md b/docs/testnet/join.md index d18386140b..8b557eb449 100644 --- a/docs/testnet/join.md +++ b/docs/testnet/join.md @@ -10,10 +10,10 @@ This document outlines the steps to join an existing testnet {synopsis} You specify the network you want to join by setting the **genesis file** and **seeds**. If you need more information about past networks, check our [testnets repo](https://github.com/tharsis/testnets). -| Network Chain ID | Description | Site | Version | -|--------------------------------------------------------|-----------------------------------|--------------------------------------------------------------------------|-------------------------------------------------------| -| `evmos_{{ $themeConfig.project.testnet_chain_id }}-2` | Olympus Mons Incentivized Testnet | [Olympus Mons](https://github.com/tharsis/testnets/tree/main/arsia_mons) | [`v0.2.x`](https://github.com/tharsis/evmos/releases) | -| `evmos_9000-1` | Arsia Mons Testnet | [Arsia Mons](https://github.com/tharsis/testnets/tree/main/arsia_mons) | [`v0.1.x`](https://github.com/tharsis/evmos/releases) | +| Network Chain ID | Description | Site | Version | +|------------------|-----------------------------------|--------------------------------------------------------------------------|-------------------------------------------------------| +| `evmos_9000-2` | Olympus Mons Incentivized Testnet | [Olympus Mons](https://github.com/tharsis/testnets/tree/main/arsia_mons) | [`v0.3.x`](https://github.com/tharsis/evmos/releases) | +| `evmos_9000-1` | Arsia Mons Testnet | [Arsia Mons](https://github.com/tharsis/testnets/tree/main/arsia_mons) | [`v0.1.x`](https://github.com/tharsis/evmos/releases) | ## Install `evmosd` @@ -84,6 +84,13 @@ Edit the file located in `~/.evmosd/config/config.toml` and the `seeds` to the f seeds = "@:" ``` +You can use the following code to get seeds from the repo and add it to your config: + +```bash +SEEDS=`curl -sL https://raw.githubusercontent.com/tharsis/testnets/main/olympus_mons/seeds.txt | awk '{print $1}' | paste -s -d, -` +sed -i.bak -e "s/^seeds =.*/seeds = \"$SEEDS\"/" ~/.evmosd/config/config.toml +``` + :::tip For more information on seeds and peers, you can the Tendermint [P2P documentation](https://docs.tendermint.com/master/spec/p2p/peer.html). ::: @@ -93,11 +100,10 @@ For more information on seeds and peers, you can the Tendermint [P2P documentati We can set the [`persistent_peers`](https://docs.tendermint.com/master/tendermint-core/using-tendermint.html#persistent-peer) field in `~/.evmosd/config/config.toml` to specify peers that your node will maintain persistent connections with. You can retrieve them from the list of available peers on the [`testnets`](https://github.com/tharsis/testnets) repo. -A list of available persistent peers is also available in the `#find-peers` channel in the [Evmos Discord](https://discord.gg/trje9XuAmy). +A list of available persistent peers is also available in the `#find-peers` channel in the [Evmos Discord](https://discord.gg/trje9XuAmy). You can get a random 10 entries from the `peers.txt` file in the `PEERS` variable by running the following command: ```bash -curl https://raw.githubusercontent.com/tharsis/testnets/main/olympus_mons/peers.txt > peers.txt -PEERS=`awk '{print $1}' peers.txt | paste -s -d, -` +PEERS=`curl -sL https://raw.githubusercontent.com/tharsis/testnets/main/olympus_mons/peers.txt | sort -R | head -n 10 | awk '{print $1}' | paste -s -d, -` ``` Use `sed` to include them into the configuration. You can also add them manually: diff --git a/ethermint b/ethermint new file mode 160000 index 0000000000..f611b0d858 --- /dev/null +++ b/ethermint @@ -0,0 +1 @@ +Subproject commit f611b0d858da94d0b8e5ae955add9ef9ce74cacf diff --git a/go.mod b/go.mod index a2a77e1ac7..9c8ed67640 100644 --- a/go.mod +++ b/go.mod @@ -13,14 +13,14 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/rakyll/statik v0.1.7 github.com/spf13/cast v1.4.1 - github.com/spf13/cobra v1.2.1 + github.com/spf13/cobra v1.3.0 github.com/stretchr/testify v1.7.0 github.com/tendermint/tendermint v0.34.14 - github.com/tendermint/tm-db v0.6.4 + github.com/tendermint/tm-db v0.6.6 github.com/tharsis/ethermint v0.8.0 go.opencensus.io v0.23.0 - google.golang.org/genproto v0.0.0-20211116182654-e63d96a377c4 - google.golang.org/grpc v1.42.0 + google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa + google.golang.org/grpc v1.43.0 google.golang.org/protobuf v1.27.1 ) @@ -32,13 +32,13 @@ require ( github.com/StackExchange/wmi v1.2.1 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/Workiva/go-datastructures v1.0.53 // indirect - github.com/allegro/bigcache v1.2.1 // indirect - github.com/armon/go-metrics v0.3.9 // indirect + github.com/adlio/schema v1.1.14 // indirect + github.com/armon/go-metrics v0.3.10 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect github.com/btcsuite/btcd v0.22.0-beta // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect - github.com/celestiaorg/optimint v0.0.0-20211119113807-406ce5950325 // indirect + github.com/celestiaorg/optimint v0.0.0-20220118134333-5bdc6d3b8868 // indirect github.com/cenkalti/backoff/v4 v4.1.1 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -165,12 +165,12 @@ require ( github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/minio/sha256-simd v1.0.0 // indirect - github.com/mitchellh/mapstructure v1.4.2 // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/multiformats/go-base32 v0.0.3 // indirect github.com/multiformats/go-base36 v0.1.0 // indirect - github.com/multiformats/go-multiaddr v0.4.1 // indirect + github.com/multiformats/go-multiaddr v0.5.0 // indirect github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect github.com/multiformats/go-multibase v0.0.3 // indirect @@ -186,16 +186,16 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1 // indirect - github.com/prometheus/client_golang v1.11.0 // indirect + github.com/prometheus/client_golang v1.12.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.30.0 // indirect + github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/statsd_exporter v0.21.0 // indirect github.com/prometheus/tsdb v0.10.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/regen-network/cosmos-proto v0.3.1 // indirect github.com/rjeczalik/notify v0.9.2 // indirect - github.com/rs/cors v1.8.0 // indirect + github.com/rs/cors v1.8.2 // indirect github.com/rs/zerolog v1.26.0 // indirect github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect @@ -203,7 +203,7 @@ require ( github.com/spf13/afero v1.6.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.9.0 // indirect + github.com/spf13/viper v1.10.1 // indirect github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect @@ -225,10 +225,10 @@ require ( golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8 // indirect golang.org/x/net v0.0.0-20211111160137-58aab5ef257a // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20211111213525-f221eed1c01e // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect golang.org/x/text v0.3.7 // indirect - gopkg.in/ini.v1 v1.63.2 // indirect + gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -236,7 +236,7 @@ require ( nhooyr.io/websocket v1.8.7 // indirect ) -replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 +// replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 @@ -245,4 +245,6 @@ replace github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210 // TODO: remove once v0.45 has been released replace github.com/cosmos/cosmos-sdk => github.com/tharsis/cosmos-sdk v0.44.3-olympus -replace github.com/tharsis/ethermint => github.com/celestiaorg/ethermint v0.6.1-0.20211119121737-68d87bd5ad40 +replace github.com/tharsis/ethermint => ./ethermint + +replace github.com/celestiaorg/optimint => ./optimint diff --git a/go.sum b/go.sum index 61a23a7154..32e7f37383 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -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= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= @@ -28,6 +28,10 @@ cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSU cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.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= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -38,7 +42,7 @@ cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -88,8 +92,6 @@ github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.4.8 h1:Rpmta4xZ/MgZnriKNd24iZMhGpP5dvUcs/uqfBapKZY= github.com/DataDog/zstd v1.4.8/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= @@ -124,9 +126,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= -github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= -github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= @@ -137,28 +138,25 @@ github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1: github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18= github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= +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/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= -github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM= -github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= -github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/benbjohnson/clock v1.0.2/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= @@ -202,16 +200,12 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= -github.com/celestiaorg/ethermint v0.6.1-0.20211119121737-68d87bd5ad40 h1:0oOCd8xMf4I+LkgK1z6kSAg2twXEddTROkc71QE2dvg= -github.com/celestiaorg/ethermint v0.6.1-0.20211119121737-68d87bd5ad40/go.mod h1:3vzqrqmpTLZN/vuBuiPqp906z0o1VkXKTjzDc6sq80A= -github.com/celestiaorg/optimint v0.0.0-20211119113807-406ce5950325 h1:92uHNWfWtETQtQiP/pn9A3Iw4kwrbvUiA25OTY9GUhI= -github.com/celestiaorg/optimint v0.0.0-20211119113807-406ce5950325/go.mod h1:OLuwV/ADWFeGZ2bJalbTB1VFM2ZpwFRAYzNfaiwE1QY= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= @@ -228,24 +222,30 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +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 h1:rgHD/nHjxLh0lMEdfGDqpTtlvtSBwULqrrZ2qPdNaCM= github.com/coinbase/rosetta-sdk-go v0.6.10/go.mod h1:J/JFMsfcePrjJZkwQFLh+hJErkAmdm9Iyy3D5Y0LfXo= -github.com/confio/ics23/go v0.0.0-20200817220745-f173e6211efb/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= -github.com/confio/ics23/go v0.6.3/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= 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/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= 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 h1:j/9Wnn+hrEWjLvHuIxUU1YI5JjEjVlT2AA68cse9rwY= github.com/containerd/continuity v0.2.0/go.mod h1:wCYX+dRqZdImhGucXOqTQn05AhX6EUDaGEMUzTFFpLg= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -264,10 +264,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= -github.com/cosmos/iavl v0.15.0-rc3.0.20201009144442-230e9bdf52cd/go.mod h1:3xOIaNNX19p0QrX0VqWa6voPRoJRGGYtny+DH8NEPvE= -github.com/cosmos/iavl v0.15.0-rc5/go.mod h1:WqoPL9yPTQ85QBMT45OOUzPxG/U/JcJoN7uMjgxke/I= -github.com/cosmos/iavl v0.15.3/go.mod h1:OLjQiAQ4fGD2KDZooyJG9yz+p2ao2IAYSbke8mVvSA4= -github.com/cosmos/iavl v0.17.1/go.mod h1:7aisPZK8yCpQdy3PMvKeO+bhq1NwDjUwjzxwwROUxFk= github.com/cosmos/iavl v0.17.2 h1:BT2u7DUvLLB+RYz9RItn/8n7Bt5xe5rj8QRTkk/PQU0= github.com/cosmos/iavl v0.17.2/go.mod h1:prJoErZFABYZGDHka1R6Oay4z9PrNeFFiMKHDAMOi4w= github.com/cosmos/ibc-go/v2 v2.0.0 h1:BMRg73JcdV9wGPI51j89ihm7VBZQsDLkqQ+tmzdeA9Y= @@ -281,6 +277,7 @@ github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9 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/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= @@ -307,9 +304,7 @@ github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzA github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= -github.com/dgraph-io/badger v1.6.2 h1:mNw0qs90GVgGGWylh0umH5iag1j6n/PeJtNvL6KY/x8= github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= -github.com/dgraph-io/badger/v2 v2.2007.1/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= github.com/dgraph-io/badger/v2 v2.2007.3 h1:Sl9tQWz92WCbVSe8pj04Tkqlm2boW+KAxd+XSs58SQI= github.com/dgraph-io/badger/v2 v2.2007.3/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= @@ -352,10 +347,19 @@ github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4pn2T/hjXMbvwTr1Cvy5THHrQkbeY9HRk= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= -github.com/ethereum/go-ethereum v1.10.4/go.mod h1:nEE0TP5MtxGzOMd7egIrbPJMQBnhVU3ELNxhBglIzhg= github.com/ethereum/go-ethereum v1.10.11 h1:KKIcwpmur9iTaVbR2dxlHu+peHVhU+/KX//NWvT1n9U= github.com/ethereum/go-ethereum v1.10.11/go.mod h1:W3yfrFyL9C1pHcwY5hmRHVDaorTiQxhYBkKyu5mEDHw= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= @@ -368,7 +372,7 @@ github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= 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= @@ -383,7 +387,6 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -397,7 +400,6 @@ github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW 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 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= @@ -428,10 +430,8 @@ github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-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 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= @@ -444,7 +444,6 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= @@ -457,7 +456,7 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -471,6 +470,8 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= @@ -567,9 +568,9 @@ github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE0 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f h1:KMlcu9X58lhTA/KrfX8Bi1LQSO4pzoVjTiL3h4Jk+Zk= -github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= @@ -592,7 +593,6 @@ github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.1/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= @@ -601,7 +601,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpg github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= @@ -615,7 +614,7 @@ github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfm github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= 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/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= @@ -627,7 +626,7 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -656,10 +655,13 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 h1:uUjLpLt6bVvZ72SQc/B4dXcPBw4Vgd7soowdRl52qEM= github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87/go.mod h1:XGsKKeXxeRr95aEOgipvluMPlgjr7dGlk9ZTWOjcUcg= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= @@ -669,12 +671,11 @@ github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.0.1-0.20210310174557-0ca763054c88/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo= github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/improbable-eng/grpc-web v0.14.1/go.mod h1:zEjGHa8DAlkoOXmswrNvhUGEYQA9UI7DhrGeHR1DMGU= @@ -687,7 +688,6 @@ github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZ github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= 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/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= @@ -807,10 +807,8 @@ github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= @@ -837,7 +835,6 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -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/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -961,7 +958,6 @@ github.com/libp2p/go-libp2p-pubsub v0.5.6/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQ github.com/libp2p/go-libp2p-quic-transport v0.10.0/go.mod h1:RfJbZ8IqXIhxBRm5hqUEJqjiiY8xmEuq3HUDS993MkA= github.com/libp2p/go-libp2p-quic-transport v0.11.2/go.mod h1:wlanzKtIh6pHrq+0U3p3DY9PJfGqxMgPaGKaK5LifwQ= github.com/libp2p/go-libp2p-quic-transport v0.12.0 h1:7IjDH4XNkmJbOMD+mxRloTe4LzMTq+vqvm2nYNL1N7M= -github.com/libp2p/go-libp2p-quic-transport v0.12.0/go.mod h1:EKHqxZbWE/FhDJZ6ebyZ/4v3X9zyuuuKIN0XR9vANT0= github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= github.com/libp2p/go-libp2p-record v0.1.3 h1:R27hoScIhQf/A8XJZ8lYpnqh9LatJ5YbHs28kCIfql0= github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= @@ -1071,7 +1067,6 @@ github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZ github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= -github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux/v2 v2.2.0 h1:RwtpYZ2/wVviZ5+3pjC8qdQ4TKnrak0/E01N1UWoAFU= github.com/libp2p/go-yamux/v2 v2.2.0/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= @@ -1081,9 +1076,10 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U github.com/lucas-clemente/quic-go v0.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8= github.com/lucas-clemente/quic-go v0.21.2/go.mod h1:vF5M1XqhBAHgbjKcJOXY3JZz3GP0T3FQhz/uyOUS38Q= github.com/lucas-clemente/quic-go v0.23.0 h1:5vFnKtZ6nHDFsc/F3uuiF4T3y/AXaQdxjUqiVw26GZE= -github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= @@ -1099,9 +1095,8 @@ github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1j github.com/marten-seemann/qtls-go1-15 v0.1.5/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= +github.com/marten-seemann/qtls-go1-17 v0.1.0-rc.1 h1:/rpmWuGvceLwwWuaKPdjpR4JJEUH0tq64/I3hvzaNLM= github.com/marten-seemann/qtls-go1-17 v0.1.0-rc.1/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= -github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= -github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= @@ -1112,8 +1107,10 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -1147,7 +1144,6 @@ github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJys github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/miguelmota/go-ethereum-hdwallet v0.1.1 h1:zdXGlHao7idpCBjEGTXThVAtMKs+IxAgivZ75xqkWK0= -github.com/miguelmota/go-ethereum-hdwallet v0.1.1/go.mod h1:f9m9uXokAHA6WNoYOPjj4AqjJS5pquQRiYYj/XSyPYc= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= @@ -1179,8 +1175,9 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= @@ -1217,8 +1214,8 @@ github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4 github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= github.com/multiformats/go-multiaddr v0.3.3/go.mod h1:lCKNGP1EQ1eZ35Za2wlqnabm9xQkib3fyB+nZXHLag0= github.com/multiformats/go-multiaddr v0.4.0/go.mod h1:YcpyLH8ZPudLxQlemYBPhSm0/oCXAT8Z4mzFpyoPyRc= -github.com/multiformats/go-multiaddr v0.4.1 h1:Pq37uLx3hsyNlTDir7FZyU8+cFCTqd5y1KiM2IzOutI= -github.com/multiformats/go-multiaddr v0.4.1/go.mod h1:3afI9HfVW8csiF8UZqtpYRiDyew8pRX7qLIGHu9FLuM= +github.com/multiformats/go-multiaddr v0.5.0 h1:i/JuOoVg4szYQ4YEzDGtb2h0o8M7CG/Yq6cGlcjWZpM= +github.com/multiformats/go-multiaddr v0.5.0/go.mod h1:3KAxNkUqLTJ20AAwN4XVX4kZar+bR+gh4zgbfr3SNug= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= @@ -1267,16 +1264,10 @@ github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q= -github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nats.go v1.12.1/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= -github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= @@ -1303,7 +1294,6 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -1311,9 +1301,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= -github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -1337,7 +1325,6 @@ github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTm github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/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/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ= @@ -1360,7 +1347,6 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= -github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= @@ -1393,8 +1379,9 @@ github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg= +github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1417,8 +1404,9 @@ github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16 github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.28.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.30.0 h1:JEkYlQnpzrzQFxi6gnukFPdQ+ac82oRhzMcIduJu/Ug= github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1456,8 +1444,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 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 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so= -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= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= @@ -1466,10 +1454,10 @@ github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE= github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/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/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4= github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= @@ -1513,7 +1501,6 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= -github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= @@ -1529,6 +1516,7 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1539,8 +1527,9 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 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 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= +github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1553,8 +1542,9 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.9.0 h1:yR6EXjTp0y0cLN8OZg1CRZmOBdI88UcGkhgyJhu6nZk= -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/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.0.0-20200402102358-957c09536969 h1:Oo2KZNP70KE0+IUJSidPj/BFS/RXNHmKIJOdckzml2E= @@ -1563,9 +1553,7 @@ github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8 github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= -github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -1583,7 +1571,6 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= -github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= @@ -1595,16 +1582,11 @@ github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RM github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= -github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= -github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= -github.com/tendermint/tendermint v0.34.13/go.mod h1:6RVVRBqwtKhA+H59APKumO+B7Nye4QXSFc6+TYxAxCI= github.com/tendermint/tendermint v0.34.14 h1:GCXmlS8Bqd2Ix3TQCpwYLUNHe+Y+QyJsm5YE+S/FkPo= github.com/tendermint/tendermint v0.34.14/go.mod h1:FrwVm3TvsVicI9Z7FlucHV6Znfd5KBc/Lpp69cCwtk0= -github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= -github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= -github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ= github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= +github.com/tendermint/tm-db v0.6.6 h1:EzhaOfR0bdKyATqcd5PNeyeq8r+V4bRPHBfyFdD9kGM= +github.com/tendermint/tm-db v0.6.6/go.mod h1:wP8d49A85B7/erz/r4YbKssKw6ylsO/hKtFk7E1aWZI= github.com/tharsis/cosmos-sdk v0.44.3-olympus h1:OPkrIgqscw8LmAAoZCvhM0gQCYsblrydoIumEKtATsM= github.com/tharsis/cosmos-sdk v0.44.3-olympus/go.mod h1:0QTCOkE8IWu5LZyfnbbjFjxYRIcV4pBOr7+zPpJwl58= github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= @@ -1681,9 +1663,11 @@ go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -1700,6 +1684,7 @@ go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzox go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1754,25 +1739,19 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -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-20200602180216-279210d13fed/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-20210220033148-5ea612d1eb83/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-20210506145944-38f3c27a63bf/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-20210813211128-0a44fdfbc16e/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= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8 h1:5QRxNnVsaJP6NAse0UdkRgL3zHMvCRRkrDVLNdNpdy4= golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1793,6 +1772,8 @@ golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8H golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -1821,6 +1802,7 @@ golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1846,7 +1828,6 @@ golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-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-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= @@ -1875,15 +1856,14 @@ golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v 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-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-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= 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-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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-20211111160137-58aab5ef257a h1:c83jeVQW0KGKNaKBRfelNYNHaev+qawl9yaA825s8XE= golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1905,6 +1885,8 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1919,6 +1901,7 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2029,11 +2012,14 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc 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-20210917161153-d61c044b1678/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-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-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211111213525-f221eed1c01e h1:zeJt6jBtVDK23XK9QXcmG0FvO0elikp0dYZQZOeL1y0= -golang.org/x/sys v0.0.0-20211111213525-f221eed1c01e/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-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -2051,15 +2037,15 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -2136,7 +2122,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= @@ -2171,7 +2156,13 @@ google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtuk google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.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/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2221,7 +2212,6 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2244,11 +2234,57 @@ google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKr google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20211116182654-e63d96a377c4 h1:nPiLDJ9/wsay2NDshdJ1B24frx+butTxmaVaCxDBChY= -google.golang.org/genproto v0.0.0-20211116182654-e63d96a377c4/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +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 h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2269,7 +2305,6 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -2277,13 +2312,12 @@ gopkg.in/cheggaaa/pb.v1 v1.0.25/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/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 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 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c= gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 h1:a6cXbcDDUkSBlpnkWV1bJ+vv3mOgQEltEJ2rPxroVu0= @@ -2311,6 +2345,7 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2327,7 +2362,6 @@ rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/init.sh b/init.sh old mode 100644 new mode 100755 index 27e4a0fdf7..d039213866 --- a/init.sh +++ b/init.sh @@ -1,6 +1,7 @@ +#!/bin/sh KEY="mykey" -CHAINID="evmosopti_9000-1" +CHAINID="opti_9000-1" MONIKER="localtestnet" KEYRING="test" KEYALGO="eth_secp256k1" @@ -15,7 +16,7 @@ command -v jq > /dev/null 2>&1 || { echo >&2 "jq not installed. More info: https # remove existing daemon rm -rf ~/.evmosd* -make install +# make install evmosd config keyring-backend $KEYRING evmosd config chain-id $CHAINID @@ -45,7 +46,7 @@ if [[ "$OSTYPE" == "darwin"* ]]; then sed -i 's/create_empty_blocks = true/create_empty_blocks = false/g' $HOME/.evmosd/config/config.toml fi -if [[ $1 == "pending" ]]; then +if [[ "$1" == "pending" ]]; then if [[ "$OSTYPE" == "darwin"* ]]; then sed -i '' 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.evmosd/config/config.toml sed -i '' 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.evmosd/config/config.toml @@ -79,11 +80,4 @@ evmosd gentx $KEY 1000000000000000000000aphoton --keyring-backend $KEYRING --cha evmosd collect-gentxs # Run this to ensure everything worked and that the genesis file is setup correctly -evmosd validate-genesis - -if [[ $1 == "pending" ]]; then - echo "pending mode is on, please wait for the first block committed." -fi - -# Start the node (remove the --pruning=nothing flag if historical queries are not needed) -evmosd start --pruning=nothing $TRACE --log_level $LOGLEVEL --minimum-gas-prices=0.0001aphoton --json-rpc.api eth,txpool,personal,net,web3 --optimint.aggregator=true --optimint.da_layer=mock +evmosd validate-genesis \ No newline at end of file diff --git a/optimint b/optimint new file mode 160000 index 0000000000..0905be5c83 --- /dev/null +++ b/optimint @@ -0,0 +1 @@ +Subproject commit 0905be5c836a0e771d18a7cacede660a49e9d813 diff --git a/proto/evmos/intrarelayer/v1/genesis.proto b/proto/evmos/intrarelayer/v1/genesis.proto index 5384b2482e..cb1ab05002 100644 --- a/proto/evmos/intrarelayer/v1/genesis.proto +++ b/proto/evmos/intrarelayer/v1/genesis.proto @@ -27,5 +27,5 @@ message Params { // parameter to enable the EVM hook to convert an ERC20 token to a Cosmos // Coin by transferring the Tokens through a MsgEthereumTx to the // ModuleAddress Ethereum address. - bool enable_e_v_m_hook = 3; + bool enable_evm_hook = 3 [(gogoproto.customname) = "EnableEVMHook"]; } \ No newline at end of file diff --git a/testutil/network/network.go b/testutil/network/network.go index 467ea13769..cac775da11 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -1,70 +1,43 @@ package network import ( - "bufio" - "context" - "encoding/json" - "errors" "fmt" - "net/http" - "net/url" - "os" - "path/filepath" - "strings" - "sync" - "testing" - "time" - "github.com/ethereum/go-ethereum/common" - "github.com/spf13/cobra" - tmcfg "github.com/tendermint/tendermint/config" - tmflags "github.com/tendermint/tendermint/libs/cli/flags" - "github.com/tendermint/tendermint/libs/log" tmrand "github.com/tendermint/tendermint/libs/rand" - "github.com/tendermint/tendermint/node" - tmclient "github.com/tendermint/tendermint/rpc/client" dbm "github.com/tendermint/tm-db" - "google.golang.org/grpc" "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "github.com/cosmos/cosmos-sdk/server" - "github.com/cosmos/cosmos-sdk/server/api" - srvconfig "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/simapp/params" storetypes "github.com/cosmos/cosmos-sdk/store/types" - 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" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/tharsis/ethermint/crypto/hd" "github.com/tharsis/ethermint/encoding" - "github.com/tharsis/ethermint/server/config" - ethermint "github.com/tharsis/ethermint/types" - evmtypes "github.com/tharsis/ethermint/x/evm/types" + "github.com/tharsis/ethermint/testutil/network" "github.com/tharsis/evmos/app" ) -// package-wide network lock to only allow one test network at a time -var lock = new(sync.Mutex) +// DefaultConfig returns a sane default configuration suitable for nearly all +// testing requirements. +func DefaultConfig() network.Config { + encCfg := encoding.MakeConfig(app.ModuleBasics) + cfg := network.DefaultConfig() -// AppConstructor defines a function which accepts a network configuration and -// creates an ABCI Application to provide to Tendermint. -type AppConstructor = func(val Validator) servertypes.Application + cfg.Codec = encCfg.Marshaler + cfg.TxConfig = encCfg.TxConfig + cfg.LegacyAmino = encCfg.Amino + cfg.InterfaceRegistry = encCfg.InterfaceRegistry + cfg.AppConstructor = NewAppConstructor(encCfg) + cfg.GenesisState = app.ModuleBasics.DefaultGenesis(encCfg.Marshaler) + + cfg.ChainID = fmt.Sprintf("evmos_%d-1", tmrand.Int63n(9999999999999)+1) + return cfg +} -// NewAppConstructor returns a new simapp AppConstructor -func NewAppConstructor(encodingCfg params.EncodingConfig) AppConstructor { - return func(val Validator) servertypes.Application { +// NewAppConstructor returns a new Evmos AppConstructor +func NewAppConstructor(encodingCfg params.EncodingConfig) network.AppConstructor { + return func(val network.Validator) servertypes.Application { return app.NewEvmos( val.Ctx.Logger, dbm.NewMemDB(), nil, true, make(map[int64]bool), val.Ctx.Config.RootDir, 0, encodingCfg, @@ -74,613 +47,3 @@ func NewAppConstructor(encodingCfg params.EncodingConfig) AppConstructor { ) } } - -// Config defines the necessary configuration used to bootstrap and start an -// in-process local testing network. -type Config struct { - Codec codec.Codec - LegacyAmino *codec.LegacyAmino // TODO: Remove! - InterfaceRegistry codectypes.InterfaceRegistry - - TxConfig client.TxConfig - AccountRetriever client.AccountRetriever - AppConstructor AppConstructor // the ABCI application constructor - GenesisState simapp.GenesisState // custom gensis state to provide - TimeoutCommit time.Duration // the consensus commitment timeout - ChainID string // the network chain-id - NumValidators int // the total number of validators to create and bond - BondDenom string // the staking bond denomination - MinGasPrices string // the minimum gas prices each validator will accept - AccountTokens sdk.Int // the amount of unique validator tokens (e.g. 1000node0) - StakingTokens sdk.Int // the amount of tokens each validator has available to stake - BondedTokens sdk.Int // the amount of tokens each validator stakes - PruningStrategy string // the pruning strategy each validator will have - EnableTMLogging bool // enable Tendermint logging to STDOUT - CleanupDir bool // remove base temporary directory during cleanup - SigningAlgo string // signing algorithm for keys - KeyringOptions []keyring.Option // keyring configuration options - RPCAddress string // RPC listen address (including port) - JSONRPCAddress string // JSON-RPC listen address (including port) - APIAddress string // REST API listen address (including port) - GRPCAddress string // GRPC server listen address (including port) - PrintMnemonic bool // print the mnemonic of first validator as log output for testing -} - -// DefaultConfig returns a sane default configuration suitable for nearly all -// testing requirements. -func DefaultConfig() Config { - encCfg := encoding.MakeConfig(app.ModuleBasics) - - return Config{ - Codec: encCfg.Marshaler, - TxConfig: encCfg.TxConfig, - LegacyAmino: encCfg.Amino, - InterfaceRegistry: encCfg.InterfaceRegistry, - AccountRetriever: authtypes.AccountRetriever{}, - AppConstructor: NewAppConstructor(encCfg), - GenesisState: app.ModuleBasics.DefaultGenesis(encCfg.Marshaler), - TimeoutCommit: 2 * time.Second, - ChainID: fmt.Sprintf("evmos_%d-1", tmrand.Int63n(9999999999999)+1), - NumValidators: 4, - BondDenom: ethermint.AttoPhoton, - MinGasPrices: fmt.Sprintf("0.000006%s", ethermint.AttoPhoton), - AccountTokens: sdk.TokensFromConsensusPower(1000, ethermint.PowerReduction), - StakingTokens: sdk.TokensFromConsensusPower(500, ethermint.PowerReduction), - BondedTokens: sdk.TokensFromConsensusPower(100, ethermint.PowerReduction), - PruningStrategy: storetypes.PruningOptionNothing, - CleanupDir: true, - SigningAlgo: string(hd.EthSecp256k1Type), - KeyringOptions: []keyring.Option{hd.EthSecp256k1Option()}, - PrintMnemonic: false, - } -} - -type ( - // Network defines a local in-process testing network using SimApp. It can be - // configured to start any number of validators, each with its own RPC and API - // clients. Typically, this test network would be used in client and integration - // testing where user input is expected. - // - // Note, due to Tendermint constraints in regards to RPC functionality, there - // may only be one test network running at a time. Thus, any caller must be - // sure to Cleanup after testing is finished in order to allow other tests - // to create networks. In addition, only the first validator will have a valid - // RPC and API server/client. - Network struct { - Logger Logger - BaseDir string - Validators []*Validator - - Config Config - } - - // Validator defines an in-process Tendermint validator node. Through this object, - // a client can make RPC and API calls and interact with any client command - // or handler. - Validator struct { - AppConfig *config.Config - ClientCtx client.Context - Ctx *server.Context - Dir string - NodeID string - PubKey cryptotypes.PubKey - Moniker string - APIAddress string - RPCAddress string - P2PAddress string - JSONRPCAddress string - Address sdk.AccAddress - ValAddress sdk.ValAddress - RPCClient tmclient.Client - - tmNode *node.Node - api *api.Server - grpc *grpc.Server - grpcWeb *http.Server - jsonrpc *http.Server - jsonrpcDone chan struct{} - } -) - -// Logger is a network logger interface that exposes testnet-level Log() methods for an in-process testing network -// This is not to be confused with logging that may happen at an individual node or validator level -type Logger interface { - Log(args ...interface{}) - Logf(format string, args ...interface{}) -} - -var ( - _ Logger = (*testing.T)(nil) - _ Logger = (*CLILogger)(nil) -) - -type CLILogger struct { - cmd *cobra.Command -} - -func (s CLILogger) Log(args ...interface{}) { - s.cmd.Println(args...) -} - -func (s CLILogger) Logf(format string, args ...interface{}) { - s.cmd.Printf(format, args...) -} - -func NewCLILogger(cmd *cobra.Command) CLILogger { - return CLILogger{cmd} -} - -// New creates a new Network for integration tests or in-process testnets run via the CLI -func New(l Logger, baseDir string, cfg Config) (*Network, error) { - // only one caller/test can create and use a network at a time - l.Log("acquiring test network lock") - lock.Lock() - - if !ethermint.IsValidChainID(cfg.ChainID) { - return nil, fmt.Errorf("invalid chain-id: %s", cfg.ChainID) - } - - network := &Network{ - Logger: l, - BaseDir: baseDir, - Validators: make([]*Validator, cfg.NumValidators), - Config: cfg, - } - - l.Logf("preparing test network with chain-id \"%s\"\n", cfg.ChainID) - - monikers := make([]string, cfg.NumValidators) - nodeIDs := make([]string, cfg.NumValidators) - valPubKeys := make([]cryptotypes.PubKey, cfg.NumValidators) - - var ( - genAccounts []authtypes.GenesisAccount - genBalances []banktypes.Balance - genFiles []string - ) - - buf := bufio.NewReader(os.Stdin) - - // generate private keys, node IDs, and initial transactions - for i := 0; i < cfg.NumValidators; i++ { - appCfg := config.DefaultConfig() - appCfg.Pruning = cfg.PruningStrategy - appCfg.MinGasPrices = cfg.MinGasPrices - appCfg.API.Enable = true - appCfg.API.Swagger = false - appCfg.Telemetry.Enabled = false - - ctx := server.NewDefaultContext() - tmCfg := ctx.Config - tmCfg.Consensus.TimeoutCommit = cfg.TimeoutCommit - - // Only allow the first validator to expose an RPC, API and gRPC - // server/client due to Tendermint in-process constraints. - apiAddr := "" - tmCfg.RPC.ListenAddress = "" - appCfg.GRPC.Enable = false - appCfg.GRPCWeb.Enable = false - apiListenAddr := "" - if i == 0 { - if cfg.APIAddress != "" { - apiListenAddr = cfg.APIAddress - } else { - var err error - apiListenAddr, _, err = server.FreeTCPAddr() - if err != nil { - return nil, err - } - } - - appCfg.API.Address = apiListenAddr - apiURL, err := url.Parse(apiListenAddr) - if err != nil { - return nil, err - } - apiAddr = fmt.Sprintf("http://%s:%s", apiURL.Hostname(), apiURL.Port()) - - if cfg.RPCAddress != "" { - tmCfg.RPC.ListenAddress = cfg.RPCAddress - } else { - rpcAddr, _, err := server.FreeTCPAddr() - if err != nil { - return nil, err - } - tmCfg.RPC.ListenAddress = rpcAddr - } - - if cfg.GRPCAddress != "" { - appCfg.GRPC.Address = cfg.GRPCAddress - } else { - _, grpcPort, err := server.FreeTCPAddr() - if err != nil { - return nil, err - } - appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", grpcPort) - } - appCfg.GRPC.Enable = true - - _, grpcWebPort, err := server.FreeTCPAddr() - if err != nil { - return nil, err - } - appCfg.GRPCWeb.Address = fmt.Sprintf("0.0.0.0:%s", grpcWebPort) - appCfg.GRPCWeb.Enable = true - - if cfg.JSONRPCAddress != "" { - appCfg.JSONRPC.Address = cfg.JSONRPCAddress - } else { - _, jsonRPCPort, err := server.FreeTCPAddr() - if err != nil { - return nil, err - } - appCfg.JSONRPC.Address = fmt.Sprintf("0.0.0.0:%s", jsonRPCPort) - } - appCfg.JSONRPC.Enable = true - appCfg.JSONRPC.API = config.GetDefaultAPINamespaces() - } - - logger := log.NewNopLogger() - if cfg.EnableTMLogging { - logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel) - } - - ctx.Logger = logger - - nodeDirName := fmt.Sprintf("node%d", i) - nodeDir := filepath.Join(network.BaseDir, nodeDirName, "evmosd") - clientDir := filepath.Join(network.BaseDir, nodeDirName, "evmoscli") - gentxsDir := filepath.Join(network.BaseDir, "gentxs") - - err := os.MkdirAll(filepath.Join(nodeDir, "config"), 0o755) - if err != nil { - return nil, err - } - - err = os.MkdirAll(clientDir, 0o755) - if err != nil { - return nil, err - } - - tmCfg.SetRoot(nodeDir) - tmCfg.Moniker = nodeDirName - monikers[i] = nodeDirName - - proxyAddr, _, err := server.FreeTCPAddr() - if err != nil { - return nil, err - } - tmCfg.ProxyApp = proxyAddr - - p2pAddr, _, err := server.FreeTCPAddr() - if err != nil { - return nil, err - } - tmCfg.P2P.ListenAddress = p2pAddr - tmCfg.P2P.AddrBookStrict = false - tmCfg.P2P.AllowDuplicateIP = true - - nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(tmCfg) - if err != nil { - return nil, err - } - nodeIDs[i] = nodeID - valPubKeys[i] = pubKey - - kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.KeyringOptions...) - if err != nil { - return nil, err - } - - keyringAlgos, _ := kb.SupportedAlgorithms() - algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos) - if err != nil { - return nil, err - } - - addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo) - if err != nil { - return nil, err - } - - // if PrintMnemonic is set to true, we print the first validator node's secret to the network's logger - // for debugging and manual testing - if cfg.PrintMnemonic && i == 0 { - printMnemonic(l, secret) - } - - info := map[string]string{"secret": secret} - infoBz, err := json.Marshal(info) - if err != nil { - return nil, err - } - - // save private key seed words - err = WriteFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz) - if err != nil { - return nil, err - } - - balances := sdk.NewCoins( - sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens), - sdk.NewCoin(cfg.BondDenom, cfg.StakingTokens), - ) - - genFiles = append(genFiles, tmCfg.GenesisFile()) - genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: balances.Sort()}) - genAccounts = append(genAccounts, ðermint.EthAccount{ - BaseAccount: authtypes.NewBaseAccount(addr, nil, 0, 0), - CodeHash: common.BytesToHash(evmtypes.EmptyCodeHash).Hex(), - }) - - commission, err := sdk.NewDecFromStr("0.5") - if err != nil { - return nil, err - } - - createValMsg, err := stakingtypes.NewMsgCreateValidator( - sdk.ValAddress(addr), - valPubKeys[i], - sdk.NewCoin(cfg.BondDenom, cfg.BondedTokens), - stakingtypes.NewDescription(nodeDirName, "", "", "", ""), - stakingtypes.NewCommissionRates(commission, sdk.OneDec(), sdk.OneDec()), - sdk.OneInt(), - ) - if err != nil { - return nil, err - } - - p2pURL, err := url.Parse(p2pAddr) - if err != nil { - return nil, err - } - - memo := fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port()) - fee := sdk.NewCoins(sdk.NewCoin(cfg.BondDenom, sdk.NewInt(0))) - txBuilder := cfg.TxConfig.NewTxBuilder() - err = txBuilder.SetMsgs(createValMsg) - if err != nil { - return nil, err - } - txBuilder.SetFeeAmount(fee) // Arbitrary fee - txBuilder.SetGasLimit(1000000) // Need at least 100386 - txBuilder.SetMemo(memo) - - txFactory := tx.Factory{} - txFactory = txFactory. - WithChainID(cfg.ChainID). - WithMemo(memo). - WithKeybase(kb). - WithTxConfig(cfg.TxConfig) - - if err := tx.Sign(txFactory, nodeDirName, txBuilder, true); err != nil { - return nil, err - } - - txBz, err := cfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) - if err != nil { - return nil, err - } - - if err := WriteFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz); err != nil { - return nil, err - } - - customAppTemplate, _ := config.AppConfig(ethermint.AttoPhoton) - srvconfig.SetConfigTemplate(customAppTemplate) - srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appCfg) - - clientCtx := client.Context{}. - WithKeyringDir(clientDir). - WithKeyring(kb). - WithHomeDir(tmCfg.RootDir). - WithChainID(cfg.ChainID). - WithInterfaceRegistry(cfg.InterfaceRegistry). - WithCodec(cfg.Codec). - WithLegacyAmino(cfg.LegacyAmino). - WithTxConfig(cfg.TxConfig). - WithAccountRetriever(cfg.AccountRetriever) - - network.Validators[i] = &Validator{ - AppConfig: appCfg, - ClientCtx: clientCtx, - Ctx: ctx, - Dir: filepath.Join(network.BaseDir, nodeDirName), - NodeID: nodeID, - PubKey: pubKey, - Moniker: nodeDirName, - RPCAddress: tmCfg.RPC.ListenAddress, - P2PAddress: tmCfg.P2P.ListenAddress, - APIAddress: apiAddr, - Address: addr, - ValAddress: sdk.ValAddress(addr), - } - } - - err := initGenFiles(cfg, genAccounts, genBalances, genFiles) - if err != nil { - return nil, err - } - err = collectGenFiles(cfg, network.Validators, network.BaseDir) - if err != nil { - return nil, err - } - - l.Log("starting test network...") - for _, v := range network.Validators { - err := startInProcess(cfg, v) - if err != nil { - return nil, err - } - } - - l.Log("started test network") - - // Ensure we cleanup incase any test was abruptly halted (e.g. SIGINT) as any - // defer in a test would not be called. - server.TrapSignal(network.Cleanup) - - return network, nil -} - -// LatestHeight returns the latest height of the network or an error if the -// query fails or no validators exist. -func (n *Network) LatestHeight() (int64, error) { - if len(n.Validators) == 0 { - return 0, errors.New("no validators available") - } - - status, err := n.Validators[0].RPCClient.Status(context.Background()) - if err != nil { - return 0, err - } - - return status.SyncInfo.LatestBlockHeight, nil -} - -// WaitForHeight performs a blocking check where it waits for a block to be -// committed after a given block. If that height is not reached within a timeout, -// an error is returned. Regardless, the latest height queried is returned. -func (n *Network) WaitForHeight(h int64) (int64, error) { - return n.WaitForHeightWithTimeout(h, 10*time.Second) -} - -// WaitForHeightWithTimeout is the same as WaitForHeight except the caller can -// provide a custom timeout. -func (n *Network) WaitForHeightWithTimeout(h int64, t time.Duration) (int64, error) { - ticker := time.NewTicker(time.Second) - timeout := time.After(t) - - if len(n.Validators) == 0 { - return 0, errors.New("no validators available") - } - - var latestHeight int64 - val := n.Validators[0] - - for { - select { - case <-timeout: - ticker.Stop() - return latestHeight, errors.New("timeout exceeded waiting for block") - case <-ticker.C: - status, err := val.RPCClient.Status(context.Background()) - if err == nil && status != nil { - latestHeight = status.SyncInfo.LatestBlockHeight - if latestHeight >= h { - return latestHeight, nil - } - } - } - } -} - -// WaitForNextBlock waits for the next block to be committed, returning an error -// upon failure. -func (n *Network) WaitForNextBlock() error { - lastBlock, err := n.LatestHeight() - if err != nil { - return err - } - - _, err = n.WaitForHeight(lastBlock + 1) - if err != nil { - return err - } - - return err -} - -// Cleanup removes the root testing (temporary) directory and stops both the -// Tendermint and API services. It allows other callers to create and start -// test networks. This method must be called when a test is finished, typically -// in a defer. -func (n *Network) Cleanup() { - defer func() { - lock.Unlock() - n.Logger.Log("released test network lock") - }() - - n.Logger.Log("cleaning up test network...") - - for _, v := range n.Validators { - if v.tmNode != nil && v.tmNode.IsRunning() { - _ = v.tmNode.Stop() - } - - if v.api != nil { - _ = v.api.Close() - } - - if v.grpc != nil { - v.grpc.Stop() - if v.grpcWeb != nil { - _ = v.grpcWeb.Close() - } - } - - if v.jsonrpc != nil { - shutdownCtx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second) - defer cancelFn() - - if err := v.jsonrpc.Shutdown(shutdownCtx); err != nil { - v.tmNode.Logger.Error("HTTP server shutdown produced a warning", "error", err.Error()) - } else { - v.tmNode.Logger.Info("HTTP server shut down, waiting 5 sec") - select { - case <-time.Tick(5 * time.Second): - case <-v.jsonrpcDone: - } - } - } - } - - if n.Config.CleanupDir { - _ = os.RemoveAll(n.BaseDir) - } - - n.Logger.Log("finished cleaning up test network") -} - -// printMnemonic prints a provided mnemonic seed phrase on a network logger -// for debugging and manual testing -func printMnemonic(l Logger, secret string) { - lines := []string{ - "THIS MNEMONIC IS FOR TESTING PURPOSES ONLY", - "DO NOT USE IN PRODUCTION", - "", - strings.Join(strings.Fields(secret)[0:8], " "), - strings.Join(strings.Fields(secret)[8:16], " "), - strings.Join(strings.Fields(secret)[16:24], " "), - } - - lineLengths := make([]int, len(lines)) - for i, line := range lines { - lineLengths[i] = len(line) - } - - maxLineLength := 0 - for _, lineLen := range lineLengths { - if lineLen > maxLineLength { - maxLineLength = lineLen - } - } - - l.Log("\n") - l.Log(strings.Repeat("+", maxLineLength+8)) - for _, line := range lines { - l.Logf("++ %s ++\n", centerText(line, maxLineLength)) - } - l.Log(strings.Repeat("+", maxLineLength+8)) - l.Log("\n") -} - -// centerText centers text across a fixed width, filling either side with whitespace buffers -func centerText(text string, width int) string { - textLen := len(text) - leftBuffer := strings.Repeat(" ", (width-textLen)/2) - rightBuffer := strings.Repeat(" ", (width-textLen)/2+(width-textLen)%2) - - return fmt.Sprintf("%s%s%s", leftBuffer, text, rightBuffer) -} diff --git a/testutil/network/network_test.go b/testutil/network/network_test.go index 7dbf183518..f5a66d61ad 100644 --- a/testutil/network/network_test.go +++ b/testutil/network/network_test.go @@ -4,12 +4,16 @@ package network_test import ( + "fmt" "testing" "time" "github.com/stretchr/testify/suite" - "github.com/cosmos/cosmos-sdk/testutil/network" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/tharsis/ethermint/server/config" + "github.com/tharsis/ethermint/testutil/network" + evmosnetwork "github.com/tharsis/evmos/testutil/network" ) type IntegrationTestSuite struct { @@ -22,11 +26,22 @@ func (s *IntegrationTestSuite) SetupSuite() { s.T().Log("setting up integration test suite") var err error - s.network, err = network.New(s.T(), s.T().TempDir(), network.DefaultConfig()) + cfg := evmosnetwork.DefaultConfig() + cfg.JSONRPCAddress = config.DefaultJSONRPCAddress + cfg.NumValidators = 1 + + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) s.Require().NoError(err) + s.Require().NotNil(s.network) - _, err = s.network.WaitForHeight(1) + _, err = s.network.WaitForHeight(2) s.Require().NoError(err) + + if s.network.Validators[0].JSONRPCClient == nil { + address := fmt.Sprintf("http://%s", s.network.Validators[0].AppConfig.JSONRPC.Address) + s.network.Validators[0].JSONRPCClient, err = ethclient.Dial(address) + s.Require().NoError(err) + } } func (s *IntegrationTestSuite) TearDownSuite() { @@ -37,6 +52,10 @@ func (s *IntegrationTestSuite) TearDownSuite() { func (s *IntegrationTestSuite) TestNetwork_Liveness() { h, err := s.network.WaitForHeightWithTimeout(10, time.Minute) s.Require().NoError(err, "expected to reach 10 blocks; got %d", h) + + latestHeight, err := s.network.LatestHeight() + s.Require().NoError(err, "latest height failed") + s.Require().GreaterOrEqual(latestHeight, h) } func TestIntegrationTestSuite(t *testing.T) { diff --git a/testutil/network/util.go b/testutil/network/util.go deleted file mode 100644 index 2441f3f21d..0000000000 --- a/testutil/network/util.go +++ /dev/null @@ -1,260 +0,0 @@ -package network - -import ( - "encoding/json" - "fmt" - "path/filepath" - "time" - - tmos "github.com/tendermint/tendermint/libs/os" - "github.com/tendermint/tendermint/node" - "github.com/tendermint/tendermint/p2p" - pvm "github.com/tendermint/tendermint/privval" - "github.com/tendermint/tendermint/proxy" - "github.com/tendermint/tendermint/rpc/client/local" - "github.com/tendermint/tendermint/types" - tmtime "github.com/tendermint/tendermint/types/time" - - "github.com/cosmos/cosmos-sdk/server/api" - servergrpc "github.com/cosmos/cosmos-sdk/server/grpc" - srvtypes "github.com/cosmos/cosmos-sdk/server/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" - "github.com/cosmos/cosmos-sdk/x/genutil" - genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - mintypes "github.com/cosmos/cosmos-sdk/x/mint/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - - "github.com/tharsis/ethermint/server" - evmtypes "github.com/tharsis/ethermint/x/evm/types" -) - -func startInProcess(cfg Config, val *Validator) error { - logger := val.Ctx.Logger - tmCfg := val.Ctx.Config - tmCfg.Instrumentation.Prometheus = false - - if err := val.AppConfig.ValidateBasic(); err != nil { - return err - } - - nodeKey, err := p2p.LoadOrGenNodeKey(tmCfg.NodeKeyFile()) - if err != nil { - return err - } - - app := cfg.AppConstructor(*val) - - genDocProvider := node.DefaultGenesisDocProviderFunc(tmCfg) - tmNode, err := node.NewNode( - tmCfg, - pvm.LoadOrGenFilePV(tmCfg.PrivValidatorKeyFile(), tmCfg.PrivValidatorStateFile()), - nodeKey, - proxy.NewLocalClientCreator(app), - genDocProvider, - node.DefaultDBProvider, - node.DefaultMetricsProvider(tmCfg.Instrumentation), - logger.With("module", val.Moniker), - ) - if err != nil { - return err - } - - if err := tmNode.Start(); err != nil { - return err - } - - val.tmNode = tmNode - - if val.RPCAddress != "" { - val.RPCClient = local.New(tmNode) - } - - // We'll need a RPC client if the validator exposes a gRPC or REST endpoint. - if val.APIAddress != "" || val.AppConfig.GRPC.Enable { - val.ClientCtx = val.ClientCtx. - WithClient(val.RPCClient) - - // Add the tx service in the gRPC router. - app.RegisterTxService(val.ClientCtx) - - // Add the tendermint queries service in the gRPC router. - app.RegisterTendermintService(val.ClientCtx) - } - - if val.AppConfig.API.Enable && val.APIAddress != "" { - apiSrv := api.New(val.ClientCtx, logger.With("module", "api-server")) - app.RegisterAPIRoutes(apiSrv, val.AppConfig.API) - - errCh := make(chan error) - - go func() { - if err := apiSrv.Start(val.AppConfig.Config); err != nil { - errCh <- err - } - }() - - select { - case err := <-errCh: - return err - case <-time.After(srvtypes.ServerStartTime): // assume server started successfully - } - - val.api = apiSrv - } - - if val.AppConfig.GRPC.Enable { - grpcSrv, err := servergrpc.StartGRPCServer(val.ClientCtx, app, val.AppConfig.GRPC.Address) - if err != nil { - return err - } - - val.grpc = grpcSrv - - if val.AppConfig.GRPCWeb.Enable { - val.grpcWeb, err = servergrpc.StartGRPCWeb(grpcSrv, val.AppConfig.Config) - if err != nil { - return err - } - } - } - - if val.AppConfig.JSONRPC.Enable && val.JSONRPCAddress != "" { - if val.Ctx == nil || val.Ctx.Viper == nil { - return fmt.Errorf("validator %s context is nil", val.Moniker) - } - - fmt.Println(&val.Ctx, &val.Ctx.Viper) - - tmEndpoint := "/websocket" - val.jsonrpc, val.jsonrpcDone, err = server.StartJSONRPC(val.Ctx, val.ClientCtx, val.JSONRPCAddress, tmEndpoint, *val.AppConfig) - if err != nil { - return err - } - } - - return nil -} - -func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error { - genTime := tmtime.Now() - - for i := 0; i < cfg.NumValidators; i++ { - tmCfg := vals[i].Ctx.Config - - nodeDir := filepath.Join(outputDir, vals[i].Moniker, "evmosd") - gentxsDir := filepath.Join(outputDir, "gentxs") - - tmCfg.Moniker = vals[i].Moniker - tmCfg.SetRoot(nodeDir) - - initCfg := genutiltypes.NewInitConfig(cfg.ChainID, gentxsDir, vals[i].NodeID, vals[i].PubKey) - - genFile := tmCfg.GenesisFile() - genDoc, err := types.GenesisDocFromFile(genFile) - if err != nil { - return err - } - - appState, err := genutil.GenAppStateFromConfig(cfg.Codec, cfg.TxConfig, - tmCfg, initCfg, *genDoc, banktypes.GenesisBalancesIterator{}) - if err != nil { - return err - } - - // overwrite each validator's genesis file to have a canonical genesis time - if err := genutil.ExportGenesisFileWithTime(genFile, cfg.ChainID, nil, appState, genTime); err != nil { - return err - } - } - - return nil -} - -func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance, genFiles []string) error { - // set the accounts in the genesis state - var authGenState authtypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &authGenState) - - accounts, err := authtypes.PackAccounts(genAccounts) - if err != nil { - return err - } - - authGenState.Accounts = append(authGenState.Accounts, accounts...) - cfg.GenesisState[authtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&authGenState) - - // set the balances in the genesis state - var bankGenState banktypes.GenesisState - bankGenState.Balances = genBalances - cfg.GenesisState[banktypes.ModuleName] = cfg.Codec.MustMarshalJSON(&bankGenState) - - var stakingGenState stakingtypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[stakingtypes.ModuleName], &stakingGenState) - - stakingGenState.Params.BondDenom = cfg.BondDenom - cfg.GenesisState[stakingtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&stakingGenState) - - var govGenState govtypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[govtypes.ModuleName], &govGenState) - - govGenState.DepositParams.MinDeposit[0].Denom = cfg.BondDenom - cfg.GenesisState[govtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&govGenState) - - var mintGenState mintypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[mintypes.ModuleName], &mintGenState) - - mintGenState.Params.MintDenom = cfg.BondDenom - cfg.GenesisState[mintypes.ModuleName] = cfg.Codec.MustMarshalJSON(&mintGenState) - - var crisisGenState crisistypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[crisistypes.ModuleName], &crisisGenState) - - crisisGenState.ConstantFee.Denom = cfg.BondDenom - cfg.GenesisState[crisistypes.ModuleName] = cfg.Codec.MustMarshalJSON(&crisisGenState) - - var evmGenState evmtypes.GenesisState - cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[evmtypes.ModuleName], &evmGenState) - - evmGenState.Params.EvmDenom = cfg.BondDenom - cfg.GenesisState[evmtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&evmGenState) - - appGenStateJSON, err := json.MarshalIndent(cfg.GenesisState, "", " ") - if err != nil { - return err - } - - genDoc := types.GenesisDoc{ - ChainID: cfg.ChainID, - AppState: appGenStateJSON, - Validators: nil, - } - - // generate empty genesis files for each validator and save - for i := 0; i < cfg.NumValidators; i++ { - if err := genDoc.SaveAs(genFiles[i]); err != nil { - return err - } - } - - return nil -} - -func WriteFile(name string, dir string, contents []byte) error { - writePath := filepath.Join(dir) - file := filepath.Join(writePath, name) - - err := tmos.EnsureDir(writePath, 0o755) - if err != nil { - return err - } - - err = tmos.WriteFile(file, contents, 0o644) - if err != nil { - return err - } - - return nil -} diff --git a/x/README.md b/x/README.md new file mode 100644 index 0000000000..cdbf57bd66 --- /dev/null +++ b/x/README.md @@ -0,0 +1,9 @@ + + +# List of Modules + +Here are some production-grade modules that can be used in Evmos applications, along with their respective documentation: + +- [Intrarelayer](intrarelayer/spec/README.md) - Trustless, on-chain bidirectional internal relaying (*aka* intrarelaying) of tokens between Evmos' EVM and Cosmos runtimes. \ No newline at end of file diff --git a/x/intrarelayer/client/query.go b/x/intrarelayer/client/cli/query.go similarity index 100% rename from x/intrarelayer/client/query.go rename to x/intrarelayer/client/cli/query.go diff --git a/x/intrarelayer/client/cli/tx.go b/x/intrarelayer/client/cli/tx.go new file mode 100644 index 0000000000..e1d1e3e93f --- /dev/null +++ b/x/intrarelayer/client/cli/tx.go @@ -0,0 +1,429 @@ +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/ethereum/go-ethereum/common" + + ethermint "github.com/tharsis/ethermint/types" + "github.com/tharsis/evmos/x/intrarelayer/types" +) + +// NewTxCmd returns a root CLI command handler for certain modules/intrarelayer transaction commands. +func NewTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "intrarelayer subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewConvertCoinCmd(), + NewConvertERC20Cmd(), + ) + return txCmd +} + +// NewConvertCoinCmd returns a CLI command handler for converting cosmos coins +func NewConvertCoinCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "convert-coin [coin] [receiver_hex]", + Short: "Convert a Cosmos coin to ERC20", + Args: cobra.RangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + coin, err := sdk.ParseCoinNormalized(args[0]) + if err != nil { + return err + } + + var receiver string + sender := cliCtx.GetFromAddress() + + if len(args) == 2 { + receiver = args[1] + if err := ethermint.ValidateAddress(receiver); err != nil { + return fmt.Errorf("invalid receiver hex address %w", err) + } + } else { + receiver = common.BytesToAddress(sender).Hex() + } + + msg := &types.MsgConvertCoin{ + Coin: coin, + Receiver: receiver, + Sender: sender.String(), + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(cliCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +// NewConvertERC20Cmd returns a CLI command handler for converting ERC20s +func NewConvertERC20Cmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "convert-erc20 [contract-address] [amount] [receiver]", + Short: "Convert an ERC20 token to Cosmos coin", + Args: cobra.RangeArgs(2, 3), + RunE: func(cmd *cobra.Command, args []string) error { + cliCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + contract := args[0] + if err := ethermint.ValidateAddress(contract); err != nil { + return fmt.Errorf("invalid ERC20 contract address %w", err) + } + + amount, ok := sdk.NewIntFromString(args[1]) + if !ok { + return fmt.Errorf("invalid amount %s", args[1]) + } + + from := common.BytesToAddress(cliCtx.GetFromAddress().Bytes()) + + receiver := cliCtx.GetFromAddress() + if len(args) == 3 { + receiver, err = sdk.AccAddressFromBech32(args[2]) + if err != nil { + return err + } + } + + msg := &types.MsgConvertERC20{ + ContractAddress: contract, + Amount: amount, + Receiver: receiver.String(), + Sender: from.Hex(), + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(cliCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +// NewRegisterCoinProposalCmd implements the command to submit a community-pool-spend proposal +func NewRegisterCoinProposalCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "register-coin [metadata]", + Args: cobra.ExactArgs(1), + Short: "Submit a register coin proposal", + Long: `Submit a proposal to register a Cosmos coin to the intrarelayer along with an initial deposit. +Upon passing, the +The proposal details must be supplied via a JSON file.`, + Example: fmt.Sprintf(`$ %s tx gov submit-proposal register-coin --from= + +Where metadata.json contains (example): + +{ + "description": "staking, gas and governance token of the Evmos testnets" + "denom_units": [ + { + "denom": "aphoton", + "exponent": 0, + "aliases": ["atto photon"] + }, + { + "denom": "photon", + "exponent": 18 + } + ], + "base": "aphoton", + "display: "photon", + "name": "Photon", + "symbol": "PHOTON" +}`, version.AppName, + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + title, err := cmd.Flags().GetString(cli.FlagTitle) + if err != nil { + return err + } + + description, err := cmd.Flags().GetString(cli.FlagDescription) + if err != nil { + return err + } + + depositStr, err := cmd.Flags().GetString(cli.FlagDeposit) + if err != nil { + return err + } + + deposit, err := sdk.ParseCoinsNormalized(depositStr) + if err != nil { + return err + } + + metadata, err := ParseMetadata(clientCtx.Codec, args[0]) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() + + content := types.NewRegisterCoinProposal(title, description, metadata) + + msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(cli.FlagTitle, "", "title of proposal") + cmd.Flags().String(cli.FlagDescription, "", "description of proposal") + cmd.Flags().String(cli.FlagDeposit, "1aphoton", "deposit of proposal") + if err := cmd.MarkFlagRequired(cli.FlagTitle); err != nil { + panic(err) + } + if err := cmd.MarkFlagRequired(cli.FlagDescription); err != nil { + panic(err) + } + if err := cmd.MarkFlagRequired(cli.FlagDeposit); err != nil { + panic(err) + } + return cmd +} + +// NewRegisterERC20ProposalCmd implements the command to submit a community-pool-spend proposal +func NewRegisterERC20ProposalCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "register-erc20 [erc20-address]", + Args: cobra.ExactArgs(1), + Short: "Submit a proposal to register an ERC20 token", + Long: "Submit a proposal to register an ERC20 token to the intrarelayer along with an initial deposit.", + Example: fmt.Sprintf("$ %s tx gov submit-proposal register-erc20 --from=", version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + title, err := cmd.Flags().GetString(cli.FlagTitle) + if err != nil { + return err + } + + description, err := cmd.Flags().GetString(cli.FlagDescription) + if err != nil { + return err + } + + depositStr, err := cmd.Flags().GetString(cli.FlagDeposit) + if err != nil { + return err + } + + deposit, err := sdk.ParseCoinsNormalized(depositStr) + if err != nil { + return err + } + + erc20Addr := args[0] + from := clientCtx.GetFromAddress() + content := types.NewRegisterERC20Proposal(title, description, erc20Addr) + + msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(cli.FlagTitle, "", "title of proposal") + cmd.Flags().String(cli.FlagDescription, "", "description of proposal") + cmd.Flags().String(cli.FlagDeposit, "1aphoton", "deposit of proposal") + if err := cmd.MarkFlagRequired(cli.FlagTitle); err != nil { + panic(err) + } + if err := cmd.MarkFlagRequired(cli.FlagDescription); err != nil { + panic(err) + } + if err := cmd.MarkFlagRequired(cli.FlagDeposit); err != nil { + panic(err) + } + return cmd +} + +// NewToggleTokenRelayProposalCmd implements the command to submit a community-pool-spend proposal +func NewToggleTokenRelayProposalCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "toggle-token-relay [token]", + Args: cobra.ExactArgs(1), + Short: "Submit a toggle token relay proposal", + Long: "Submit a proposal to toggle the relaying of a token pair along with an initial deposit.", + Example: fmt.Sprintf("$ %s tx gov submit-proposal toggle-token-relay --from=", version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + title, err := cmd.Flags().GetString(cli.FlagTitle) + if err != nil { + return err + } + + description, err := cmd.Flags().GetString(cli.FlagDescription) + if err != nil { + return err + } + + depositStr, err := cmd.Flags().GetString(cli.FlagDeposit) + if err != nil { + return err + } + + deposit, err := sdk.ParseCoinsNormalized(depositStr) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress() + token := args[0] + content := types.NewToggleTokenRelayProposal(title, description, token) + + msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(cli.FlagTitle, "", "title of proposal") + cmd.Flags().String(cli.FlagDescription, "", "description of proposal") + cmd.Flags().String(cli.FlagDeposit, "1aphoton", "deposit of proposal") + if err := cmd.MarkFlagRequired(cli.FlagTitle); err != nil { + panic(err) + } + if err := cmd.MarkFlagRequired(cli.FlagDescription); err != nil { + panic(err) + } + if err := cmd.MarkFlagRequired(cli.FlagDeposit); err != nil { + panic(err) + } + return cmd +} + +// NewUpdateTokenPairERC20ProposalCmd implements the command to submit a community-pool-spend proposal +func NewUpdateTokenPairERC20ProposalCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-token-pair-erc20 [erc20_address] [new_erc20_address]", + Args: cobra.ExactArgs(2), + Short: "Submit a update token pair ERC20 proposal", + Long: `Submit a proposal to update the ERC20 address of a token pair along with an initial deposit.`, + Example: fmt.Sprintf("$ %s tx gov submit-proposal update-token-pair-erc20 --from=", version.AppName), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + title, err := cmd.Flags().GetString(cli.FlagTitle) + if err != nil { + return err + } + + description, err := cmd.Flags().GetString(cli.FlagDescription) + if err != nil { + return err + } + + depositStr, err := cmd.Flags().GetString(cli.FlagDeposit) + if err != nil { + return err + } + + deposit, err := sdk.ParseCoinsNormalized(depositStr) + if err != nil { + return err + } + + erc20Addr := args[0] + newERC20Addr := args[1] + + from := clientCtx.GetFromAddress() + content := types.NewUpdateTokenPairERC20Proposal(title, description, erc20Addr, newERC20Addr) + msg, err := govtypes.NewMsgSubmitProposal(content, deposit, from) + if err != nil { + return err + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(cli.FlagTitle, "", "title of proposal") + cmd.Flags().String(cli.FlagDescription, "", "description of proposal") + cmd.Flags().String(cli.FlagDeposit, "1aphoton", "deposit of proposal") + if err := cmd.MarkFlagRequired(cli.FlagTitle); err != nil { + panic(err) + } + if err := cmd.MarkFlagRequired(cli.FlagDescription); err != nil { + panic(err) + } + if err := cmd.MarkFlagRequired(cli.FlagDeposit); err != nil { + panic(err) + } + return cmd +} diff --git a/x/intrarelayer/client/cli/utils.go b/x/intrarelayer/client/cli/utils.go new file mode 100644 index 0000000000..f9f77de39c --- /dev/null +++ b/x/intrarelayer/client/cli/utils.go @@ -0,0 +1,25 @@ +package cli + +import ( + "io/ioutil" + "path/filepath" + + "github.com/cosmos/cosmos-sdk/codec" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// ParseRegisterCoinProposal reads and parses a ParseRegisterCoinProposal from a file. +func ParseMetadata(cdc codec.JSONCodec, metadataFile string) (banktypes.Metadata, error) { + metadata := banktypes.Metadata{} + + contents, err := ioutil.ReadFile(filepath.Clean(metadataFile)) + if err != nil { + return metadata, err + } + + if err = cdc.UnmarshalJSON(contents, &metadata); err != nil { + return metadata, err + } + + return metadata, nil +} diff --git a/x/intrarelayer/client/proposal_handler.go b/x/intrarelayer/client/proposal_handler.go new file mode 100644 index 0000000000..1a4094eebc --- /dev/null +++ b/x/intrarelayer/client/proposal_handler.go @@ -0,0 +1,14 @@ +package client + +import ( + govclient "github.com/cosmos/cosmos-sdk/x/gov/client" + "github.com/tharsis/evmos/x/intrarelayer/client/cli" + "github.com/tharsis/evmos/x/intrarelayer/client/rest" +) + +var ( + RegisterCoinProposalHandler = govclient.NewProposalHandler(cli.NewRegisterCoinProposalCmd, rest.RegisterCoinProposalRESTHandler) + RegisterERC20ProposalHandler = govclient.NewProposalHandler(cli.NewRegisterERC20ProposalCmd, rest.RegisterERC20ProposalRESTHandler) + ToggleTokenRelayProposalHandler = govclient.NewProposalHandler(cli.NewToggleTokenRelayProposalCmd, rest.ToggleTokenRelayRESTHandler) + UpdateTokenPairERC20ProposalHandler = govclient.NewProposalHandler(cli.NewUpdateTokenPairERC20ProposalCmd, rest.UpdateTokenPairERC20ProposalRESTHandler) +) diff --git a/x/intrarelayer/client/rest/rest.go b/x/intrarelayer/client/rest/rest.go new file mode 100644 index 0000000000..0ab612dcaf --- /dev/null +++ b/x/intrarelayer/client/rest/rest.go @@ -0,0 +1,211 @@ +package rest + +import ( + "net/http" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + govrest "github.com/cosmos/cosmos-sdk/x/gov/client/rest" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/tharsis/evmos/x/intrarelayer/types" +) + +// RegisterCoinProposalRequest defines a request for a new register coin proposal. +type RegisterCoinProposalRequest struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Title string `json:"title" yaml:"title"` + Description string `json:"description" yaml:"description"` + Deposit sdk.Coins `json:"deposit" yaml:"deposit"` + Metadata banktypes.Metadata `json:"metadata" yaml:"metadata"` +} + +// RegisterERC20ProposalRequest defines a request for a new register ERC20 proposal. +type RegisterERC20ProposalRequest struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Title string `json:"title" yaml:"title"` + Description string `json:"description" yaml:"description"` + Deposit sdk.Coins `json:"deposit" yaml:"deposit"` + ERC20Address string `json:"erc20_address" yaml:"erc20_address"` +} + +// ToggleTokenRelayProposalRequest defines a request for a toggle token relay proposal. +type ToggleTokenRelayProposalRequest struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Title string `json:"title" yaml:"title"` + Description string `json:"description" yaml:"description"` + Deposit sdk.Coins `json:"deposit" yaml:"deposit"` + Token string `json:"token" yaml:"token"` +} + +// UpdateTokenPairERC20ProposalRequest defines a request for a update token pair ERC20 proposal. +type UpdateTokenPairERC20ProposalRequest struct { + BaseReq rest.BaseReq `json:"base_req" yaml:"base_req"` + Title string `json:"title" yaml:"title"` + Description string `json:"description" yaml:"description"` + Deposit sdk.Coins `json:"deposit" yaml:"deposit"` + ERC20Address string `json:"erc20_address" yaml:"erc20_address"` + NewERC20Address string `json:"new_erc20_address" yaml:"new_erc20_address"` +} + +func RegisterCoinProposalRESTHandler(clientCtx client.Context) govrest.ProposalRESTHandler { + return govrest.ProposalRESTHandler{ + SubRoute: types.ModuleName, + Handler: newRegisterCoinProposalHandler(clientCtx), + } +} + +func RegisterERC20ProposalRESTHandler(clientCtx client.Context) govrest.ProposalRESTHandler { + return govrest.ProposalRESTHandler{ + SubRoute: types.ModuleName, + Handler: newRegisterERC20ProposalHandler(clientCtx), + } +} + +func ToggleTokenRelayRESTHandler(clientCtx client.Context) govrest.ProposalRESTHandler { + return govrest.ProposalRESTHandler{ + SubRoute: types.ModuleName, + Handler: newToggleTokenRelayHandler(clientCtx), + } +} + +func UpdateTokenPairERC20ProposalRESTHandler(clientCtx client.Context) govrest.ProposalRESTHandler { + return govrest.ProposalRESTHandler{ + SubRoute: types.ModuleName, + Handler: newUpdateTokenPairERC20ProposalHandler(clientCtx), + } +} + +// nolint: dupl +func newRegisterCoinProposalHandler(clientCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req RegisterCoinProposalRequest + + if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + fromAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From) + if rest.CheckBadRequestError(w, err) { + return + } + + content := types.NewRegisterCoinProposal(req.Title, req.Description, req.Metadata) + msg, err := govtypes.NewMsgSubmitProposal(content, req.Deposit, fromAddr) + if rest.CheckBadRequestError(w, err) { + return + } + + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) + } +} + +// nolint: dupl +func newRegisterERC20ProposalHandler(clientCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req RegisterERC20ProposalRequest + + if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + fromAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From) + if rest.CheckBadRequestError(w, err) { + return + } + + content := types.NewRegisterERC20Proposal(req.Title, req.Description, req.ERC20Address) + msg, err := govtypes.NewMsgSubmitProposal(content, req.Deposit, fromAddr) + if rest.CheckBadRequestError(w, err) { + return + } + + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) + } +} + +// nolint: dupl +func newToggleTokenRelayHandler(clientCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req ToggleTokenRelayProposalRequest + + if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + fromAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From) + if rest.CheckBadRequestError(w, err) { + return + } + + content := types.NewToggleTokenRelayProposal(req.Title, req.Description, req.Token) + msg, err := govtypes.NewMsgSubmitProposal(content, req.Deposit, fromAddr) + if rest.CheckBadRequestError(w, err) { + return + } + + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) + } +} + +func newUpdateTokenPairERC20ProposalHandler(clientCtx client.Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req UpdateTokenPairERC20ProposalRequest + + if !rest.ReadRESTReq(w, r, clientCtx.LegacyAmino, &req) { + return + } + + req.BaseReq = req.BaseReq.Sanitize() + if !req.BaseReq.ValidateBasic(w) { + return + } + + fromAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From) + if rest.CheckBadRequestError(w, err) { + return + } + + content := types.NewUpdateTokenPairERC20Proposal(req.Title, req.Description, req.ERC20Address, req.NewERC20Address) + msg, err := govtypes.NewMsgSubmitProposal(content, req.Deposit, fromAddr) + if rest.CheckBadRequestError(w, err) { + return + } + + if rest.CheckBadRequestError(w, msg.ValidateBasic()) { + return + } + + tx.WriteGeneratedTxResponse(clientCtx, w, req.BaseReq, msg) + } +} diff --git a/x/intrarelayer/client/testutil/cli_test.go b/x/intrarelayer/client/testutil/cli_test.go new file mode 100644 index 0000000000..c43579ce0a --- /dev/null +++ b/x/intrarelayer/client/testutil/cli_test.go @@ -0,0 +1,83 @@ +package testutil + +import ( + "fmt" + "strings" + "testing" + + tmcli "github.com/tendermint/tendermint/libs/cli" + + "github.com/stretchr/testify/suite" + + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + + "github.com/tharsis/ethermint/testutil/network" + evmosnetwork "github.com/tharsis/evmos/testutil/network" + "github.com/tharsis/evmos/x/intrarelayer/client/cli" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network +} + +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + var err error + s.cfg = evmosnetwork.DefaultConfig() + s.cfg.NumValidators = 1 + + s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) + s.Require().NoError(err) + s.Require().NotNil(s.network) + + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestCmdParams() { + val := s.network.Validators[0] + + testCases := []struct { + name string + args []string + expectedOutput string + }{ + { + "intrarelayer params", + []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + `{"params":{"enable_intrarelayer":true,"token_pair_voting_period":"172800s","enable_evm_hook":true}}`, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetParamsCmd() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + s.Require().NoError(err) + s.Require().Equal(strings.TrimSpace(tc.expectedOutput), strings.TrimSpace(out.String())) + }) + } +} diff --git a/x/intrarelayer/client/tx.go b/x/intrarelayer/client/tx.go deleted file mode 100644 index 056e8c35e9..0000000000 --- a/x/intrarelayer/client/tx.go +++ /dev/null @@ -1,131 +0,0 @@ -package cli - -import ( - "fmt" - - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/ethereum/go-ethereum/common" - - ethermint "github.com/tharsis/ethermint/types" - "github.com/tharsis/evmos/x/intrarelayer/types" -) - -// NewTxCmd returns a root CLI command handler for certain modules/intrarelayer transaction commands. -func NewTxCmd() *cobra.Command { - txCmd := &cobra.Command{ - Use: types.ModuleName, - Short: "intrarelayer subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - txCmd.AddCommand( - NewConvertCoinCmd(), - ) - return txCmd -} - -// NewConvertCoinCmd returns a CLI command handler for converting cosmos coins -func NewConvertCoinCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "convert-coin [coin] [receiver_hex]", - Short: "Convert a Cosmos coin to ERC20", - Args: cobra.RangeArgs(1, 2), - RunE: func(cmd *cobra.Command, args []string) error { - cliCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - coin, err := sdk.ParseCoinNormalized(args[0]) - if err != nil { - return err - } - - var receiver string - sender := cliCtx.GetFromAddress() - - if len(args) == 2 { - receiver = args[1] - if err := ethermint.ValidateAddress(receiver); err != nil { - return fmt.Errorf("invalid receiver hex address %w", err) - } - } else { - receiver = common.BytesToAddress(sender).Hex() - } - - msg := &types.MsgConvertCoin{ - Coin: coin, - Receiver: receiver, - Sender: sender.String(), - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(cliCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - return cmd -} - -// NewConvertERC20Cmd returns a CLI command handler for converting ERC20s -func NewConvertERC20Cmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "convert-erc20 [contract-address] [amount] [receiver]", - Short: "Convert an ERC20 token to Cosmos coin", - Args: cobra.RangeArgs(2, 3), - RunE: func(cmd *cobra.Command, args []string) error { - cliCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - contract := args[0] - if err := ethermint.ValidateAddress(contract); err != nil { - return fmt.Errorf("invalid ERC20 contract address %w", err) - } - - amount, ok := sdk.NewIntFromString(args[1]) - if !ok { - return fmt.Errorf("invalid amount %s", args[1]) - } - - from := common.BytesToAddress(cliCtx.GetFromAddress().Bytes()) - - receiver := cliCtx.GetFromAddress() - if len(args) == 3 { - receiver, err = sdk.AccAddressFromBech32(args[2]) - if err != nil { - return err - } - } - - msg := &types.MsgConvertERC20{ - ContractAddress: contract, - Amount: amount, - Receiver: receiver.String(), - Sender: from.Hex(), - } - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(cliCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - return cmd -} diff --git a/x/intrarelayer/keeper/evm.go b/x/intrarelayer/keeper/evm.go index ebbfdf4f67..afe697dffc 100644 --- a/x/intrarelayer/keeper/evm.go +++ b/x/intrarelayer/keeper/evm.go @@ -104,7 +104,7 @@ func (k Keeper) CallEVMWithPayload(ctx sdk.Context, from common.Address, contrac return nil, err } - k.evmKeeper.SetNonce(types.ModuleAddress, nonce+1) + k.evmKeeper.SetNonce(from, nonce+1) if res.Failed() { return nil, sdkerrors.Wrap(evmtypes.ErrVMExecution, res.VmError) diff --git a/x/intrarelayer/keeper/evm_hooks_test.go b/x/intrarelayer/keeper/evm_hooks_test.go index 43e7cdb632..2cb29ba6f6 100644 --- a/x/intrarelayer/keeper/evm_hooks_test.go +++ b/x/intrarelayer/keeper/evm_hooks_test.go @@ -9,6 +9,16 @@ import ( "github.com/tharsis/evmos/x/intrarelayer/types" ) +// ensureHooksSet tries to set the hooks on EVMKeeper, this will fail if the intrarelayer hook is already set +func (suite *KeeperTestSuite) ensureHooksSet() { + // TODO: PR to Ethermint to add the functionality `GetHooks` or `areHooksSet` to avoid catching a panic + defer func() { + err := recover() + suite.Require().NotNil(err) + }() + suite.app.EvmKeeper.SetHooks(suite.app.IntrarelayerKeeper) +} + func (suite *KeeperTestSuite) TestEvmHooksRegisterERC20() { testCases := []struct { name string @@ -18,7 +28,6 @@ func (suite *KeeperTestSuite) TestEvmHooksRegisterERC20() { { "correct execution", func(contractAddr common.Address) { - // pair := types.NewTokenPair(contractAddr, "coinevm", true, types.OWNER_MODULE) _, err := suite.app.IntrarelayerKeeper.RegisterERC20(suite.ctx, contractAddr) suite.Require().NoError(err) @@ -28,16 +37,14 @@ func (suite *KeeperTestSuite) TestEvmHooksRegisterERC20() { // Burn the 10 tokens of suite.address (owner) msg := suite.BurnERC20Token(contractAddr, suite.address, big.NewInt(10)) - logs := suite.app.EvmKeeper.GetTxLogsTransient(msg.AsTransaction().Hash()) - - // After this execution, the burned tokens will be available on the cosmos chain - err = suite.app.IntrarelayerKeeper.PostTxProcessing(suite.ctx, msg.AsTransaction().Hash(), logs) - suite.Require().NoError(err) + hash := msg.AsTransaction().Hash() + logs := suite.app.EvmKeeper.GetTxLogsTransient(hash) + suite.Require().NotEmpty(logs) }, true, }, { - "Unregistered pair", + "unregistered pair", func(contractAddr common.Address) { // Mint 10 tokens to suite.address (owner) _ = suite.MintERC20Token(contractAddr, suite.address, suite.address, big.NewInt(10)) @@ -45,27 +52,23 @@ func (suite *KeeperTestSuite) TestEvmHooksRegisterERC20() { // Burn the 10 tokens of suite.address (owner) msg := suite.BurnERC20Token(contractAddr, suite.address, big.NewInt(10)) - logs := suite.app.EvmKeeper.GetTxLogsTransient(msg.AsTransaction().Hash()) - - // Since theres no pair registered, no coins should be minted - err := suite.app.IntrarelayerKeeper.PostTxProcessing(suite.ctx, msg.AsTransaction().Hash(), logs) - suite.Require().NoError(err) + hash := msg.AsTransaction().Hash() + logs := suite.app.EvmKeeper.GetTxLogsTransient(hash) + suite.Require().NotEmpty(logs) }, false, }, { - "Wrong event", + "wrong event", func(contractAddr common.Address) { _, err := suite.app.IntrarelayerKeeper.RegisterERC20(suite.ctx, contractAddr) suite.Require().NoError(err) // Mint 10 tokens to suite.address (owner) msg := suite.MintERC20Token(contractAddr, suite.address, suite.address, big.NewInt(10)) - logs := suite.app.EvmKeeper.GetTxLogsTransient(msg.AsTransaction().Hash()) - - // No coins should be minted on cosmos after a mint of the erc20 token - err = suite.app.IntrarelayerKeeper.PostTxProcessing(suite.ctx, msg.AsTransaction().Hash(), logs) - suite.Require().NoError(err) + hash := msg.AsTransaction().Hash() + logs := suite.app.EvmKeeper.GetTxLogsTransient(hash) + suite.Require().NotEmpty(logs) }, false, }, @@ -75,19 +78,21 @@ func (suite *KeeperTestSuite) TestEvmHooksRegisterERC20() { suite.mintFeeCollector = true suite.SetupTest() + suite.ensureHooksSet() + contractAddr := suite.DeployContract("coin", "token") suite.Commit() tc.malleate(contractAddr) - balance := suite.app.BankKeeper.GetBalance(suite.ctx, sdk.AccAddress(suite.address.Bytes()), "irm"+contractAddr.String()) + balance := suite.app.BankKeeper.GetBalance(suite.ctx, sdk.AccAddress(suite.address.Bytes()), types.CreateDenom(contractAddr.String())) suite.Commit() if tc.result { // Check if the execution was successfull - suite.Require().Equal(balance.Amount, sdk.NewInt(10)) + suite.Require().Equal(int64(10), balance.Amount.Int64()) } else { // Check that no changes were made to the account - suite.Require().Equal(balance.Amount, sdk.NewInt(0)) + suite.Require().Equal(int64(0), balance.Amount.Int64()) } }) } @@ -109,6 +114,9 @@ func (suite *KeeperTestSuite) TestEvmHooksRegisterCoin() { suite.Run(fmt.Sprintf("Case %s", tc.name), func() { suite.mintFeeCollector = true suite.SetupTest() + + suite.ensureHooksSet() + metadata, pair := suite.setupRegisterCoin() suite.Require().NotNil(metadata) suite.Require().NotNil(pair) @@ -137,11 +145,7 @@ func (suite *KeeperTestSuite) TestEvmHooksRegisterCoin() { suite.Require().Equal(balance, big.NewInt(tc.burn)) // Burn the 10 tokens of suite.address (owner) - msg := suite.BurnERC20Token(contractAddr, suite.address, big.NewInt(tc.reconvert)) - logs := suite.app.EvmKeeper.GetTxLogsTransient(msg.AsTransaction().Hash()) - - // After this execution, the burned tokens will be available on the cosmos chain - err = suite.app.IntrarelayerKeeper.PostTxProcessing(suite.ctx, msg.AsTransaction().Hash(), logs) + _ = suite.BurnERC20Token(contractAddr, suite.address, big.NewInt(tc.reconvert)) balance = suite.BalanceOf(common.HexToAddress(pair.Erc20Address), suite.address) cosmosBalance = suite.app.BankKeeper.GetBalance(suite.ctx, sender, metadata.Base) diff --git a/x/intrarelayer/keeper/migrations.go b/x/intrarelayer/keeper/migrations.go new file mode 100644 index 0000000000..3be1ada66f --- /dev/null +++ b/x/intrarelayer/keeper/migrations.go @@ -0,0 +1,13 @@ +package keeper + +// Migrator is a struct for handling in-place store migrations. +type Migrator struct { + keeper Keeper +} + +// NewMigrator returns a new Migrator. +func NewMigrator(keeper Keeper) Migrator { + return Migrator{ + keeper: keeper, + } +} diff --git a/x/intrarelayer/keeper/msg_server_test.go b/x/intrarelayer/keeper/msg_server_test.go index 58ce21b7a3..6a54d2c809 100644 --- a/x/intrarelayer/keeper/msg_server_test.go +++ b/x/intrarelayer/keeper/msg_server_test.go @@ -5,6 +5,7 @@ import ( "math/big" sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/ethereum/go-ethereum/common" "github.com/tharsis/evmos/x/intrarelayer/types" ) @@ -174,7 +175,7 @@ func (suite *KeeperTestSuite) TestConvertECR20NativeERC20() { tc.malleate() suite.Commit() - coinName := "irm" + contractAddr.String() + coinName := types.CreateDenom(contractAddr.String()) sender := sdk.AccAddress(suite.address.Bytes()) msg := types.NewMsgConvertERC20( sdk.NewInt(tc.burn), @@ -225,7 +226,7 @@ func (suite *KeeperTestSuite) TestConvertCoinNativeERC20() { suite.Require().NotNil(contractAddr) // Precondition: Convert ERC20 to Coins - coinName := "irm" + contractAddr.String() + coinName := types.CreateDenom(contractAddr.String()) sender := sdk.AccAddress(suite.address.Bytes()) suite.MintERC20Token(contractAddr, suite.address, suite.address, big.NewInt(tc.mint)) suite.Commit() @@ -271,3 +272,28 @@ func (suite *KeeperTestSuite) TestConvertCoinNativeERC20() { } suite.mintFeeCollector = false } + +func (suite *KeeperTestSuite) TestConvertNativeIBC() { + suite.SetupTest() + validMetadata := banktypes.Metadata{ + Description: "ATOM IBC voucher (channel 14)", + Base: "ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", + // NOTE: Denom units MUST be increasing + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: "ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", + Exponent: 0, + }, + { + Denom: "coin2", + Exponent: uint32(18), + }, + }, + Name: "ATOM channel-14", + Symbol: "ibcATOM-14", + Display: "ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", + } + _, err := suite.app.IntrarelayerKeeper.RegisterCoin(suite.ctx, validMetadata) + suite.Require().NoError(err) + suite.Commit() +} diff --git a/x/intrarelayer/keeper/proposals.go b/x/intrarelayer/keeper/proposals.go index 73d62f7b69..8d683f0360 100644 --- a/x/intrarelayer/keeper/proposals.go +++ b/x/intrarelayer/keeper/proposals.go @@ -22,6 +22,10 @@ func (k Keeper) RegisterCoin(ctx sdk.Context, coinMetadata banktypes.Metadata) ( return nil, sdkerrors.Wrapf(types.ErrInternalTokenPair, "coin denomination already registered: %s", coinMetadata.Name) } + if err := k.verifyMetadata(ctx, coinMetadata); err != nil { + return nil, sdkerrors.Wrapf(types.ErrInternalTokenPair, "coin metadata is invalid %s", coinMetadata.Name) + } + addr, err := k.DeployERC20Contract(ctx, coinMetadata) if err != nil { return nil, sdkerrors.Wrap(err, "failed to create wrapped coin denom metadata for ERC20") @@ -35,16 +39,18 @@ func (k Keeper) RegisterCoin(ctx sdk.Context, coinMetadata banktypes.Metadata) ( return &pair, nil } +func (k Keeper) verifyMetadata(ctx sdk.Context, coinMetadata banktypes.Metadata) error { + meta, found := k.bankKeeper.GetDenomMetaData(ctx, coinMetadata.Base) + if !found { + k.bankKeeper.SetDenomMetaData(ctx, coinMetadata) + return nil + } + // If it already existed, Check that is equal to what is stored + return equalMetadata(meta, coinMetadata) +} + // DeployERC20Contract creates and deploys an ERC20 contract on the EVM with the intrarelayer module account as owner func (k Keeper) DeployERC20Contract(ctx sdk.Context, coinMetadata banktypes.Metadata) (common.Address, error) { - // meta, found := k.bankKeeper.GetDenomMetaData(ctx, pair.Denom) - // if !found { - // // metadata already exists; exit - // // TODO: validate that the fields from the ERC20 match the denom metadata's - // return common.Address{}, sdkerrors.Wrapf(types.ErrInternalTokenPair, "coin denomination is not registered") - // } - // k.evmKeeper.SetNonce(types.ModuleAddress, 1) - ctorArgs, err := contracts.ERC20BurnableAndMintableContract.ABI.Pack("", coinMetadata.Name, coinMetadata.Symbol) if err != nil { return common.Address{}, sdkerrors.Wrapf(err, "coin metadata is invalid %s", coinMetadata.Name) @@ -88,7 +94,7 @@ func (k Keeper) RegisterERC20(ctx sdk.Context, contract common.Address) (*types. k.SetTokenPair(ctx, pair) k.SetDenomMap(ctx, pair.Denom, pair.GetID()) k.SetERC20Map(ctx, common.HexToAddress(pair.Erc20Address), pair.GetID()) - return nil, nil + return &pair, nil } // CreateCoinMetadata generates the metadata to represent the ERC20 token on evmos. @@ -103,7 +109,6 @@ func (k Keeper) CreateCoinMetadata(ctx sdk.Context, contract common.Address) (*b _, found := k.bankKeeper.GetDenomMetaData(ctx, types.CreateDenom(strContract)) if found { // metadata already exists; exit - // TODO: validate that the fields from the ERC20 match the denom metadata's return nil, sdkerrors.Wrapf(types.ErrInternalTokenPair, "coin denomination already registered") } @@ -176,22 +181,53 @@ func (k Keeper) UpdateTokenPairERC20(ctx sdk.Context, erc20Addr, newERC20Addr co if !found { return types.TokenPair{}, sdkerrors.Wrapf(types.ErrInternalTokenPair, "could not get metadata for %s", pair.Denom) } + + // safety check + if len(metadata.DenomUnits) == 0 { + return types.TokenPair{}, sdkerrors.Wrapf(types.ErrInternalTokenPair, "metadata denom units for %s cannot be empty", pair.Erc20Address) + } + // Get new erc20 values erc20Data, err := k.QueryERC20(ctx, newERC20Addr) if err != nil { return types.TokenPair{}, sdkerrors.Wrapf(types.ErrInternalTokenPair, "could not get token %s erc20Data", newERC20Addr.String()) } - // Compare - if len(metadata.DenomUnits) != 2 { - return types.TokenPair{}, sdkerrors.Wrapf(types.ErrInternalTokenPair, "invalid metadata for %s ", pair.Erc20Address) - } + // compare metadata and ERC20 details if metadata.Display != erc20Data.Name || metadata.Symbol != erc20Data.Symbol || - metadata.DenomUnits[1].Denom != erc20Data.Name || - metadata.DenomUnits[1].Exponent != uint32(erc20Data.Decimals) || metadata.Description != types.CreateDenomDescription(erc20Addr.String()) { - return types.TokenPair{}, sdkerrors.Wrapf(types.ErrInternalTokenPair, "invalid metadata for %s ", pair.Erc20Address) + return types.TokenPair{}, sdkerrors.Wrapf(types.ErrInternalTokenPair, "metadata details (display, symbol, description) don't match the ERC20 details from %s ", pair.Erc20Address) + } + + // check that the denom units contain one item with the same + // name and decimal values as the ERC20 + found = false + for _, denomUnit := range metadata.DenomUnits { + // iterate denom units until we found the one with the ERC20 Name + if denomUnit.Denom != erc20Data.Name { + continue + } + + // once found, check it has the same exponent + if denomUnit.Exponent != uint32(erc20Data.Decimals) { + return types.TokenPair{}, sdkerrors.Wrapf( + types.ErrInternalTokenPair, "metadata denom unit exponent doesn't match the ERC20 details from %s, expected %d, got %d", + pair.Erc20Address, erc20Data.Decimals, denomUnit.Exponent, + ) + } + + // break as metadata might contain denom units for higher exponents + found = true + break + } + + if !found { + return types.TokenPair{}, sdkerrors.Wrapf( + types.ErrInternalTokenPair, + "metadata doesn't contain denom unit found for ERC20 %s (%s)", + erc20Data.Name, pair.Erc20Address, + ) } // Update the metadata description with the new address diff --git a/x/intrarelayer/keeper/proposals_test.go b/x/intrarelayer/keeper/proposals_test.go index 9cf0a8e3ce..9332321c2f 100644 --- a/x/intrarelayer/keeper/proposals_test.go +++ b/x/intrarelayer/keeper/proposals_test.go @@ -77,6 +77,35 @@ func (suite KeeperTestSuite) TestRegisterCoin() { }, false, }, + { + "metadata different that stored", + func() { + validMetadata := banktypes.Metadata{ + Description: "desc", + Base: cosmosTokenName, + // NOTE: Denom units MUST be increasing + DenomUnits: []*banktypes.DenomUnit{ + { + Denom: cosmosTokenName, + Exponent: 0, + }, + { + Denom: "coin2", + Exponent: uint32(1), + }, + { + Denom: "extraDenom", + Exponent: uint32(2), + }, + }, + Name: "otherName", + Symbol: "token", + Display: cosmosTokenName, + } + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, validMetadata) + }, + false, + }, { "ok", func() {}, @@ -177,7 +206,7 @@ func (suite KeeperTestSuite) TestRegisterERC20() { contractAddr = suite.DeployContract(erc20Name, erc20Symbol) suite.Commit() - coinName := "irm" + contractAddr.String() + coinName := types.CreateDenom(contractAddr.String()) pair = types.NewTokenPair(contractAddr, coinName, true, types.OWNER_EXTERNAL) tc.malleate() @@ -340,13 +369,83 @@ func (suite KeeperTestSuite) TestUpdateTokenPairERC20() { }, false, }, + { + "empty denom units", + func() { + var found bool + contractAddr = suite.setupRegisterERC20Pair() + id := suite.app.IntrarelayerKeeper.GetTokenPairID(suite.ctx, contractAddr.String()) + pair, found = suite.app.IntrarelayerKeeper.GetTokenPair(suite.ctx, id) + suite.Require().True(found) + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, banktypes.Metadata{Base: pair.Denom}) + suite.Commit() + + // Deploy a new contrat with the same values + newContractAddr = suite.DeployContract(erc20Name, erc20Symbol) + }, + false, + }, + { + "metadata ERC20 details mismatch", + func() { + var found bool + contractAddr = suite.setupRegisterERC20Pair() + id := suite.app.IntrarelayerKeeper.GetTokenPairID(suite.ctx, contractAddr.String()) + pair, found = suite.app.IntrarelayerKeeper.GetTokenPair(suite.ctx, id) + suite.Require().True(found) + metadata := banktypes.Metadata{Base: pair.Denom, DenomUnits: []*banktypes.DenomUnit{{}}} + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, metadata) + suite.Commit() + + // Deploy a new contrat with the same values + newContractAddr = suite.DeployContract(erc20Name, erc20Symbol) + }, + false, + }, + { + "no denom unit with ERC20 name", + func() { + var found bool + contractAddr = suite.setupRegisterERC20Pair() + id := suite.app.IntrarelayerKeeper.GetTokenPairID(suite.ctx, contractAddr.String()) + pair, found = suite.app.IntrarelayerKeeper.GetTokenPair(suite.ctx, id) + suite.Require().True(found) + metadata := banktypes.Metadata{Base: pair.Denom, Display: erc20Name, Description: types.CreateDenomDescription(contractAddr.String()), Symbol: erc20Symbol, DenomUnits: []*banktypes.DenomUnit{{}}} + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, metadata) + suite.Commit() + + // Deploy a new contrat with the same values + newContractAddr = suite.DeployContract(erc20Name, erc20Symbol) + }, + false, + }, + { + "denom unit and ERC20 decimals mismatch", + func() { + var found bool + contractAddr = suite.setupRegisterERC20Pair() + id := suite.app.IntrarelayerKeeper.GetTokenPairID(suite.ctx, contractAddr.String()) + pair, found = suite.app.IntrarelayerKeeper.GetTokenPair(suite.ctx, id) + suite.Require().True(found) + metadata := banktypes.Metadata{Base: pair.Denom, Display: erc20Name, Description: types.CreateDenomDescription(contractAddr.String()), Symbol: erc20Symbol, DenomUnits: []*banktypes.DenomUnit{{Denom: erc20Name}}} + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, metadata) + suite.Commit() + + // Deploy a new contrat with the same values + newContractAddr = suite.DeployContract(erc20Name, erc20Symbol) + }, + false, + }, { "ok", func() { + var found bool contractAddr = suite.setupRegisterERC20Pair() id := suite.app.IntrarelayerKeeper.GetTokenPairID(suite.ctx, contractAddr.String()) - pair, _ = suite.app.IntrarelayerKeeper.GetTokenPair(suite.ctx, id) - metadata, _ = suite.app.BankKeeper.GetDenomMetaData(suite.ctx, cosmosTokenName) + pair, found = suite.app.IntrarelayerKeeper.GetTokenPair(suite.ctx, id) + suite.Require().True(found) + metadata := banktypes.Metadata{Base: pair.Denom, Display: erc20Name, Description: types.CreateDenomDescription(contractAddr.String()), Symbol: erc20Symbol, DenomUnits: []*banktypes.DenomUnit{{Denom: erc20Name, Exponent: 18}}} + suite.app.BankKeeper.SetDenomMetaData(suite.ctx, metadata) suite.Commit() // Deploy a new contrat with the same values @@ -363,7 +462,7 @@ func (suite KeeperTestSuite) TestUpdateTokenPairERC20() { var err error pair, err = suite.app.IntrarelayerKeeper.UpdateTokenPairERC20(suite.ctx, contractAddr, newContractAddr) - metadata, _ = suite.app.BankKeeper.GetDenomMetaData(suite.ctx, "irm"+contractAddr.String()) + metadata, _ = suite.app.BankKeeper.GetDenomMetaData(suite.ctx, types.CreateDenom(contractAddr.String())) if tc.expPass { suite.Require().NoError(err, tc.name) diff --git a/x/intrarelayer/keeper/utils.go b/x/intrarelayer/keeper/utils.go new file mode 100644 index 0000000000..559c8b4866 --- /dev/null +++ b/x/intrarelayer/keeper/utils.go @@ -0,0 +1,22 @@ +package keeper + +import ( + "fmt" + + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func equalMetadata(a, b banktypes.Metadata) error { + if a.Base == b.Base && a.Description == b.Description && a.Display == b.Display && a.Name == b.Name && a.Symbol == b.Symbol { + if len(a.DenomUnits) != len(b.DenomUnits) { + return fmt.Errorf("metadata provided has different denom units from stored, %d ≠ %d", len(a.DenomUnits), len(b.DenomUnits)) + } + for i, v := range a.DenomUnits { + if v != b.DenomUnits[i] { + return fmt.Errorf("metadata provided has different denom unit from stored, %s ≠ %s", a.DenomUnits[i], b.DenomUnits[i]) + } + } + return nil + } + return fmt.Errorf("metadata provided is different from stored") +} diff --git a/x/intrarelayer/module.go b/x/intrarelayer/module.go index faf4a1f1dc..20a0185543 100644 --- a/x/intrarelayer/module.go +++ b/x/intrarelayer/module.go @@ -18,7 +18,7 @@ import ( "github.com/spf13/cobra" abci "github.com/tendermint/tendermint/abci/types" - cli "github.com/tharsis/evmos/x/intrarelayer/client" + "github.com/tharsis/evmos/x/intrarelayer/client/cli" "github.com/tharsis/evmos/x/intrarelayer/keeper" "github.com/tharsis/evmos/x/intrarelayer/types" ) @@ -128,6 +128,8 @@ func (am AppModule) LegacyQuerierHandler(amino *codec.LegacyAmino) sdk.Querier { func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), am.keeper) types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + + _ = keeper.NewMigrator(am.keeper) } func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) { diff --git a/x/intrarelayer/proposal_handler.go b/x/intrarelayer/proposal_handler.go index 067fdc837d..e08d1e6e74 100644 --- a/x/intrarelayer/proposal_handler.go +++ b/x/intrarelayer/proposal_handler.go @@ -11,7 +11,7 @@ import ( // NewIntrarelayerProposalHandler creates a governance handler to manage new proposal types. // It enables RegisterTokenPairProposal to propose a registration of token mapping -func NewIntrarelayerProposalHandler(k keeper.Keeper) govtypes.Handler { +func NewIntrarelayerProposalHandler(k *keeper.Keeper) govtypes.Handler { return func(ctx sdk.Context, content govtypes.Content) error { switch c := content.(type) { case *types.RegisterCoinProposal: @@ -29,7 +29,7 @@ func NewIntrarelayerProposalHandler(k keeper.Keeper) govtypes.Handler { } } -func handleRegisterCoinProposal(ctx sdk.Context, k keeper.Keeper, p *types.RegisterCoinProposal) error { +func handleRegisterCoinProposal(ctx sdk.Context, k *keeper.Keeper, p *types.RegisterCoinProposal) error { pair, err := k.RegisterCoin(ctx, p.Metadata) if err != nil { return err @@ -45,7 +45,7 @@ func handleRegisterCoinProposal(ctx sdk.Context, k keeper.Keeper, p *types.Regis return nil } -func handleRegisterERC20Proposal(ctx sdk.Context, k keeper.Keeper, p *types.RegisterERC20Proposal) error { +func handleRegisterERC20Proposal(ctx sdk.Context, k *keeper.Keeper, p *types.RegisterERC20Proposal) error { pair, err := k.RegisterERC20(ctx, common.HexToAddress(p.Erc20Address)) if err != nil { return err @@ -61,7 +61,7 @@ func handleRegisterERC20Proposal(ctx sdk.Context, k keeper.Keeper, p *types.Regi return nil } -func handleToggleRelayProposal(ctx sdk.Context, k keeper.Keeper, p *types.ToggleTokenRelayProposal) error { +func handleToggleRelayProposal(ctx sdk.Context, k *keeper.Keeper, p *types.ToggleTokenRelayProposal) error { pair, err := k.ToggleRelay(ctx, p.Token) if err != nil { return err @@ -78,7 +78,7 @@ func handleToggleRelayProposal(ctx sdk.Context, k keeper.Keeper, p *types.Toggle return nil } -func handleUpdateTokenPairERC20Proposal(ctx sdk.Context, k keeper.Keeper, p *types.UpdateTokenPairERC20Proposal) error { +func handleUpdateTokenPairERC20Proposal(ctx sdk.Context, k *keeper.Keeper, p *types.UpdateTokenPairERC20Proposal) error { pair, err := k.UpdateTokenPairERC20(ctx, p.GetERC20Address(), p.GetNewERC20Address()) if err != nil { return err diff --git a/x/intrarelayer/spec/01_concepts.md b/x/intrarelayer/spec/01_concepts.md new file mode 100644 index 0000000000..550b11a474 --- /dev/null +++ b/x/intrarelayer/spec/01_concepts.md @@ -0,0 +1,70 @@ + + +# Concepts + +## Token Pair + +The `x/intrarelayer` module maintains a canonical one-to-one mapping of native Cosmos Coin denomination to ERC20 Token contract addresses (i.e `sdk.Coin` ←→ ERC20), called `TokenPair`. The conversion of the ERC20 tokens ←→ Coin of a given pair can be enabled or disabled via governance. + +## Token Pair Registration + +Users can register a new token pair proposal through the governance module and initiate a vote to include the token pair in the module. + +When the proposal passes, the intrarelayer module registers the Cosmos Coin and ERC20 Token mapping on the application's store. + +### Registration of a Cosmos Coin + +A native Cosmos Coin corresponds to an `sdk.Coin` that is native to the bank module. It can be either the native staking/gas denomination (eg: EVMOS, ATOM, etc) or an IBC fungible token voucher (i.e with denom format of `ibc/{hash}`). + +When a proposal is initiated for an existing native Cosmos Coin, the intrarelayer module will deploy a factory ERC20 contract, representing the ERC20 token for the token pair, giving the module ownership of that contract. + +### Registration of an ERC20 token + +A proposal for an existing (i.e already deployed) ERC20 contract can be initiated too. In this case, the ERC20 maintains the original owner of the contract and uses an escrow & mint / burn & unescrow mechanism similar to the one defined by the [ICS20 - Fungible Token Transfer](https://github.com/cosmos/ibc/blob/master/spec/app/ics-020-fungible-token-transfer) specification. The token pair is composed of the original ERC20 token and a corresponding native Cosmos coin denomination. + +### Token details and metadata + +Coin metadata is derived from the ERC20 token details (name, symbol, decimals) and vice versa. A special case is also described below that for the ERC20 representation of IBC fungible token (ICS20) vouchers. + +#### Coin Metadata to ERC20 details + +During the registration of a Cosmos Coin the following bank `Metadata` is used to deploy a ERC20 contract: + +- **Name** +- **Symbol** +- **Decimals** + +The native Cosmos Coin contains a more extensive metadata than the ERC20 and includes all necessary details for the conversion into a ERC20 Token, which requires no additional population of data. + +#### IBC voucher Metadata to ERC20 details + +IBC vouchers should comply to the following standard: + +- **Name**: `{NAME} channel-{channel}` +- **Symbol**: `ibc{NAME}-{channel}` +- **Decimals**: derived from bank `Metadata` + +#### ERC20 details to Coin Metadata + +During the Registration of an ERC20 Token the Coin metadata is derived from the ERC20 metadata and the bank metadata: + +- **Description**: `Cosmos coin token representation of {contractAddress}` +- **DenomUnits**: + - Coin: `0` + - ERC20: `{uint32(erc20Data.Decimals)}` +- **Base**: `{"irm%s", address}` +- **Display**: `{erc20Data.Name}` +- **Name**: `{types.CreateDenom(strContract)}` +- **Symbol:** `{erc20Data.Symbol}` + +## Token Pair Modifiers + +A valid token pair can be modified through several governance proposals. The internal relaying of a token pair can be toggled with `ToggleTokenRelayProposal`, so that the conversions between the token pair's tokens can be enabled or disabled. Additionally, the ERC20 contract address of a token pair can be updated with `UpdateTokenPairERC20Proposal`. + +## Token Conversion + +Once a token pair proposal passes, the module allows for the conversion of that token pair. Holders of native Cosmos coins and IBC vouchers on the Evmos chain can convert their Coin into ERC20 Tokens, which can then be used in Evmos EVM, by creating a `ConvertCoin` Tx. Vice versa, the `ConvertERC20` Tx allows holders of ERC20 tokens on the Evmos chain to convert ERC-20 tokens back to their native Cosmos Coin representation. + +Depending on the ownership of the ERC20 contract, the ERC20 tokens either follow a burn/mint or a transfer/escrow mechanism during conversion. diff --git a/x/intrarelayer/spec/02_state.md b/x/intrarelayer/spec/02_state.md new file mode 100644 index 0000000000..18ea33ffb1 --- /dev/null +++ b/x/intrarelayer/spec/02_state.md @@ -0,0 +1,89 @@ + + +# State + +## State Objects + +The `x/intrarelayer` module keeps the following objects in state: + +| State Object | Description | Key | Value | +| ------------------- | ---------------------------------------------- | --------------------------- | ------------------- | +| Token Pair | Token Pair bytecode | `[]byte{1} + []byte(id)` | `[]byte{tokenPair}` | +| Token Pair by ERC20 | Token Pair id bytecode by erc20 contract bytes | `[]byte{2} + []byte(erc20)` | `[]byte(id)` | +| Token Pair by Denom | Token Pair id bytecode by denom string | `[]byte{3} + []byte(denom)` | `[]byte(id)` | + +### Token Pair + +One-to-one mapping of native Cosmos coin denomination to ERC20 token contract addresses (i.e `sdk.Coin` ←→ ERC20). + +```go +type TokenPair struct { + // address of ERC20 contract token + Erc20Address string `protobuf:"bytes,1,opt,name=erc20_address,json=erc20Address,proto3" json:"erc20_address,omitempty"` + // cosmos base denomination to be mapped to + Denom string `protobuf:"bytes,2,opt,name=denom,proto3" json:"denom,omitempty"` + // shows token mapping enable status + Enabled bool `protobuf:"varint,3,opt,name=enabled,proto3" json:"enabled,omitempty"` + // ERC20 owner address ENUM (0 invalid, 1 ModuleAccount, 2 external address + ContractOwner Owner `protobuf:"varint,4,opt,name=contract_owner,json=contractOwner,proto3,enum=evmos.intrarelayer.v1.Owner" json:"contract_owner,omitempty"` +} +``` + +### **Token pair ID** + +The unique identifier of a `TokenPair` is obtained by obtaining the SHA256 hash of the ERC20 hex contract address and the Coin denomination using the following function: + +```tsx +tokenPairId = sha256(erc20 + "|" + denom) +``` + +### Token Origin + +The `ConvertCoin` and `ConvertERC20` functionality need to check if the token being used is a native Coin or a native ERC20. The owner field is based on the token registration proposal type (`RegisterCoinProposal` = 1, `RegisterERC20Proposal` = 2). + +The `Owner` enumerates the ownership of a ERC20 contract. + +```go +type Owner int32 + +const ( + // OWNER_UNSPECIFIED defines an invalid/undefined owner. + OWNER_UNSPECIFIED Owner = 0 + // OWNER_MODULE erc20 is owned by the intrarelayer module account. + OWNER_MODULE Owner = 1 + // EXTERNAL erc20 is owned by an external account. + OWNER_EXTERNAL Owner = 2 +) +``` + +The `Owner` can be checked with the following helper functions: + +```go +// IsNativeCoin returns true if the owner of the ERC20 contract is the +// intrarelayer module account +func (tp TokenPair) IsNativeCoin() bool { + return tp.ContractOwner == OWNER_MODULE +} + +// IsNativeERC20 returns true if the owner of the ERC20 contract not the +// intrarelayer module account +func (tp TokenPair) IsNativeERC20() bool { + return tp.ContractOwner == OWNER_EXTERNAL +} +``` + +## Genesis State + +The `x/intrarelayer` module's `GenesisState` defines the state necessary for initializing the chain from a previous exported height. It contains the module parameters and the registered token pairs : + +```go +// GenesisState defines the module's genesis state. +type GenesisState struct { + // module parameters + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + // registered token pairs + TokenPairs []TokenPair `protobuf:"bytes,2,rep,name=token_pairs,json=tokenPairs,proto3" json:"token_pairs"` +} +``` \ No newline at end of file diff --git a/x/intrarelayer/spec/03_state_transitions.md b/x/intrarelayer/spec/03_state_transitions.md new file mode 100644 index 0000000000..a51ee2e287 --- /dev/null +++ b/x/intrarelayer/spec/03_state_transitions.md @@ -0,0 +1,103 @@ + + +# State Transitions + +The intrarelayer modules allows for two types of registration state transitions. Depending on how token pairs are registered, with `RegisterCoinProposal` or `RegisterERC20Proposal`, there are four possible conversion state transitions. + +## Token Pair Registration + +### 1. Register Coin + +A user registers a native Cosmos Coin. Once the proposal passes (i.e is approved by governance), the Intrarelayer module uses a factory pattern to deploy an ERC20 token contract representation of the Cosmos Coin. + +1. User submits a `RegisterCoinProposal` +2. Validators of the Evmos Hub vote on the proposal using `MsgVote` and proposal passes +3. If Cosmos coin or IBC voucher already exist on the bank module supply, create the ERC20 token contract on the EVM based on the ERC20Mintable ([ERC20Mintable by openzeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20)) interface + - Initial supply: 0 + - Token details (Name, Symbol, Decimals, etc) are derived from the bank module `Metadata` field on the proposal content. + +### 2. Register ERC20 + +A user registers a ERC20 token contract that is already deployed on the EVM module. Once the proposal passes (i.e is approved by governance), the Intrarelayer module creates an Cosmos coin representation of the ERC20 token. + +1. User submits a `RegisterERC20Proposal` +2. Validators of the EVMOS chain vote on the proposal using `MsgVote` and proposal passes +3. If ERC-20 contract is deployed on the EVM module, create a bank coin `Metadata` from the ERC20 details. + +## Token Pair Conversion + +Conversion of a registered `TokenPair` can be done via: + +- Cosmos transaction (`ConvertCoin` and `ConvertERC20)` +- Ethereum transaction (i.e sending a `MsgEthereumTx` that leverages the EVM hook) + +### 1. Registered Coin + +::: tip +👉 **Context:** A `TokenPair` has been created through a `RegisterCoinProposal` governance proposal. The proposal created an `ERC20` contract ([ERC20Mintable by openzeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20)) of the ERC20 token representation of the Coin from the `ModuleAccount`, assigning it as the `owner` of the contract and thus granting it the permission to call the `mint()` and `burnFrom()` methods of the ERC20. +::: + +#### Invariants + +- Only the ModuleAccount should have the Minter Role on the ERC20. Otherwise, the user could unilaterally mint an infinite supply of the ERC20 token and then convert them to the native Coin +- The user and the ModuleAccount (owner) should be the only ones that have the Burn Role for a Cosmos Coin +- There shouldn't exist any native Cosmos Coin ERC20 Contract (eg Evmos, Atom, Osmo ERC20 contracts) that is not owned by the governance +- Token/Coin supply is maintained at all times: + - Total Coin supply = Coins + Escrowed Coins + - Total Token supply = Escrowed Coins = Minted Tokens + +#### 1.1 Coin to ERC20 + +1. User submits `ConvertCoin` Tx +2. Check if intrarelaying is allowed for the pair, sender and recipient + - global parameter is enabled + - token pair is enabled + - sender tokens are not vesting + - recipient address is not blocklisted +3. If Coin is a native Cosmos Coin && Token Owner is `ModuleAccount` + 1. Escrow Cosmos coin by sending them to the intrarelayer module account + 2. Call `mint()` ERC20 tokens from the `ModuleAccount` address + 3. Send minted Tokens to recipient address + +#### 1.2 ERC20 to Coin + +1. User submits a `ConvertERC20` Tx +2. Check if intrarelaying is allowed for the pair, sender and recipient (See 1.1 Coin to ERC20) +3. If token is a ERC20 && Token Owner is `ModuleAccount` + 1. Call `burnCoins()` on ERC20 to burn ERC20 tokens from the user balance + 2. Send Coins (previously escrowed see 1.1) from module to the recipient address. + +### 2. Registered ERC20 + +::: tip +👉 **Context:** A `TokenPair` has been created through a `RegisterERC20Proposal` governance proposal. The `ModuleAccount` is not the owner of the contract, so it can't mint new tokens or burn on behalf of the user. The mechanism described below follows the same model as the ICS20 standard, by using escrow & mint / burn & unescrow logic. +::: + +#### Invariants + +- ERC20 Token supply on the EVM runtime is maintained at all times: + - Escrowed ERC20 + Minted Cosmos Coin representation of ERC20 = Burned Cosmos Coin representation of ERC20 + Unescrowed ERC20 + - Convert 10 ERC20 → Coin, the total supply increases by 10. Mint on Cosmos side, no changes on EVM + - Convert 10 Coin → ERC20, the total supply decreases by 10. Burn on Cosmos side , no changes of supply on EVM + - Total ERC20 token supply = Non Escrowed Tokens + Escrowed Tokens (on Module account address) + - Total Coin supply for the native ERC20 = Escrowed ERC20 Tokens on module account (i.e balance) = Minted Coins + +#### 2.1 ERC20 to Coin + +1. User submits a `ConvertERC20` Tx +2. Check if intrarelaying is allowed for the pair, sender and recipient (See 1.1 Coin to ERC20) +3. If token is a ERC20 && Token Owner is **not** `ModuleAccount` + 1. Escrow ERC20 token by sending them to the intrarelayer module account + 2. Mint Cosmos coins of the corresponding token pair denomination + 3. Send coins to the recipient address + +#### 2.2 Coin to ERC20 + +1. User submits `ConvertCoin` Tx +2. Check if intrarelaying is allowed for the pair, sender and recipient +3. If coin is a native Cosmos coin && Token Owner is **not** `ModuleAccount` + 1. Escrow Cosmos Coins by sending them to the intrarelayer module account + 2. Unlock escrowed ERC20 from the module address by sending it to the recipient + 3. Burn escrowed Cosmos coins diff --git a/x/intrarelayer/spec/04_transactions.md b/x/intrarelayer/spec/04_transactions.md new file mode 100644 index 0000000000..a137f1f13d --- /dev/null +++ b/x/intrarelayer/spec/04_transactions.md @@ -0,0 +1,134 @@ + + +# Transactions + +This section defines the `sdk.Msg` concrete types that result in the state transitions defined on the previous section. + +## `RegisterCoinProposal` + +A gov `Content` type to register a token pair from a Cosmos Coin. Governance users vote on this proposal and it automatically executes the custom handler for `RegisterCoinProposal` when the vote passes. + +```go +type RegisterCoinProposal struct { + // title of the proposal + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + // proposal description + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // token pair of Cosmos native denom and ERC20 token address + Metadata types.Metadata `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata"` +} +``` + +The proposal content stateless validation fails if: + +- Title is invalid (length or char) +- Description is invalid (length or char) +- Metadata is invalid + - Name and Symbol are not blank + - Base and Display denominations are valid coin denominations + - Base and Display denominations are present in the DenomUnit slice + - Base denomination has exponent 0 + - Denomination units are sorted in ascending order + - Denomination units not duplicated + +## `RegisterERC20Proposal` + +A gov `Content` type to register a token pair from an ERC20 Token. Governance users vote on this proposal and it automatically executes the custom handler for `RegisterERC20Proposal` when the vote passes. + +```go +type RegisterERC20Proposal struct { + // title of the proposal + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + // proposal description + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // contract address of ERC20 token + Erc20Address string `protobuf:"bytes,3,opt,name=erc20address,proto3" json:"erc20address,omitempty"` +} +``` + +The proposal Content stateless validation fails if: + +- Title is invalid (length or char) +- Description is invalid (length or char) +- ERC20Address is invalid + +## `MsgConvertCoin` + +A user broadcasts a `MsgConvertCoin` message to convert a Cosmos Coin to a ERC20 token. + +```go +type MsgConvertCoin struct { + // Cosmos coin which denomination is registered on intrarelayer bridge. + // The coin amount defines the total ERC20 tokens to convert. + Coin types.Coin `protobuf:"bytes,1,opt,name=coin,proto3" json:"coin"` + // recipient hex address to receive ERC20 token + Receiver string `protobuf:"bytes,2,opt,name=receiver,proto3" json:"receiver,omitempty"` + // cosmos bech32 address from the owner of the given ERC20 tokens + Sender string `protobuf:"bytes,3,opt,name=sender,proto3" json:"sender,omitempty"` +} +``` + +Message stateless validation fails if: + +- Coin is invalid (invalid denom or non-positive amount) +- Receiver hex address is invalid +- Sender bech32 address is invalid + +## `MsgConvertERC20` + +A user broadcasts a `MsgConvertERC20` message to convert a ERC20 token to a native Cosmos coin. + +```go +type MsgConvertERC20 struct { + // ERC20 token contract address registered on intrarelayer bridge + ContractAddress string `protobuf:"bytes,1,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty"` + // amount of ERC20 tokens to mint + Amount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,2,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"amount"` + // bech32 address to receive SDK coins. + Receiver string `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"` + // sender hex address from the owner of the given ERC20 tokens + Sender string `protobuf:"bytes,4,opt,name=sender,proto3" json:"sender,omitempty"` +} +``` + +Message stateless validation fails if: + +- Contract address is invalid +- Amount is not positive +- Receiver bech32 address is invalid +- Sender hex address is invalid + +## `ToggleTokenRelayProposal` + +A gov Content type to toggle the internal relaying of a token pair. + +```go +type ToggleTokenRelayProposal struct { + // title of the proposal + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + // proposal description + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // token identifier can be either the hex contract address of the ERC20 or the + // Cosmos base denomination + Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"` +} +``` + +## `UpdateTokenPairERC20Proposal` + +A gov Content type to update a token pair's ERC20 contract address. + +```go +type UpdateTokenPairERC20Proposal struct { + // title of the proposal + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + // proposal description + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // contract address of ERC20 token + Erc20Address string `protobuf:"bytes,3,opt,name=erc20_address,json=erc20Address,proto3" json:"erc20_address,omitempty"` + // new address of ERC20 token contract + NewErc20Address string `protobuf:"bytes,4,opt,name=new_erc20_address,json=newErc20Address,proto3" json:"new_erc20_address,omitempty"` +} +``` diff --git a/x/intrarelayer/spec/05_hooks.md b/x/intrarelayer/spec/05_hooks.md new file mode 100644 index 0000000000..e0e15748ff --- /dev/null +++ b/x/intrarelayer/spec/05_hooks.md @@ -0,0 +1,45 @@ + + +# Hooks + +The intrarelayer module implements two transaction hooks from the EVM and Governance modules + +## EVM Hooks + +::: tip +👉 **Purpose**: Allow for users to convert ERC20s to Cosmos Coins by sending an Ethereum tx transfer to the module account address. This enables native conversion of tokens via Metamask and EVM-enabled wallets. +::: + +### Registered Coin: ERC20 to Coin + +1. User transfers ERC20 tokens to the `ModuleAccount` address to escrow (lock) +2. Check if the ERC20 Token that was transferred from the sender is a native ERC20 or a native cosmos coin by looking at the ethereum Logs +3. If the token contract address is corresponds to the ERC20 representation of a native Cosmos Coin + 1. Call `burn()` ERC20 method from the `ModuleAccount` + 1. NOTE: This is the same as 1.2, but since the tokens are already on the ModuleAccount balance, we burn the tokens from the module address instead of calling `burnFrom()` + 2. NOTE: We don't need to mint because (1.1) escrows the coin + 2. Transfer Cosmos Coin to the bech32 account address of the sender hex address (1.) + +### Registered ERC20: ERC20 to Coin + +1. User transfers coins to the Module Account to escrow (lock) +2. Check if the ERC20 Token that was transferred is a native ERC20 or a native cosmos coin +3. If the token contract address is a native ERC20 token + 1. Mint Cosmos Coin + 2. Transfer Cosmos Coin to the bech32 account address of the sender hex (1.) + +## Governance Hooks + +::: tip +👉 **Purpose:** speed up the approval process of a token pair registration by defining a custom `VotingPeriod` duration for the `RegisterCoinProposal` and `RegisterERC20Proposal`. +::: + +### Overwriting the Voting Period + +By Implementing the [GovHooks](https://github.com/cosmos/cosmos-sdk/blob/86474748888204515f59aaeab9be295066563f46/x/gov/types/expected_keepers.go#L57) Interface from the Cosmos-SDK, the voting period for all proposals of the Intrarelayer module can be customized using the `AfterProposalDeposit` hook. + +1. Set the voting period on the intrarelayer module parameters at genesis or through governance +2. Submit a new governance proposal, e.g. `RegisterERC20Proposal` +3. The `AfterProposalDeposit` hook is automatically called and overrides the voting period for all proposals to the value defined on the intrarelayer module parameters. diff --git a/x/intrarelayer/spec/06_events.md b/x/intrarelayer/spec/06_events.md new file mode 100644 index 0000000000..19c9dc851f --- /dev/null +++ b/x/intrarelayer/spec/06_events.md @@ -0,0 +1,57 @@ + + +# Events + +The `x/intrarelayer` module emits the following events: + +## Register Coin Proposal + +| Type | Attibute Key | Attibute Value | +| --------------- | --------------- | ----------------- | +| `register_coin` | `"cosmos_coin"` | `{denom}` | +| `register_coin` | `"erc20_token"` | `{erc20_address}` | + +## Register ERC20 Proposal + +| Type | Attibute Key | Attibute Value | +| ---------------- | --------------- | ----------------- | +| `register_erc20` | `"cosmos_coin"` | `{denom}` | +| `register_erc20` | `"erc20_token"` | `{erc20_address}` | + +## Toggle Token Relay + +| Type | Attibute Key | Attibute Value | +| -------------------- | --------------- | ----------------- | +| `toggle_token_relay` | `"erc20_token"` | `{erc20_address}` | +| `toggle_token_relay` | `"cosmos_coin"` | `{denom}` | + +## Update Token Pair ERC20 + +| Type | Attibute Key | Attibute Value | +| ------------------------- | --------------- | ----------------- | +| `update_token_pair_erc20` | `"erc20_token"` | `{erc20_address}` | +| `update_token_pair_erc20` | `"cosmos_coin"` | `{denom}` | + +## Convert Coin + +| Type | Attibute Key | Attibute Value | +| -------------- | --------------- | --------------------------- | +| `convert_coin` | `"sender"` | `{msg.Sender}` | +| `convert_coin` | `"receiver"` | `{msg.Receiver}` | +| `convert_coin` | `"amount"` | `{msg.Coin.Amount.String()}` | +| `convert_coin` | `"cosmos_coin"` | `{denom}` | +| `convert_coin` | `"erc20_token"` | `{erc20_address}` | + +## Convert ERC20 + +| Type | Attibute Key | Attibute Value | +| --------------- | --------------- | --------------------------- | +| `convert_erc20` | `"sender"` | `{msg.Sender}` | +| `convert_erc20` | `"receiver"` | `{msg.Receiver}` | +| `convert_erc20` | `"amount"` | `{msg.Amount.String()}` | +| `convert_erc20` | `"cosmos_coin"` | `{denom}` | +| `convert_erc20` | `"erc20_token"` | `{msg.ContractAddress}` | + + diff --git a/x/intrarelayer/spec/07_parameters.md b/x/intrarelayer/spec/07_parameters.md new file mode 100644 index 0000000000..e95e30ba46 --- /dev/null +++ b/x/intrarelayer/spec/07_parameters.md @@ -0,0 +1,25 @@ + + +# Parameters + +The intrarelayer module contains the following parameters: + +| Key | Type | Default Value | +| ----------------------- | ------------- | ----------------------------- | +| `EnableIntrarelayer` | bool | `true` | +| `TokenPairVotingPeriod` | time.Duration | `172800000000000` (=48h0m0s) | +| `EnableEVMHook` | bool | `true` | + +## Enable Intrarelayer + +The `EnableIntrarelayer` parameter toggles all state transitions in the module. When the parameter is disabled, it will prevent all token pair registration and conversion functionality. + +## Token Pair Voting Period + +The `TokenPairVotingPeriod` parameter defines the period of time in which validators can submit their vote for a token pair registration proposal. This value overrides the default value of the governance module. + +### Enable EVM Hook + +The `EnableEVMHook` parameter enables the EVM hook to convert an ERC20 token to a Cosmos Coin by transferring the Tokens through a `MsgEthereumTx` to the `ModuleAddress` Ethereum address. diff --git a/x/intrarelayer/spec/08_clients.md b/x/intrarelayer/spec/08_clients.md new file mode 100644 index 0000000000..b0474ac91a --- /dev/null +++ b/x/intrarelayer/spec/08_clients.md @@ -0,0 +1,58 @@ + + +# Clients + +## CLI + +Find below a list of  `evmosd` commands added with the `x/intrarelayer` module. You can obtain the full list by using the `evmosd -h` command. A CLI command can look like this: + +```bash +evmosd query intrarelayer params +``` + +### Queries + +| Command | Subcommand | Description | +| ---------------------- | ------------- | ------------------------------ | +| `query` `intrarelayer` | `params` | Get intrarelayer params | +| `query` `intrarelayer` | `token-pair` | Get registered token pair | +| `query` `intrarelayer` | `token-pairs` | Get all registered token pairs | + +### Transactions + +| Command | Subcommand | Description | +| ------------------- | --------------- | ------------------------------ | +| `tx` `intrarelayer` | `convert-coin` | Convert a Cosmos Coin to ERC20 | +| `tx` `intrarelayer` | `convert-erc20` | Convert a ERC20 to Cosmos Coin | + +## gRPC + +### Queries + +| Verb | Method | Description | +| ------ | ---------------------------------------- | ------------------------------ | +| `gRPC` | `evmos.intrarelayer.v1.Query/Params` | Get intrarelayer params | +| `gRPC` | `evmos.intrarelayer.v1.Query/TokenPair` | Get registered token pair | +| `gRPC` | `evmos.intrarelayer.v1.Query/TokenPairs` | Get all registered token pairs | +| `GET` | `/evmos/intrarelayer/v1/params` | Get intrarelayer params | +| `GET` | `/evmos/intrarelayer/v1/token_pair` | Get registered token pair | +| `GET` | `/evmos/intrarelayer/v1/token_pairs` | Get all registered token pairs | + +### Transactions + +| Verb | Method | Description | +| ------ | ----------------------------------------- | ------------------------------ | +| `gRPC` | `evmos.intrarelayer.v1.Msg/ConvertCoin` | Convert a Cosmos Coin to ERC20 | +| `gRPC` | `evmos.intrarelayer.v1.Msg/ConvertERC20` | Convert a ERC20 to Cosmos Coin | +| `GET` | `/evmos/intrarelayer/v1/tx/convert_coin` | Convert a Cosmos Coin to ERC20 | +| `GET` | `/evmos/intrarelayer/v1/tx/convert_erc20` | Convert a ERC20 to Cosmos Coin | + + diff --git a/x/intrarelayer/spec/README.md b/x/intrarelayer/spec/README.md new file mode 100644 index 0000000000..ad5ec702b6 --- /dev/null +++ b/x/intrarelayer/spec/README.md @@ -0,0 +1,35 @@ + + +# `intrarelayer` + +## Abstract + +This document specifies the internal `x/intrarelayer` module of the Evmos Hub. + +The `x/intrarelayer` module enables the Evmos Hub to support a trustless, on-chain bidirectional internal relaying (aka intrarelaying) of tokens between Evmos' EVM and Cosmos runtimes, specifically the `x/evm` and `x/bank` modules. This allows token holders on Evmos to instantaneously convert their native Cosmos `sdk.Coins` (in this document referred to as "Coin(s)") to ERC-20 (aka "Token(s)") and vice versa, while retaining fungibility with the original asset on the issuing environment/runtime (EVM or Cosmos) and preserving ownership of the ERC-20 contract. + +This intrarelaying functionality is fully governed by native $EVMOS token holders who manage the canonical `TokenPair` registrations (ie, ERC20 ←→ Coin mappings). This governance functionality is implemented using the Cosmos-SDK `gov` module with custom proposal types for registering and updating the canonical mappings respectively. + +Why is this important? Cosmos and the EVM are two runtimes that are not compatible by default. The native Cosmos Coins cannot be used in applications that require the ERC-20 standard. Cosmos coins are held on the `x/bank` module (with access to module methods like querying the supply or balances) and ERC-20 Tokens live on smart contracts. This problem is similar to [wETH](https://weth.io/), with the difference, that it not only applies to gas tokens (like $EVMOS), but to all Cosmos Coins (IBC vouchers, staking and gov coins, etc.) as well. + +With the `x/intrarelayer` users on Evmos can + +- use existing native cosmos assets (like $OSMO or $ATOM) on EVM-based chains, e.g. for Trading IBC tokens on DeFi protocols, buying NFT, etc. +- transfer existing tokens on Ethereum and other EVM-based chains to Evmos to take advantage of application-specific chains in the Cosmos ecosystem +- build new applications that are based on ERC-20 smart contracts and have access to the Cosmos ecosystem. + +## Contents + +1. **[Concepts](01_concepts.md)** +2. **[State](02_state.md)** +3. **[State Transitions](03_state_transitions.md)** +4. **[Transactions](04_transactions.md)** +5. **[Hooks](05_hooks.md)** +6. **[Events](06_events.md)** +7. **[Parameters](07_params.md)** +8. **[Clients](08_clients.md)** diff --git a/x/intrarelayer/testing/integration_test.go b/x/intrarelayer/testing/integration_test.go new file mode 100644 index 0000000000..a5e24902b1 --- /dev/null +++ b/x/intrarelayer/testing/integration_test.go @@ -0,0 +1,91 @@ +package testing + +import ( + "context" + "fmt" + "testing" + + // . "github.com/onsi/ginkgo" + // . "github.com/onsi/gomega" + + "github.com/stretchr/testify/suite" + "google.golang.org/grpc" + + "github.com/ethereum/go-ethereum/ethclient" + + "github.com/tharsis/ethermint/server/config" + "github.com/tharsis/ethermint/testutil/network" + evmosnetwork "github.com/tharsis/evmos/testutil/network" + "github.com/tharsis/evmos/x/intrarelayer/types" +) + +// var _ = Describe("E2e", func() { +// }) + +// func TestJsonRpc(t *testing.T) { +// RegisterFailHandler(Fail) +// RunSpecs(t, "JSON-RPC Suite") +// } + +// TODO: migrate to Ginkgo BDD +type IntegrationTestSuite struct { + suite.Suite + + ctx context.Context + cfg network.Config + network *network.Network + grpcQueryClient types.QueryClient + grpcTxClient types.MsgClient +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + var err error + cfg := evmosnetwork.DefaultConfig() + cfg.JSONRPCAddress = config.DefaultJSONRPCAddress + cfg.NumValidators = 1 + + s.ctx = context.Background() + s.cfg = cfg + s.network, err = network.New(s.T(), s.T().TempDir(), cfg) + s.Require().NoError(err) + s.Require().NotNil(s.network) + + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) + + if s.network.Validators[0].JSONRPCClient == nil { + address := fmt.Sprintf("http://%s", s.network.Validators[0].AppConfig.JSONRPC.Address) + s.network.Validators[0].JSONRPCClient, err = ethclient.Dial(address) + s.Require().NoError(err) + } + + // Create a connection to the gRPC server. + grpcConn, err := grpc.Dial( + s.network.Validators[0].AppConfig.GRPC.Address, // gRPC server address. + grpc.WithInsecure(), // The Cosmos SDK doesn't support any transport security mechanism. + ) + s.Require().NoError(err) + + s.grpcQueryClient = types.NewQueryClient(grpcConn) + + // FIXME: "unknown service evmos.intrarelayer.v1.Msg" + s.grpcTxClient = types.NewMsgClient(grpcConn) +} + +func (s *IntegrationTestSuite) TestLiveness() { + // test the gRPC query client to check if everything's ok + resParams, err := s.grpcQueryClient.Params(s.ctx, &types.QueryParamsRequest{}) + s.Require().NoError(err) + s.Require().NotNil(resParams) + + // FIXME: enable + // res, err := s.grpcTxClient.ConvertCoin(s.ctx, &types.MsgConvertCoin{}) + // s.Require().NoError(err) + // s.Require().NotNil(res) +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/intrarelayer/types/events.go b/x/intrarelayer/types/events.go index bdc77de38d..460ecfa984 100644 --- a/x/intrarelayer/types/events.go +++ b/x/intrarelayer/types/events.go @@ -16,11 +16,11 @@ const ( EventTypeBurn = "burn" EventTypeRegisterCoin = "register_coin" EventTypeRegisterERC20 = "register_erc20" - EventTypeToggleTokenRelay = "toggle_token_relay" // nolint: gosec + EventTypeToggleTokenRelay = "toggle_token_relay" // #nosec EventTypeUpdateTokenPairERC20 = "update_token_pair_erc20" AttributeKeyCosmosCoin = "cosmos_coin" - AttributeKeyERC20Token = "erc20_token" // nolint: gosec + AttributeKeyERC20Token = "erc20_token" // #nosec AttributeKeyReceiver = "receiver" ERC20EventTransfer = "Transfer" diff --git a/x/intrarelayer/types/genesis.pb.go b/x/intrarelayer/types/genesis.pb.go index bbf611e36c..952603a2c7 100644 --- a/x/intrarelayer/types/genesis.pb.go +++ b/x/intrarelayer/types/genesis.pb.go @@ -91,7 +91,7 @@ type Params struct { // parameter to enable the EVM hook to convert an ERC20 token to a Cosmos // Coin by transferring the Tokens through a MsgEthereumTx to the // ModuleAddress Ethereum address. - EnableEVMHook bool `protobuf:"varint,3,opt,name=enable_e_v_m_hook,json=enableEVMHook,proto3" json:"enable_e_v_m_hook,omitempty"` + EnableEVMHook bool `protobuf:"varint,3,opt,name=enable_evm_hook,json=enableEvmHook,proto3" json:"enable_evm_hook,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -158,31 +158,32 @@ func init() { } var fileDescriptor_ab56df1cf11ba6de = []byte{ - // 375 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x41, 0x4f, 0xe2, 0x40, - 0x14, 0xc7, 0x3b, 0xb0, 0x21, 0x64, 0xd8, 0x3d, 0x6c, 0x77, 0x49, 0xba, 0x24, 0x5b, 0x08, 0x5e, - 0x7a, 0x71, 0x26, 0xe0, 0xd1, 0x1b, 0xd1, 0xa0, 0x07, 0x13, 0x82, 0x86, 0x83, 0x31, 0x69, 0xa6, - 0x32, 0x96, 0x09, 0xb4, 0xaf, 0x99, 0x19, 0x1a, 0xf9, 0x16, 0x1e, 0x3c, 0xf8, 0x75, 0xbc, 0x71, - 0xe4, 0xe8, 0x49, 0x0d, 0x7c, 0x11, 0xc3, 0xb4, 0x28, 0x24, 0x78, 0x7b, 0x7d, 0xff, 0xff, 0xfb, - 0xf7, 0x37, 0xef, 0xe1, 0x03, 0x9e, 0x46, 0xa0, 0xa8, 0x88, 0xb5, 0x64, 0x92, 0x4f, 0xd8, 0x8c, - 0x4b, 0x9a, 0xb6, 0x68, 0xc8, 0x63, 0xae, 0x84, 0x22, 0x89, 0x04, 0x0d, 0x76, 0xd5, 0x98, 0xc8, - 0xb6, 0x89, 0xa4, 0xad, 0x9a, 0xb7, 0x7f, 0x76, 0xc7, 0x66, 0x02, 0x6a, 0x7f, 0x43, 0x08, 0xc1, - 0x94, 0x74, 0x5d, 0xe5, 0x5d, 0x37, 0x04, 0x08, 0x27, 0x9c, 0x9a, 0xaf, 0x60, 0x7a, 0x47, 0x87, - 0x53, 0xc9, 0xb4, 0x80, 0x38, 0xd3, 0x9b, 0x8f, 0x08, 0xff, 0xec, 0x66, 0x20, 0x97, 0x9a, 0x69, - 0x6e, 0x1f, 0xe3, 0x52, 0xc2, 0x24, 0x8b, 0x94, 0x83, 0x1a, 0xc8, 0xab, 0xb4, 0xff, 0x93, 0xbd, - 0x60, 0xa4, 0x67, 0x4c, 0x9d, 0x1f, 0xf3, 0xd7, 0xba, 0xd5, 0xcf, 0x47, 0xec, 0x2e, 0xae, 0x68, - 0x18, 0xf3, 0xd8, 0x4f, 0x98, 0x90, 0xca, 0x29, 0x34, 0x8a, 0x5e, 0xa5, 0xdd, 0xf8, 0x26, 0xe1, - 0x6a, 0xed, 0xec, 0x31, 0x21, 0xf3, 0x10, 0xac, 0x37, 0x0d, 0xd5, 0x7c, 0x46, 0xb8, 0x94, 0xfd, - 0xc1, 0xa6, 0xf8, 0x0f, 0x8f, 0x59, 0x30, 0xe1, 0xfe, 0x76, 0x80, 0xa1, 0x2b, 0xf7, 0xed, 0x4c, - 0x3a, 0xdf, 0x52, 0xec, 0x1b, 0xec, 0x7c, 0x41, 0xf8, 0x29, 0x68, 0x11, 0x87, 0x7e, 0xc2, 0xa5, - 0x80, 0xa1, 0x53, 0x30, 0x6f, 0xfa, 0x47, 0xb2, 0xad, 0x90, 0xcd, 0x56, 0xc8, 0x49, 0xbe, 0x95, - 0x4e, 0x79, 0x8d, 0xf2, 0xf4, 0x56, 0x47, 0xfd, 0xea, 0x27, 0xce, 0xc0, 0x44, 0xf4, 0x4c, 0x82, - 0xed, 0xe1, 0xdf, 0x39, 0x0e, 0xf7, 0x53, 0x3f, 0xf2, 0x47, 0x00, 0x63, 0xa7, 0x68, 0x60, 0x7e, - 0x65, 0xc2, 0xe9, 0xe0, 0xe2, 0x0c, 0x60, 0xdc, 0xe9, 0xce, 0x97, 0x2e, 0x5a, 0x2c, 0x5d, 0xf4, - 0xbe, 0x74, 0xd1, 0xc3, 0xca, 0xb5, 0x16, 0x2b, 0xd7, 0x7a, 0x59, 0xb9, 0xd6, 0xf5, 0x61, 0x28, - 0xf4, 0x68, 0x1a, 0x90, 0x5b, 0x88, 0xa8, 0x1e, 0x31, 0xa9, 0x84, 0xa2, 0xd9, 0x9d, 0xef, 0x77, - 0x2f, 0xad, 0x67, 0x09, 0x57, 0x41, 0xc9, 0x60, 0x1e, 0x7d, 0x04, 0x00, 0x00, 0xff, 0xff, 0x49, - 0x51, 0x15, 0x29, 0x48, 0x02, 0x00, 0x00, + // 387 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0xc1, 0xae, 0xd2, 0x40, + 0x14, 0x86, 0x3b, 0x60, 0x08, 0x19, 0x24, 0xc6, 0x2a, 0x49, 0x25, 0xb1, 0x10, 0xdc, 0xb0, 0x71, + 0x26, 0xe0, 0xca, 0xb8, 0x6b, 0x24, 0xe8, 0xc2, 0x84, 0x54, 0xc3, 0xc2, 0x98, 0x34, 0x53, 0x19, + 0xcb, 0x04, 0xda, 0xd3, 0xcc, 0x0c, 0x8d, 0xbc, 0x85, 0x0b, 0x17, 0x3e, 0x12, 0x4b, 0xe2, 0xca, + 0x15, 0xde, 0x94, 0x17, 0xb9, 0xe9, 0xb4, 0xdc, 0x0b, 0x09, 0x77, 0x37, 0xe7, 0xfc, 0xff, 0xf9, + 0xfb, 0xf5, 0x1c, 0xfc, 0x8a, 0x67, 0x31, 0x28, 0x2a, 0x12, 0x2d, 0x99, 0xe4, 0x6b, 0xb6, 0xe5, + 0x92, 0x66, 0x23, 0x1a, 0xf1, 0x84, 0x2b, 0xa1, 0x48, 0x2a, 0x41, 0x83, 0xdd, 0x31, 0x26, 0x72, + 0x6e, 0x22, 0xd9, 0xa8, 0x3b, 0xbc, 0x3e, 0x7b, 0x61, 0x33, 0x01, 0xdd, 0xe7, 0x11, 0x44, 0x60, + 0x9e, 0xb4, 0x78, 0x55, 0x5d, 0x37, 0x02, 0x88, 0xd6, 0x9c, 0x9a, 0x2a, 0xdc, 0xfc, 0xa0, 0x8b, + 0x8d, 0x64, 0x5a, 0x40, 0x52, 0xea, 0x83, 0xdf, 0x08, 0x3f, 0x9e, 0x96, 0x20, 0x9f, 0x35, 0xd3, + 0xdc, 0x7e, 0x87, 0x1b, 0x29, 0x93, 0x2c, 0x56, 0x0e, 0xea, 0xa3, 0x61, 0x6b, 0xfc, 0x92, 0x5c, + 0x05, 0x23, 0x33, 0x63, 0xf2, 0x1e, 0xed, 0x0e, 0x3d, 0xcb, 0xaf, 0x46, 0xec, 0x29, 0x6e, 0x69, + 0x58, 0xf1, 0x24, 0x48, 0x99, 0x90, 0xca, 0xa9, 0xf5, 0xeb, 0xc3, 0xd6, 0xb8, 0xff, 0x40, 0xc2, + 0x97, 0xc2, 0x39, 0x63, 0x42, 0x56, 0x21, 0x58, 0x9f, 0x1a, 0x6a, 0xf0, 0x17, 0xe1, 0x46, 0xf9, + 0x05, 0x9b, 0xe2, 0x67, 0x3c, 0x61, 0xe1, 0x9a, 0x07, 0xe7, 0x01, 0x86, 0xae, 0xe9, 0xdb, 0xa5, + 0xf4, 0xf1, 0x4c, 0xb1, 0xbf, 0x61, 0xe7, 0x1e, 0x22, 0xc8, 0x40, 0x8b, 0x24, 0x0a, 0x52, 0x2e, + 0x05, 0x2c, 0x9c, 0x9a, 0xf9, 0xa7, 0x17, 0xa4, 0xdc, 0x0a, 0x39, 0x6d, 0x85, 0xbc, 0xaf, 0xb6, + 0xe2, 0x35, 0x0b, 0x94, 0x3f, 0xff, 0x7b, 0xc8, 0xef, 0xdc, 0xe1, 0xcc, 0x4d, 0xc4, 0xcc, 0x24, + 0xd8, 0x6f, 0xf1, 0x93, 0x0a, 0x87, 0x67, 0x71, 0xb0, 0x04, 0x58, 0x39, 0xf5, 0x02, 0xc5, 0x7b, + 0x9a, 0x1f, 0x7a, 0xed, 0x89, 0x91, 0x26, 0xf3, 0x4f, 0x1f, 0x00, 0x56, 0x7e, 0xbb, 0x74, 0x4e, + 0xb2, 0xb8, 0x28, 0xbd, 0xe9, 0x2e, 0x77, 0xd1, 0x3e, 0x77, 0xd1, 0x4d, 0xee, 0xa2, 0x5f, 0x47, + 0xd7, 0xda, 0x1f, 0x5d, 0xeb, 0xdf, 0xd1, 0xb5, 0xbe, 0xbe, 0x8e, 0x84, 0x5e, 0x6e, 0x42, 0xf2, + 0x1d, 0x62, 0xaa, 0x97, 0x4c, 0x2a, 0xa1, 0x68, 0x79, 0xf8, 0x9f, 0x97, 0xa7, 0xd7, 0xdb, 0x94, + 0xab, 0xb0, 0x61, 0xb8, 0xdf, 0xdc, 0x06, 0x00, 0x00, 0xff, 0xff, 0xb2, 0x2e, 0xc1, 0x49, 0x59, + 0x02, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { diff --git a/x/intrarelayer/types/msg.go b/x/intrarelayer/types/msg.go index d6e9b5eeef..d006bea5ba 100644 --- a/x/intrarelayer/types/msg.go +++ b/x/intrarelayer/types/msg.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + ibctransfertypes "github.com/cosmos/ibc-go/v2/modules/apps/transfer/types" "github.com/ethereum/go-ethereum/common" ) @@ -34,9 +35,12 @@ func (msg MsgConvertCoin) Type() string { return TypeMsgConvertCoin } // ValidateBasic runs stateless checks on the message func (msg MsgConvertCoin) ValidateBasic() error { - if err := sdk.ValidateDenom(msg.Coin.Denom); err != nil { - return err + if err := ValidateIntrarelayerDenom(msg.Coin.Denom); err != nil { + if err := ibctransfertypes.ValidateIBCDenom(msg.Coin.Denom); err != nil { + return err + } } + if !msg.Coin.Amount.IsPositive() { return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "cannot mint a non-positive amount") } diff --git a/x/intrarelayer/types/msg_test.go b/x/intrarelayer/types/msg_test.go index fd63545e06..bea1b8ff83 100644 --- a/x/intrarelayer/types/msg_test.go +++ b/x/intrarelayer/types/msg_test.go @@ -83,7 +83,7 @@ func (suite *MsgsTestSuite) TestMsgConvertCoin() { { "negative coin amount", sdk.Coin{ - Denom: "test", + Denom: "coin", Amount: sdk.NewInt(-100), }, "0x0000", @@ -92,21 +92,35 @@ func (suite *MsgsTestSuite) TestMsgConvertCoin() { }, { "msg convert coin - invalid sender", - sdk.NewCoin("test", sdk.NewInt(100)), + sdk.NewCoin("coin", sdk.NewInt(100)), tests.GenerateAddress().String(), "evmosinvalid", false, }, { "msg convert coin - invalid receiver", - sdk.NewCoin("test", sdk.NewInt(100)), + sdk.NewCoin("coin", sdk.NewInt(100)), "0x0000", sdk.AccAddress(tests.GenerateAddress().Bytes()).String(), false, }, { "msg convert coin - pass", - sdk.NewCoin("test", sdk.NewInt(100)), + sdk.NewCoin("coin", sdk.NewInt(100)), + tests.GenerateAddress().String(), + sdk.AccAddress(tests.GenerateAddress().Bytes()).String(), + true, + }, + { + "msg convert coin - pass with `intrarelayer/` denom", + sdk.NewCoin("intrarelayer/0xdac17f958d2ee523a2206206994597c13d831ec7", sdk.NewInt(100)), + tests.GenerateAddress().String(), + sdk.AccAddress(tests.GenerateAddress().Bytes()).String(), + true, + }, + { + "msg convert coin - pass with `ibc/{hash}` denom", + sdk.NewCoin("ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", sdk.NewInt(100)), tests.GenerateAddress().String(), sdk.AccAddress(tests.GenerateAddress().Bytes()).String(), true, diff --git a/x/intrarelayer/types/proposal.go b/x/intrarelayer/types/proposal.go index 2b71d2bb95..de8c194ffa 100644 --- a/x/intrarelayer/types/proposal.go +++ b/x/intrarelayer/types/proposal.go @@ -2,11 +2,13 @@ package types import ( "fmt" + "strings" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + ibctransfertypes "github.com/cosmos/ibc-go/v2/modules/apps/transfer/types" "github.com/ethereum/go-ethereum/common" ethermint "github.com/tharsis/ethermint/types" ) @@ -15,7 +17,7 @@ import ( const ( ProposalTypeRegisterCoin string = "RegisterCoin" ProposalTypeRegisterERC20 string = "RegisterERC20" - ProposalTypeToggleTokenRelay string = "ToggleTokenRelay" // nolint: gosec + ProposalTypeToggleTokenRelay string = "ToggleTokenRelay" // #nosec ProposalTypeUpdateTokenPairERC20 string = "UpdateTokenPairERC20" ) @@ -38,12 +40,14 @@ func init() { govtypes.RegisterProposalTypeCodec(&UpdateTokenPairERC20Proposal{}, "intrarelayer/UpdateTokenPairERC20Proposal") } +// CreateDenomDescription generates a string with the coin description func CreateDenomDescription(address string) string { return fmt.Sprintf("Cosmos coin token representation of %s", address) } +// CreateDenom generates a string the module name plus the address to avoid conflicts with names staring with a number func CreateDenom(address string) string { - return fmt.Sprintf("irm%s", address) + return fmt.Sprintf("%s/%s", ModuleName, address) } // NewRegisterCoinProposal returns new instance of RegisterCoinProposal @@ -69,9 +73,54 @@ func (rtbp *RegisterCoinProposal) ValidateBasic() error { return err } + if err := ibctransfertypes.ValidateIBCDenom(rtbp.Metadata.Base); err != nil { + return err + } + + if err := validateIBC(rtbp.Metadata); err != nil { + return err + } + return govtypes.ValidateAbstract(rtbp) } +func validateIBC(metadata banktypes.Metadata) error { + // Check ibc/ denom + denomSplit := strings.SplitN(metadata.Base, "/", 2) + + if denomSplit[0] == metadata.Base && strings.TrimSpace(metadata.Base) != "" { + // Not IBC + return nil + } + + if len(denomSplit) != 2 || denomSplit[0] != ibctransfertypes.DenomPrefix { + // NOTE: should be unaccessible (covered on ValidateIBCDenom) + return fmt.Errorf("invalid metadata. %s denomination should be prefixed with the format 'ibc/", metadata.Base) + } + + if !strings.Contains(metadata.Name, "channel-") { + return fmt.Errorf("invalid metadata (Name) for ibc. %s should include channel", metadata.Name) + } + + if !strings.HasPrefix(metadata.Symbol, "ibc") { + return fmt.Errorf("invalid metadata (Symbol) for ibc. %s should include \"ibc\" prefix", metadata.Symbol) + } + + return nil +} + +// ValidateIntrarelayerDenom checks if a denom is a valid intrarelayer/ +// denomination +func ValidateIntrarelayerDenom(denom string) error { + denomSplit := strings.SplitN(denom, "/", 2) + + if len(denomSplit) != 2 || denomSplit[0] != ModuleName { + return fmt.Errorf("invalid denom. %s denomination should be prefixed with the format 'intrarelayer/", denom) + } + + return ethermint.ValidateAddress(denomSplit[1]) +} + // NewRegisterERC20Proposal returns new instance of RegisterERC20Proposal func NewRegisterERC20Proposal(title, description, erc20Addr string) govtypes.Content { return &RegisterERC20Proposal{ @@ -128,12 +177,12 @@ func (etrp *ToggleTokenRelayProposal) ValidateBasic() error { } // NewUpdateTokenPairERC20Proposal returns new instance of UpdateTokenPairERC20Proposal -func NewUpdateTokenPairERC20Proposal(title, description string, erc20Addr, newERC20Addr common.Address) govtypes.Content { +func NewUpdateTokenPairERC20Proposal(title, description, erc20Addr, newERC20Addr string) govtypes.Content { return &UpdateTokenPairERC20Proposal{ Title: title, Description: description, - Erc20Address: erc20Addr.String(), - NewErc20Address: newERC20Addr.String(), + Erc20Address: erc20Addr, + NewErc20Address: newERC20Addr, } } diff --git a/x/intrarelayer/types/proposal_test.go b/x/intrarelayer/types/proposal_test.go index 30af3677f4..2228b8fc83 100644 --- a/x/intrarelayer/types/proposal_test.go +++ b/x/intrarelayer/types/proposal_test.go @@ -32,6 +32,49 @@ func (suite *ProposalTestSuite) TestKeysTypes() { suite.Require().Equal("ToggleTokenRelay", (&ToggleTokenRelayProposal{}).ProposalType()) } +func (suite *ProposalTestSuite) TestValidateIntrarelayerDenom() { + testCases := []struct { + name string + denom string + expPass bool + }{ + { + "- instead of /", + "intrarelayer-0xdac17f958d2ee523a2206206994597c13d831ec7", + false, + }, + { + "without /", + "intrarelayerCoin", + false, + }, + { + "// instead of /", + "intrarelayer//0xdac17f958d2ee523a2206206994597c13d831ec7", + false, + }, + { + "multiple /", + "intrarelayer/0xdac17f958d2ee523a2206206994597c13d831ec7/test", + false, + }, + { + "pass", + "intrarelayer/0xdac17f958d2ee523a2206206994597c13d831ec7", + true, + }, + } + for _, tc := range testCases { + err := ValidateIntrarelayerDenom(tc.denom) + + if tc.expPass { + suite.Require().Nil(err, tc.name) + } else { + suite.Require().Error(err, tc.name) + } + } +} + func (suite *ProposalTestSuite) TestRegisterERC20Proposal() { testCases := []struct { msg string @@ -65,7 +108,7 @@ func (suite *ProposalTestSuite) TestRegisterERC20Proposal() { } } -func createMetadata(denom, symbol string) banktypes.Metadata { +func createFullMetadata(denom, symbol, name string) banktypes.Metadata { return banktypes.Metadata{ Description: "desc", Base: denom, @@ -80,12 +123,16 @@ func createMetadata(denom, symbol string) banktypes.Metadata { Exponent: uint32(18), }, }, - Name: denom, + Name: name, Symbol: symbol, Display: denom, } } +func createMetadata(denom, symbol string) banktypes.Metadata { + return createFullMetadata(denom, symbol, denom) +} + func (suite *ProposalTestSuite) TestRegisterCoinProposal() { validMetadata := banktypes.Metadata{ Description: "desc", @@ -106,6 +153,10 @@ func (suite *ProposalTestSuite) TestRegisterCoinProposal() { Display: "coin", } + validIBCDenom := "ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2" + validIBCSymbol := "ibcATOM-14" + validIBCName := "ATOM channel-14" + testCases := []struct { msg string title string @@ -127,6 +178,12 @@ func (suite *ProposalTestSuite) TestRegisterCoinProposal() { {msg: "Register token pair - invalid length token (128)", title: "test", description: "test desc", metadata: createMetadata(strings.Repeat("a", 129), "test"), expectPass: false}, {msg: "Register token pair - invalid length title (140)", title: strings.Repeat("a", length.MaxTitleLength+1), description: "test desc", metadata: validMetadata, expectPass: false}, {msg: "Register token pair - invalid length description (5000)", title: "title", description: strings.Repeat("a", length.MaxDescriptionLength+1), metadata: validMetadata, expectPass: false}, + + // Ibc + {msg: "Register token pair - ibc", title: "test", description: "test desc", metadata: createFullMetadata(validIBCDenom, validIBCSymbol, validIBCName), expectPass: true}, + {msg: "Register token pair - ibc invalid denom", title: "test", description: "test desc", metadata: createFullMetadata("ibc/", validIBCSymbol, validIBCName), expectPass: false}, + {msg: "Register token pair - ibc invalid symbol", title: "test", description: "test desc", metadata: createFullMetadata(validIBCDenom, "badSymbol", validIBCName), expectPass: false}, + {msg: "Register token pair - ibc invalid name", title: "test", description: "test desc", metadata: createFullMetadata(validIBCDenom, validIBCSymbol, validIBCDenom), expectPass: false}, } for i, tc := range testCases { @@ -195,7 +252,7 @@ func (suite *ProposalTestSuite) TestUpdateTokenPairERC20Proposal() { } for i, tc := range testCases { - tx := NewUpdateTokenPairERC20Proposal(tc.title, tc.description, tc.erc20Addr, tc.newErc20Addr) + tx := NewUpdateTokenPairERC20Proposal(tc.title, tc.description, tc.erc20Addr.Hex(), tc.newErc20Addr.Hex()) err := tx.ValidateBasic() if tc.expectPass {