From 956a749b2435bc2cfdcd6f9fde1a53633c842d60 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Tue, 17 Oct 2023 19:46:35 -0400 Subject: [PATCH 01/18] add burn module --- .github/dependabot.yml | 54 ++---- .github/workflows/build.yml | 11 +- .github/workflows/build_docker.yml | 8 +- .github/workflows/codeql-analyzer.yml | 35 ---- .github/workflows/codeql.yml | 17 +- .github/workflows/dependency-review.yml | 20 +++ .github/workflows/golangci-lint.yml | 12 +- .github/workflows/interchaintest-E2E.yml | 208 +++++++--------------- .github/workflows/push-docker-image.yml | 10 +- .github/workflows/release.yml | 2 +- Makefile | 5 + app/keepers/keepers.go | 6 + app/test_helpers.go | 20 +-- app/upgrades/v4/constants.go | 16 ++ app/upgrades/v4/upgrade.go | 21 +++ interchaintest/contracts/cw_testburn.wasm | Bin 0 -> 147255 bytes interchaintest/module_burn_test.go | 60 +++++++ interchaintest/state_sync_test.go | 83 +++++++++ x/burn/README.md | 7 + x/burn/burner.go | 50 ++++++ x/burn/constants.go | 5 + 21 files changed, 390 insertions(+), 260 deletions(-) delete mode 100644 .github/workflows/codeql-analyzer.yml create mode 100644 .github/workflows/dependency-review.yml create mode 100644 app/upgrades/v4/constants.go create mode 100644 app/upgrades/v4/upgrade.go create mode 100644 interchaintest/contracts/cw_testburn.wasm create mode 100644 interchaintest/module_burn_test.go create mode 100644 interchaintest/state_sync_test.go create mode 100644 x/burn/README.md create mode 100644 x/burn/burner.go create mode 100644 x/burn/constants.go diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3d21b52..613da7c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,45 +1,11 @@ +--- version: 2 -updates: -- package-ecosystem: github-actions - directory: "/" - schedule: - interval: daily - open-pull-requests-limit: 10 -- package-ecosystem: gomod - directory: "/" - schedule: - interval: daily - open-pull-requests-limit: 10 - ignore: - - dependency-name: github.com/CosmWasm/wasmvm - versions: - - 0.14.0-beta2 - - 0.14.0-beta3 - - 0.14.0-beta4 - - 0.14.0-beta5 - - 0.14.0-rc1 - - dependency-name: github.com/cometbft/cometbft - versions: - - 0.34.10 - - 0.34.4 - - 0.34.7 - - 0.34.8 - - 0.34.9 - - dependency-name: github.com/cosmos/cosmos-sdk - versions: - - 0.41.4 - - 0.42.0 - - 0.42.1 - - 0.42.2 - - 0.42.4 - - dependency-name: google.golang.org/grpc - versions: - - 1.36.0 - - 1.36.1 - - 1.37.0 - - dependency-name: github.com/spf13/cobra - versions: - - 1.1.2 - - dependency-name: github.com/cometbft/cometbft-db - versions: - - 0.6.4 +updates: + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily + - package-ecosystem: gomod + directory: "/" + schedule: + interval: daily diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cbe476c..35a91ce 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,16 +11,19 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +env: + GO_VERSION: 1.21.0 + jobs: build: runs-on: ubuntu-latest name: build steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup go uses: actions/setup-go@v4 with: - go-version: 1.20.0 + go-version: ${{ env.GO_VERSION }} - run: go build ./... test: @@ -30,7 +33,7 @@ jobs: - name: Install Go uses: actions/setup-go@v3 with: - go-version: 1.20.0 + go-version: ${{ env.GO_VERSION }} - name: Checkout code uses: actions/checkout@v3 - name: Test @@ -44,7 +47,7 @@ jobs: - name: Setup go uses: actions/setup-go@v4 with: - go-version: 1.20.0 + go-version: ${{ env.GO_VERSION }} - run: | go mod tidy CHANGES_IN_REPO=$(git status --porcelain) diff --git a/.github/workflows/build_docker.yml b/.github/workflows/build_docker.yml index d832b9b..676302a 100644 --- a/.github/workflows/build_docker.yml +++ b/.github/workflows/build_docker.yml @@ -16,13 +16,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Build without push - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . platforms: linux/amd64 diff --git a/.github/workflows/codeql-analyzer.yml b/.github/workflows/codeql-analyzer.yml deleted file mode 100644 index 77f3446..0000000 --- a/.github/workflows/codeql-analyzer.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: "Code Scanning - Action" - -on: - pull_request: - paths: - - "**.go" - push: - branches: [ main ] - paths: - - "**.go" - -jobs: - CodeQL-Build: - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - steps: - - name: Checkout repository - uses: actions/checkout@v3.5.0 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: 'go' - queries: crypto-com/cosmos-sdk-codeql@main,security-and-quality - - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 \ No newline at end of file diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 40b385c..7777018 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,16 +1,25 @@ -name: "Code Scanning - Action" +--- +# THIS GITHUB ACTION LIFTED WITH LOVE FROM THE COSMOS-SDK +name: "CodeQL" on: pull_request: paths: - "**.go" push: - branches: + branches: - main - release/** paths: - "**.go" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + GO_VERSION: 1.21.0 + jobs: analyze: name: Analyze @@ -22,10 +31,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: - go-version: 1.20.0 + go-version: ${{ env.GO_VERSION }} # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v2 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..5545cd2 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,20 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v4 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v2 diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 2ae2c07..c64bc88 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -8,14 +8,16 @@ on: - master - main pull_request: - paths: - - '**.go' + permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true + +env: + GO_VERSION: 1.21.0 jobs: golangci: @@ -24,10 +26,10 @@ jobs: steps: - uses: actions/setup-go@v4 with: - go-version: 1.20.0 - - uses: actions/checkout@v3 + go-version: ${{ env.GO_VERSION }} + - uses: actions/checkout@v4 - - name: golangci-lint + - name: golangci-lint-terpd uses: golangci/golangci-lint-action@v3 with: version: latest diff --git a/.github/workflows/interchaintest-E2E.yml b/.github/workflows/interchaintest-E2E.yml index 9a894e8..1a3c443 100644 --- a/.github/workflows/interchaintest-E2E.yml +++ b/.github/workflows/interchaintest-E2E.yml @@ -1,186 +1,98 @@ name: ictest E2E on: + pull_request: push: tags: - - '**' + - "**" branches: - - '**' - paths: - - '**.yml' - - '**.go' - - '**.mod' - - '**.sum' + - "main" + - "master" + +permissions: + contents: read + packages: write env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }}-e2e - GO_VERSION: 1.20.0 + GO_VERSION: 1.21.0 + TAR_PATH: /tmp/terp-docker-image.tar + IMAGE_NAME: terp-docker-image concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: - build-and-push-image: + build-docker: runs-on: ubuntu-latest - outputs: - branchTag: ${{ steps.meta.outputs.version }} - permissions: - contents: read - packages: write - steps: - - name: Checkout repository - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v4 - # We setup go & cache dependencies here. This way each child job - # does not have to reinstall all dependencies individually. - - name: Setup Golang with cache - uses: magnetikonline/action-golang-cache@v4 + - name: Setup Go ${{ env.GO_VERSION }} + uses: actions/setup-go@v4 with: go-version: ${{ env.GO_VERSION }} - id: go - - - name: Download dependencies - run: | - go mod download - cd interchaintest && go mod download - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + cache-dependency-path: interchaintest/go.sum - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Log in to the Container registry - uses: docker/login-action@v2 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + uses: docker/setup-buildx-action@v3 - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v4 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - - - name: Build and push Docker image - id: push - uses: docker/build-push-action@v4 + - name: Build and export + uses: docker/build-push-action@v5 with: context: . - platforms: linux/amd64 - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - - # make terp-core:branchname here for all needs.build-and-push-image.outputs.branchTag - # then upload to github. Then download for each as a cache. This way its only built once + tags: terp:local + outputs: type=docker,dest=${{ env.TAR_PATH }} - # TODO: Add reusable job template here, just changing the `make` command for each - - test-terp-basic: - runs-on: ubuntu-latest - needs: build-and-push-image - steps: - - name: checkout chain - uses: actions/checkout@v2 - - - name: Setup Golang with cache - uses: magnetikonline/action-golang-cache@v4 + - name: Upload artifact + uses: actions/upload-artifact@v3 with: - go-version: ${{ env.GO_VERSION }} - id: go + name: ${{ env.IMAGE_NAME }} + path: ${{ env.TAR_PATH }} - - run: make ictest-basic - env: - BRANCH_CI: ${{needs.build-and-push-image.outputs.branchTag}} - - test-terp-ibc: + e2e-tests: + needs: build-docker runs-on: ubuntu-latest - needs: build-and-push-image - steps: - - name: Setup Golang with cache - uses: magnetikonline/action-golang-cache@v4 - with: - go-version: ${{ env.GO_VERSION }} - id: go - - - name: checkout chain - uses: actions/checkout@v2 + strategy: + matrix: + # names of `make` commands to run tests + test: + - "ictest-basic" + - "ictest-statesync" + - "ictest-ibchooks" + - "ictest-tokenfactory" + - "ictest-feeshare" + - "ictest-pfm" + - "ictest-upgrade" + - "ictest-ibc" + # - "ictest-pob" + # - "ictest-drip" + - "ictest-burn" + # - "ictest-cwhooks" + # - "ictest-clock" + fail-fast: false - - run: make ictest-ibc - env: - BRANCH_CI: ${{needs.build-and-push-image.outputs.branchTag}} - - test-terp-upgrade: - runs-on: ubuntu-latest - needs: build-and-push-image steps: - - name: checkout chain - uses: actions/checkout@v2 - - - name: Setup Golang with cache - uses: magnetikonline/action-golang-cache@v4 + - name: Set up Go ${{ env.GO_VERSION }} + uses: actions/setup-go@v4 with: go-version: ${{ env.GO_VERSION }} - id: go - - - run: make ictest-upgrade - env: - BRANCH_CI: ${{needs.build-and-push-image.outputs.branchTag}} - - test-terp-ibchooks: - runs-on: ubuntu-latest - needs: build-and-push-image - steps: - - name: checkout chain - uses: actions/checkout@v2 - - - name: Setup Golang with cache - uses: magnetikonline/action-golang-cache@v4 - with: - go-version: ${{ env.GO_VERSION }} - id: go - - - run: make ictest-ibchooks - env: - BRANCH_CI: ${{needs.build-and-push-image.outputs.branchTag}} + cache-dependency-path: interchaintest/go.sum - test-terp-pfm: - runs-on: ubuntu-latest - needs: build-and-push-image - steps: - name: checkout chain - uses: actions/checkout@v2 + uses: actions/checkout@v4 - - name: Setup Golang with cache - uses: magnetikonline/action-golang-cache@v4 + - name: Download Tarball Artifact + uses: actions/download-artifact@v3 with: - go-version: ${{ env.GO_VERSION }} - id: go + name: ${{ env.IMAGE_NAME }} + path: /tmp - - run: make ictest-pfm - env: - BRANCH_CI: ${{needs.build-and-push-image.outputs.branchTag}} - - test-terp-tokenfactory: - runs-on: ubuntu-latest - needs: build-and-push-image - steps: - - name: Setup Golang with cache - uses: magnetikonline/action-golang-cache@v4 - with: - go-version: ${{ env.GO_VERSION }} - id: go - - - name: checkout chain - uses: actions/checkout@v2 + - name: Load Docker Image + run: | + docker image load -i ${{ env.TAR_PATH }} + docker image ls -a - - run: make ictest-tokenfactory - env: - BRANCH_CI: ${{needs.build-and-push-image.outputs.branchTag}} \ No newline at end of file + - name: Run Test + run: make ${{ matrix.test }} \ No newline at end of file diff --git a/.github/workflows/push-docker-image.yml b/.github/workflows/push-docker-image.yml index 6436aed..d35fab2 100644 --- a/.github/workflows/push-docker-image.yml +++ b/.github/workflows/push-docker-image.yml @@ -34,15 +34,15 @@ jobs: steps: - name: Check out the repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -62,7 +62,7 @@ jobs: - name: Build and push id: build_push_image - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: file: Dockerfile context: . diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8df5eb6..5e09014 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Docker compose run: STAKE_TOKEN="uterp" TIMEOUT_COMMIT=500ms docker-compose up -d diff --git a/Makefile b/Makefile index 1c545f7..02da8cb 100644 --- a/Makefile +++ b/Makefile @@ -195,6 +195,9 @@ format: format-tools ictest-basic: rm-testcache cd interchaintest && go test -race -v -run TestBasicTerpStart . +ictest-statesync: rm-testcache + cd interchaintest && go test -race -v -run TestTerpStateSync . + ictest-ibchooks: rm-testcache cd interchaintest && go test -race -v -run TestTerpIBCHooks . @@ -203,6 +206,8 @@ ictest-pfm: rm-testcache ictest-tokenfactory: rm-testcache cd interchaintest && go test -race -v -run TestTerpTokenFactory . +ictest-burn: rm-testcache + cd interchaintest && go test -race -v -run TestTerpBurnModule . ictest-feeshare: rm-testcache cd interchaintest && go test -race -v -run TestTerpFeeShare . diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index c59cd09..5363a47 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -92,6 +92,7 @@ import ( upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + denomburn "github.com/terpnetwork/terp-core/v2/x/burn" feesharekeeper "github.com/terpnetwork/terp-core/v2/x/feeshare/keeper" feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" @@ -132,6 +133,7 @@ var maccPerms = map[string][]string{ globalfee.ModuleName: nil, wasmtypes.ModuleName: {authtypes.Burner}, tokenfactorytypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + denomburn.ModuleName: {authtypes.Burner}, } type AppKeepers struct { @@ -526,6 +528,10 @@ func NewAppKeepers( }) wasmOpts = append(wasmOpts, querierOpts) + denomBurnerPlugin := denomburn.NewBurnerPlugin(appKeepers.BankKeeper, appKeepers.MintKeeper) + burnOverride := wasmkeeper.WithMessageHandler(wasmkeeper.NewBurnCoinMessageHandler(denomBurnerPlugin)) + wasmOpts = append(wasmOpts, burnOverride) + appKeepers.WasmKeeper = wasmkeeper.NewKeeper( appCodec, appKeepers.keys[wasmtypes.StoreKey], diff --git a/app/test_helpers.go b/app/test_helpers.go index 0148173..b485176 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -46,7 +46,7 @@ func (ao EmptyBaseAppOptions) Get(_ string) interface{} { } // DefaultConsensusParams defines the default Tendermint consensus params used -// in junoApp testing. +// in terpApp testing. var DefaultConsensusParams = &tmproto.ConsensusParams{ Block: &tmproto.BlockParams{ MaxBytes: 200000, @@ -92,21 +92,21 @@ func Setup(t *testing.T) *TerpApp { return app } -// SetupWithGenesisValSet initializes a new junoApp with a validator set and genesis accounts +// SetupWithGenesisValSet initializes a new terpApp with a validator set and genesis accounts // that also act as delegators. For simplicity, each validator is bonded with a delegation // of one consensus engine unit in the default token of the TerpApp from first genesis // account. A Nop logger is set in TerpApp. func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, balances ...banktypes.Balance) *TerpApp { t.Helper() - junoApp, genesisState := setup(t, true) - genesisState = genesisStateWithValSet(t, junoApp, genesisState, valSet, genAccs, balances...) + terpApp, genesisState := setup(t, true) + genesisState = genesisStateWithValSet(t, terpApp, genesisState, valSet, genAccs, balances...) stateBytes, err := json.MarshalIndent(genesisState, "", " ") require.NoError(t, err) // init chain will set the validator set and initialize the genesis accounts - junoApp.InitChain( + terpApp.InitChain( abci.RequestInitChain{ Validators: []abci.ValidatorUpdate{}, ConsensusParams: DefaultConsensusParams, @@ -118,17 +118,17 @@ func SetupWithGenesisValSet(t *testing.T, valSet *tmtypes.ValidatorSet, genAccs ) // commit genesis changes - junoApp.Commit() - junoApp.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{ + terpApp.Commit() + terpApp.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{ ChainID: "testing", - Height: junoApp.LastBlockHeight() + 1, - AppHash: junoApp.LastCommitID().Hash, + Height: terpApp.LastBlockHeight() + 1, + AppHash: terpApp.LastCommitID().Hash, ValidatorsHash: valSet.Hash(), NextValidatorsHash: valSet.Hash(), Time: time.Now().UTC(), }}) - return junoApp + return terpApp } func setup(t *testing.T, withGenesis bool, opts ...wasmkeeper.Option) (*TerpApp, GenesisState) { diff --git a/app/upgrades/v4/constants.go b/app/upgrades/v4/constants.go new file mode 100644 index 0000000..f60e754 --- /dev/null +++ b/app/upgrades/v4/constants.go @@ -0,0 +1,16 @@ +package v4 + +import ( + "github.com/terpnetwork/terp-core/v2/app/upgrades" + + store "github.com/cosmos/cosmos-sdk/store/types" +) + +// UpgradeName defines the on-chain upgrade name for the Terp v4 upgrade. +const UpgradeName = "v4" + +var Upgrade = upgrades.Upgrade{ + UpgradeName: UpgradeName, + CreateUpgradeHandler: CreateV4UpgradeHandler, + StoreUpgrades: store.StoreUpgrades{}, +} diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go new file mode 100644 index 0000000..6004e2f --- /dev/null +++ b/app/upgrades/v4/upgrade.go @@ -0,0 +1,21 @@ +package v4 + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + + "github.com/terpnetwork/terp-core/v2/app/keepers" +) + +// CreateUpgradeHandler creates an SDK upgrade handler for v4 +func CreateV4UpgradeHandler( + mm *module.Manager, + cfg module.Configurator, + keepers *keepers.AppKeepers, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + + return vm, nil + } +} diff --git a/interchaintest/contracts/cw_testburn.wasm b/interchaintest/contracts/cw_testburn.wasm new file mode 100644 index 0000000000000000000000000000000000000000..4b47f362350ed56ff2391db6e516e19db72def39 GIT binary patch literal 147255 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 z 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

m>$D6S1{_FQAqi5Q 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 Date: Tue, 17 Oct 2023 20:27:05 -0400 Subject: [PATCH 02/18] add clock module --- .github/workflows/interchaintest-E2E.yml | 2 +- Makefile | 4 + app/keepers/keepers.go | 9 + app/keepers/keys.go | 2 + app/modules.go | 12 +- interchaintest/contracts/clock_example.wasm | Bin 0 -> 140100 bytes interchaintest/helpers/query_helpers.go | 7 +- interchaintest/helpers/types.go | 7 + interchaintest/module_clock_test.go | 85 ++ interchaintest/setup.go | 35 +- proto/terp/clock/v1/genesis.proto | 30 + proto/terp/clock/v1/query.proto | 42 + proto/terp/clock/v1/tx.proto | 40 + x/clock/README.md | 5 + x/clock/abci.go | 42 + x/clock/client/cli/query.go | 73 ++ x/clock/genesis.go | 61 ++ x/clock/genesis_test.go | 107 +++ x/clock/keeper/keeper.go | 70 ++ x/clock/keeper/keeper_test.go | 59 ++ x/clock/keeper/msg_server.go | 39 + x/clock/keeper/msg_server_test.go | 72 ++ x/clock/keeper/querier.go | 43 + x/clock/keeper/querier_test.go | 60 ++ x/clock/module.go | 149 ++++ x/clock/spec/01_authorization.md | 39 + x/clock/spec/02_integration.md | 56 ++ x/clock/spec/README.md | 14 + x/clock/types/codec.go | 44 + x/clock/types/codec_test.go | 30 + x/clock/types/genesis.pb.go | 542 ++++++++++++ x/clock/types/keys.go | 11 + x/clock/types/msgs.go | 55 ++ x/clock/types/msgs_test.go | 40 + x/clock/types/params.go | 65 ++ x/clock/types/params_test.go | 44 + x/clock/types/query.pb.go | 884 ++++++++++++++++++++ x/clock/types/query.pb.gw.go | 218 +++++ x/clock/types/tx.pb.go | 605 ++++++++++++++ 39 files changed, 3691 insertions(+), 11 deletions(-) create mode 100644 interchaintest/contracts/clock_example.wasm create mode 100644 interchaintest/module_clock_test.go create mode 100644 proto/terp/clock/v1/genesis.proto create mode 100644 proto/terp/clock/v1/query.proto create mode 100644 proto/terp/clock/v1/tx.proto create mode 100644 x/clock/README.md create mode 100644 x/clock/abci.go create mode 100644 x/clock/client/cli/query.go create mode 100644 x/clock/genesis.go create mode 100644 x/clock/genesis_test.go create mode 100644 x/clock/keeper/keeper.go create mode 100644 x/clock/keeper/keeper_test.go create mode 100644 x/clock/keeper/msg_server.go create mode 100644 x/clock/keeper/msg_server_test.go create mode 100644 x/clock/keeper/querier.go create mode 100644 x/clock/keeper/querier_test.go create mode 100644 x/clock/module.go create mode 100644 x/clock/spec/01_authorization.md create mode 100644 x/clock/spec/02_integration.md create mode 100644 x/clock/spec/README.md create mode 100644 x/clock/types/codec.go create mode 100644 x/clock/types/codec_test.go create mode 100644 x/clock/types/genesis.pb.go create mode 100644 x/clock/types/keys.go create mode 100644 x/clock/types/msgs.go create mode 100644 x/clock/types/msgs_test.go create mode 100644 x/clock/types/params.go create mode 100644 x/clock/types/params_test.go create mode 100644 x/clock/types/query.pb.go create mode 100644 x/clock/types/query.pb.gw.go create mode 100644 x/clock/types/tx.pb.go diff --git a/.github/workflows/interchaintest-E2E.yml b/.github/workflows/interchaintest-E2E.yml index 1a3c443..dd1866c 100644 --- a/.github/workflows/interchaintest-E2E.yml +++ b/.github/workflows/interchaintest-E2E.yml @@ -70,7 +70,7 @@ jobs: # - "ictest-drip" - "ictest-burn" # - "ictest-cwhooks" - # - "ictest-clock" + - "ictest-clock" fail-fast: false steps: diff --git a/Makefile b/Makefile index 02da8cb..1066133 100644 --- a/Makefile +++ b/Makefile @@ -206,9 +206,13 @@ ictest-pfm: rm-testcache ictest-tokenfactory: rm-testcache cd interchaintest && go test -race -v -run TestTerpTokenFactory . + ictest-burn: rm-testcache cd interchaintest && go test -race -v -run TestTerpBurnModule . +ictest-clock: rm-testcache + cd interchaintest && go test -race -v -run TestTerpClock . + ictest-feeshare: rm-testcache cd interchaintest && go test -race -v -run TestTerpFeeShare . diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 5363a47..c65d0f8 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -93,6 +93,8 @@ import ( upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" denomburn "github.com/terpnetwork/terp-core/v2/x/burn" + clockkeeper "github.com/terpnetwork/terp-core/v2/x/clock/keeper" + clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" feesharekeeper "github.com/terpnetwork/terp-core/v2/x/feeshare/keeper" feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" @@ -173,6 +175,7 @@ type AppKeepers struct { PacketForwardKeeper *packetforwardkeeper.Keeper ICQKeeper icqkeeper.Keeper ICAHostKeeper icahostkeeper.Keeper + ClockKeeper clockkeeper.Keeper TransferKeeper ibctransferkeeper.Keeper WasmKeeper wasmkeeper.Keeper @@ -572,6 +575,12 @@ func NewAppKeepers( appKeepers.keys[globalfeetypes.StoreKey], govModAddress, ) + appKeepers.ClockKeeper = clockkeeper.NewKeeper( + appKeepers.keys[clocktypes.StoreKey], + appCodec, + *appKeepers.ContractKeeper, + govModAddress, + ) // The gov proposal types can be individually enabled if len(enabledProposals) != 0 { diff --git a/app/keepers/keys.go b/app/keepers/keys.go index f563941..5bd4040 100644 --- a/app/keepers/keys.go +++ b/app/keepers/keys.go @@ -34,6 +34,7 @@ import ( icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v7/types" ibchookstypes "github.com/cosmos/ibc-apps/modules/ibc-hooks/v7/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" + clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" ) func (appKeepers *AppKeepers) GenerateKeys() { @@ -67,6 +68,7 @@ func (appKeepers *AppKeepers) GenerateKeys() { ibchookstypes.StoreKey, feesharetypes.StoreKey, globalfeetypes.StoreKey, + clocktypes.StoreKey, tokenfactorytypes.StoreKey, ) diff --git a/app/modules.go b/app/modules.go index 2eddb85..c090562 100644 --- a/app/modules.go +++ b/app/modules.go @@ -4,6 +4,8 @@ import ( wasm "github.com/CosmWasm/wasmd/x/wasm" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + mint "github.com/cosmos/cosmos-sdk/x/mint" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" packetforward "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/router" packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/router/types" icq "github.com/cosmos/ibc-apps/modules/async-icq/v7" @@ -17,9 +19,8 @@ import ( ibc "github.com/cosmos/ibc-go/v7/modules/core" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - - mint "github.com/cosmos/cosmos-sdk/x/mint" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/terpnetwork/terp-core/v2/x/clock" + clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" @@ -108,6 +109,7 @@ var ModuleBasics = module.NewBasicManager( packetforward.AppModuleBasic{}, feeshare.AppModuleBasic{}, globalfee.AppModuleBasic{}, + clock.AppModuleBasic{}, tokenfactory.AppModuleBasic{}, ) @@ -154,6 +156,7 @@ func appModules( ica.NewAppModule(&app.AppKeepers.ICAControllerKeeper, &app.AppKeepers.ICAHostKeeper), icq.NewAppModule(app.AppKeepers.ICQKeeper), packetforward.NewAppModule(app.AppKeepers.PacketForwardKeeper), + clock.NewAppModule(appCodec, app.AppKeepers.ClockKeeper), ibchooks.NewAppModule(app.AppKeepers.AccountKeeper), crisis.NewAppModule(app.AppKeepers.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)), // always be last to make sure that it checks for all invariants and not only part of them } @@ -219,6 +222,7 @@ func orderBeginBlockers() []string { packetforwardtypes.ModuleName, feesharetypes.ModuleName, globalfee.ModuleName, + clocktypes.ModuleName, ibchookstypes.ModuleName, tokenfactorytypes.ModuleName, wasmtypes.ModuleName, @@ -255,6 +259,7 @@ func orderEndBlockers() []string { packetforwardtypes.ModuleName, feesharetypes.ModuleName, globalfee.ModuleName, + clocktypes.ModuleName, ibchookstypes.ModuleName, tokenfactorytypes.ModuleName, wasmtypes.ModuleName, @@ -280,6 +285,7 @@ func orderInitBlockers() []string { packetforwardtypes.ModuleName, ibchookstypes.ModuleName, tokenfactorytypes.ModuleName, + clocktypes.ModuleName, wasmtypes.ModuleName, } } diff --git a/interchaintest/contracts/clock_example.wasm b/interchaintest/contracts/clock_example.wasm new file mode 100644 index 0000000000000000000000000000000000000000..cb3f0833ca1e7b5b4cb445b00673ac97b73a39ad GIT binary patch literal 140100 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 '{"get_withdrawal_ready_time":{}}' --output json - var res WithdrawalTimestampResponse - err := chain.QueryContract(ctx, contract, QueryMsg{GetWithdrawalReadyTime: &struct{}{}}, &res) +func GetClockContractValue(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, contract string) ClockContractResponse { + var res ClockContractResponse + err := chain.QueryContract(ctx, contract, QueryMsg{GetConfig: &struct{}{}}, &res) require.NoError(t, err) return res } diff --git a/interchaintest/helpers/types.go b/interchaintest/helpers/types.go index d3d49d7..4181725 100644 --- a/interchaintest/helpers/types.go +++ b/interchaintest/helpers/types.go @@ -76,3 +76,10 @@ type GetCountResponse struct { type GetCountObj struct { Count int64 `json:"count"` } + +type ClockContractResponse struct { + Data *ClockContractObj `json:"data"` +} +type ClockContractObj struct { + Val uint32 `json:"val"` +} diff --git a/interchaintest/module_clock_test.go b/interchaintest/module_clock_test.go new file mode 100644 index 0000000..9abd76a --- /dev/null +++ b/interchaintest/module_clock_test.go @@ -0,0 +1,85 @@ +package interchaintest + +import ( + "context" + "fmt" + "testing" + + cosmosproto "github.com/cosmos/gogoproto/proto" + "github.com/strangelove-ventures/interchaintest/v7" + "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" + "github.com/strangelove-ventures/interchaintest/v7/ibc" + "github.com/strangelove-ventures/interchaintest/v7/testutil" + "github.com/stretchr/testify/require" + clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + + helpers "github.com/terpnetwork/terp-core/tests/interchaintest/helpers" +) + +// TestJunoClock ensures the clock module auto executes allowed contracts. +func TestTerpClock(t *testing.T) { + t.Parallel() + + cfg := terpConfig + + // Base setup + chains := CreateChainWithCustomConfig(t, 1, 0, cfg) + ic, ctx, _, _ := BuildInitialChain(t, chains) + + // Chains + terp := chains[0].(*cosmos.CosmosChain) + + // Users + users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), terp, terp) + user := users[0] + + // Upload & init contract payment to another address + _, contractAddr := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/clock_example.wasm", `{}`) + + // Ensure config is 0 + res := helpers.GetClockContractValue(t, ctx, terp, contractAddr) + fmt.Printf("- res: %v\n", res.Data.Val) + require.Equal(t, uint32(0), res.Data.Val) + + // Submit the proposal to add it to the allowed contracts list + SubmitParamChangeProp(t, ctx, terp, user, []string{contractAddr}) + + // Wait 1 block + _ = testutil.WaitForBlocks(ctx, 1, terp) + + // Validate the contract is now auto incrementing from the end blocker + res = helpers.GetClockContractValue(t, ctx, terp, contractAddr) + fmt.Printf("- res: %v\n", res.Data.Val) + require.GreaterOrEqual(t, res.Data.Val, uint32(1)) + + t.Cleanup(func() { + _ = ic.Close() + }) +} + +func SubmitParamChangeProp(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contracts []string) string { + govAcc := "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq" + updateParams := []cosmosproto.Message{ + &clocktypes.MsgUpdateParams{ + Authority: govAcc, + Params: clocktypes.NewParams(contracts, 1_000_000_000), + }, + } + + proposal, err := chain.BuildProposal(updateParams, "Params Add Contract", "params", "ipfs://CID", fmt.Sprintf(`500000000%s`, chain.Config().Denom)) + require.NoError(t, err, "error building proposal") + + txProp, err := chain.SubmitProposal(ctx, user.KeyName(), proposal) + t.Log("txProp", txProp) + require.NoError(t, err, "error submitting proposal") + + height, _ := chain.Height(ctx) + + err = chain.VoteOnProposalAllValidators(ctx, txProp.ProposalID, cosmos.ProposalVoteYes) + require.NoError(t, err, "failed to submit votes") + + _, err = cosmos.PollForProposalStatus(ctx, chain, height, height+haltHeightDelta, txProp.ProposalID, cosmos.ProposalStatusPassed) + require.NoError(t, err, "proposal status did not change to passed in expected number of blocks") + + return txProp.ProposalID +} diff --git a/interchaintest/setup.go b/interchaintest/setup.go index 016b865..03e8b97 100644 --- a/interchaintest/setup.go +++ b/interchaintest/setup.go @@ -7,17 +7,19 @@ import ( wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" ibclocalhost "github.com/cosmos/ibc-go/v7/modules/light-clients/09-localhost" - "github.com/docker/docker/client" - interchaintest "github.com/strangelove-ventures/interchaintest/v7" "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v7/ibc" "github.com/strangelove-ventures/interchaintest/v7/testreporter" - "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" + clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + tokenfactorytypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + + sdk "github.com/cosmos/cosmos-sdk/types" testutil "github.com/cosmos/cosmos-sdk/types/module/testutil" ) @@ -78,6 +80,10 @@ var ( genesisWalletAmount = int64(10_000_000) ) +func init() { + sdk.GetConfig().SetBech32PrefixForAccount("terp", "terp") +} + // terpEncoding registers the Terp specific module codecs so that the associated types and msgs // will be supported when writing to the blocksdb sqlite database. func terpEncoding() *testutil.TestEncodingConfig { @@ -86,6 +92,9 @@ func terpEncoding() *testutil.TestEncodingConfig { // register custom types ibclocalhost.RegisterInterfaces(cfg.InterfaceRegistry) wasmtypes.RegisterInterfaces(cfg.InterfaceRegistry) + feesharetypes.RegisterInterfaces(cfg.InterfaceRegistry) + tokenfactorytypes.RegisterInterfaces(cfg.InterfaceRegistry) + clocktypes.RegisterInterfaces(cfg.InterfaceRegistry) // github.com/cosmos/cosmos-sdk/types/module/testutil @@ -119,6 +128,26 @@ func CreateThisBranchChain(t *testing.T, numVals, numFull int) []ibc.Chain { return chains } +func CreateChainWithCustomConfig(t *testing.T, numVals, numFull int, config ibc.ChainConfig) []ibc.Chain { + cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ + { + Name: "terp", + ChainName: "terpnetwork", + Version: config.Images[0].Version, + ChainConfig: config, + NumValidators: &numVals, + NumFullNodes: &numFull, + }, + }) + + // Get chains from the chain factory + chains, err := cf.Chains(t.Name()) + require.NoError(t, err) + + // chain := chains[0].(*cosmos.CosmosChain) + return chains +} + func BuildInitialChain(t *testing.T, chains []ibc.Chain) (*interchaintest.Interchain, context.Context, *client.Client, string) { // Create a new Interchain object which describes the chains, relayers, and IBC connections we want to use ic := interchaintest.NewInterchain() diff --git a/proto/terp/clock/v1/genesis.proto b/proto/terp/clock/v1/genesis.proto new file mode 100644 index 0000000..7e66137 --- /dev/null +++ b/proto/terp/clock/v1/genesis.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; +package terp.clock.v1; + +import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; + +option go_package = "github.com/terpnetwork/terp-core/x/clock/types"; + +// GenesisState - initial state of module +message GenesisState { + // Params of this module + Params params = 1 [ + (gogoproto.nullable) = false, + (gogoproto.jsontag) = "params,omitempty" + ]; +} + +// Params defines the set of module parameters. +message Params { + // contract_addresses stores the list of executable contracts to be ticked on every block. + repeated string contract_addresses = 1 [ + (gogoproto.jsontag) = "contract_addresses,omitempty", + (gogoproto.moretags) = "yaml:\"contract_addresses\"" + ]; + + uint64 contract_gas_limit = 2 [ + (gogoproto.jsontag) = "contract_gas_limit,omitempty", + (gogoproto.moretags) = "yaml:\"contract_gas_limit\"" + ]; +} diff --git a/proto/terp/clock/v1/query.proto b/proto/terp/clock/v1/query.proto new file mode 100644 index 0000000..db0485a --- /dev/null +++ b/proto/terp/clock/v1/query.proto @@ -0,0 +1,42 @@ +syntax = "proto3"; +package terp.clock.v1; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "terp/clock/v1/genesis.proto"; + +option go_package = "github.com/terpnetwork/terp-core/x/clock/types"; + +// Query defines the gRPC querier service. +service Query { + // ClockContracts + rpc ClockContracts(QueryClockContracts) + returns (QueryClockContractsResponse) { + option (google.api.http).get = + "/terp/clock/v1/contracts"; + } + // Params + rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { + option (google.api.http).get = "/terp/clock/v1/params"; + } +} + +// QueryClockContracts is the request type to get all contracts. +message QueryClockContracts {} + +// QueryClockContractsResponse is the response type for the Query/ClockContracts RPC method. +message QueryClockContractsResponse { + repeated string contract_addresses = 1 [ + (gogoproto.jsontag) = "contract_addresses,omitempty", + (gogoproto.moretags) = "yaml:\"contract_addresses\"" + ]; +} + +// QueryParams is the request type to get all module params. +message QueryParamsRequest {} + +// QueryClockContractsResponse is the response type for the Query/ClockContracts RPC method. +message QueryParamsResponse { + Params params = 1 [(gogoproto.jsontag) = "params", (gogoproto.moretags) = "yaml:\"params\""]; +} diff --git a/proto/terp/clock/v1/tx.proto b/proto/terp/clock/v1/tx.proto new file mode 100644 index 0000000..6b1bf02 --- /dev/null +++ b/proto/terp/clock/v1/tx.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package terp.clock.v1; + +option go_package = "github.com/terpnetwork/terp-core/x/clock/types"; + +import "cosmos/msg/v1/msg.proto"; +import "terp/clock/v1/genesis.proto"; +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "amino/amino.proto"; + +// Msg defines the Msg service. +service Msg { + // UpdateParams defines a governance operation for updating the x/clock module + // parameters. The authority is hard-coded to the x/gov module account. + // + // Since: cosmos-sdk 0.47 + rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse); +} + +// MsgUpdateParams is the Msg/UpdateParams request type. +// +// Since: cosmos-sdk 0.47 +message MsgUpdateParams { + option (cosmos.msg.v1.signer) = "authority"; + + // authority is the address of the governance account. + string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // params defines the x/clock parameters to update. + // + // NOTE: All parameters must be supplied. + Params params = 2 [(gogoproto.nullable) = false]; +} + +// MsgUpdateParamsResponse defines the response structure for executing a +// MsgUpdateParams message. +// +// Since: cosmos-sdk 0.47 +message MsgUpdateParamsResponse {} diff --git a/x/clock/README.md b/x/clock/README.md new file mode 100644 index 0000000..ba05f64 --- /dev/null +++ b/x/clock/README.md @@ -0,0 +1,5 @@ +# Clock + +This module allows smart contracts to execute logic at the end of every block without an external bot. + +[Clock Spec](./spec/README.md) diff --git a/x/clock/abci.go b/x/clock/abci.go new file mode 100644 index 0000000..4c21539 --- /dev/null +++ b/x/clock/abci.go @@ -0,0 +1,42 @@ +package clock + +import ( + "log" + "time" + + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v2/x/clock/keeper" + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +// EndBlocker executes on contracts at the end of the block. +func EndBlocker(ctx sdk.Context, k keeper.Keeper) { + defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) + + message := []byte(types.EndBlockSudoMessage) + + p := k.GetParams(ctx) + + errorExecs := make([]string, len(p.ContractAddresses)) + + for idx, addr := range p.ContractAddresses { + contract, err := sdk.AccAddressFromBech32(addr) + if err != nil { + errorExecs[idx] = addr + continue + } + + childCtx := ctx.WithGasMeter(sdk.NewGasMeter(p.ContractGasLimit)) + _, err = k.GetContractKeeper().Sudo(childCtx, contract, message) + if err != nil { + errorExecs[idx] = addr + continue + } + } + + if len(errorExecs) > 0 { + log.Printf("[x/clock] Execute Errors: %v", errorExecs) + } +} diff --git a/x/clock/client/cli/query.go b/x/clock/client/cli/query.go new file mode 100644 index 0000000..2eb1f66 --- /dev/null +++ b/x/clock/client/cli/query.go @@ -0,0 +1,73 @@ +package cli + +import ( + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +func GetQueryCmd() *cobra.Command { + queryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for cosmwasm modules", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + queryCmd.AddCommand( + GetCmdShowContracts(), + GetCmdParams(), + ) + return queryCmd +} + +func GetCmdShowContracts() *cobra.Command { + cmd := &cobra.Command{ + Use: "contracts", + Short: "Show addresses of all current contract modules", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.ClockContracts(cmd.Context(), &types.QueryClockContracts{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + +func GetCmdParams() *cobra.Command { + cmd := &cobra.Command{ + Use: "params", + Short: "Show all module params", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) + return cmd +} diff --git a/x/clock/genesis.go b/x/clock/genesis.go new file mode 100644 index 0000000..7692e4b --- /dev/null +++ b/x/clock/genesis.go @@ -0,0 +1,61 @@ +package clock + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v2/x/clock/keeper" + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +// NewGenesisState - Create a new genesis state +func NewGenesisState(params types.Params) *types.GenesisState { + return &types.GenesisState{ + Params: params, + } +} + +// DefaultGenesisState - Return a default genesis state +func DefaultGenesisState() *types.GenesisState { + return NewGenesisState(types.DefaultParams()) +} + +// GetGenesisStateFromAppState returns x/auth GenesisState given raw application +// genesis state. +func GetGenesisStateFromAppState(cdc codec.Codec, appState map[string]json.RawMessage) *types.GenesisState { + var genesisState types.GenesisState + + if appState[ModuleName] != nil { + cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState) + } + + return &genesisState +} + +func ValidateGenesis(data types.GenesisState) error { + return data.Params.Validate() +} + +// InitGenesis import module genesis +func InitGenesis( + ctx sdk.Context, + k keeper.Keeper, + data types.GenesisState, +) { + if err := ValidateGenesis(data); err != nil { + panic(err) + } + + if err := k.SetParams(ctx, data.Params); err != nil { + panic(err) + } +} + +// ExportGenesis export module state +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { + return &types.GenesisState{ + Params: k.GetParams(ctx), + } +} diff --git a/x/clock/genesis_test.go b/x/clock/genesis_test.go new file mode 100644 index 0000000..96cdb60 --- /dev/null +++ b/x/clock/genesis_test.go @@ -0,0 +1,107 @@ +package clock_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v2/app" + clock "github.com/terpnetwork/terp-core/v2/x/clock" + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +type GenesisTestSuite struct { + suite.Suite + + ctx sdk.Context + + app *app.TerpApp +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} + +func (suite *GenesisTestSuite) SetupTest() { + app := app.Setup(suite.T()) + ctx := app.BaseApp.NewContext(false, tmproto.Header{ + ChainID: "testing", + }) + + suite.app = app + suite.ctx = ctx +} + +func (suite *GenesisTestSuite) TestClockInitGenesis() { + _, _, addr := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + defaultParams := types.DefaultParams() + + testCases := []struct { + name string + genesis types.GenesisState + expPanic bool + }{ + { + "default genesis", + *clock.DefaultGenesisState(), + false, + }, + { + "custom genesis - none", + types.GenesisState{ + Params: types.Params{ + ContractAddresses: []string(nil), + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + false, + }, + { + "custom genesis - incorrect addr", + types.GenesisState{ + Params: types.Params{ + ContractAddresses: []string{"incorrectaddr"}, + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + true, + }, + { + "custom genesis - only one addr allowed", + types.GenesisState{ + Params: types.Params{ + ContractAddresses: []string{addr.String(), addr2.String()}, + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + false, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.name), func() { + suite.SetupTest() // reset + + if tc.expPanic { + suite.Require().Panics(func() { + clock.InitGenesis(suite.ctx, suite.app.AppKeepers.ClockKeeper, tc.genesis) + }) + } else { + suite.Require().NotPanics(func() { + clock.InitGenesis(suite.ctx, suite.app.AppKeepers.ClockKeeper, tc.genesis) + }) + + params := suite.app.AppKeepers.ClockKeeper.GetParams(suite.ctx) + suite.Require().Equal(tc.genesis.Params, params) + } + }) + } +} diff --git a/x/clock/keeper/keeper.go b/x/clock/keeper/keeper.go new file mode 100644 index 0000000..95c1589 --- /dev/null +++ b/x/clock/keeper/keeper.go @@ -0,0 +1,70 @@ +package keeper + +import ( + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + + "github.com/cosmos/cosmos-sdk/codec" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +// Keeper of the clock store +type Keeper struct { + storeKey storetypes.StoreKey + cdc codec.BinaryCodec + + contractKeeper wasmkeeper.PermissionedKeeper + + authority string +} + +func NewKeeper( + key storetypes.StoreKey, + cdc codec.BinaryCodec, + contractKeeper wasmkeeper.PermissionedKeeper, + authority string, +) Keeper { + return Keeper{ + cdc: cdc, + storeKey: key, + contractKeeper: contractKeeper, + authority: authority, + } +} + +// GetAuthority returns the x/clock module's authority. +func (k Keeper) GetAuthority() string { + return k.authority +} + +// SetParams sets the x/clock module parameters. +func (k Keeper) SetParams(ctx sdk.Context, p types.Params) error { + if err := p.Validate(); err != nil { + return err + } + + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&p) + store.Set(types.ParamsKey, bz) + + return nil +} + +// GetParams returns the current x/clock module parameters. +func (k Keeper) GetParams(ctx sdk.Context) (p types.Params) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(types.ParamsKey) + if bz == nil { + return p + } + + k.cdc.MustUnmarshal(bz, &p) + return p +} + +// GetContractKeeper returns the x/wasm module's contract keeper. +func (k Keeper) GetContractKeeper() wasmkeeper.PermissionedKeeper { + return k.contractKeeper +} diff --git a/x/clock/keeper/keeper_test.go b/x/clock/keeper/keeper_test.go new file mode 100644 index 0000000..4b1520b --- /dev/null +++ b/x/clock/keeper/keeper_test.go @@ -0,0 +1,59 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + + "github.com/terpnetwork/terp-core/v2/app" + "github.com/terpnetwork/terp-core/v2/x/clock/keeper" + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +type IntegrationTestSuite struct { + suite.Suite + + ctx sdk.Context + app *app.TerpApp + bankKeeper bankkeeper.Keeper + queryClient types.QueryClient + clockMsgServer types.MsgServer +} + +func (s *IntegrationTestSuite) SetupTest() { + isCheckTx := false + s.app = app.Setup(s.T()) + + s.ctx = s.app.BaseApp.NewContext(isCheckTx, tmproto.Header{ + ChainID: "testing", + Height: 1, + Time: time.Now().UTC(), + }) + + queryHelper := baseapp.NewQueryServerTestHelper(s.ctx, s.app.InterfaceRegistry()) + types.RegisterQueryServer(queryHelper, keeper.NewQuerier(s.app.AppKeepers.ClockKeeper)) + + s.queryClient = types.NewQueryClient(queryHelper) + s.bankKeeper = s.app.AppKeepers.BankKeeper + s.clockMsgServer = keeper.NewMsgServerImpl(s.app.AppKeepers.ClockKeeper) +} + +func (s *IntegrationTestSuite) FundAccount(ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { + if err := s.bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { + return err + } + + return s.bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts) +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/clock/keeper/msg_server.go b/x/clock/keeper/msg_server.go new file mode 100644 index 0000000..a695d5b --- /dev/null +++ b/x/clock/keeper/msg_server.go @@ -0,0 +1,39 @@ +package keeper + +import ( + "context" + + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +var _ types.MsgServer = &msgServer{} + +// msgServer is a wrapper of Keeper. +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the x/clock MsgServer interface. +func NewMsgServerImpl(k Keeper) types.MsgServer { + return &msgServer{ + Keeper: k, + } +} + +func (k msgServer) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { + if k.authority != req.Authority { + return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, req.Authority) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := k.SetParams(ctx, req.Params); err != nil { + return nil, err + } + + return &types.MsgUpdateParamsResponse{}, nil +} diff --git a/x/clock/keeper/msg_server_test.go b/x/clock/keeper/msg_server_test.go new file mode 100644 index 0000000..7344db6 --- /dev/null +++ b/x/clock/keeper/msg_server_test.go @@ -0,0 +1,72 @@ +package keeper_test + +import ( + _ "embed" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +func (s *IntegrationTestSuite) TestUpdateClockParams() { + _, _, addr := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + for _, tc := range []struct { + desc string + isEnabled bool + ContractAddresses []string + success bool + }{ + { + desc: "Success - Valid on", + isEnabled: true, + ContractAddresses: []string{}, + success: true, + }, + { + desc: "Success - Valid off", + isEnabled: false, + ContractAddresses: []string{}, + success: true, + }, + { + desc: "Success - On and 1 allowed address", + isEnabled: true, + ContractAddresses: []string{addr.String()}, + success: true, + }, + { + desc: "Fail - On and 2 duplicate addresses", + isEnabled: true, + ContractAddresses: []string{addr.String(), addr.String()}, + success: false, + }, + { + desc: "Success - On and 2 unique", + isEnabled: true, + ContractAddresses: []string{addr.String(), addr2.String()}, + success: true, + }, + { + desc: "Success - On and 2 duplicate 1 unique", + isEnabled: true, + ContractAddresses: []string{addr.String(), addr2.String(), addr.String()}, + success: false, + }, + } { + tc := tc + s.Run(tc.desc, func() { + params := types.DefaultParams() + params.ContractAddresses = tc.ContractAddresses + + err := s.app.AppKeepers.ClockKeeper.SetParams(s.ctx, params) + + if !tc.success { + s.Require().Error(err) + } else { + s.Require().NoError(err) + } + }) + } +} diff --git a/x/clock/keeper/querier.go b/x/clock/keeper/querier.go new file mode 100644 index 0000000..a04cacd --- /dev/null +++ b/x/clock/keeper/querier.go @@ -0,0 +1,43 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +var _ types.QueryServer = &Querier{} + +type Querier struct { + keeper Keeper +} + +func NewQuerier(k Keeper) Querier { + return Querier{ + keeper: k, + } +} + +// ContractModules returns contract addresses which are using the clock +func (q Querier) ClockContracts(stdCtx context.Context, _ *types.QueryClockContracts) (*types.QueryClockContractsResponse, error) { + ctx := sdk.UnwrapSDKContext(stdCtx) + + p := q.keeper.GetParams(ctx) + + return &types.QueryClockContractsResponse{ + ContractAddresses: p.ContractAddresses, + }, nil +} + +// Params returns the total set of clock parameters. +func (q Querier) Params(stdCtx context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { + ctx := sdk.UnwrapSDKContext(stdCtx) + + p := q.keeper.GetParams(ctx) + + return &types.QueryParamsResponse{ + Params: &p, + }, nil +} diff --git a/x/clock/keeper/querier_test.go b/x/clock/keeper/querier_test.go new file mode 100644 index 0000000..5c651ae --- /dev/null +++ b/x/clock/keeper/querier_test.go @@ -0,0 +1,60 @@ +package keeper_test + +import ( + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +func (s *IntegrationTestSuite) TestClockQueryParams() { + _, _, addr := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + defaultParams := types.DefaultParams() + + for _, tc := range []struct { + desc string + Expected types.Params + }{ + { + desc: "On empty", + Expected: types.Params{ + ContractAddresses: []string(nil), + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + { + desc: "On 1 address", + Expected: types.Params{ + ContractAddresses: []string{addr.String()}, + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + { + desc: "On 2 Unique", + Expected: types.Params{ + ContractAddresses: []string{addr.String(), addr2.String()}, + ContractGasLimit: defaultParams.ContractGasLimit, + }, + }, + } { + tc := tc + s.Run(tc.desc, func() { + // Set the params to what is expected, then query and ensure the query is the same + err := s.app.AppKeepers.ClockKeeper.SetParams(s.ctx, tc.Expected) + s.Require().NoError(err) + + // Contracts check + goCtx := sdk.WrapSDKContext(s.ctx) + resp, err := s.queryClient.ClockContracts(goCtx, &types.QueryClockContracts{}) + s.Require().NoError(err) + s.Require().Equal(tc.Expected.ContractAddresses, resp.ContractAddresses) + + // All Params Check + resp2, err := s.queryClient.Params(goCtx, &types.QueryParamsRequest{}) + s.Require().NoError(err) + s.Require().Equal(tc.Expected, *resp2.Params) + }) + } +} diff --git a/x/clock/module.go b/x/clock/module.go new file mode 100644 index 0000000..1545408 --- /dev/null +++ b/x/clock/module.go @@ -0,0 +1,149 @@ +package clock + +import ( + "context" + "encoding/json" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/cometbft/cometbft/abci/types" + + errorsmod "cosmossdk.io/errors" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/terpnetwork/terp-core/v2/x/clock/client/cli" + "github.com/terpnetwork/terp-core/v2/x/clock/keeper" + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +const ( + ModuleName = types.ModuleName + + // ConsensusVersion defines the current x/clock module consensus version. + ConsensusVersion = 1 +) + +var ( + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleGenesis = AppModule{} + _ module.AppModule = AppModule{} +) + +// AppModuleBasic defines the basic application module used by the wasm module. +type AppModuleBasic struct { + cdc codec.Codec +} + +func (a AppModuleBasic) Name() string { + return types.ModuleName +} + +func (a AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(&types.GenesisState{ + Params: types.DefaultParams(), + }) +} + +func (a AppModuleBasic) ValidateGenesis(marshaler codec.JSONCodec, _ client.TxEncodingConfig, message json.RawMessage) error { + var data types.GenesisState + err := marshaler.UnmarshalJSON(message, &data) + if err != nil { + return err + } + if err := data.Params.Validate(); err != nil { + return errorsmod.Wrap(err, "params") + } + return nil +} + +func (a AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) { +} + +func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { + err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) + if err != nil { + // same behavior as in cosmos-sdk + panic(err) + } +} + +func (a AppModuleBasic) GetTxCmd() *cobra.Command { + return nil +} + +func (a AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +func (a AppModuleBasic) RegisterInterfaces(r codectypes.InterfaceRegistry) { + types.RegisterInterfaces(r) +} + +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper +} + +// NewAppModule constructor +func NewAppModule( + cdc codec.Codec, + keeper keeper.Keeper, +) *AppModule { + return &AppModule{ + AppModuleBasic: AppModuleBasic{cdc: cdc}, + keeper: keeper, + } +} + +func (a AppModule) InitGenesis(ctx sdk.Context, marshaler codec.JSONCodec, message json.RawMessage) []abci.ValidatorUpdate { + var genesisState types.GenesisState + marshaler.MustUnmarshalJSON(message, &genesisState) + _ = a.keeper.SetParams(ctx, genesisState.Params) + return nil +} + +func (a AppModule) ExportGenesis(ctx sdk.Context, marshaler codec.JSONCodec) json.RawMessage { + params := a.keeper.GetParams(ctx) + genState := NewGenesisState(params) + return marshaler.MustMarshalJSON(genState) +} + +func (a AppModule) RegisterInvariants(_ sdk.InvariantRegistry) { +} + +func (a AppModule) QuerierRoute() string { + return types.QuerierRoute +} + +func (a AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(a.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQuerier(a.keeper)) +} + +func (a AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) { +} + +func (a AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + EndBlocker(ctx, a.keeper) + return nil +} + +// ConsensusVersion is a sequence number for state-breaking change of the +// module. It should be incremented on each consensus-breaking change +// introduced by the module. To avoid wrong/empty versions, the initial version +// should be set to 1. +func (a AppModule) ConsensusVersion() uint64 { + return ConsensusVersion +} diff --git a/x/clock/spec/01_authorization.md b/x/clock/spec/01_authorization.md new file mode 100644 index 0000000..8d88b80 --- /dev/null +++ b/x/clock/spec/01_authorization.md @@ -0,0 +1,39 @@ +# Authorization + +For security purposes, only the governance module can add new contracts to the EndBlocker executes. + +## Query contracts + +You can query the list of contracts that are 'ticked' every block with the following command: + +```bash + junod q clock contracts --output json + # {"contract_addresses":[]} +``` + +## Governance proposal + +To update the authorized address is possible to create an onchain new proposal. You can use the following example `proposal.json` file + +```json +{ + "messages": [ + { + "@type": "/terp.clock.v1.MsgUpdateParams", + "authority": "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq", + "params": { + "contract_addresses": [ + "juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8" + ], + "contract_gas_limit": "1000000" + } + } + ], + "metadata": "{\"title\": \"Allow a new contract to use the x/clock module for our features\", \"authors\": [\"Reece\"], \"summary\": \"If this proposal passes juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be added to the authorized addresses of the clock module\", \"details\": \"If this proposal passes juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be added to the authorized addresses of the clock module\", \"proposal_forum_url\": \"https://commonwealth.im/juno/discussion/9697-juno-protocol-level-defi-incentives\", \"vote_option_context\": \"yes\"}", + "deposit": "1000000ujuno", + "title": "Allow a new contract to use the x/clock module for our features", + "summary": "If this proposal passes juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be allowed to use the x/clock module to perform XYZ actions" +} +``` + +It can be submitted with the standard `junod tx gov submit-proposal proposal.json --from=YOURKEY` command. diff --git a/x/clock/spec/02_integration.md b/x/clock/spec/02_integration.md new file mode 100644 index 0000000..fa76463 --- /dev/null +++ b/x/clock/spec/02_integration.md @@ -0,0 +1,56 @@ +# CosmWasm Integration + +This module does not require any custom bindings. Rather, you must just add the following Sudo message to your contract. If your contract is not whitelisted, you can still upload it to the chain. However, to get it to execute, you must submit a proposal to add your contract to the whitelist. + +You can find a basic [cw-clock contract here](https://github.com/Reecepbcups/cw-clock-example) + +## Implementation + +Add the following to your Rust Contract: + +```rust +// msg.rs +#[cw_serde] +pub enum SudoMsg { + ClockEndBlock { }, +} + +// contract.rs +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> Result { + match msg { + SudoMsg::ClockEndBlock { } => { + let mut config = CONFIG.load(deps.storage)?; + config.val += 1; + CONFIG.save(deps.storage, &config)?; + + Ok(Response::new()) + } + } +} +``` + +Using the above example, for every block the module will increase the `val` Config variable by 1. This is a simple example, but you can use this to perform any action you want (ex: cleanup, auto compounding, etc). + +If you wish not to have your action performed every block, you can use the `env` variable in the Sudo message to check the block height and only perform an action every X blocks. + +```rust +// contract.rs +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result { + match msg { + SudoMsg::ClockEndBlock { } => { + // If the block is not divisible by ten, do nothing. + if env.block.height % 10 != 0 { + return Ok(Response::new()); + } + + let mut config = CONFIG.load(deps.storage)?; + config.val += 1; + CONFIG.save(deps.storage, &config)?; + + Ok(Response::new()) + } + } +} +``` diff --git a/x/clock/spec/README.md b/x/clock/spec/README.md new file mode 100644 index 0000000..982d7ec --- /dev/null +++ b/x/clock/spec/README.md @@ -0,0 +1,14 @@ +# `clock` + +## Abstract + +This document specifies the internal `x/clock` module of Juno Network. + +The `x/clock` module allows specific contracts to be executed at the end of every block. This allows the smart contract to perform actions that may need to happen every block, or at set block intervals. + +By using this module, your application can remove the headache of external whitelisted bots and instead depend on the chain itself for constant executions. + +## Contents + +1. **[Authorization](01_authorization.md)** +2. **[Contract Integration](02_integration.md)** diff --git a/x/clock/types/codec.go b/x/clock/types/codec.go new file mode 100644 index 0000000..46ccaa4 --- /dev/null +++ b/x/clock/types/codec.go @@ -0,0 +1,44 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" + "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" +) + +var ( + amino = codec.NewLegacyAmino() + AminoCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) + cryptocodec.RegisterCrypto(amino) + sdk.RegisterLegacyAminoCodec(amino) + + // Register all Amino interfaces and concrete types on the authz and gov Amino codec + // so that this can later be used to properly serialize MsgGrant and MsgExec + // instances. + RegisterLegacyAminoCodec(authzcodec.Amino) + RegisterLegacyAminoCodec(govcodec.Amino) +} + +// RegisterLegacyAminoCodec registers concrete types on the LegacyAmino codec +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(Params{}, "terp/x/clock/Params", nil) + legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "terp/x/clock/MsgUpdateParams") +} + +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgUpdateParams{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} diff --git a/x/clock/types/codec_test.go b/x/clock/types/codec_test.go new file mode 100644 index 0000000..92c1c18 --- /dev/null +++ b/x/clock/types/codec_test.go @@ -0,0 +1,30 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type CodecTestSuite struct { + suite.Suite +} + +func TestCodecSuite(t *testing.T) { + suite.Run(t, new(CodecTestSuite)) +} + +func (suite *CodecTestSuite) TestRegisterInterfaces() { + registry := codectypes.NewInterfaceRegistry() + registry.RegisterInterface(sdk.MsgInterfaceProtoName, (*sdk.Msg)(nil)) + RegisterInterfaces(registry) + + impls := registry.ListImplementations(sdk.MsgInterfaceProtoName) + suite.Require().Equal(1, len(impls)) + suite.Require().ElementsMatch([]string{ + "/terp.clock.v1.MsgUpdateParams", + }, impls) +} diff --git a/x/clock/types/genesis.pb.go b/x/clock/types/genesis.pb.go new file mode 100644 index 0000000..0677a7e --- /dev/null +++ b/x/clock/types/genesis.pb.go @@ -0,0 +1,542 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: terp/clock/v1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState - initial state of module +type GenesisState struct { + // Params of this module + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_c31a7855fe794abe, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// Params defines the set of module parameters. +type Params struct { + // contract_addresses stores the list of executable contracts to be ticked on every block. + ContractAddresses []string `protobuf:"bytes,1,rep,name=contract_addresses,json=contractAddresses,proto3" json:"contract_addresses,omitempty" yaml:"contract_addresses"` + ContractGasLimit uint64 `protobuf:"varint,2,opt,name=contract_gas_limit,json=contractGasLimit,proto3" json:"contract_gas_limit,omitempty" yaml:"contract_gas_limit"` +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_c31a7855fe794abe, []int{1} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetContractAddresses() []string { + if m != nil { + return m.ContractAddresses + } + return nil +} + +func (m *Params) GetContractGasLimit() uint64 { + if m != nil { + return m.ContractGasLimit + } + return 0 +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "terp.clock.v1.GenesisState") + proto.RegisterType((*Params)(nil), "terp.clock.v1.Params") +} + +func init() { proto.RegisterFile("terp/clock/v1/genesis.proto", fileDescriptor_c31a7855fe794abe) } + +var fileDescriptor_c31a7855fe794abe = []byte{ + // 329 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0x3f, 0x4b, 0xc3, 0x40, + 0x18, 0xc6, 0x73, 0x2a, 0x05, 0xa3, 0x42, 0x0d, 0x0a, 0xb5, 0xca, 0xa5, 0x64, 0xea, 0xa0, 0x39, + 0xa2, 0x9b, 0xe0, 0x60, 0x3b, 0x64, 0x71, 0x90, 0x3a, 0x08, 0x2e, 0xe5, 0x72, 0x3d, 0x62, 0x6c, + 0x2e, 0x17, 0xf2, 0x5e, 0x8b, 0xfd, 0x16, 0x7e, 0xac, 0x8e, 0x1d, 0x9d, 0x82, 0x34, 0x5b, 0x47, + 0x3f, 0x81, 0xe4, 0xd2, 0xd6, 0x3f, 0x05, 0xb7, 0x97, 0xe7, 0xf7, 0xbc, 0xcf, 0x33, 0x3c, 0xe6, + 0xe9, 0xcb, 0x28, 0x91, 0x84, 0xc5, 0x92, 0x0d, 0xc9, 0xd8, 0x23, 0x21, 0x4f, 0x38, 0x44, 0xe0, + 0xa6, 0x99, 0x54, 0xd2, 0x3a, 0x28, 0xa1, 0xab, 0xa1, 0x3b, 0xf6, 0x9a, 0x47, 0xa1, 0x0c, 0xa5, + 0x26, 0xa4, 0xbc, 0x2a, 0x53, 0x13, 0x33, 0x09, 0x42, 0x02, 0x09, 0x28, 0x70, 0x32, 0xf6, 0x02, + 0xae, 0xa8, 0x47, 0x98, 0x8c, 0x92, 0x8a, 0x3b, 0x8f, 0xe6, 0xbe, 0x5f, 0xa5, 0x3e, 0x28, 0xaa, + 0xb8, 0xe5, 0x9b, 0xb5, 0x94, 0x66, 0x54, 0x40, 0x03, 0xb5, 0x50, 0x7b, 0xef, 0xf2, 0xd8, 0xfd, + 0xd5, 0xe2, 0xde, 0x6b, 0xd8, 0x69, 0x4c, 0x73, 0xdb, 0x58, 0xe4, 0x76, 0xbd, 0x32, 0x9f, 0x4b, + 0x11, 0x29, 0x2e, 0x52, 0x35, 0xe9, 0x2d, 0xdf, 0x9d, 0x02, 0x99, 0xb5, 0xca, 0x6c, 0xc5, 0xa6, + 0xc5, 0x64, 0xa2, 0x32, 0xca, 0x54, 0x9f, 0x0e, 0x06, 0x19, 0x07, 0xe0, 0x65, 0xfe, 0x76, 0x7b, + 0xb7, 0x73, 0xb3, 0xc8, 0xed, 0xb3, 0x4d, 0xfa, 0x1d, 0xf8, 0x99, 0xdb, 0x27, 0x13, 0x2a, 0xe2, + 0x6b, 0x67, 0xd3, 0xe5, 0xf4, 0x0e, 0x57, 0xe2, 0xed, 0x4a, 0xb3, 0x86, 0x3f, 0xda, 0x42, 0x0a, + 0xfd, 0x38, 0x12, 0x91, 0x6a, 0x6c, 0xb5, 0x50, 0x7b, 0xe7, 0x4f, 0xdb, 0x9a, 0xfe, 0xdb, 0xb6, + 0x76, 0x39, 0xbd, 0xfa, 0x4a, 0xf4, 0x29, 0xdc, 0x95, 0x52, 0xc7, 0x9f, 0xce, 0x31, 0x9a, 0xcd, + 0x31, 0xfa, 0x98, 0x63, 0xf4, 0x56, 0x60, 0x63, 0x56, 0x60, 0xe3, 0xbd, 0xc0, 0xc6, 0xd3, 0x45, + 0x18, 0xa9, 0xe7, 0x51, 0xe0, 0x32, 0x29, 0x48, 0x57, 0x6f, 0xd0, 0x5d, 0x3e, 0x03, 0xd1, 0xab, + 0xbe, 0x2e, 0x77, 0x55, 0x93, 0x94, 0x43, 0x50, 0xd3, 0x73, 0x5c, 0x7d, 0x05, 0x00, 0x00, 0xff, + 0xff, 0xe7, 0x62, 0x4a, 0xd0, 0xf2, 0x01, 0x00, 0x00, +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Params) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ContractGasLimit != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.ContractGasLimit)) + i-- + dAtA[i] = 0x10 + } + if len(m.ContractAddresses) > 0 { + for iNdEx := len(m.ContractAddresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ContractAddresses[iNdEx]) + copy(dAtA[i:], m.ContractAddresses[iNdEx]) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.ContractAddresses[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ContractAddresses) > 0 { + for _, s := range m.ContractAddresses { + l = len(s) + n += 1 + l + sovGenesis(uint64(l)) + } + } + if m.ContractGasLimit != 0 { + n += 1 + sovGenesis(uint64(m.ContractGasLimit)) + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Params) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractAddresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ContractAddresses = append(m.ContractAddresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractGasLimit", wireType) + } + m.ContractGasLimit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ContractGasLimit |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/clock/types/keys.go b/x/clock/types/keys.go new file mode 100644 index 0000000..3b97c28 --- /dev/null +++ b/x/clock/types/keys.go @@ -0,0 +1,11 @@ +package types + +var ParamsKey = []byte{0x00} + +const ( + ModuleName = "clock" + + StoreKey = ModuleName + + QuerierRoute = ModuleName +) diff --git a/x/clock/types/msgs.go b/x/clock/types/msgs.go new file mode 100644 index 0000000..cae1e8c --- /dev/null +++ b/x/clock/types/msgs.go @@ -0,0 +1,55 @@ +package types + +import ( + "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/terpnetwork/terp-core/v2/x/feeshare/types" +) + +const ( + // Sudo Message called on the contracts + EndBlockSudoMessage = `{"clock_end_block":{}}` +) + +// == MsgUpdateParams == +const TypeMsgUpdateParams = "update_clock_params" + +var _ sdk.Msg = &MsgUpdateParams{} + +// NewMsgUpdateParams creates new instance of MsgUpdateParams +func NewMsgUpdateParams( + sender sdk.Address, + contracts []string, +) *MsgUpdateParams { + return &MsgUpdateParams{ + Authority: sender.String(), + Params: Params{ContractAddresses: contracts}, + } +} + +// Route returns the name of the module +func (msg MsgUpdateParams) Route() string { return types.RouterKey } + +// Type returns the the action +func (msg MsgUpdateParams) Type() string { return TypeMsgUpdateParams } + +// GetSignBytes implements the LegacyMsg interface. +func (msg MsgUpdateParams) GetSignBytes() []byte { + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) +} + +// GetSigners returns the expected signers for a MsgUpdateParams message. +func (msg *MsgUpdateParams) GetSigners() []sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(msg.Authority) + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data. +func (msg *MsgUpdateParams) ValidateBasic() error { + if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { + return errors.Wrap(err, "invalid authority address") + } + + return msg.Params.Validate() +} diff --git a/x/clock/types/msgs_test.go b/x/clock/types/msgs_test.go new file mode 100644 index 0000000..88276e8 --- /dev/null +++ b/x/clock/types/msgs_test.go @@ -0,0 +1,40 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/suite" + "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type MsgsTestSuite struct { + suite.Suite + govModule string +} + +func TestMsgsTestSuite(t *testing.T) { + suite.Run(t, new(MsgsTestSuite)) +} + +func (suite *MsgsTestSuite) SetupTest() { + suite.govModule = "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq" +} + +func (suite *MsgsTestSuite) TestMsgUpdateParams() { + p := MsgUpdateParams{ + Authority: suite.govModule, + Params: Params{ + ContractAddresses: []string{}, + }, + } + + acc, _ := sdk.AccAddressFromBech32(p.Authority) + + msg := NewMsgUpdateParams(acc, []string(nil)) + + suite.Require().Equal(types.RouterKey, msg.Route()) + suite.Require().Equal(TypeMsgUpdateParams, msg.Type()) + suite.Require().NotNil(msg.GetSigners()) +} diff --git a/x/clock/types/params.go b/x/clock/types/params.go new file mode 100644 index 0000000..46b5dfb --- /dev/null +++ b/x/clock/types/params.go @@ -0,0 +1,65 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// DefaultParams returns default parameters +func DefaultParams() Params { + return Params{ + ContractAddresses: []string(nil), + ContractGasLimit: 1_000_000_000, // 1 billion + } +} + +// NewParams creates a new Params object +func NewParams( + contracts []string, + contractGasLimit uint64, +) Params { + return Params{ + ContractAddresses: contracts, + ContractGasLimit: contractGasLimit, + } +} + +// Validate performs basic validation. +func (p Params) Validate() error { + minimumGas := uint64(100_000) + if p.ContractGasLimit < minimumGas { + return errorsmod.Wrapf( + sdkerrors.ErrInvalidRequest, + "invalid contract gas limit: %d. Must be above %d", p.ContractGasLimit, minimumGas, + ) + } + + for _, addr := range p.ContractAddresses { + // Valid address check + if _, err := sdk.AccAddressFromBech32(addr); err != nil { + return errorsmod.Wrapf( + sdkerrors.ErrInvalidAddress, + "invalid contract address: %s", err.Error(), + ) + } + + // duplicate address check + count := 0 + for _, addr2 := range p.ContractAddresses { + if addr == addr2 { + count++ + } + + if count > 1 { + return errorsmod.Wrapf( + sdkerrors.ErrInvalidAddress, + "duplicate contract address: %s", addr, + ) + } + } + } + + return nil +} diff --git a/x/clock/types/params_test.go b/x/clock/types/params_test.go new file mode 100644 index 0000000..871a892 --- /dev/null +++ b/x/clock/types/params_test.go @@ -0,0 +1,44 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/terpnetwork/terp-core/v2/x/clock/types" +) + +func TestParamsValidate(t *testing.T) { + testCases := []struct { + name string + params types.Params + expError bool + }{ + {"default", types.DefaultParams(), false}, + { + "valid: no contracts, enough gas", + types.NewParams([]string(nil), 100_000), + false, + }, + { + "invalid: address malformed", + types.NewParams([]string{"invalid address"}, 100_000), + true, + }, + { + "invalid: not enough gas", + types.NewParams([]string(nil), 1), + true, + }, + } + + for _, tc := range testCases { + err := tc.params.Validate() + + if tc.expError { + require.Error(t, err, tc.name) + } else { + require.NoError(t, err, tc.name) + } + } +} diff --git a/x/clock/types/query.pb.go b/x/clock/types/query.pb.go new file mode 100644 index 0000000..ad24441 --- /dev/null +++ b/x/clock/types/query.pb.go @@ -0,0 +1,884 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: terp/clock/v1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryClockContracts is the request type to get all contracts. +type QueryClockContracts struct { +} + +func (m *QueryClockContracts) Reset() { *m = QueryClockContracts{} } +func (m *QueryClockContracts) String() string { return proto.CompactTextString(m) } +func (*QueryClockContracts) ProtoMessage() {} +func (*QueryClockContracts) Descriptor() ([]byte, []int) { + return fileDescriptor_7da208f579d775c8, []int{0} +} +func (m *QueryClockContracts) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClockContracts) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClockContracts.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClockContracts) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClockContracts.Merge(m, src) +} +func (m *QueryClockContracts) XXX_Size() int { + return m.Size() +} +func (m *QueryClockContracts) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClockContracts.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClockContracts proto.InternalMessageInfo + +// QueryClockContractsResponse is the response type for the Query/ClockContracts RPC method. +type QueryClockContractsResponse struct { + ContractAddresses []string `protobuf:"bytes,1,rep,name=contract_addresses,json=contractAddresses,proto3" json:"contract_addresses,omitempty" yaml:"contract_addresses"` +} + +func (m *QueryClockContractsResponse) Reset() { *m = QueryClockContractsResponse{} } +func (m *QueryClockContractsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryClockContractsResponse) ProtoMessage() {} +func (*QueryClockContractsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_7da208f579d775c8, []int{1} +} +func (m *QueryClockContractsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryClockContractsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryClockContractsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryClockContractsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryClockContractsResponse.Merge(m, src) +} +func (m *QueryClockContractsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryClockContractsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryClockContractsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryClockContractsResponse proto.InternalMessageInfo + +func (m *QueryClockContractsResponse) GetContractAddresses() []string { + if m != nil { + return m.ContractAddresses + } + return nil +} + +// QueryParams is the request type to get all module params. +type QueryParamsRequest struct { +} + +func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } +func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryParamsRequest) ProtoMessage() {} +func (*QueryParamsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_7da208f579d775c8, []int{2} +} +func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryParamsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsRequest.Merge(m, src) +} +func (m *QueryParamsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo + +// QueryClockContractsResponse is the response type for the Query/ClockContracts RPC method. +type QueryParamsResponse struct { + Params *Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params" yaml:"params"` +} + +func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } +func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryParamsResponse) ProtoMessage() {} +func (*QueryParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_7da208f579d775c8, []int{3} +} +func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryParamsResponse.Merge(m, src) +} +func (m *QueryParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo + +func (m *QueryParamsResponse) GetParams() *Params { + if m != nil { + return m.Params + } + return nil +} + +func init() { + proto.RegisterType((*QueryClockContracts)(nil), "terp.clock.v1.QueryClockContracts") + proto.RegisterType((*QueryClockContractsResponse)(nil), "terp.clock.v1.QueryClockContractsResponse") + proto.RegisterType((*QueryParamsRequest)(nil), "terp.clock.v1.QueryParamsRequest") + proto.RegisterType((*QueryParamsResponse)(nil), "terp.clock.v1.QueryParamsResponse") +} + +func init() { proto.RegisterFile("terp/clock/v1/query.proto", fileDescriptor_7da208f579d775c8) } + +var fileDescriptor_7da208f579d775c8 = []byte{ + // 423 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xb1, 0x8f, 0xd3, 0x30, + 0x18, 0xc5, 0x6b, 0x10, 0x95, 0x30, 0x3a, 0x24, 0xcc, 0x55, 0xf4, 0xd2, 0x23, 0x2d, 0x9e, 0x4e, + 0x08, 0x62, 0xe5, 0xd8, 0x90, 0x18, 0x68, 0x07, 0x24, 0x26, 0xc8, 0xc8, 0x82, 0x1c, 0x9f, 0x15, + 0x02, 0x89, 0xbf, 0x5c, 0xec, 0x54, 0x64, 0xbd, 0x95, 0x05, 0x89, 0x7f, 0x8a, 0xf1, 0x24, 0x16, + 0xa6, 0x08, 0xb5, 0x4c, 0x37, 0xde, 0xcc, 0x80, 0xe2, 0xb8, 0x95, 0x72, 0x57, 0xc1, 0x96, 0xbc, + 0xdf, 0xcb, 0xf7, 0x9e, 0xbf, 0x18, 0x1f, 0x7c, 0xac, 0x14, 0x30, 0x91, 0x81, 0xf8, 0xc4, 0x96, + 0x21, 0x3b, 0xad, 0x64, 0x59, 0x07, 0x45, 0x09, 0x06, 0xc8, 0x5e, 0x8b, 0x02, 0x8b, 0x82, 0x65, + 0xe8, 0xed, 0x27, 0x90, 0x80, 0x25, 0xac, 0x7d, 0xea, 0x4c, 0xde, 0x61, 0x02, 0x90, 0x64, 0x92, + 0xf1, 0x22, 0x65, 0x5c, 0x29, 0x30, 0xdc, 0xa4, 0xa0, 0xb4, 0xa3, 0xbe, 0x00, 0x9d, 0x83, 0x66, + 0x31, 0xd7, 0x92, 0x2d, 0xc3, 0x58, 0x1a, 0x1e, 0x32, 0x01, 0xa9, 0x72, 0x7c, 0xd2, 0x4f, 0x4f, + 0xa4, 0x92, 0x3a, 0x75, 0x1f, 0xd3, 0x11, 0xbe, 0xff, 0xb6, 0xad, 0xb3, 0x68, 0xf1, 0x02, 0x94, + 0x29, 0xb9, 0x30, 0x9a, 0x7e, 0x41, 0x78, 0xb2, 0x43, 0x8f, 0xa4, 0x2e, 0x40, 0x69, 0x49, 0x32, + 0x4c, 0x84, 0x13, 0xdf, 0xf3, 0x93, 0x93, 0x52, 0x6a, 0x2d, 0xf5, 0x18, 0xcd, 0x6e, 0x1e, 0xdd, + 0x9e, 0xbf, 0xb8, 0x68, 0xa6, 0x87, 0xd7, 0xe9, 0x13, 0xc8, 0x53, 0x23, 0xf3, 0xc2, 0xd4, 0x97, + 0xcd, 0xf4, 0xa0, 0xe6, 0x79, 0xf6, 0x9c, 0x5e, 0x77, 0xd1, 0xe8, 0xde, 0x46, 0x7c, 0xb9, 0xd5, + 0xf6, 0x31, 0xb1, 0x65, 0xde, 0xf0, 0x92, 0xe7, 0x3a, 0x92, 0xa7, 0x95, 0xd4, 0x86, 0x72, 0x57, + 0x7d, 0xa3, 0xba, 0x6a, 0xaf, 0xf1, 0xb0, 0xb0, 0xca, 0x18, 0xcd, 0xd0, 0xd1, 0x9d, 0xe3, 0x51, + 0xd0, 0x5b, 0x71, 0xd0, 0xd9, 0xe7, 0x93, 0x8b, 0x66, 0xea, 0x8c, 0x97, 0xcd, 0x74, 0xaf, 0xeb, + 0xd3, 0xbd, 0xd3, 0xc8, 0x81, 0xe3, 0x3f, 0x08, 0xdf, 0xb2, 0x19, 0xe4, 0x0c, 0xe1, 0xbb, 0xfd, + 0x5d, 0x10, 0x7a, 0x65, 0xf0, 0x8e, 0x7d, 0x79, 0x8f, 0xff, 0xef, 0xd9, 0x14, 0xa7, 0xb3, 0xb3, + 0x1f, 0xbf, 0xbf, 0xdd, 0xf0, 0xc8, 0x98, 0xf5, 0x7f, 0x98, 0xd8, 0x26, 0x2a, 0x3c, 0xec, 0xda, + 0x93, 0x47, 0xbb, 0xe6, 0xf6, 0xd6, 0xe3, 0xd1, 0x7f, 0x59, 0x5c, 0xe4, 0x43, 0x1b, 0xf9, 0x80, + 0x8c, 0xae, 0x44, 0x76, 0xc7, 0x9f, 0xbf, 0xfa, 0xbe, 0xf2, 0xd1, 0xf9, 0xca, 0x47, 0xbf, 0x56, + 0x3e, 0xfa, 0xba, 0xf6, 0x07, 0xe7, 0x6b, 0x7f, 0xf0, 0x73, 0xed, 0x0f, 0xde, 0x3d, 0x4d, 0x52, + 0xf3, 0xa1, 0x8a, 0x03, 0x01, 0x39, 0x5b, 0xd8, 0xeb, 0xb7, 0x3d, 0x4f, 0x37, 0xea, 0xb3, 0x1b, + 0x66, 0xea, 0x42, 0xea, 0x78, 0x68, 0x2f, 0xdb, 0xb3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xdb, + 0x57, 0xe2, 0x8b, 0x09, 0x03, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // ClockContracts + ClockContracts(ctx context.Context, in *QueryClockContracts, opts ...grpc.CallOption) (*QueryClockContractsResponse, error) + // Params + Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) ClockContracts(ctx context.Context, in *QueryClockContracts, opts ...grpc.CallOption) (*QueryClockContractsResponse, error) { + out := new(QueryClockContractsResponse) + err := c.cc.Invoke(ctx, "/terp.clock.v1.Query/ClockContracts", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { + out := new(QueryParamsResponse) + err := c.cc.Invoke(ctx, "/terp.clock.v1.Query/Params", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // ClockContracts + ClockContracts(context.Context, *QueryClockContracts) (*QueryClockContractsResponse, error) + // Params + Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) ClockContracts(ctx context.Context, req *QueryClockContracts) (*QueryClockContractsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ClockContracts not implemented") +} +func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_ClockContracts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryClockContracts) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ClockContracts(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/terp.clock.v1.Query/ClockContracts", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ClockContracts(ctx, req.(*QueryClockContracts)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryParamsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Params(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/terp.clock.v1.Query/Params", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "terp.clock.v1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ClockContracts", + Handler: _Query_ClockContracts_Handler, + }, + { + MethodName: "Params", + Handler: _Query_Params_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "terp/clock/v1/query.proto", +} + +func (m *QueryClockContracts) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClockContracts) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClockContracts) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryClockContractsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryClockContractsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryClockContractsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ContractAddresses) > 0 { + for iNdEx := len(m.ContractAddresses) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.ContractAddresses[iNdEx]) + copy(dAtA[i:], m.ContractAddresses[iNdEx]) + i = encodeVarintQuery(dAtA, i, uint64(len(m.ContractAddresses[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Params != nil { + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryClockContracts) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryClockContractsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ContractAddresses) > 0 { + for _, s := range m.ContractAddresses { + l = len(s) + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *QueryParamsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *QueryParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Params != nil { + l = m.Params.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryClockContracts) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClockContracts: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClockContracts: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryClockContractsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryClockContractsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryClockContractsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractAddresses", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ContractAddresses = append(m.ContractAddresses, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Params == nil { + m.Params = &Params{} + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/clock/types/query.pb.gw.go b/x/clock/types/query.pb.gw.go new file mode 100644 index 0000000..5adb17c --- /dev/null +++ b/x/clock/types/query.pb.gw.go @@ -0,0 +1,218 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: terp/clock/v1/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_ClockContracts_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClockContracts + var metadata runtime.ServerMetadata + + msg, err := client.ClockContracts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ClockContracts_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryClockContracts + var metadata runtime.ServerMetadata + + msg, err := server.ClockContracts(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryParamsRequest + var metadata runtime.ServerMetadata + + msg, err := server.Params(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_ClockContracts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ClockContracts_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClockContracts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_ClockContracts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ClockContracts_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ClockContracts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_ClockContracts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"terp", "clock", "v1", "contracts"}, "", runtime.AssumeColonVerbOpt(false))) + + pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"terp", "clock", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) +) + +var ( + forward_Query_ClockContracts_0 = runtime.ForwardResponseMessage + + forward_Query_Params_0 = runtime.ForwardResponseMessage +) diff --git a/x/clock/types/tx.pb.go b/x/clock/types/tx.pb.go new file mode 100644 index 0000000..4a188aa --- /dev/null +++ b/x/clock/types/tx.pb.go @@ -0,0 +1,605 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: terp/clock/v1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgUpdateParams is the Msg/UpdateParams request type. +// +// Since: cosmos-sdk 0.47 +type MsgUpdateParams struct { + // authority is the address of the governance account. + Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` + // params defines the x/clock parameters to update. + // + // NOTE: All parameters must be supplied. + Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` +} + +func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } +func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParams) ProtoMessage() {} +func (*MsgUpdateParams) Descriptor() ([]byte, []int) { + return fileDescriptor_76642a1e9a85f94b, []int{0} +} +func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParams.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgUpdateParams) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParams.Merge(m, src) +} +func (m *MsgUpdateParams) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParams) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo + +func (m *MsgUpdateParams) GetAuthority() string { + if m != nil { + return m.Authority + } + return "" +} + +func (m *MsgUpdateParams) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +// MsgUpdateParamsResponse defines the response structure for executing a +// MsgUpdateParams message. +// +// Since: cosmos-sdk 0.47 +type MsgUpdateParamsResponse struct { +} + +func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } +func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateParamsResponse) ProtoMessage() {} +func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_76642a1e9a85f94b, []int{1} +} +func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateParamsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) +} +func (m *MsgUpdateParamsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgUpdateParams)(nil), "terp.clock.v1.MsgUpdateParams") + proto.RegisterType((*MsgUpdateParamsResponse)(nil), "terp.clock.v1.MsgUpdateParamsResponse") +} + +func init() { proto.RegisterFile("terp/clock/v1/tx.proto", fileDescriptor_76642a1e9a85f94b) } + +var fileDescriptor_76642a1e9a85f94b = []byte{ + // 333 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcb, 0x2a, 0xcd, 0xcb, + 0xd7, 0x4f, 0xce, 0xc9, 0x4f, 0xce, 0xd6, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, + 0x2f, 0xc9, 0x17, 0xe2, 0x05, 0x89, 0xeb, 0x81, 0xc5, 0xf5, 0xca, 0x0c, 0xa5, 0xc4, 0x93, 0xf3, + 0x8b, 0x73, 0xf3, 0x8b, 0xf5, 0x73, 0x8b, 0xd3, 0x41, 0xca, 0x72, 0x8b, 0xd3, 0x21, 0xea, 0xa4, + 0xa4, 0x51, 0xf5, 0xa7, 0xa7, 0xe6, 0xa5, 0x16, 0x67, 0x16, 0x43, 0x25, 0x45, 0xd2, 0xf3, 0xd3, + 0xf3, 0xc1, 0x4c, 0x7d, 0x10, 0x0b, 0x2a, 0x2a, 0x09, 0x31, 0x2b, 0x1e, 0x22, 0x01, 0xe1, 0x40, + 0xa5, 0x04, 0x13, 0x73, 0x33, 0xf3, 0xf2, 0xf5, 0xc1, 0x24, 0x44, 0x48, 0xa9, 0x8f, 0x91, 0x8b, + 0xdf, 0xb7, 0x38, 0x3d, 0xb4, 0x20, 0x25, 0xb1, 0x24, 0x35, 0x20, 0xb1, 0x28, 0x31, 0xb7, 0x58, + 0xc8, 0x8c, 0x8b, 0x33, 0xb1, 0xb4, 0x24, 0x23, 0xbf, 0x28, 0xb3, 0xa4, 0x52, 0x82, 0x51, 0x81, + 0x51, 0x83, 0xd3, 0x49, 0xe2, 0xd2, 0x16, 0x5d, 0x11, 0xa8, 0x59, 0x8e, 0x29, 0x29, 0x45, 0xa9, + 0xc5, 0xc5, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x41, 0x08, 0xa5, 0x42, 0xc6, 0x5c, 0x6c, 0x05, + 0x60, 0x13, 0x24, 0x98, 0x14, 0x18, 0x35, 0xb8, 0x8d, 0x44, 0xf5, 0x50, 0x7c, 0xa9, 0x07, 0x31, + 0xde, 0x89, 0xe5, 0xc4, 0x3d, 0x79, 0x86, 0x20, 0xa8, 0x52, 0x2b, 0xbe, 0xa6, 0xe7, 0x1b, 0xb4, + 0x10, 0x86, 0x28, 0x49, 0x72, 0x89, 0xa3, 0xb9, 0x27, 0x28, 0xb5, 0xb8, 0x20, 0x3f, 0xaf, 0x38, + 0xd5, 0x28, 0x96, 0x8b, 0xd9, 0xb7, 0x38, 0x5d, 0x28, 0x8c, 0x8b, 0x07, 0xc5, 0xb9, 0x72, 0x68, + 0xd6, 0xa0, 0x69, 0x97, 0x52, 0xc3, 0x2f, 0x0f, 0x33, 0xde, 0xc9, 0xfd, 0xc4, 0x23, 0x39, 0xc6, + 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, + 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0x74, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, + 0x73, 0xf5, 0x9d, 0xc1, 0x81, 0xe0, 0x9c, 0x9f, 0x57, 0x52, 0x94, 0x98, 0x5c, 0x52, 0xac, 0x0f, + 0x8e, 0xa0, 0x0a, 0x68, 0x14, 0x95, 0x54, 0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, 0x83, 0xd6, 0x18, + 0x10, 0x00, 0x00, 0xff, 0xff, 0xda, 0x7a, 0xd4, 0x12, 0xfd, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // UpdateParams defines a governance operation for updating the x/clock module + // parameters. The authority is hard-coded to the x/gov module account. + // + // Since: cosmos-sdk 0.47 + UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { + out := new(MsgUpdateParamsResponse) + err := c.cc.Invoke(ctx, "/terp.clock.v1.Msg/UpdateParams", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // UpdateParams defines a governance operation for updating the x/clock module + // parameters. The authority is hard-coded to the x/gov module account. + // + // Since: cosmos-sdk 0.47 + UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateParams(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/terp.clock.v1.Msg/UpdateParams", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "terp.clock.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "UpdateParams", + Handler: _Msg_UpdateParams_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "terp/clock/v1/tx.proto", +} + +func (m *MsgUpdateParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Authority) > 0 { + i -= len(m.Authority) + copy(dAtA[i:], m.Authority) + i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateParamsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgUpdateParams) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Authority) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Params.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgUpdateParamsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authority = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) From d964298d019190022f78a07c745aeb2529a5a608 Mon Sep 17 00:00:00 2001 From: discoverdefiteam Date: Tue, 17 Oct 2023 20:48:15 -0400 Subject: [PATCH 03/18] update proto --- .gitignore | 4 ++ x/clock/types/genesis.pb.go | 50 +++++++++++------------ x/clock/types/query.pb.go | 70 ++++++++++++++++---------------- x/clock/types/tx.pb.go | 24 +++++------ x/globalfee/types/genesis.pb.go | 30 +++----------- x/globalfee/types/query.pb.go | 42 ++++++------------- x/globalfee/types/query.pb.gw.go | 30 +++++++++----- x/globalfee/types/tx.pb.go | 42 ++++++------------- 8 files changed, 125 insertions(+), 167 deletions(-) diff --git a/.gitignore b/.gitignore index ed049cc..e60ff67 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,7 @@ dependency-graph.png *.out *.synctex.gz contract_tests/* + +# Protobuf +gogoproto +github.com \ No newline at end of file diff --git a/x/clock/types/genesis.pb.go b/x/clock/types/genesis.pb.go index 0677a7e..c3c5122 100644 --- a/x/clock/types/genesis.pb.go +++ b/x/clock/types/genesis.pb.go @@ -34,7 +34,7 @@ func (m *GenesisState) Reset() { *m = GenesisState{} } func (m *GenesisState) String() string { return proto.CompactTextString(m) } func (*GenesisState) ProtoMessage() {} func (*GenesisState) Descriptor() ([]byte, []int) { - return fileDescriptor_c31a7855fe794abe, []int{0} + return fileDescriptor_5814f6c7e1ff453c, []int{0} } func (m *GenesisState) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -81,7 +81,7 @@ func (m *Params) Reset() { *m = Params{} } func (m *Params) String() string { return proto.CompactTextString(m) } func (*Params) ProtoMessage() {} func (*Params) Descriptor() ([]byte, []int) { - return fileDescriptor_c31a7855fe794abe, []int{1} + return fileDescriptor_5814f6c7e1ff453c, []int{1} } func (m *Params) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -129,31 +129,31 @@ func init() { proto.RegisterType((*Params)(nil), "terp.clock.v1.Params") } -func init() { proto.RegisterFile("terp/clock/v1/genesis.proto", fileDescriptor_c31a7855fe794abe) } +func init() { proto.RegisterFile("terp/clock/v1/genesis.proto", fileDescriptor_5814f6c7e1ff453c) } -var fileDescriptor_c31a7855fe794abe = []byte{ - // 329 bytes of a gzipped FileDescriptorProto +var fileDescriptor_5814f6c7e1ff453c = []byte{ + // 332 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0x3f, 0x4b, 0xc3, 0x40, - 0x18, 0xc6, 0x73, 0x2a, 0x05, 0xa3, 0x42, 0x0d, 0x0a, 0xb5, 0xca, 0xa5, 0x64, 0xea, 0xa0, 0x39, - 0xa2, 0x9b, 0xe0, 0x60, 0x3b, 0x64, 0x71, 0x90, 0x3a, 0x08, 0x2e, 0xe5, 0x72, 0x3d, 0x62, 0x6c, - 0x2e, 0x17, 0xf2, 0x5e, 0x8b, 0xfd, 0x16, 0x7e, 0xac, 0x8e, 0x1d, 0x9d, 0x82, 0x34, 0x5b, 0x47, - 0x3f, 0x81, 0xe4, 0xd2, 0xd6, 0x3f, 0x05, 0xb7, 0x97, 0xe7, 0xf7, 0xbc, 0xcf, 0x33, 0x3c, 0xe6, - 0xe9, 0xcb, 0x28, 0x91, 0x84, 0xc5, 0x92, 0x0d, 0xc9, 0xd8, 0x23, 0x21, 0x4f, 0x38, 0x44, 0xe0, - 0xa6, 0x99, 0x54, 0xd2, 0x3a, 0x28, 0xa1, 0xab, 0xa1, 0x3b, 0xf6, 0x9a, 0x47, 0xa1, 0x0c, 0xa5, - 0x26, 0xa4, 0xbc, 0x2a, 0x53, 0x13, 0x33, 0x09, 0x42, 0x02, 0x09, 0x28, 0x70, 0x32, 0xf6, 0x02, - 0xae, 0xa8, 0x47, 0x98, 0x8c, 0x92, 0x8a, 0x3b, 0x8f, 0xe6, 0xbe, 0x5f, 0xa5, 0x3e, 0x28, 0xaa, - 0xb8, 0xe5, 0x9b, 0xb5, 0x94, 0x66, 0x54, 0x40, 0x03, 0xb5, 0x50, 0x7b, 0xef, 0xf2, 0xd8, 0xfd, - 0xd5, 0xe2, 0xde, 0x6b, 0xd8, 0x69, 0x4c, 0x73, 0xdb, 0x58, 0xe4, 0x76, 0xbd, 0x32, 0x9f, 0x4b, - 0x11, 0x29, 0x2e, 0x52, 0x35, 0xe9, 0x2d, 0xdf, 0x9d, 0x02, 0x99, 0xb5, 0xca, 0x6c, 0xc5, 0xa6, - 0xc5, 0x64, 0xa2, 0x32, 0xca, 0x54, 0x9f, 0x0e, 0x06, 0x19, 0x07, 0xe0, 0x65, 0xfe, 0x76, 0x7b, - 0xb7, 0x73, 0xb3, 0xc8, 0xed, 0xb3, 0x4d, 0xfa, 0x1d, 0xf8, 0x99, 0xdb, 0x27, 0x13, 0x2a, 0xe2, - 0x6b, 0x67, 0xd3, 0xe5, 0xf4, 0x0e, 0x57, 0xe2, 0xed, 0x4a, 0xb3, 0x86, 0x3f, 0xda, 0x42, 0x0a, - 0xfd, 0x38, 0x12, 0x91, 0x6a, 0x6c, 0xb5, 0x50, 0x7b, 0xe7, 0x4f, 0xdb, 0x9a, 0xfe, 0xdb, 0xb6, - 0x76, 0x39, 0xbd, 0xfa, 0x4a, 0xf4, 0x29, 0xdc, 0x95, 0x52, 0xc7, 0x9f, 0xce, 0x31, 0x9a, 0xcd, - 0x31, 0xfa, 0x98, 0x63, 0xf4, 0x56, 0x60, 0x63, 0x56, 0x60, 0xe3, 0xbd, 0xc0, 0xc6, 0xd3, 0x45, - 0x18, 0xa9, 0xe7, 0x51, 0xe0, 0x32, 0x29, 0x48, 0x57, 0x6f, 0xd0, 0x5d, 0x3e, 0x03, 0xd1, 0xab, - 0xbe, 0x2e, 0x77, 0x55, 0x93, 0x94, 0x43, 0x50, 0xd3, 0x73, 0x5c, 0x7d, 0x05, 0x00, 0x00, 0xff, - 0xff, 0xe7, 0x62, 0x4a, 0xd0, 0xf2, 0x01, 0x00, 0x00, + 0x18, 0xc6, 0x73, 0x2a, 0x05, 0xa3, 0x42, 0x0d, 0x0a, 0xb5, 0xca, 0xa5, 0x64, 0xea, 0xa0, 0x77, + 0x44, 0x37, 0xc1, 0xc1, 0x2e, 0x75, 0x70, 0x90, 0x3a, 0x08, 0x2e, 0xe5, 0x72, 0x3d, 0x62, 0x68, + 0x2e, 0x17, 0xee, 0x5e, 0xab, 0xfd, 0x16, 0x7e, 0xac, 0x8e, 0x1d, 0x9d, 0x82, 0x34, 0x5b, 0x47, + 0x3f, 0x81, 0x24, 0x69, 0xeb, 0x9f, 0x82, 0xdb, 0xcb, 0xf3, 0xfb, 0xdd, 0xfb, 0xc0, 0xbd, 0xf6, + 0x31, 0x08, 0x9d, 0x52, 0x1e, 0x2b, 0x3e, 0xa4, 0x23, 0x9f, 0x86, 0x22, 0x11, 0x26, 0x32, 0x24, + 0xd5, 0x0a, 0x94, 0xb3, 0x57, 0x40, 0x52, 0x42, 0x32, 0xf2, 0x9b, 0x07, 0xa1, 0x0a, 0x55, 0x49, + 0x68, 0x31, 0x55, 0x52, 0x13, 0x73, 0x65, 0xa4, 0x32, 0x34, 0x60, 0x46, 0xd0, 0x91, 0x1f, 0x08, + 0x60, 0x3e, 0xe5, 0x2a, 0x4a, 0x2a, 0xee, 0x3d, 0xd8, 0xbb, 0xdd, 0x6a, 0xeb, 0x3d, 0x30, 0x10, + 0x4e, 0xd7, 0xae, 0xa5, 0x4c, 0x33, 0x69, 0x1a, 0xa8, 0x85, 0xda, 0x3b, 0xe7, 0x87, 0xe4, 0x57, + 0x0b, 0xb9, 0x2b, 0x61, 0xa7, 0x31, 0xc9, 0x5c, 0x6b, 0x9e, 0xb9, 0xf5, 0x4a, 0x3e, 0x55, 0x32, + 0x02, 0x21, 0x53, 0x18, 0xf7, 0x16, 0xcf, 0xbd, 0x1c, 0xd9, 0xb5, 0x4a, 0x76, 0x62, 0xdb, 0xe1, + 0x2a, 0x01, 0xcd, 0x38, 0xf4, 0xd9, 0x60, 0xa0, 0x85, 0x31, 0xa2, 0xd8, 0xbf, 0xd9, 0xde, 0xee, + 0x5c, 0xcd, 0x33, 0xf7, 0x64, 0x9d, 0x7e, 0x2f, 0xfc, 0xcc, 0xdc, 0xa3, 0x31, 0x93, 0xf1, 0xa5, + 0xb7, 0x6e, 0x79, 0xbd, 0xfd, 0x65, 0x78, 0xbd, 0xcc, 0x9c, 0xe1, 0x8f, 0xb6, 0x90, 0x99, 0x7e, + 0x1c, 0xc9, 0x08, 0x1a, 0x1b, 0x2d, 0xd4, 0xde, 0xfa, 0xd3, 0xb6, 0xa2, 0xff, 0xb6, 0xad, 0x2c, + 0xaf, 0x57, 0x5f, 0x86, 0x5d, 0x66, 0x6e, 0x8b, 0xa8, 0x73, 0x33, 0x99, 0x61, 0x34, 0x9d, 0x61, + 0xf4, 0x31, 0xc3, 0xe8, 0x2d, 0xc7, 0xd6, 0x34, 0xc7, 0xd6, 0x7b, 0x8e, 0xad, 0x47, 0x12, 0x46, + 0xf0, 0xf4, 0x1c, 0x10, 0xae, 0x24, 0x2d, 0xbe, 0x30, 0x11, 0xf0, 0xa2, 0xf4, 0xb0, 0x9c, 0xcf, + 0xb8, 0xd2, 0x82, 0xbe, 0x2e, 0x0e, 0x0b, 0xe3, 0x54, 0x98, 0xa0, 0x56, 0xde, 0xe3, 0xe2, 0x2b, + 0x00, 0x00, 0xff, 0xff, 0xcc, 0xa3, 0xd5, 0x20, 0xf3, 0x01, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { diff --git a/x/clock/types/query.pb.go b/x/clock/types/query.pb.go index ad24441..2d92ef0 100644 --- a/x/clock/types/query.pb.go +++ b/x/clock/types/query.pb.go @@ -38,7 +38,7 @@ func (m *QueryClockContracts) Reset() { *m = QueryClockContracts{} } func (m *QueryClockContracts) String() string { return proto.CompactTextString(m) } func (*QueryClockContracts) ProtoMessage() {} func (*QueryClockContracts) Descriptor() ([]byte, []int) { - return fileDescriptor_7da208f579d775c8, []int{0} + return fileDescriptor_06ba6c07aa2f39a1, []int{0} } func (m *QueryClockContracts) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -76,7 +76,7 @@ func (m *QueryClockContractsResponse) Reset() { *m = QueryClockContracts func (m *QueryClockContractsResponse) String() string { return proto.CompactTextString(m) } func (*QueryClockContractsResponse) ProtoMessage() {} func (*QueryClockContractsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7da208f579d775c8, []int{1} + return fileDescriptor_06ba6c07aa2f39a1, []int{1} } func (m *QueryClockContractsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -120,7 +120,7 @@ func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } func (*QueryParamsRequest) ProtoMessage() {} func (*QueryParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_7da208f579d775c8, []int{2} + return fileDescriptor_06ba6c07aa2f39a1, []int{2} } func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -158,7 +158,7 @@ func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } func (*QueryParamsResponse) ProtoMessage() {} func (*QueryParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_7da208f579d775c8, []int{3} + return fileDescriptor_06ba6c07aa2f39a1, []int{3} } func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -201,37 +201,37 @@ func init() { proto.RegisterType((*QueryParamsResponse)(nil), "terp.clock.v1.QueryParamsResponse") } -func init() { proto.RegisterFile("terp/clock/v1/query.proto", fileDescriptor_7da208f579d775c8) } - -var fileDescriptor_7da208f579d775c8 = []byte{ - // 423 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xb1, 0x8f, 0xd3, 0x30, - 0x18, 0xc5, 0x6b, 0x10, 0x95, 0x30, 0x3a, 0x24, 0xcc, 0x55, 0xf4, 0xd2, 0x23, 0x2d, 0x9e, 0x4e, - 0x08, 0x62, 0xe5, 0xd8, 0x90, 0x18, 0x68, 0x07, 0x24, 0x26, 0xc8, 0xc8, 0x82, 0x1c, 0x9f, 0x15, - 0x02, 0x89, 0xbf, 0x5c, 0xec, 0x54, 0x64, 0xbd, 0x95, 0x05, 0x89, 0x7f, 0x8a, 0xf1, 0x24, 0x16, - 0xa6, 0x08, 0xb5, 0x4c, 0x37, 0xde, 0xcc, 0x80, 0xe2, 0xb8, 0x95, 0x72, 0x57, 0xc1, 0x96, 0xbc, - 0xdf, 0xcb, 0xf7, 0x9e, 0xbf, 0x18, 0x1f, 0x7c, 0xac, 0x14, 0x30, 0x91, 0x81, 0xf8, 0xc4, 0x96, - 0x21, 0x3b, 0xad, 0x64, 0x59, 0x07, 0x45, 0x09, 0x06, 0xc8, 0x5e, 0x8b, 0x02, 0x8b, 0x82, 0x65, - 0xe8, 0xed, 0x27, 0x90, 0x80, 0x25, 0xac, 0x7d, 0xea, 0x4c, 0xde, 0x61, 0x02, 0x90, 0x64, 0x92, - 0xf1, 0x22, 0x65, 0x5c, 0x29, 0x30, 0xdc, 0xa4, 0xa0, 0xb4, 0xa3, 0xbe, 0x00, 0x9d, 0x83, 0x66, - 0x31, 0xd7, 0x92, 0x2d, 0xc3, 0x58, 0x1a, 0x1e, 0x32, 0x01, 0xa9, 0x72, 0x7c, 0xd2, 0x4f, 0x4f, - 0xa4, 0x92, 0x3a, 0x75, 0x1f, 0xd3, 0x11, 0xbe, 0xff, 0xb6, 0xad, 0xb3, 0x68, 0xf1, 0x02, 0x94, - 0x29, 0xb9, 0x30, 0x9a, 0x7e, 0x41, 0x78, 0xb2, 0x43, 0x8f, 0xa4, 0x2e, 0x40, 0x69, 0x49, 0x32, - 0x4c, 0x84, 0x13, 0xdf, 0xf3, 0x93, 0x93, 0x52, 0x6a, 0x2d, 0xf5, 0x18, 0xcd, 0x6e, 0x1e, 0xdd, - 0x9e, 0xbf, 0xb8, 0x68, 0xa6, 0x87, 0xd7, 0xe9, 0x13, 0xc8, 0x53, 0x23, 0xf3, 0xc2, 0xd4, 0x97, - 0xcd, 0xf4, 0xa0, 0xe6, 0x79, 0xf6, 0x9c, 0x5e, 0x77, 0xd1, 0xe8, 0xde, 0x46, 0x7c, 0xb9, 0xd5, - 0xf6, 0x31, 0xb1, 0x65, 0xde, 0xf0, 0x92, 0xe7, 0x3a, 0x92, 0xa7, 0x95, 0xd4, 0x86, 0x72, 0x57, - 0x7d, 0xa3, 0xba, 0x6a, 0xaf, 0xf1, 0xb0, 0xb0, 0xca, 0x18, 0xcd, 0xd0, 0xd1, 0x9d, 0xe3, 0x51, - 0xd0, 0x5b, 0x71, 0xd0, 0xd9, 0xe7, 0x93, 0x8b, 0x66, 0xea, 0x8c, 0x97, 0xcd, 0x74, 0xaf, 0xeb, - 0xd3, 0xbd, 0xd3, 0xc8, 0x81, 0xe3, 0x3f, 0x08, 0xdf, 0xb2, 0x19, 0xe4, 0x0c, 0xe1, 0xbb, 0xfd, - 0x5d, 0x10, 0x7a, 0x65, 0xf0, 0x8e, 0x7d, 0x79, 0x8f, 0xff, 0xef, 0xd9, 0x14, 0xa7, 0xb3, 0xb3, - 0x1f, 0xbf, 0xbf, 0xdd, 0xf0, 0xc8, 0x98, 0xf5, 0x7f, 0x98, 0xd8, 0x26, 0x2a, 0x3c, 0xec, 0xda, - 0x93, 0x47, 0xbb, 0xe6, 0xf6, 0xd6, 0xe3, 0xd1, 0x7f, 0x59, 0x5c, 0xe4, 0x43, 0x1b, 0xf9, 0x80, - 0x8c, 0xae, 0x44, 0x76, 0xc7, 0x9f, 0xbf, 0xfa, 0xbe, 0xf2, 0xd1, 0xf9, 0xca, 0x47, 0xbf, 0x56, - 0x3e, 0xfa, 0xba, 0xf6, 0x07, 0xe7, 0x6b, 0x7f, 0xf0, 0x73, 0xed, 0x0f, 0xde, 0x3d, 0x4d, 0x52, - 0xf3, 0xa1, 0x8a, 0x03, 0x01, 0x39, 0x5b, 0xd8, 0xeb, 0xb7, 0x3d, 0x4f, 0x37, 0xea, 0xb3, 0x1b, - 0x66, 0xea, 0x42, 0xea, 0x78, 0x68, 0x2f, 0xdb, 0xb3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xdb, - 0x57, 0xe2, 0x8b, 0x09, 0x03, 0x00, 0x00, +func init() { proto.RegisterFile("terp/clock/v1/query.proto", fileDescriptor_06ba6c07aa2f39a1) } + +var fileDescriptor_06ba6c07aa2f39a1 = []byte{ + // 427 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xb1, 0x6f, 0xd3, 0x40, + 0x14, 0xc6, 0x73, 0x20, 0x22, 0x71, 0xa8, 0x48, 0x1c, 0x8d, 0x48, 0x9d, 0xe2, 0x84, 0x9b, 0x2a, + 0x04, 0x3e, 0xa5, 0x6c, 0x48, 0x0c, 0xa4, 0x0b, 0x62, 0x82, 0x8c, 0x2c, 0xe8, 0x72, 0x7d, 0x32, + 0x56, 0xe3, 0x7b, 0xee, 0xdd, 0x25, 0x90, 0xb5, 0x2b, 0x0b, 0x12, 0xff, 0x14, 0x63, 0x25, 0x16, + 0x26, 0x0b, 0x25, 0x4c, 0x1d, 0x3b, 0x33, 0x20, 0x9f, 0x2f, 0x95, 0xdc, 0x44, 0x74, 0x3b, 0x7f, + 0xbf, 0xef, 0xde, 0xf7, 0xf9, 0xd9, 0x74, 0xcf, 0x81, 0x29, 0x84, 0x9a, 0xa2, 0x3a, 0x11, 0xf3, + 0xa1, 0x38, 0x9d, 0x81, 0x59, 0x24, 0x85, 0x41, 0x87, 0x6c, 0xa7, 0x42, 0x89, 0x47, 0xc9, 0x7c, + 0x18, 0xed, 0xa6, 0x98, 0xa2, 0x27, 0xa2, 0x3a, 0xd5, 0xa6, 0x68, 0x3f, 0x45, 0x4c, 0xa7, 0x20, + 0x64, 0x91, 0x09, 0xa9, 0x35, 0x3a, 0xe9, 0x32, 0xd4, 0x36, 0xd0, 0x58, 0xa1, 0xcd, 0xd1, 0x8a, + 0x89, 0xb4, 0x20, 0xe6, 0xc3, 0x09, 0x38, 0x39, 0x14, 0x0a, 0x33, 0x1d, 0x78, 0xaf, 0x99, 0x9e, + 0x82, 0x06, 0x9b, 0x85, 0xcb, 0xbc, 0x43, 0x1f, 0xbe, 0xaf, 0xea, 0x1c, 0x55, 0xf8, 0x08, 0xb5, + 0x33, 0x52, 0x39, 0xcb, 0xbf, 0x12, 0xda, 0xdb, 0xa2, 0x8f, 0xc1, 0x16, 0xa8, 0x2d, 0xb0, 0x29, + 0x65, 0x2a, 0x88, 0x1f, 0xe5, 0xf1, 0xb1, 0x01, 0x6b, 0xc1, 0x76, 0xc9, 0xe0, 0xf6, 0xc1, 0xdd, + 0xd1, 0xab, 0x8b, 0xb2, 0xbf, 0xbf, 0x49, 0x9f, 0x61, 0x9e, 0x39, 0xc8, 0x0b, 0xb7, 0xb8, 0x2c, + 0xfb, 0x7b, 0x0b, 0x99, 0x4f, 0x5f, 0xf2, 0x4d, 0x17, 0x1f, 0x3f, 0x58, 0x8b, 0xaf, 0xaf, 0xb4, + 0x5d, 0xca, 0x7c, 0x99, 0x77, 0xd2, 0xc8, 0xdc, 0x8e, 0xe1, 0x74, 0x06, 0xd6, 0x71, 0x19, 0xaa, + 0xaf, 0xd5, 0x50, 0xed, 0x2d, 0x6d, 0x17, 0x5e, 0xe9, 0x92, 0x01, 0x39, 0xb8, 0x77, 0xd8, 0x49, + 0x1a, 0x2b, 0x4e, 0x6a, 0xfb, 0xa8, 0x77, 0x51, 0xf6, 0x83, 0xf1, 0xb2, 0xec, 0xef, 0xd4, 0x7d, + 0xea, 0x67, 0x3e, 0x0e, 0xe0, 0xf0, 0x2f, 0xa1, 0x77, 0x7c, 0x06, 0x3b, 0x23, 0xf4, 0x7e, 0x73, + 0x17, 0x8c, 0x5f, 0x1b, 0xbc, 0x65, 0x5f, 0xd1, 0xd3, 0x9b, 0x3d, 0xeb, 0xe2, 0x7c, 0x70, 0xf6, + 0xf3, 0xcf, 0xf7, 0x5b, 0x11, 0xeb, 0x8a, 0xe6, 0x07, 0x53, 0x57, 0x89, 0x9a, 0xb6, 0xeb, 0xf6, + 0xec, 0xc9, 0xb6, 0xb9, 0x8d, 0xf5, 0x44, 0xfc, 0x7f, 0x96, 0x10, 0xf9, 0xd8, 0x47, 0x3e, 0x62, + 0x9d, 0x6b, 0x91, 0xf5, 0xeb, 0x8f, 0xde, 0xfc, 0x58, 0xc6, 0xe4, 0x7c, 0x19, 0x93, 0xdf, 0xcb, + 0x98, 0x7c, 0x5b, 0xc5, 0xad, 0xf3, 0x55, 0xdc, 0xfa, 0xb5, 0x8a, 0x5b, 0x1f, 0x92, 0x34, 0x73, + 0x9f, 0x66, 0x93, 0x44, 0x61, 0xee, 0xaf, 0x6a, 0x70, 0x9f, 0xd1, 0x9c, 0xf8, 0xf3, 0x73, 0x85, + 0x06, 0xc4, 0x97, 0x30, 0xcd, 0x2d, 0x0a, 0xb0, 0x93, 0xb6, 0xff, 0xdb, 0x5e, 0xfc, 0x0b, 0x00, + 0x00, 0xff, 0xff, 0xda, 0x94, 0x2b, 0xdd, 0x0a, 0x03, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/clock/types/tx.pb.go b/x/clock/types/tx.pb.go index 4a188aa..c07bee4 100644 --- a/x/clock/types/tx.pb.go +++ b/x/clock/types/tx.pb.go @@ -47,7 +47,7 @@ func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } func (*MsgUpdateParams) ProtoMessage() {} func (*MsgUpdateParams) Descriptor() ([]byte, []int) { - return fileDescriptor_76642a1e9a85f94b, []int{0} + return fileDescriptor_ad9dd5417a79a74f, []int{0} } func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -101,7 +101,7 @@ func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } func (*MsgUpdateParamsResponse) ProtoMessage() {} func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_76642a1e9a85f94b, []int{1} + return fileDescriptor_ad9dd5417a79a74f, []int{1} } func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -135,12 +135,12 @@ func init() { proto.RegisterType((*MsgUpdateParamsResponse)(nil), "terp.clock.v1.MsgUpdateParamsResponse") } -func init() { proto.RegisterFile("terp/clock/v1/tx.proto", fileDescriptor_76642a1e9a85f94b) } +func init() { proto.RegisterFile("terp/clock/v1/tx.proto", fileDescriptor_ad9dd5417a79a74f) } -var fileDescriptor_76642a1e9a85f94b = []byte{ - // 333 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcb, 0x2a, 0xcd, 0xcb, - 0xd7, 0x4f, 0xce, 0xc9, 0x4f, 0xce, 0xd6, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, +var fileDescriptor_ad9dd5417a79a74f = []byte{ + // 334 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2b, 0x49, 0x2d, 0x2a, + 0xd0, 0x4f, 0xce, 0xc9, 0x4f, 0xce, 0xd6, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x05, 0x89, 0xeb, 0x81, 0xc5, 0xf5, 0xca, 0x0c, 0xa5, 0xc4, 0x93, 0xf3, 0x8b, 0x73, 0xf3, 0x8b, 0xf5, 0x73, 0x8b, 0xd3, 0x41, 0xca, 0x72, 0x8b, 0xd3, 0x21, 0xea, 0xa4, 0xa4, 0x51, 0xf5, 0xa7, 0xa7, 0xe6, 0xa5, 0x16, 0x67, 0x16, 0x43, 0x25, 0x45, 0xd2, 0xf3, 0xd3, @@ -154,12 +154,12 @@ var fileDescriptor_76642a1e9a85f94b = []byte{ 0xde, 0x89, 0xe5, 0xc4, 0x3d, 0x79, 0x86, 0x20, 0xa8, 0x52, 0x2b, 0xbe, 0xa6, 0xe7, 0x1b, 0xb4, 0x10, 0x86, 0x28, 0x49, 0x72, 0x89, 0xa3, 0xb9, 0x27, 0x28, 0xb5, 0xb8, 0x20, 0x3f, 0xaf, 0x38, 0xd5, 0x28, 0x96, 0x8b, 0xd9, 0xb7, 0x38, 0x5d, 0x28, 0x8c, 0x8b, 0x07, 0xc5, 0xb9, 0x72, 0x68, - 0xd6, 0xa0, 0x69, 0x97, 0x52, 0xc3, 0x2f, 0x0f, 0x33, 0xde, 0xc9, 0xfd, 0xc4, 0x23, 0x39, 0xc6, + 0xd6, 0xa0, 0x69, 0x97, 0x52, 0xc3, 0x2f, 0x0f, 0x33, 0xde, 0xc9, 0xe3, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, - 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0x74, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, - 0x73, 0xf5, 0x9d, 0xc1, 0x81, 0xe0, 0x9c, 0x9f, 0x57, 0x52, 0x94, 0x98, 0x5c, 0x52, 0xac, 0x0f, - 0x8e, 0xa0, 0x0a, 0x68, 0x14, 0x95, 0x54, 0x16, 0xa4, 0x16, 0x27, 0xb1, 0x81, 0x83, 0xd6, 0x18, - 0x10, 0x00, 0x00, 0xff, 0xff, 0xda, 0x7a, 0xd4, 0x12, 0xfd, 0x01, 0x00, 0x00, + 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0xf4, 0xd2, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, + 0x73, 0xf5, 0x41, 0x66, 0xe5, 0xa5, 0x96, 0x94, 0xe7, 0x17, 0x65, 0x83, 0xd9, 0xba, 0xc9, 0xf9, + 0x45, 0xa9, 0xfa, 0x15, 0xd0, 0x38, 0x2a, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x87, 0xad, + 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x12, 0xb9, 0xe4, 0x93, 0xfe, 0x01, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/globalfee/types/genesis.pb.go b/x/globalfee/types/genesis.pb.go index a478fad..9c91da8 100644 --- a/x/globalfee/types/genesis.pb.go +++ b/x/globalfee/types/genesis.pb.go @@ -5,22 +5,19 @@ package types import ( fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. -var ( - _ = proto.Marshal - _ = fmt.Errorf - _ = math.Inf -) +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. @@ -40,11 +37,9 @@ func (*GenesisState) ProtoMessage() {} func (*GenesisState) Descriptor() ([]byte, []int) { return fileDescriptor_015b3e8b7a7c65c5, []int{0} } - func (m *GenesisState) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } - func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) @@ -57,15 +52,12 @@ func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) return b[:n], nil } } - func (m *GenesisState) XXX_Merge(src proto.Message) { xxx_messageInfo_GenesisState.Merge(m, src) } - func (m *GenesisState) XXX_Size() int { return m.Size() } - func (m *GenesisState) XXX_DiscardUnknown() { xxx_messageInfo_GenesisState.DiscardUnknown(m) } @@ -95,11 +87,9 @@ func (*Params) ProtoMessage() {} func (*Params) Descriptor() ([]byte, []int) { return fileDescriptor_015b3e8b7a7c65c5, []int{1} } - func (m *Params) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } - func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { return xxx_messageInfo_Params.Marshal(b, m, deterministic) @@ -112,15 +102,12 @@ func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { return b[:n], nil } } - func (m *Params) XXX_Merge(src proto.Message) { xxx_messageInfo_Params.Merge(m, src) } - func (m *Params) XXX_Size() int { return m.Size() } - func (m *Params) XXX_DiscardUnknown() { xxx_messageInfo_Params.DiscardUnknown(m) } @@ -249,7 +236,6 @@ func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } - func (m *GenesisState) Size() (n int) { if m == nil { return 0 @@ -279,11 +265,9 @@ func (m *Params) Size() (n int) { func sovGenesis(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } - func sozGenesis(x uint64) (n int) { return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } - func (m *GenesisState) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -367,7 +351,6 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { } return nil } - func (m *Params) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -452,7 +435,6 @@ func (m *Params) Unmarshal(dAtA []byte) error { } return nil } - func skipGenesis(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/globalfee/types/query.pb.go b/x/globalfee/types/query.pb.go index b94a154..5b87eb6 100644 --- a/x/globalfee/types/query.pb.go +++ b/x/globalfee/types/query.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/gogoproto/gogoproto" @@ -19,14 +15,15 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. -var ( - _ = proto.Marshal - _ = fmt.Errorf - _ = math.Inf -) +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. @@ -36,7 +33,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // QueryMinimumGasPricesRequest is the request type for the // Query/MinimumGasPrices RPC method. -type QueryMinimumGasPricesRequest struct{} +type QueryMinimumGasPricesRequest struct { +} func (m *QueryMinimumGasPricesRequest) Reset() { *m = QueryMinimumGasPricesRequest{} } func (m *QueryMinimumGasPricesRequest) String() string { return proto.CompactTextString(m) } @@ -44,11 +42,9 @@ func (*QueryMinimumGasPricesRequest) ProtoMessage() {} func (*QueryMinimumGasPricesRequest) Descriptor() ([]byte, []int) { return fileDescriptor_12a736cede25d10a, []int{0} } - func (m *QueryMinimumGasPricesRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } - func (m *QueryMinimumGasPricesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { return xxx_messageInfo_QueryMinimumGasPricesRequest.Marshal(b, m, deterministic) @@ -61,15 +57,12 @@ func (m *QueryMinimumGasPricesRequest) XXX_Marshal(b []byte, deterministic bool) return b[:n], nil } } - func (m *QueryMinimumGasPricesRequest) XXX_Merge(src proto.Message) { xxx_messageInfo_QueryMinimumGasPricesRequest.Merge(m, src) } - func (m *QueryMinimumGasPricesRequest) XXX_Size() int { return m.Size() } - func (m *QueryMinimumGasPricesRequest) XXX_DiscardUnknown() { xxx_messageInfo_QueryMinimumGasPricesRequest.DiscardUnknown(m) } @@ -88,11 +81,9 @@ func (*QueryMinimumGasPricesResponse) ProtoMessage() {} func (*QueryMinimumGasPricesResponse) Descriptor() ([]byte, []int) { return fileDescriptor_12a736cede25d10a, []int{1} } - func (m *QueryMinimumGasPricesResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } - func (m *QueryMinimumGasPricesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { return xxx_messageInfo_QueryMinimumGasPricesResponse.Marshal(b, m, deterministic) @@ -105,15 +96,12 @@ func (m *QueryMinimumGasPricesResponse) XXX_Marshal(b []byte, deterministic bool return b[:n], nil } } - func (m *QueryMinimumGasPricesResponse) XXX_Merge(src proto.Message) { xxx_messageInfo_QueryMinimumGasPricesResponse.Merge(m, src) } - func (m *QueryMinimumGasPricesResponse) XXX_Size() int { return m.Size() } - func (m *QueryMinimumGasPricesResponse) XXX_DiscardUnknown() { xxx_messageInfo_QueryMinimumGasPricesResponse.DiscardUnknown(m) } @@ -165,10 +153,8 @@ var fileDescriptor_12a736cede25d10a = []byte{ } // Reference imports to suppress errors if they are not otherwise used. -var ( - _ context.Context - _ grpc.ClientConn -) +var _ context.Context +var _ grpc.ClientConn // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. @@ -206,7 +192,8 @@ type QueryServer interface { } // UnimplementedQueryServer can be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct{} +type UnimplementedQueryServer struct { +} func (*UnimplementedQueryServer) MinimumGasPrices(ctx context.Context, req *QueryMinimumGasPricesRequest) (*QueryMinimumGasPricesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method MinimumGasPrices not implemented") @@ -318,7 +305,6 @@ func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } - func (m *QueryMinimumGasPricesRequest) Size() (n int) { if m == nil { return 0 @@ -346,11 +332,9 @@ func (m *QueryMinimumGasPricesResponse) Size() (n int) { func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } - func sozQuery(x uint64) (n int) { return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } - func (m *QueryMinimumGasPricesRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -401,7 +385,6 @@ func (m *QueryMinimumGasPricesRequest) Unmarshal(dAtA []byte) error { } return nil } - func (m *QueryMinimumGasPricesResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -486,7 +469,6 @@ func (m *QueryMinimumGasPricesResponse) Unmarshal(dAtA []byte) error { } return nil } - func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/globalfee/types/query.pb.gw.go b/x/globalfee/types/query.pb.gw.go index 123396e..a7b2956 100644 --- a/x/globalfee/types/query.pb.gw.go +++ b/x/globalfee/types/query.pb.gw.go @@ -25,15 +25,13 @@ import ( ) // Suppress "imported and not used" errors -var ( - _ codes.Code - _ io.Reader - _ status.Status - _ = runtime.String - _ = utilities.NewDoubleArray - _ = descriptor.ForMessage - _ = metadata.Join -) +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join func request_Query_MinimumGasPrices_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryMinimumGasPricesRequest @@ -41,6 +39,7 @@ func request_Query_MinimumGasPrices_0(ctx context.Context, marshaler runtime.Mar msg, err := client.MinimumGasPrices(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err + } func local_request_Query_MinimumGasPrices_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { @@ -49,6 +48,7 @@ func local_request_Query_MinimumGasPrices_0(ctx context.Context, marshaler runti msg, err := server.MinimumGasPrices(ctx, &protoReq) return msg, metadata, err + } // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". @@ -56,6 +56,7 @@ func local_request_Query_MinimumGasPrices_0(ctx context.Context, marshaler runti // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + mux.Handle("GET", pattern_Query_MinimumGasPrices_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -76,6 +77,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv } forward_Query_MinimumGasPrices_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil @@ -118,6 +120,7 @@ func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in // "QueryClient" to call the correct interceptors. func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + mux.Handle("GET", pattern_Query_MinimumGasPrices_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -135,11 +138,16 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie } forward_Query_MinimumGasPrices_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } -var pattern_Query_MinimumGasPrices_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gaia", "globalfee", "v1beta1", "minimum_gas_prices"}, "", runtime.AssumeColonVerbOpt(false))) +var ( + pattern_Query_MinimumGasPrices_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gaia", "globalfee", "v1beta1", "minimum_gas_prices"}, "", runtime.AssumeColonVerbOpt(false))) +) -var forward_Query_MinimumGasPrices_0 = runtime.ForwardResponseMessage +var ( + forward_Query_MinimumGasPrices_0 = runtime.ForwardResponseMessage +) diff --git a/x/globalfee/types/tx.pb.go b/x/globalfee/types/tx.pb.go index c5d9b2c..5438344 100644 --- a/x/globalfee/types/tx.pb.go +++ b/x/globalfee/types/tx.pb.go @@ -6,10 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - _ "github.com/cosmos/cosmos-proto" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/gogoproto/gogoproto" @@ -18,14 +14,15 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. -var ( - _ = proto.Marshal - _ = fmt.Errorf - _ = math.Inf -) +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. @@ -51,11 +48,9 @@ func (*MsgUpdateParams) ProtoMessage() {} func (*MsgUpdateParams) Descriptor() ([]byte, []int) { return fileDescriptor_1b7ff262ac5784d9, []int{0} } - func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } - func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { return xxx_messageInfo_MsgUpdateParams.Marshal(b, m, deterministic) @@ -68,15 +63,12 @@ func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, err return b[:n], nil } } - func (m *MsgUpdateParams) XXX_Merge(src proto.Message) { xxx_messageInfo_MsgUpdateParams.Merge(m, src) } - func (m *MsgUpdateParams) XXX_Size() int { return m.Size() } - func (m *MsgUpdateParams) XXX_DiscardUnknown() { xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) } @@ -101,7 +93,8 @@ func (m *MsgUpdateParams) GetParams() Params { // MsgUpdateParams message. // // Since: cosmos-sdk 0.47 -type MsgUpdateParamsResponse struct{} +type MsgUpdateParamsResponse struct { +} func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } @@ -109,11 +102,9 @@ func (*MsgUpdateParamsResponse) ProtoMessage() {} func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { return fileDescriptor_1b7ff262ac5784d9, []int{1} } - func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) } - func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { return xxx_messageInfo_MsgUpdateParamsResponse.Marshal(b, m, deterministic) @@ -126,15 +117,12 @@ func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]b return b[:n], nil } } - func (m *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) } - func (m *MsgUpdateParamsResponse) XXX_Size() int { return m.Size() } - func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) } @@ -174,10 +162,8 @@ var fileDescriptor_1b7ff262ac5784d9 = []byte{ } // Reference imports to suppress errors if they are not otherwise used. -var ( - _ context.Context - _ grpc.ClientConn -) +var _ context.Context +var _ grpc.ClientConn // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. @@ -221,7 +207,8 @@ type MsgServer interface { } // UnimplementedMsgServer can be embedded to have forward compatible implementations. -type UnimplementedMsgServer struct{} +type UnimplementedMsgServer struct { +} func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") @@ -336,7 +323,6 @@ func encodeVarintTx(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } - func (m *MsgUpdateParams) Size() (n int) { if m == nil { return 0 @@ -364,11 +350,9 @@ func (m *MsgUpdateParamsResponse) Size() (n int) { func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } - func sozTx(x uint64) (n int) { return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } - func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -484,7 +468,6 @@ func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { } return nil } - func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -535,7 +518,6 @@ func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { } return nil } - func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From e5648d8b928513a9713dfb06be7e30b4dcf2ace3 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Tue, 17 Oct 2023 21:49:56 -0400 Subject: [PATCH 04/18] v4 upgrade logic --- app/app.go | 2 ++ app/upgrades/v4/constants.go | 7 ++++++- app/upgrades/v4/upgrade.go | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/app.go b/app/app.go index ff880f9..cfd9814 100644 --- a/app/app.go +++ b/app/app.go @@ -65,6 +65,7 @@ import ( "github.com/terpnetwork/terp-core/v2/app/openapiconsole" v2 "github.com/terpnetwork/terp-core/v2/app/upgrades/v2" v3 "github.com/terpnetwork/terp-core/v2/app/upgrades/v3" + v4 "github.com/terpnetwork/terp-core/v2/app/upgrades/v4" "github.com/terpnetwork/terp-core/v2/docs" "github.com/CosmWasm/wasmd/x/wasm" @@ -99,6 +100,7 @@ var ( Upgrades = []upgrades.Upgrade{ v2.Upgrade, v3.Upgrade, + v4.Upgrade, } ) diff --git a/app/upgrades/v4/constants.go b/app/upgrades/v4/constants.go index f60e754..740a241 100644 --- a/app/upgrades/v4/constants.go +++ b/app/upgrades/v4/constants.go @@ -4,6 +4,7 @@ import ( "github.com/terpnetwork/terp-core/v2/app/upgrades" store "github.com/cosmos/cosmos-sdk/store/types" + clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" ) // UpgradeName defines the on-chain upgrade name for the Terp v4 upgrade. @@ -12,5 +13,9 @@ const UpgradeName = "v4" var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, CreateUpgradeHandler: CreateV4UpgradeHandler, - StoreUpgrades: store.StoreUpgrades{}, + StoreUpgrades: store.StoreUpgrades{ + Added: []string{ + clocktypes.ModuleName, + }, + }, } diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go index 6004e2f..af9c505 100644 --- a/app/upgrades/v4/upgrade.go +++ b/app/upgrades/v4/upgrade.go @@ -6,6 +6,7 @@ import ( upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/terpnetwork/terp-core/v2/app/keepers" + clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" ) // CreateUpgradeHandler creates an SDK upgrade handler for v4 @@ -16,6 +17,11 @@ func CreateV4UpgradeHandler( ) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + // x/clock + if err := keepers.ClockKeeper.SetParams(ctx, clocktypes.DefaultParams()); err != nil { + return nil, err + } + return vm, nil } } From 98205191886a8c13d67862d2aa68aadd35b9267e Mon Sep 17 00:00:00 2001 From: hard-nett Date: Sun, 29 Oct 2023 05:20:12 -0400 Subject: [PATCH 05/18] global-fee param update, cosmwasm1_3 capability, headstash-patch --- app/keepers/keepers.go | 2 +- app/upgrades/v4/headstash-patch.go | 51 ++++++++++++++++++++++++++++++ app/upgrades/v4/upgrade.go | 21 ++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 app/upgrades/v4/headstash-patch.go diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index c65d0f8..15b3e93 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -110,7 +110,7 @@ import ( ) var ( - wasmCapabilities = "iterator,staking,stargate,token_factory,cosmwasm_1_1,cosmwasm_1_2,tokenfactory" + wasmCapabilities = "iterator,staking,stargate,token_factory,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,tokenfactory" tokenFactoryCapabilities = []string{ tokenfactorytypes.EnableBurnFrom, diff --git a/app/upgrades/v4/headstash-patch.go b/app/upgrades/v4/headstash-patch.go new file mode 100644 index 0000000..1ad3b45 --- /dev/null +++ b/app/upgrades/v4/headstash-patch.go @@ -0,0 +1,51 @@ +package v4 + +import ( + "fmt" + "strconv" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + + "github.com/terpnetwork/terp-core/v2/app/upgrades" +) + + // revert headstash allocation by depositing funds back into community pool + func ReturnFundsToCommunityPool(ctx sdk.Context, dk keepers.DistrKeeper, bk keepers.BankKeeper) error { + + headstashes := GetHeadstashPayments() + + nativeDenom := upgrades.GetChainsDenomToken(ctx.ChainID()) + nativeFeeDenom := upgrades.GetChainsFeeDenomToken(ctx.ChainID()) + + for _, headstash := range headstashes { + addr, err := sdk.AccAddressFromBech32(headstash[0]) + if err != nil { + panic(err) + } + // defines the value associated with a given address + amount, err := strconv.ParseInt(strings.TrimSpace(headstash[1]), 10, 64) + if err != nil { + panic(err) + } + terpcoins := sdk.NewCoins( + sdk.NewInt64Coin(nativeDenom, amount), + ) + thiolcoins := sdk.NewCoins( + sdk.NewInt64Coin(nativeFeeDenom, amount), + ) + if err := dsk.FundCommunityPool(ctx, terpcoins, addr); err != nil { + panic(err) + } + if err := dsk.FundCommunityPool(ctx, thiolcoins, addr); err != nil { + panic(err) + } + total += amount + } + + } + + // TODO: handle headstash-patch contract upload & instantiation \ No newline at end of file diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go index af9c505..0447b6a 100644 --- a/app/upgrades/v4/upgrade.go +++ b/app/upgrades/v4/upgrade.go @@ -21,6 +21,27 @@ func CreateV4UpgradeHandler( if err := keepers.ClockKeeper.SetParams(ctx, clocktypes.DefaultParams()); err != nil { return nil, err } + // GlobalFee + nativeDenom := upgrades.GetChainsDenomToken(ctx.ChainID()) + nativeFeeDenom := upgrades.GetChainsFeeDenomToken(ctx.ChainID()) + minGasPrices := sdk.DecCoins{ + // 0.0025uterp + sdk.NewDecCoinFromDec(nativeDenom, sdk.NewDecWithPrec(25, 4)), + // 0.05uthiol + sdk.NewDecCoinFromDec(nativeFeeDenom, sdk.NewDecWithPrec(5, 2)), + } + newGlobalFeeParams := globalfeetypes.Params{ + MinimumGasPrices: minGasPrices, + } + if err := keepers.GlobalFeeKeeper.SetParams(ctx, newGlobalFeeParams); err != nil { + return nil, err + } + logger.Info(fmt.Sprintf("upgraded global fee params to %s", minGasPrices)) + + // revert headstash allocation + ReturnFundsToCommunityPool(ctx, keepers.BankKeeper, keepers.DistrKeeper) + + // TODO: handle deployment & instantiation of headstash patch contract return vm, nil } From 7a117b916ef9b46f459cf26d778da70b5aea10f7 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Tue, 31 Oct 2023 00:01:01 -0400 Subject: [PATCH 06/18] bump v4 upgrade --- app/upgrades/v4/headstash-patch.go | 75 ++++++++++++++++-------------- app/upgrades/v4/upgrade.go | 10 ++-- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/app/upgrades/v4/headstash-patch.go b/app/upgrades/v4/headstash-patch.go index 1ad3b45..56fcdc8 100644 --- a/app/upgrades/v4/headstash-patch.go +++ b/app/upgrades/v4/headstash-patch.go @@ -1,7 +1,6 @@ package v4 import ( - "fmt" "strconv" "strings" @@ -9,43 +8,49 @@ import ( bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" - "github.com/terpnetwork/terp-core/v2/app/upgrades" + + v3 "github.com/terpnetwork/terp-core/v2/app/upgrades/v3" ) - // revert headstash allocation by depositing funds back into community pool - func ReturnFundsToCommunityPool(ctx sdk.Context, dk keepers.DistrKeeper, bk keepers.BankKeeper) error { - - headstashes := GetHeadstashPayments() - - nativeDenom := upgrades.GetChainsDenomToken(ctx.ChainID()) - nativeFeeDenom := upgrades.GetChainsFeeDenomToken(ctx.ChainID()) - - for _, headstash := range headstashes { - addr, err := sdk.AccAddressFromBech32(headstash[0]) - if err != nil { - panic(err) - } - // defines the value associated with a given address - amount, err := strconv.ParseInt(strings.TrimSpace(headstash[1]), 10, 64) - if err != nil { - panic(err) - } - terpcoins := sdk.NewCoins( - sdk.NewInt64Coin(nativeDenom, amount), - ) - thiolcoins := sdk.NewCoins( - sdk.NewInt64Coin(nativeFeeDenom, amount), - ) - if err := dsk.FundCommunityPool(ctx, terpcoins, addr); err != nil { - panic(err) - } - if err := dsk.FundCommunityPool(ctx, thiolcoins, addr); err != nil { - panic(err) - } - total += amount - } +// revert headstash allocation by depositing funds back into community pool +func ReturnFundsToCommunityPool( + ctx sdk.Context, + dk distrkeeper.Keeper, + bk bankkeeper.Keeper, +) { + + headstashes := v3.GetHeadstashPayments() + total := int64(0) + + nativeDenom := upgrades.GetChainsDenomToken(ctx.ChainID()) + nativeFeeDenom := upgrades.GetChainsFeeDenomToken(ctx.ChainID()) + for _, headstash := range headstashes { + addr, err := sdk.AccAddressFromBech32(headstash[0]) + if err != nil { + panic(err) + } + // defines the value associated with a given address + amount, err := strconv.ParseInt(strings.TrimSpace(headstash[1]), 10, 64) + if err != nil { + panic(err) + } + terpcoins := sdk.NewCoins( + sdk.NewInt64Coin(nativeDenom, amount), + ) + thiolcoins := sdk.NewCoins( + sdk.NewInt64Coin(nativeFeeDenom, amount), + ) + if err := dk.FundCommunityPool(ctx, terpcoins, addr); err != nil { + panic(err) + } + if err := dk.FundCommunityPool(ctx, thiolcoins, addr); err != nil { + panic(err) + } + total += amount } - // TODO: handle headstash-patch contract upload & instantiation \ No newline at end of file +} + +// TODO: handle headstash-patch contract upload & instantiation diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go index 0447b6a..6f03ae2 100644 --- a/app/upgrades/v4/upgrade.go +++ b/app/upgrades/v4/upgrade.go @@ -1,12 +1,16 @@ package v4 import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/terpnetwork/terp-core/v2/app/keepers" + "github.com/terpnetwork/terp-core/v2/app/upgrades" clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + globalfeetypes "github.com/terpnetwork/terp-core/v2/x/globalfee/types" ) // CreateUpgradeHandler creates an SDK upgrade handler for v4 @@ -16,7 +20,7 @@ func CreateV4UpgradeHandler( keepers *keepers.AppKeepers, ) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { - + logger := ctx.Logger().With("upgrade", UpgradeName) // x/clock if err := keepers.ClockKeeper.SetParams(ctx, clocktypes.DefaultParams()); err != nil { return nil, err @@ -38,8 +42,8 @@ func CreateV4UpgradeHandler( } logger.Info(fmt.Sprintf("upgraded global fee params to %s", minGasPrices)) - // revert headstash allocation - ReturnFundsToCommunityPool(ctx, keepers.BankKeeper, keepers.DistrKeeper) + // revert headstash allocation + ReturnFundsToCommunityPool(ctx, keepers.DistrKeeper, keepers.BankKeeper) // TODO: handle deployment & instantiation of headstash patch contract From 2a2bff431c1ceafaff06c31ec13fc5c1e8d8efcb Mon Sep 17 00:00:00 2001 From: hard-nett Date: Tue, 31 Oct 2023 03:07:20 -0400 Subject: [PATCH 07/18] remove x/clock for now --- Makefile | 4 +- app/keepers/keepers.go | 22 +- app/keepers/keys.go | 4 +- app/modules.go | 15 +- app/upgrades/v4/constants.go | 7 +- app/upgrades/v4/upgrade.go | 6 +- interchaintest/module_clock_test.go | 126 ++-- interchaintest/setup.go | 4 +- x/clock/README.md | 5 - x/clock/abci.go | 42 -- x/clock/client/cli/query.go | 73 --- x/clock/genesis.go | 61 -- x/clock/genesis_test.go | 107 ---- x/clock/keeper/keeper.go | 70 --- x/clock/keeper/keeper_test.go | 59 -- x/clock/keeper/msg_server.go | 39 -- x/clock/keeper/msg_server_test.go | 72 --- x/clock/keeper/querier.go | 43 -- x/clock/keeper/querier_test.go | 60 -- x/clock/module.go | 149 ----- x/clock/spec/01_authorization.md | 39 -- x/clock/spec/02_integration.md | 56 -- x/clock/spec/README.md | 14 - x/clock/types/codec.go | 44 -- x/clock/types/codec_test.go | 30 - x/clock/types/genesis.pb.go | 542 ----------------- x/clock/types/keys.go | 11 - x/clock/types/msgs.go | 55 -- x/clock/types/msgs_test.go | 40 -- x/clock/types/params.go | 65 -- x/clock/types/params_test.go | 44 -- x/clock/types/query.pb.go | 884 ---------------------------- x/clock/types/query.pb.gw.go | 218 ------- x/clock/types/tx.pb.go | 605 ------------------- 34 files changed, 90 insertions(+), 3525 deletions(-) delete mode 100644 x/clock/README.md delete mode 100644 x/clock/abci.go delete mode 100644 x/clock/client/cli/query.go delete mode 100644 x/clock/genesis.go delete mode 100644 x/clock/genesis_test.go delete mode 100644 x/clock/keeper/keeper.go delete mode 100644 x/clock/keeper/keeper_test.go delete mode 100644 x/clock/keeper/msg_server.go delete mode 100644 x/clock/keeper/msg_server_test.go delete mode 100644 x/clock/keeper/querier.go delete mode 100644 x/clock/keeper/querier_test.go delete mode 100644 x/clock/module.go delete mode 100644 x/clock/spec/01_authorization.md delete mode 100644 x/clock/spec/02_integration.md delete mode 100644 x/clock/spec/README.md delete mode 100644 x/clock/types/codec.go delete mode 100644 x/clock/types/codec_test.go delete mode 100644 x/clock/types/genesis.pb.go delete mode 100644 x/clock/types/keys.go delete mode 100644 x/clock/types/msgs.go delete mode 100644 x/clock/types/msgs_test.go delete mode 100644 x/clock/types/params.go delete mode 100644 x/clock/types/params_test.go delete mode 100644 x/clock/types/query.pb.go delete mode 100644 x/clock/types/query.pb.gw.go delete mode 100644 x/clock/types/tx.pb.go diff --git a/Makefile b/Makefile index 1066133..e143904 100644 --- a/Makefile +++ b/Makefile @@ -210,8 +210,8 @@ ictest-tokenfactory: rm-testcache ictest-burn: rm-testcache cd interchaintest && go test -race -v -run TestTerpBurnModule . -ictest-clock: rm-testcache - cd interchaintest && go test -race -v -run TestTerpClock . +# ictest-clock: rm-testcache +# cd interchaintest && go test -race -v -run TestTerpClock . ictest-feeshare: rm-testcache cd interchaintest && go test -race -v -run TestTerpFeeShare . diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 15b3e93..879ef57 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -93,8 +93,8 @@ import ( upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" denomburn "github.com/terpnetwork/terp-core/v2/x/burn" - clockkeeper "github.com/terpnetwork/terp-core/v2/x/clock/keeper" - clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + // clockkeeper "github.com/terpnetwork/terp-core/v2/x/clock/keeper" + // clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" feesharekeeper "github.com/terpnetwork/terp-core/v2/x/feeshare/keeper" feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" @@ -175,9 +175,9 @@ type AppKeepers struct { PacketForwardKeeper *packetforwardkeeper.Keeper ICQKeeper icqkeeper.Keeper ICAHostKeeper icahostkeeper.Keeper - ClockKeeper clockkeeper.Keeper - TransferKeeper ibctransferkeeper.Keeper - WasmKeeper wasmkeeper.Keeper + // ClockKeeper clockkeeper.Keeper + TransferKeeper ibctransferkeeper.Keeper + WasmKeeper wasmkeeper.Keeper ScopedIBCKeeper capabilitykeeper.ScopedKeeper ScopedICAHostKeeper capabilitykeeper.ScopedKeeper @@ -575,12 +575,12 @@ func NewAppKeepers( appKeepers.keys[globalfeetypes.StoreKey], govModAddress, ) - appKeepers.ClockKeeper = clockkeeper.NewKeeper( - appKeepers.keys[clocktypes.StoreKey], - appCodec, - *appKeepers.ContractKeeper, - govModAddress, - ) + // appKeepers.ClockKeeper = clockkeeper.NewKeeper( + // appKeepers.keys[clocktypes.StoreKey], + // appCodec, + // *appKeepers.ContractKeeper, + // govModAddress, + // ) // The gov proposal types can be individually enabled if len(enabledProposals) != 0 { diff --git a/app/keepers/keys.go b/app/keepers/keys.go index 5bd4040..6df5867 100644 --- a/app/keepers/keys.go +++ b/app/keepers/keys.go @@ -34,7 +34,7 @@ import ( icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v7/types" ibchookstypes "github.com/cosmos/ibc-apps/modules/ibc-hooks/v7/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" - clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + // clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" ) func (appKeepers *AppKeepers) GenerateKeys() { @@ -68,7 +68,7 @@ func (appKeepers *AppKeepers) GenerateKeys() { ibchookstypes.StoreKey, feesharetypes.StoreKey, globalfeetypes.StoreKey, - clocktypes.StoreKey, + // clocktypes.StoreKey, tokenfactorytypes.StoreKey, ) diff --git a/app/modules.go b/app/modules.go index c090562..46d1f0b 100644 --- a/app/modules.go +++ b/app/modules.go @@ -19,8 +19,9 @@ import ( ibc "github.com/cosmos/ibc-go/v7/modules/core" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - "github.com/terpnetwork/terp-core/v2/x/clock" - clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + + // "github.com/terpnetwork/terp-core/v2/x/clock" + // clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" @@ -109,7 +110,7 @@ var ModuleBasics = module.NewBasicManager( packetforward.AppModuleBasic{}, feeshare.AppModuleBasic{}, globalfee.AppModuleBasic{}, - clock.AppModuleBasic{}, + // clock.AppModuleBasic{}, tokenfactory.AppModuleBasic{}, ) @@ -156,7 +157,7 @@ func appModules( ica.NewAppModule(&app.AppKeepers.ICAControllerKeeper, &app.AppKeepers.ICAHostKeeper), icq.NewAppModule(app.AppKeepers.ICQKeeper), packetforward.NewAppModule(app.AppKeepers.PacketForwardKeeper), - clock.NewAppModule(appCodec, app.AppKeepers.ClockKeeper), + // clock.NewAppModule(appCodec, app.AppKeepers.ClockKeeper), ibchooks.NewAppModule(app.AppKeepers.AccountKeeper), crisis.NewAppModule(app.AppKeepers.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)), // always be last to make sure that it checks for all invariants and not only part of them } @@ -222,7 +223,7 @@ func orderBeginBlockers() []string { packetforwardtypes.ModuleName, feesharetypes.ModuleName, globalfee.ModuleName, - clocktypes.ModuleName, + // clocktypes.ModuleName, ibchookstypes.ModuleName, tokenfactorytypes.ModuleName, wasmtypes.ModuleName, @@ -259,7 +260,7 @@ func orderEndBlockers() []string { packetforwardtypes.ModuleName, feesharetypes.ModuleName, globalfee.ModuleName, - clocktypes.ModuleName, + // clocktypes.ModuleName, ibchookstypes.ModuleName, tokenfactorytypes.ModuleName, wasmtypes.ModuleName, @@ -285,7 +286,7 @@ func orderInitBlockers() []string { packetforwardtypes.ModuleName, ibchookstypes.ModuleName, tokenfactorytypes.ModuleName, - clocktypes.ModuleName, + // clocktypes.ModuleName, wasmtypes.ModuleName, } } diff --git a/app/upgrades/v4/constants.go b/app/upgrades/v4/constants.go index 740a241..f60e754 100644 --- a/app/upgrades/v4/constants.go +++ b/app/upgrades/v4/constants.go @@ -4,7 +4,6 @@ import ( "github.com/terpnetwork/terp-core/v2/app/upgrades" store "github.com/cosmos/cosmos-sdk/store/types" - clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" ) // UpgradeName defines the on-chain upgrade name for the Terp v4 upgrade. @@ -13,9 +12,5 @@ const UpgradeName = "v4" var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, CreateUpgradeHandler: CreateV4UpgradeHandler, - StoreUpgrades: store.StoreUpgrades{ - Added: []string{ - clocktypes.ModuleName, - }, - }, + StoreUpgrades: store.StoreUpgrades{}, } diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go index 6f03ae2..3678d57 100644 --- a/app/upgrades/v4/upgrade.go +++ b/app/upgrades/v4/upgrade.go @@ -9,7 +9,6 @@ import ( "github.com/terpnetwork/terp-core/v2/app/keepers" "github.com/terpnetwork/terp-core/v2/app/upgrades" - clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" globalfeetypes "github.com/terpnetwork/terp-core/v2/x/globalfee/types" ) @@ -21,10 +20,7 @@ func CreateV4UpgradeHandler( ) upgradetypes.UpgradeHandler { return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { logger := ctx.Logger().With("upgrade", UpgradeName) - // x/clock - if err := keepers.ClockKeeper.SetParams(ctx, clocktypes.DefaultParams()); err != nil { - return nil, err - } + // GlobalFee nativeDenom := upgrades.GetChainsDenomToken(ctx.ChainID()) nativeFeeDenom := upgrades.GetChainsFeeDenomToken(ctx.ChainID()) diff --git a/interchaintest/module_clock_test.go b/interchaintest/module_clock_test.go index 9abd76a..f0b97cf 100644 --- a/interchaintest/module_clock_test.go +++ b/interchaintest/module_clock_test.go @@ -1,85 +1,85 @@ package interchaintest -import ( - "context" - "fmt" - "testing" +// import ( +// "context" +// "fmt" +// "testing" - cosmosproto "github.com/cosmos/gogoproto/proto" - "github.com/strangelove-ventures/interchaintest/v7" - "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" - "github.com/strangelove-ventures/interchaintest/v7/ibc" - "github.com/strangelove-ventures/interchaintest/v7/testutil" - "github.com/stretchr/testify/require" - clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" +// cosmosproto "github.com/cosmos/gogoproto/proto" +// "github.com/strangelove-ventures/interchaintest/v7" +// "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" +// "github.com/strangelove-ventures/interchaintest/v7/ibc" +// "github.com/strangelove-ventures/interchaintest/v7/testutil" +// "github.com/stretchr/testify/require" +// clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" - helpers "github.com/terpnetwork/terp-core/tests/interchaintest/helpers" -) +// helpers "github.com/terpnetwork/terp-core/tests/interchaintest/helpers" +// ) -// TestJunoClock ensures the clock module auto executes allowed contracts. -func TestTerpClock(t *testing.T) { - t.Parallel() +// // TestJunoClock ensures the clock module auto executes allowed contracts. +// func TestTerpClock(t *testing.T) { +// t.Parallel() - cfg := terpConfig +// cfg := terpConfig - // Base setup - chains := CreateChainWithCustomConfig(t, 1, 0, cfg) - ic, ctx, _, _ := BuildInitialChain(t, chains) +// // Base setup +// chains := CreateChainWithCustomConfig(t, 1, 0, cfg) +// ic, ctx, _, _ := BuildInitialChain(t, chains) - // Chains - terp := chains[0].(*cosmos.CosmosChain) +// // Chains +// terp := chains[0].(*cosmos.CosmosChain) - // Users - users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), terp, terp) - user := users[0] +// // Users +// users := interchaintest.GetAndFundTestUsers(t, ctx, "default", int64(10_000_000_000), terp, terp) +// user := users[0] - // Upload & init contract payment to another address - _, contractAddr := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/clock_example.wasm", `{}`) +// // Upload & init contract payment to another address +// _, contractAddr := helpers.SetupContract(t, ctx, terp, user.KeyName(), "contracts/clock_example.wasm", `{}`) - // Ensure config is 0 - res := helpers.GetClockContractValue(t, ctx, terp, contractAddr) - fmt.Printf("- res: %v\n", res.Data.Val) - require.Equal(t, uint32(0), res.Data.Val) +// // Ensure config is 0 +// res := helpers.GetClockContractValue(t, ctx, terp, contractAddr) +// fmt.Printf("- res: %v\n", res.Data.Val) +// require.Equal(t, uint32(0), res.Data.Val) - // Submit the proposal to add it to the allowed contracts list - SubmitParamChangeProp(t, ctx, terp, user, []string{contractAddr}) +// // Submit the proposal to add it to the allowed contracts list +// SubmitParamChangeProp(t, ctx, terp, user, []string{contractAddr}) - // Wait 1 block - _ = testutil.WaitForBlocks(ctx, 1, terp) +// // Wait 1 block +// _ = testutil.WaitForBlocks(ctx, 1, terp) - // Validate the contract is now auto incrementing from the end blocker - res = helpers.GetClockContractValue(t, ctx, terp, contractAddr) - fmt.Printf("- res: %v\n", res.Data.Val) - require.GreaterOrEqual(t, res.Data.Val, uint32(1)) +// // Validate the contract is now auto incrementing from the end blocker +// res = helpers.GetClockContractValue(t, ctx, terp, contractAddr) +// fmt.Printf("- res: %v\n", res.Data.Val) +// require.GreaterOrEqual(t, res.Data.Val, uint32(1)) - t.Cleanup(func() { - _ = ic.Close() - }) -} +// t.Cleanup(func() { +// _ = ic.Close() +// }) +// } -func SubmitParamChangeProp(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contracts []string) string { - govAcc := "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq" - updateParams := []cosmosproto.Message{ - &clocktypes.MsgUpdateParams{ - Authority: govAcc, - Params: clocktypes.NewParams(contracts, 1_000_000_000), - }, - } +// func SubmitParamChangeProp(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet, contracts []string) string { +// govAcc := "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq" +// updateParams := []cosmosproto.Message{ +// &clocktypes.MsgUpdateParams{ +// Authority: govAcc, +// Params: clocktypes.NewParams(contracts, 1_000_000_000), +// }, +// } - proposal, err := chain.BuildProposal(updateParams, "Params Add Contract", "params", "ipfs://CID", fmt.Sprintf(`500000000%s`, chain.Config().Denom)) - require.NoError(t, err, "error building proposal") +// proposal, err := chain.BuildProposal(updateParams, "Params Add Contract", "params", "ipfs://CID", fmt.Sprintf(`500000000%s`, chain.Config().Denom)) +// require.NoError(t, err, "error building proposal") - txProp, err := chain.SubmitProposal(ctx, user.KeyName(), proposal) - t.Log("txProp", txProp) - require.NoError(t, err, "error submitting proposal") +// txProp, err := chain.SubmitProposal(ctx, user.KeyName(), proposal) +// t.Log("txProp", txProp) +// require.NoError(t, err, "error submitting proposal") - height, _ := chain.Height(ctx) +// height, _ := chain.Height(ctx) - err = chain.VoteOnProposalAllValidators(ctx, txProp.ProposalID, cosmos.ProposalVoteYes) - require.NoError(t, err, "failed to submit votes") +// err = chain.VoteOnProposalAllValidators(ctx, txProp.ProposalID, cosmos.ProposalVoteYes) +// require.NoError(t, err, "failed to submit votes") - _, err = cosmos.PollForProposalStatus(ctx, chain, height, height+haltHeightDelta, txProp.ProposalID, cosmos.ProposalStatusPassed) - require.NoError(t, err, "proposal status did not change to passed in expected number of blocks") +// _, err = cosmos.PollForProposalStatus(ctx, chain, height, height+haltHeightDelta, txProp.ProposalID, cosmos.ProposalStatusPassed) +// require.NoError(t, err, "proposal status did not change to passed in expected number of blocks") - return txProp.ProposalID -} +// return txProp.ProposalID +// } diff --git a/interchaintest/setup.go b/interchaintest/setup.go index 03e8b97..89ad11b 100644 --- a/interchaintest/setup.go +++ b/interchaintest/setup.go @@ -15,7 +15,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" - clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + // clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" tokenfactorytypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" @@ -94,7 +94,7 @@ func terpEncoding() *testutil.TestEncodingConfig { wasmtypes.RegisterInterfaces(cfg.InterfaceRegistry) feesharetypes.RegisterInterfaces(cfg.InterfaceRegistry) tokenfactorytypes.RegisterInterfaces(cfg.InterfaceRegistry) - clocktypes.RegisterInterfaces(cfg.InterfaceRegistry) + // clocktypes.RegisterInterfaces(cfg.InterfaceRegistry) // github.com/cosmos/cosmos-sdk/types/module/testutil diff --git a/x/clock/README.md b/x/clock/README.md deleted file mode 100644 index ba05f64..0000000 --- a/x/clock/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Clock - -This module allows smart contracts to execute logic at the end of every block without an external bot. - -[Clock Spec](./spec/README.md) diff --git a/x/clock/abci.go b/x/clock/abci.go deleted file mode 100644 index 4c21539..0000000 --- a/x/clock/abci.go +++ /dev/null @@ -1,42 +0,0 @@ -package clock - -import ( - "log" - "time" - - "github.com/cosmos/cosmos-sdk/telemetry" - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/terpnetwork/terp-core/v2/x/clock/keeper" - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -// EndBlocker executes on contracts at the end of the block. -func EndBlocker(ctx sdk.Context, k keeper.Keeper) { - defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) - - message := []byte(types.EndBlockSudoMessage) - - p := k.GetParams(ctx) - - errorExecs := make([]string, len(p.ContractAddresses)) - - for idx, addr := range p.ContractAddresses { - contract, err := sdk.AccAddressFromBech32(addr) - if err != nil { - errorExecs[idx] = addr - continue - } - - childCtx := ctx.WithGasMeter(sdk.NewGasMeter(p.ContractGasLimit)) - _, err = k.GetContractKeeper().Sudo(childCtx, contract, message) - if err != nil { - errorExecs[idx] = addr - continue - } - } - - if len(errorExecs) > 0 { - log.Printf("[x/clock] Execute Errors: %v", errorExecs) - } -} diff --git a/x/clock/client/cli/query.go b/x/clock/client/cli/query.go deleted file mode 100644 index 2eb1f66..0000000 --- a/x/clock/client/cli/query.go +++ /dev/null @@ -1,73 +0,0 @@ -package cli - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -func GetQueryCmd() *cobra.Command { - queryCmd := &cobra.Command{ - Use: types.ModuleName, - Short: "Querying commands for cosmwasm modules", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - queryCmd.AddCommand( - GetCmdShowContracts(), - GetCmdParams(), - ) - return queryCmd -} - -func GetCmdShowContracts() *cobra.Command { - cmd := &cobra.Command{ - Use: "contracts", - Short: "Show addresses of all current contract modules", - Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - - queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.ClockContracts(cmd.Context(), &types.QueryClockContracts{}) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - flags.AddQueryFlagsToCmd(cmd) - return cmd -} - -func GetCmdParams() *cobra.Command { - cmd := &cobra.Command{ - Use: "params", - Short: "Show all module params", - Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - - queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - flags.AddQueryFlagsToCmd(cmd) - return cmd -} diff --git a/x/clock/genesis.go b/x/clock/genesis.go deleted file mode 100644 index 7692e4b..0000000 --- a/x/clock/genesis.go +++ /dev/null @@ -1,61 +0,0 @@ -package clock - -import ( - "encoding/json" - - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/terpnetwork/terp-core/v2/x/clock/keeper" - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -// NewGenesisState - Create a new genesis state -func NewGenesisState(params types.Params) *types.GenesisState { - return &types.GenesisState{ - Params: params, - } -} - -// DefaultGenesisState - Return a default genesis state -func DefaultGenesisState() *types.GenesisState { - return NewGenesisState(types.DefaultParams()) -} - -// GetGenesisStateFromAppState returns x/auth GenesisState given raw application -// genesis state. -func GetGenesisStateFromAppState(cdc codec.Codec, appState map[string]json.RawMessage) *types.GenesisState { - var genesisState types.GenesisState - - if appState[ModuleName] != nil { - cdc.MustUnmarshalJSON(appState[ModuleName], &genesisState) - } - - return &genesisState -} - -func ValidateGenesis(data types.GenesisState) error { - return data.Params.Validate() -} - -// InitGenesis import module genesis -func InitGenesis( - ctx sdk.Context, - k keeper.Keeper, - data types.GenesisState, -) { - if err := ValidateGenesis(data); err != nil { - panic(err) - } - - if err := k.SetParams(ctx, data.Params); err != nil { - panic(err) - } -} - -// ExportGenesis export module state -func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { - return &types.GenesisState{ - Params: k.GetParams(ctx), - } -} diff --git a/x/clock/genesis_test.go b/x/clock/genesis_test.go deleted file mode 100644 index 96cdb60..0000000 --- a/x/clock/genesis_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package clock_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/suite" - - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - - "github.com/cosmos/cosmos-sdk/testutil/testdata" - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/terpnetwork/terp-core/v2/app" - clock "github.com/terpnetwork/terp-core/v2/x/clock" - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -type GenesisTestSuite struct { - suite.Suite - - ctx sdk.Context - - app *app.TerpApp -} - -func TestGenesisTestSuite(t *testing.T) { - suite.Run(t, new(GenesisTestSuite)) -} - -func (suite *GenesisTestSuite) SetupTest() { - app := app.Setup(suite.T()) - ctx := app.BaseApp.NewContext(false, tmproto.Header{ - ChainID: "testing", - }) - - suite.app = app - suite.ctx = ctx -} - -func (suite *GenesisTestSuite) TestClockInitGenesis() { - _, _, addr := testdata.KeyTestPubAddr() - _, _, addr2 := testdata.KeyTestPubAddr() - - defaultParams := types.DefaultParams() - - testCases := []struct { - name string - genesis types.GenesisState - expPanic bool - }{ - { - "default genesis", - *clock.DefaultGenesisState(), - false, - }, - { - "custom genesis - none", - types.GenesisState{ - Params: types.Params{ - ContractAddresses: []string(nil), - ContractGasLimit: defaultParams.ContractGasLimit, - }, - }, - false, - }, - { - "custom genesis - incorrect addr", - types.GenesisState{ - Params: types.Params{ - ContractAddresses: []string{"incorrectaddr"}, - ContractGasLimit: defaultParams.ContractGasLimit, - }, - }, - true, - }, - { - "custom genesis - only one addr allowed", - types.GenesisState{ - Params: types.Params{ - ContractAddresses: []string{addr.String(), addr2.String()}, - ContractGasLimit: defaultParams.ContractGasLimit, - }, - }, - false, - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Case %s", tc.name), func() { - suite.SetupTest() // reset - - if tc.expPanic { - suite.Require().Panics(func() { - clock.InitGenesis(suite.ctx, suite.app.AppKeepers.ClockKeeper, tc.genesis) - }) - } else { - suite.Require().NotPanics(func() { - clock.InitGenesis(suite.ctx, suite.app.AppKeepers.ClockKeeper, tc.genesis) - }) - - params := suite.app.AppKeepers.ClockKeeper.GetParams(suite.ctx) - suite.Require().Equal(tc.genesis.Params, params) - } - }) - } -} diff --git a/x/clock/keeper/keeper.go b/x/clock/keeper/keeper.go deleted file mode 100644 index 95c1589..0000000 --- a/x/clock/keeper/keeper.go +++ /dev/null @@ -1,70 +0,0 @@ -package keeper - -import ( - wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" - - "github.com/cosmos/cosmos-sdk/codec" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -// Keeper of the clock store -type Keeper struct { - storeKey storetypes.StoreKey - cdc codec.BinaryCodec - - contractKeeper wasmkeeper.PermissionedKeeper - - authority string -} - -func NewKeeper( - key storetypes.StoreKey, - cdc codec.BinaryCodec, - contractKeeper wasmkeeper.PermissionedKeeper, - authority string, -) Keeper { - return Keeper{ - cdc: cdc, - storeKey: key, - contractKeeper: contractKeeper, - authority: authority, - } -} - -// GetAuthority returns the x/clock module's authority. -func (k Keeper) GetAuthority() string { - return k.authority -} - -// SetParams sets the x/clock module parameters. -func (k Keeper) SetParams(ctx sdk.Context, p types.Params) error { - if err := p.Validate(); err != nil { - return err - } - - store := ctx.KVStore(k.storeKey) - bz := k.cdc.MustMarshal(&p) - store.Set(types.ParamsKey, bz) - - return nil -} - -// GetParams returns the current x/clock module parameters. -func (k Keeper) GetParams(ctx sdk.Context) (p types.Params) { - store := ctx.KVStore(k.storeKey) - bz := store.Get(types.ParamsKey) - if bz == nil { - return p - } - - k.cdc.MustUnmarshal(bz, &p) - return p -} - -// GetContractKeeper returns the x/wasm module's contract keeper. -func (k Keeper) GetContractKeeper() wasmkeeper.PermissionedKeeper { - return k.contractKeeper -} diff --git a/x/clock/keeper/keeper_test.go b/x/clock/keeper/keeper_test.go deleted file mode 100644 index 4b1520b..0000000 --- a/x/clock/keeper/keeper_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package keeper_test - -import ( - "testing" - "time" - - "github.com/stretchr/testify/suite" - - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - - "github.com/cosmos/cosmos-sdk/baseapp" - sdk "github.com/cosmos/cosmos-sdk/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - - "github.com/terpnetwork/terp-core/v2/app" - "github.com/terpnetwork/terp-core/v2/x/clock/keeper" - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -type IntegrationTestSuite struct { - suite.Suite - - ctx sdk.Context - app *app.TerpApp - bankKeeper bankkeeper.Keeper - queryClient types.QueryClient - clockMsgServer types.MsgServer -} - -func (s *IntegrationTestSuite) SetupTest() { - isCheckTx := false - s.app = app.Setup(s.T()) - - s.ctx = s.app.BaseApp.NewContext(isCheckTx, tmproto.Header{ - ChainID: "testing", - Height: 1, - Time: time.Now().UTC(), - }) - - queryHelper := baseapp.NewQueryServerTestHelper(s.ctx, s.app.InterfaceRegistry()) - types.RegisterQueryServer(queryHelper, keeper.NewQuerier(s.app.AppKeepers.ClockKeeper)) - - s.queryClient = types.NewQueryClient(queryHelper) - s.bankKeeper = s.app.AppKeepers.BankKeeper - s.clockMsgServer = keeper.NewMsgServerImpl(s.app.AppKeepers.ClockKeeper) -} - -func (s *IntegrationTestSuite) FundAccount(ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { - if err := s.bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { - return err - } - - return s.bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts) -} - -func TestKeeperTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/x/clock/keeper/msg_server.go b/x/clock/keeper/msg_server.go deleted file mode 100644 index a695d5b..0000000 --- a/x/clock/keeper/msg_server.go +++ /dev/null @@ -1,39 +0,0 @@ -package keeper - -import ( - "context" - - errorsmod "cosmossdk.io/errors" - - sdk "github.com/cosmos/cosmos-sdk/types" - govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -var _ types.MsgServer = &msgServer{} - -// msgServer is a wrapper of Keeper. -type msgServer struct { - Keeper -} - -// NewMsgServerImpl returns an implementation of the x/clock MsgServer interface. -func NewMsgServerImpl(k Keeper) types.MsgServer { - return &msgServer{ - Keeper: k, - } -} - -func (k msgServer) UpdateParams(goCtx context.Context, req *types.MsgUpdateParams) (*types.MsgUpdateParamsResponse, error) { - if k.authority != req.Authority { - return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.authority, req.Authority) - } - - ctx := sdk.UnwrapSDKContext(goCtx) - if err := k.SetParams(ctx, req.Params); err != nil { - return nil, err - } - - return &types.MsgUpdateParamsResponse{}, nil -} diff --git a/x/clock/keeper/msg_server_test.go b/x/clock/keeper/msg_server_test.go deleted file mode 100644 index 7344db6..0000000 --- a/x/clock/keeper/msg_server_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package keeper_test - -import ( - _ "embed" - - "github.com/cosmos/cosmos-sdk/testutil/testdata" - - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -func (s *IntegrationTestSuite) TestUpdateClockParams() { - _, _, addr := testdata.KeyTestPubAddr() - _, _, addr2 := testdata.KeyTestPubAddr() - - for _, tc := range []struct { - desc string - isEnabled bool - ContractAddresses []string - success bool - }{ - { - desc: "Success - Valid on", - isEnabled: true, - ContractAddresses: []string{}, - success: true, - }, - { - desc: "Success - Valid off", - isEnabled: false, - ContractAddresses: []string{}, - success: true, - }, - { - desc: "Success - On and 1 allowed address", - isEnabled: true, - ContractAddresses: []string{addr.String()}, - success: true, - }, - { - desc: "Fail - On and 2 duplicate addresses", - isEnabled: true, - ContractAddresses: []string{addr.String(), addr.String()}, - success: false, - }, - { - desc: "Success - On and 2 unique", - isEnabled: true, - ContractAddresses: []string{addr.String(), addr2.String()}, - success: true, - }, - { - desc: "Success - On and 2 duplicate 1 unique", - isEnabled: true, - ContractAddresses: []string{addr.String(), addr2.String(), addr.String()}, - success: false, - }, - } { - tc := tc - s.Run(tc.desc, func() { - params := types.DefaultParams() - params.ContractAddresses = tc.ContractAddresses - - err := s.app.AppKeepers.ClockKeeper.SetParams(s.ctx, params) - - if !tc.success { - s.Require().Error(err) - } else { - s.Require().NoError(err) - } - }) - } -} diff --git a/x/clock/keeper/querier.go b/x/clock/keeper/querier.go deleted file mode 100644 index a04cacd..0000000 --- a/x/clock/keeper/querier.go +++ /dev/null @@ -1,43 +0,0 @@ -package keeper - -import ( - "context" - - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -var _ types.QueryServer = &Querier{} - -type Querier struct { - keeper Keeper -} - -func NewQuerier(k Keeper) Querier { - return Querier{ - keeper: k, - } -} - -// ContractModules returns contract addresses which are using the clock -func (q Querier) ClockContracts(stdCtx context.Context, _ *types.QueryClockContracts) (*types.QueryClockContractsResponse, error) { - ctx := sdk.UnwrapSDKContext(stdCtx) - - p := q.keeper.GetParams(ctx) - - return &types.QueryClockContractsResponse{ - ContractAddresses: p.ContractAddresses, - }, nil -} - -// Params returns the total set of clock parameters. -func (q Querier) Params(stdCtx context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { - ctx := sdk.UnwrapSDKContext(stdCtx) - - p := q.keeper.GetParams(ctx) - - return &types.QueryParamsResponse{ - Params: &p, - }, nil -} diff --git a/x/clock/keeper/querier_test.go b/x/clock/keeper/querier_test.go deleted file mode 100644 index 5c651ae..0000000 --- a/x/clock/keeper/querier_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package keeper_test - -import ( - "github.com/cosmos/cosmos-sdk/testutil/testdata" - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -func (s *IntegrationTestSuite) TestClockQueryParams() { - _, _, addr := testdata.KeyTestPubAddr() - _, _, addr2 := testdata.KeyTestPubAddr() - - defaultParams := types.DefaultParams() - - for _, tc := range []struct { - desc string - Expected types.Params - }{ - { - desc: "On empty", - Expected: types.Params{ - ContractAddresses: []string(nil), - ContractGasLimit: defaultParams.ContractGasLimit, - }, - }, - { - desc: "On 1 address", - Expected: types.Params{ - ContractAddresses: []string{addr.String()}, - ContractGasLimit: defaultParams.ContractGasLimit, - }, - }, - { - desc: "On 2 Unique", - Expected: types.Params{ - ContractAddresses: []string{addr.String(), addr2.String()}, - ContractGasLimit: defaultParams.ContractGasLimit, - }, - }, - } { - tc := tc - s.Run(tc.desc, func() { - // Set the params to what is expected, then query and ensure the query is the same - err := s.app.AppKeepers.ClockKeeper.SetParams(s.ctx, tc.Expected) - s.Require().NoError(err) - - // Contracts check - goCtx := sdk.WrapSDKContext(s.ctx) - resp, err := s.queryClient.ClockContracts(goCtx, &types.QueryClockContracts{}) - s.Require().NoError(err) - s.Require().Equal(tc.Expected.ContractAddresses, resp.ContractAddresses) - - // All Params Check - resp2, err := s.queryClient.Params(goCtx, &types.QueryParamsRequest{}) - s.Require().NoError(err) - s.Require().Equal(tc.Expected, *resp2.Params) - }) - } -} diff --git a/x/clock/module.go b/x/clock/module.go deleted file mode 100644 index 1545408..0000000 --- a/x/clock/module.go +++ /dev/null @@ -1,149 +0,0 @@ -package clock - -import ( - "context" - "encoding/json" - - "github.com/gorilla/mux" - "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/spf13/cobra" - - abci "github.com/cometbft/cometbft/abci/types" - - errorsmod "cosmossdk.io/errors" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" - - "github.com/terpnetwork/terp-core/v2/x/clock/client/cli" - "github.com/terpnetwork/terp-core/v2/x/clock/keeper" - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -const ( - ModuleName = types.ModuleName - - // ConsensusVersion defines the current x/clock module consensus version. - ConsensusVersion = 1 -) - -var ( - _ module.AppModuleBasic = AppModuleBasic{} - _ module.AppModuleGenesis = AppModule{} - _ module.AppModule = AppModule{} -) - -// AppModuleBasic defines the basic application module used by the wasm module. -type AppModuleBasic struct { - cdc codec.Codec -} - -func (a AppModuleBasic) Name() string { - return types.ModuleName -} - -func (a AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { - return cdc.MustMarshalJSON(&types.GenesisState{ - Params: types.DefaultParams(), - }) -} - -func (a AppModuleBasic) ValidateGenesis(marshaler codec.JSONCodec, _ client.TxEncodingConfig, message json.RawMessage) error { - var data types.GenesisState - err := marshaler.UnmarshalJSON(message, &data) - if err != nil { - return err - } - if err := data.Params.Validate(); err != nil { - return errorsmod.Wrap(err, "params") - } - return nil -} - -func (a AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) { -} - -func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) { - err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) - if err != nil { - // same behavior as in cosmos-sdk - panic(err) - } -} - -func (a AppModuleBasic) GetTxCmd() *cobra.Command { - return nil -} - -func (a AppModuleBasic) GetQueryCmd() *cobra.Command { - return cli.GetQueryCmd() -} - -func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { - types.RegisterLegacyAminoCodec(cdc) -} - -func (a AppModuleBasic) RegisterInterfaces(r codectypes.InterfaceRegistry) { - types.RegisterInterfaces(r) -} - -type AppModule struct { - AppModuleBasic - - keeper keeper.Keeper -} - -// NewAppModule constructor -func NewAppModule( - cdc codec.Codec, - keeper keeper.Keeper, -) *AppModule { - return &AppModule{ - AppModuleBasic: AppModuleBasic{cdc: cdc}, - keeper: keeper, - } -} - -func (a AppModule) InitGenesis(ctx sdk.Context, marshaler codec.JSONCodec, message json.RawMessage) []abci.ValidatorUpdate { - var genesisState types.GenesisState - marshaler.MustUnmarshalJSON(message, &genesisState) - _ = a.keeper.SetParams(ctx, genesisState.Params) - return nil -} - -func (a AppModule) ExportGenesis(ctx sdk.Context, marshaler codec.JSONCodec) json.RawMessage { - params := a.keeper.GetParams(ctx) - genState := NewGenesisState(params) - return marshaler.MustMarshalJSON(genState) -} - -func (a AppModule) RegisterInvariants(_ sdk.InvariantRegistry) { -} - -func (a AppModule) QuerierRoute() string { - return types.QuerierRoute -} - -func (a AppModule) RegisterServices(cfg module.Configurator) { - types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(a.keeper)) - types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQuerier(a.keeper)) -} - -func (a AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) { -} - -func (a AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { - EndBlocker(ctx, a.keeper) - return nil -} - -// ConsensusVersion is a sequence number for state-breaking change of the -// module. It should be incremented on each consensus-breaking change -// introduced by the module. To avoid wrong/empty versions, the initial version -// should be set to 1. -func (a AppModule) ConsensusVersion() uint64 { - return ConsensusVersion -} diff --git a/x/clock/spec/01_authorization.md b/x/clock/spec/01_authorization.md deleted file mode 100644 index 8d88b80..0000000 --- a/x/clock/spec/01_authorization.md +++ /dev/null @@ -1,39 +0,0 @@ -# Authorization - -For security purposes, only the governance module can add new contracts to the EndBlocker executes. - -## Query contracts - -You can query the list of contracts that are 'ticked' every block with the following command: - -```bash - junod q clock contracts --output json - # {"contract_addresses":[]} -``` - -## Governance proposal - -To update the authorized address is possible to create an onchain new proposal. You can use the following example `proposal.json` file - -```json -{ - "messages": [ - { - "@type": "/terp.clock.v1.MsgUpdateParams", - "authority": "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq", - "params": { - "contract_addresses": [ - "juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8" - ], - "contract_gas_limit": "1000000" - } - } - ], - "metadata": "{\"title\": \"Allow a new contract to use the x/clock module for our features\", \"authors\": [\"Reece\"], \"summary\": \"If this proposal passes juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be added to the authorized addresses of the clock module\", \"details\": \"If this proposal passes juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be added to the authorized addresses of the clock module\", \"proposal_forum_url\": \"https://commonwealth.im/juno/discussion/9697-juno-protocol-level-defi-incentives\", \"vote_option_context\": \"yes\"}", - "deposit": "1000000ujuno", - "title": "Allow a new contract to use the x/clock module for our features", - "summary": "If this proposal passes juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8 will be allowed to use the x/clock module to perform XYZ actions" -} -``` - -It can be submitted with the standard `junod tx gov submit-proposal proposal.json --from=YOURKEY` command. diff --git a/x/clock/spec/02_integration.md b/x/clock/spec/02_integration.md deleted file mode 100644 index fa76463..0000000 --- a/x/clock/spec/02_integration.md +++ /dev/null @@ -1,56 +0,0 @@ -# CosmWasm Integration - -This module does not require any custom bindings. Rather, you must just add the following Sudo message to your contract. If your contract is not whitelisted, you can still upload it to the chain. However, to get it to execute, you must submit a proposal to add your contract to the whitelist. - -You can find a basic [cw-clock contract here](https://github.com/Reecepbcups/cw-clock-example) - -## Implementation - -Add the following to your Rust Contract: - -```rust -// msg.rs -#[cw_serde] -pub enum SudoMsg { - ClockEndBlock { }, -} - -// contract.rs -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> Result { - match msg { - SudoMsg::ClockEndBlock { } => { - let mut config = CONFIG.load(deps.storage)?; - config.val += 1; - CONFIG.save(deps.storage, &config)?; - - Ok(Response::new()) - } - } -} -``` - -Using the above example, for every block the module will increase the `val` Config variable by 1. This is a simple example, but you can use this to perform any action you want (ex: cleanup, auto compounding, etc). - -If you wish not to have your action performed every block, you can use the `env` variable in the Sudo message to check the block height and only perform an action every X blocks. - -```rust -// contract.rs -#[cfg_attr(not(feature = "library"), entry_point)] -pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result { - match msg { - SudoMsg::ClockEndBlock { } => { - // If the block is not divisible by ten, do nothing. - if env.block.height % 10 != 0 { - return Ok(Response::new()); - } - - let mut config = CONFIG.load(deps.storage)?; - config.val += 1; - CONFIG.save(deps.storage, &config)?; - - Ok(Response::new()) - } - } -} -``` diff --git a/x/clock/spec/README.md b/x/clock/spec/README.md deleted file mode 100644 index 982d7ec..0000000 --- a/x/clock/spec/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# `clock` - -## Abstract - -This document specifies the internal `x/clock` module of Juno Network. - -The `x/clock` module allows specific contracts to be executed at the end of every block. This allows the smart contract to perform actions that may need to happen every block, or at set block intervals. - -By using this module, your application can remove the headache of external whitelisted bots and instead depend on the chain itself for constant executions. - -## Contents - -1. **[Authorization](01_authorization.md)** -2. **[Contract Integration](02_integration.md)** diff --git a/x/clock/types/codec.go b/x/clock/types/codec.go deleted file mode 100644 index 46ccaa4..0000000 --- a/x/clock/types/codec.go +++ /dev/null @@ -1,44 +0,0 @@ -package types - -import ( - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/codec/legacy" - "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/msgservice" - authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" - govcodec "github.com/cosmos/cosmos-sdk/x/gov/codec" -) - -var ( - amino = codec.NewLegacyAmino() - AminoCdc = codec.NewAminoCodec(amino) -) - -func init() { - RegisterLegacyAminoCodec(amino) - cryptocodec.RegisterCrypto(amino) - sdk.RegisterLegacyAminoCodec(amino) - - // Register all Amino interfaces and concrete types on the authz and gov Amino codec - // so that this can later be used to properly serialize MsgGrant and MsgExec - // instances. - RegisterLegacyAminoCodec(authzcodec.Amino) - RegisterLegacyAminoCodec(govcodec.Amino) -} - -// RegisterLegacyAminoCodec registers concrete types on the LegacyAmino codec -func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { - cdc.RegisterConcrete(Params{}, "terp/x/clock/Params", nil) - legacy.RegisterAminoMsg(cdc, &MsgUpdateParams{}, "terp/x/clock/MsgUpdateParams") -} - -func RegisterInterfaces(registry types.InterfaceRegistry) { - registry.RegisterImplementations( - (*sdk.Msg)(nil), - &MsgUpdateParams{}, - ) - - msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) -} diff --git a/x/clock/types/codec_test.go b/x/clock/types/codec_test.go deleted file mode 100644 index 92c1c18..0000000 --- a/x/clock/types/codec_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/suite" - - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type CodecTestSuite struct { - suite.Suite -} - -func TestCodecSuite(t *testing.T) { - suite.Run(t, new(CodecTestSuite)) -} - -func (suite *CodecTestSuite) TestRegisterInterfaces() { - registry := codectypes.NewInterfaceRegistry() - registry.RegisterInterface(sdk.MsgInterfaceProtoName, (*sdk.Msg)(nil)) - RegisterInterfaces(registry) - - impls := registry.ListImplementations(sdk.MsgInterfaceProtoName) - suite.Require().Equal(1, len(impls)) - suite.Require().ElementsMatch([]string{ - "/terp.clock.v1.MsgUpdateParams", - }, impls) -} diff --git a/x/clock/types/genesis.pb.go b/x/clock/types/genesis.pb.go deleted file mode 100644 index c3c5122..0000000 --- a/x/clock/types/genesis.pb.go +++ /dev/null @@ -1,542 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: terp/clock/v1/genesis.proto - -package types - -import ( - fmt "fmt" - _ "github.com/cosmos/cosmos-sdk/types" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/cosmos/gogoproto/proto" - io "io" - math "math" - math_bits "math/bits" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package - -// GenesisState - initial state of module -type GenesisState struct { - // Params of this module - Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params,omitempty"` -} - -func (m *GenesisState) Reset() { *m = GenesisState{} } -func (m *GenesisState) String() string { return proto.CompactTextString(m) } -func (*GenesisState) ProtoMessage() {} -func (*GenesisState) Descriptor() ([]byte, []int) { - return fileDescriptor_5814f6c7e1ff453c, []int{0} -} -func (m *GenesisState) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *GenesisState) XXX_Merge(src proto.Message) { - xxx_messageInfo_GenesisState.Merge(m, src) -} -func (m *GenesisState) XXX_Size() int { - return m.Size() -} -func (m *GenesisState) XXX_DiscardUnknown() { - xxx_messageInfo_GenesisState.DiscardUnknown(m) -} - -var xxx_messageInfo_GenesisState proto.InternalMessageInfo - -func (m *GenesisState) GetParams() Params { - if m != nil { - return m.Params - } - return Params{} -} - -// Params defines the set of module parameters. -type Params struct { - // contract_addresses stores the list of executable contracts to be ticked on every block. - ContractAddresses []string `protobuf:"bytes,1,rep,name=contract_addresses,json=contractAddresses,proto3" json:"contract_addresses,omitempty" yaml:"contract_addresses"` - ContractGasLimit uint64 `protobuf:"varint,2,opt,name=contract_gas_limit,json=contractGasLimit,proto3" json:"contract_gas_limit,omitempty" yaml:"contract_gas_limit"` -} - -func (m *Params) Reset() { *m = Params{} } -func (m *Params) String() string { return proto.CompactTextString(m) } -func (*Params) ProtoMessage() {} -func (*Params) Descriptor() ([]byte, []int) { - return fileDescriptor_5814f6c7e1ff453c, []int{1} -} -func (m *Params) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Params.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *Params) XXX_Merge(src proto.Message) { - xxx_messageInfo_Params.Merge(m, src) -} -func (m *Params) XXX_Size() int { - return m.Size() -} -func (m *Params) XXX_DiscardUnknown() { - xxx_messageInfo_Params.DiscardUnknown(m) -} - -var xxx_messageInfo_Params proto.InternalMessageInfo - -func (m *Params) GetContractAddresses() []string { - if m != nil { - return m.ContractAddresses - } - return nil -} - -func (m *Params) GetContractGasLimit() uint64 { - if m != nil { - return m.ContractGasLimit - } - return 0 -} - -func init() { - proto.RegisterType((*GenesisState)(nil), "terp.clock.v1.GenesisState") - proto.RegisterType((*Params)(nil), "terp.clock.v1.Params") -} - -func init() { proto.RegisterFile("terp/clock/v1/genesis.proto", fileDescriptor_5814f6c7e1ff453c) } - -var fileDescriptor_5814f6c7e1ff453c = []byte{ - // 332 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0x3f, 0x4b, 0xc3, 0x40, - 0x18, 0xc6, 0x73, 0x2a, 0x05, 0xa3, 0x42, 0x0d, 0x0a, 0xb5, 0xca, 0xa5, 0x64, 0xea, 0xa0, 0x77, - 0x44, 0x37, 0xc1, 0xc1, 0x2e, 0x75, 0x70, 0x90, 0x3a, 0x08, 0x2e, 0xe5, 0x72, 0x3d, 0x62, 0x68, - 0x2e, 0x17, 0xee, 0x5e, 0xab, 0xfd, 0x16, 0x7e, 0xac, 0x8e, 0x1d, 0x9d, 0x82, 0x34, 0x5b, 0x47, - 0x3f, 0x81, 0x24, 0x69, 0xeb, 0x9f, 0x82, 0xdb, 0xcb, 0xf3, 0xfb, 0xdd, 0xfb, 0xc0, 0xbd, 0xf6, - 0x31, 0x08, 0x9d, 0x52, 0x1e, 0x2b, 0x3e, 0xa4, 0x23, 0x9f, 0x86, 0x22, 0x11, 0x26, 0x32, 0x24, - 0xd5, 0x0a, 0x94, 0xb3, 0x57, 0x40, 0x52, 0x42, 0x32, 0xf2, 0x9b, 0x07, 0xa1, 0x0a, 0x55, 0x49, - 0x68, 0x31, 0x55, 0x52, 0x13, 0x73, 0x65, 0xa4, 0x32, 0x34, 0x60, 0x46, 0xd0, 0x91, 0x1f, 0x08, - 0x60, 0x3e, 0xe5, 0x2a, 0x4a, 0x2a, 0xee, 0x3d, 0xd8, 0xbb, 0xdd, 0x6a, 0xeb, 0x3d, 0x30, 0x10, - 0x4e, 0xd7, 0xae, 0xa5, 0x4c, 0x33, 0x69, 0x1a, 0xa8, 0x85, 0xda, 0x3b, 0xe7, 0x87, 0xe4, 0x57, - 0x0b, 0xb9, 0x2b, 0x61, 0xa7, 0x31, 0xc9, 0x5c, 0x6b, 0x9e, 0xb9, 0xf5, 0x4a, 0x3e, 0x55, 0x32, - 0x02, 0x21, 0x53, 0x18, 0xf7, 0x16, 0xcf, 0xbd, 0x1c, 0xd9, 0xb5, 0x4a, 0x76, 0x62, 0xdb, 0xe1, - 0x2a, 0x01, 0xcd, 0x38, 0xf4, 0xd9, 0x60, 0xa0, 0x85, 0x31, 0xa2, 0xd8, 0xbf, 0xd9, 0xde, 0xee, - 0x5c, 0xcd, 0x33, 0xf7, 0x64, 0x9d, 0x7e, 0x2f, 0xfc, 0xcc, 0xdc, 0xa3, 0x31, 0x93, 0xf1, 0xa5, - 0xb7, 0x6e, 0x79, 0xbd, 0xfd, 0x65, 0x78, 0xbd, 0xcc, 0x9c, 0xe1, 0x8f, 0xb6, 0x90, 0x99, 0x7e, - 0x1c, 0xc9, 0x08, 0x1a, 0x1b, 0x2d, 0xd4, 0xde, 0xfa, 0xd3, 0xb6, 0xa2, 0xff, 0xb6, 0xad, 0x2c, - 0xaf, 0x57, 0x5f, 0x86, 0x5d, 0x66, 0x6e, 0x8b, 0xa8, 0x73, 0x33, 0x99, 0x61, 0x34, 0x9d, 0x61, - 0xf4, 0x31, 0xc3, 0xe8, 0x2d, 0xc7, 0xd6, 0x34, 0xc7, 0xd6, 0x7b, 0x8e, 0xad, 0x47, 0x12, 0x46, - 0xf0, 0xf4, 0x1c, 0x10, 0xae, 0x24, 0x2d, 0xbe, 0x30, 0x11, 0xf0, 0xa2, 0xf4, 0xb0, 0x9c, 0xcf, - 0xb8, 0xd2, 0x82, 0xbe, 0x2e, 0x0e, 0x0b, 0xe3, 0x54, 0x98, 0xa0, 0x56, 0xde, 0xe3, 0xe2, 0x2b, - 0x00, 0x00, 0xff, 0xff, 0xcc, 0xa3, 0xd5, 0x20, 0xf3, 0x01, 0x00, 0x00, -} - -func (m *GenesisState) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - return len(dAtA) - i, nil -} - -func (m *Params) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *Params) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.ContractGasLimit != 0 { - i = encodeVarintGenesis(dAtA, i, uint64(m.ContractGasLimit)) - i-- - dAtA[i] = 0x10 - } - if len(m.ContractAddresses) > 0 { - for iNdEx := len(m.ContractAddresses) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.ContractAddresses[iNdEx]) - copy(dAtA[i:], m.ContractAddresses[iNdEx]) - i = encodeVarintGenesis(dAtA, i, uint64(len(m.ContractAddresses[iNdEx]))) - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { - offset -= sovGenesis(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *GenesisState) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.Params.Size() - n += 1 + l + sovGenesis(uint64(l)) - return n -} - -func (m *Params) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.ContractAddresses) > 0 { - for _, s := range m.ContractAddresses { - l = len(s) - n += 1 + l + sovGenesis(uint64(l)) - } - } - if m.ContractGasLimit != 0 { - n += 1 + sovGenesis(uint64(m.ContractGasLimit)) - } - return n -} - -func sovGenesis(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozGenesis(x uint64) (n int) { - return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *GenesisState) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenesis(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *Params) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Params: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ContractAddresses", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ContractAddresses = append(m.ContractAddresses, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field ContractGasLimit", wireType) - } - m.ContractGasLimit = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.ContractGasLimit |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipGenesis(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipGenesis(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenesis - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenesis - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowGenesis - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthGenesis - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupGenesis - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthGenesis - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/clock/types/keys.go b/x/clock/types/keys.go deleted file mode 100644 index 3b97c28..0000000 --- a/x/clock/types/keys.go +++ /dev/null @@ -1,11 +0,0 @@ -package types - -var ParamsKey = []byte{0x00} - -const ( - ModuleName = "clock" - - StoreKey = ModuleName - - QuerierRoute = ModuleName -) diff --git a/x/clock/types/msgs.go b/x/clock/types/msgs.go deleted file mode 100644 index cae1e8c..0000000 --- a/x/clock/types/msgs.go +++ /dev/null @@ -1,55 +0,0 @@ -package types - -import ( - "cosmossdk.io/errors" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" -) - -const ( - // Sudo Message called on the contracts - EndBlockSudoMessage = `{"clock_end_block":{}}` -) - -// == MsgUpdateParams == -const TypeMsgUpdateParams = "update_clock_params" - -var _ sdk.Msg = &MsgUpdateParams{} - -// NewMsgUpdateParams creates new instance of MsgUpdateParams -func NewMsgUpdateParams( - sender sdk.Address, - contracts []string, -) *MsgUpdateParams { - return &MsgUpdateParams{ - Authority: sender.String(), - Params: Params{ContractAddresses: contracts}, - } -} - -// Route returns the name of the module -func (msg MsgUpdateParams) Route() string { return types.RouterKey } - -// Type returns the the action -func (msg MsgUpdateParams) Type() string { return TypeMsgUpdateParams } - -// GetSignBytes implements the LegacyMsg interface. -func (msg MsgUpdateParams) GetSignBytes() []byte { - return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) -} - -// GetSigners returns the expected signers for a MsgUpdateParams message. -func (msg *MsgUpdateParams) GetSigners() []sdk.AccAddress { - addr, _ := sdk.AccAddressFromBech32(msg.Authority) - return []sdk.AccAddress{addr} -} - -// ValidateBasic does a sanity check on the provided data. -func (msg *MsgUpdateParams) ValidateBasic() error { - if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil { - return errors.Wrap(err, "invalid authority address") - } - - return msg.Params.Validate() -} diff --git a/x/clock/types/msgs_test.go b/x/clock/types/msgs_test.go deleted file mode 100644 index 88276e8..0000000 --- a/x/clock/types/msgs_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/suite" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type MsgsTestSuite struct { - suite.Suite - govModule string -} - -func TestMsgsTestSuite(t *testing.T) { - suite.Run(t, new(MsgsTestSuite)) -} - -func (suite *MsgsTestSuite) SetupTest() { - suite.govModule = "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq" -} - -func (suite *MsgsTestSuite) TestMsgUpdateParams() { - p := MsgUpdateParams{ - Authority: suite.govModule, - Params: Params{ - ContractAddresses: []string{}, - }, - } - - acc, _ := sdk.AccAddressFromBech32(p.Authority) - - msg := NewMsgUpdateParams(acc, []string(nil)) - - suite.Require().Equal(types.RouterKey, msg.Route()) - suite.Require().Equal(TypeMsgUpdateParams, msg.Type()) - suite.Require().NotNil(msg.GetSigners()) -} diff --git a/x/clock/types/params.go b/x/clock/types/params.go deleted file mode 100644 index 46b5dfb..0000000 --- a/x/clock/types/params.go +++ /dev/null @@ -1,65 +0,0 @@ -package types - -import ( - errorsmod "cosmossdk.io/errors" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// DefaultParams returns default parameters -func DefaultParams() Params { - return Params{ - ContractAddresses: []string(nil), - ContractGasLimit: 1_000_000_000, // 1 billion - } -} - -// NewParams creates a new Params object -func NewParams( - contracts []string, - contractGasLimit uint64, -) Params { - return Params{ - ContractAddresses: contracts, - ContractGasLimit: contractGasLimit, - } -} - -// Validate performs basic validation. -func (p Params) Validate() error { - minimumGas := uint64(100_000) - if p.ContractGasLimit < minimumGas { - return errorsmod.Wrapf( - sdkerrors.ErrInvalidRequest, - "invalid contract gas limit: %d. Must be above %d", p.ContractGasLimit, minimumGas, - ) - } - - for _, addr := range p.ContractAddresses { - // Valid address check - if _, err := sdk.AccAddressFromBech32(addr); err != nil { - return errorsmod.Wrapf( - sdkerrors.ErrInvalidAddress, - "invalid contract address: %s", err.Error(), - ) - } - - // duplicate address check - count := 0 - for _, addr2 := range p.ContractAddresses { - if addr == addr2 { - count++ - } - - if count > 1 { - return errorsmod.Wrapf( - sdkerrors.ErrInvalidAddress, - "duplicate contract address: %s", addr, - ) - } - } - } - - return nil -} diff --git a/x/clock/types/params_test.go b/x/clock/types/params_test.go deleted file mode 100644 index 871a892..0000000 --- a/x/clock/types/params_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/terpnetwork/terp-core/v2/x/clock/types" -) - -func TestParamsValidate(t *testing.T) { - testCases := []struct { - name string - params types.Params - expError bool - }{ - {"default", types.DefaultParams(), false}, - { - "valid: no contracts, enough gas", - types.NewParams([]string(nil), 100_000), - false, - }, - { - "invalid: address malformed", - types.NewParams([]string{"invalid address"}, 100_000), - true, - }, - { - "invalid: not enough gas", - types.NewParams([]string(nil), 1), - true, - }, - } - - for _, tc := range testCases { - err := tc.params.Validate() - - if tc.expError { - require.Error(t, err, tc.name) - } else { - require.NoError(t, err, tc.name) - } - } -} diff --git a/x/clock/types/query.pb.go b/x/clock/types/query.pb.go deleted file mode 100644 index 2d92ef0..0000000 --- a/x/clock/types/query.pb.go +++ /dev/null @@ -1,884 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: terp/clock/v1/query.proto - -package types - -import ( - context "context" - fmt "fmt" - _ "github.com/cosmos/cosmos-sdk/types" - _ "github.com/cosmos/gogoproto/gogoproto" - grpc1 "github.com/cosmos/gogoproto/grpc" - proto "github.com/cosmos/gogoproto/proto" - _ "google.golang.org/genproto/googleapis/api/annotations" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package - -// QueryClockContracts is the request type to get all contracts. -type QueryClockContracts struct { -} - -func (m *QueryClockContracts) Reset() { *m = QueryClockContracts{} } -func (m *QueryClockContracts) String() string { return proto.CompactTextString(m) } -func (*QueryClockContracts) ProtoMessage() {} -func (*QueryClockContracts) Descriptor() ([]byte, []int) { - return fileDescriptor_06ba6c07aa2f39a1, []int{0} -} -func (m *QueryClockContracts) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryClockContracts) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryClockContracts.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *QueryClockContracts) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryClockContracts.Merge(m, src) -} -func (m *QueryClockContracts) XXX_Size() int { - return m.Size() -} -func (m *QueryClockContracts) XXX_DiscardUnknown() { - xxx_messageInfo_QueryClockContracts.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryClockContracts proto.InternalMessageInfo - -// QueryClockContractsResponse is the response type for the Query/ClockContracts RPC method. -type QueryClockContractsResponse struct { - ContractAddresses []string `protobuf:"bytes,1,rep,name=contract_addresses,json=contractAddresses,proto3" json:"contract_addresses,omitempty" yaml:"contract_addresses"` -} - -func (m *QueryClockContractsResponse) Reset() { *m = QueryClockContractsResponse{} } -func (m *QueryClockContractsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryClockContractsResponse) ProtoMessage() {} -func (*QueryClockContractsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_06ba6c07aa2f39a1, []int{1} -} -func (m *QueryClockContractsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryClockContractsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryClockContractsResponse.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *QueryClockContractsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryClockContractsResponse.Merge(m, src) -} -func (m *QueryClockContractsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryClockContractsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryClockContractsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryClockContractsResponse proto.InternalMessageInfo - -func (m *QueryClockContractsResponse) GetContractAddresses() []string { - if m != nil { - return m.ContractAddresses - } - return nil -} - -// QueryParams is the request type to get all module params. -type QueryParamsRequest struct { -} - -func (m *QueryParamsRequest) Reset() { *m = QueryParamsRequest{} } -func (m *QueryParamsRequest) String() string { return proto.CompactTextString(m) } -func (*QueryParamsRequest) ProtoMessage() {} -func (*QueryParamsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_06ba6c07aa2f39a1, []int{2} -} -func (m *QueryParamsRequest) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryParamsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryParamsRequest.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *QueryParamsRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryParamsRequest.Merge(m, src) -} -func (m *QueryParamsRequest) XXX_Size() int { - return m.Size() -} -func (m *QueryParamsRequest) XXX_DiscardUnknown() { - xxx_messageInfo_QueryParamsRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryParamsRequest proto.InternalMessageInfo - -// QueryClockContractsResponse is the response type for the Query/ClockContracts RPC method. -type QueryParamsResponse struct { - Params *Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params" yaml:"params"` -} - -func (m *QueryParamsResponse) Reset() { *m = QueryParamsResponse{} } -func (m *QueryParamsResponse) String() string { return proto.CompactTextString(m) } -func (*QueryParamsResponse) ProtoMessage() {} -func (*QueryParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_06ba6c07aa2f39a1, []int{3} -} -func (m *QueryParamsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryParamsResponse.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *QueryParamsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryParamsResponse.Merge(m, src) -} -func (m *QueryParamsResponse) XXX_Size() int { - return m.Size() -} -func (m *QueryParamsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_QueryParamsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryParamsResponse proto.InternalMessageInfo - -func (m *QueryParamsResponse) GetParams() *Params { - if m != nil { - return m.Params - } - return nil -} - -func init() { - proto.RegisterType((*QueryClockContracts)(nil), "terp.clock.v1.QueryClockContracts") - proto.RegisterType((*QueryClockContractsResponse)(nil), "terp.clock.v1.QueryClockContractsResponse") - proto.RegisterType((*QueryParamsRequest)(nil), "terp.clock.v1.QueryParamsRequest") - proto.RegisterType((*QueryParamsResponse)(nil), "terp.clock.v1.QueryParamsResponse") -} - -func init() { proto.RegisterFile("terp/clock/v1/query.proto", fileDescriptor_06ba6c07aa2f39a1) } - -var fileDescriptor_06ba6c07aa2f39a1 = []byte{ - // 427 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0xb1, 0x6f, 0xd3, 0x40, - 0x14, 0xc6, 0x73, 0x20, 0x22, 0x71, 0xa8, 0x48, 0x1c, 0x8d, 0x48, 0x9d, 0xe2, 0x84, 0x9b, 0x2a, - 0x04, 0x3e, 0xa5, 0x6c, 0x48, 0x0c, 0xa4, 0x0b, 0x62, 0x82, 0x8c, 0x2c, 0xe8, 0x72, 0x7d, 0x32, - 0x56, 0xe3, 0x7b, 0xee, 0xdd, 0x25, 0x90, 0xb5, 0x2b, 0x0b, 0x12, 0xff, 0x14, 0x63, 0x25, 0x16, - 0x26, 0x0b, 0x25, 0x4c, 0x1d, 0x3b, 0x33, 0x20, 0x9f, 0x2f, 0x95, 0xdc, 0x44, 0x74, 0x3b, 0x7f, - 0xbf, 0xef, 0xde, 0xf7, 0xf9, 0xd9, 0x74, 0xcf, 0x81, 0x29, 0x84, 0x9a, 0xa2, 0x3a, 0x11, 0xf3, - 0xa1, 0x38, 0x9d, 0x81, 0x59, 0x24, 0x85, 0x41, 0x87, 0x6c, 0xa7, 0x42, 0x89, 0x47, 0xc9, 0x7c, - 0x18, 0xed, 0xa6, 0x98, 0xa2, 0x27, 0xa2, 0x3a, 0xd5, 0xa6, 0x68, 0x3f, 0x45, 0x4c, 0xa7, 0x20, - 0x64, 0x91, 0x09, 0xa9, 0x35, 0x3a, 0xe9, 0x32, 0xd4, 0x36, 0xd0, 0x58, 0xa1, 0xcd, 0xd1, 0x8a, - 0x89, 0xb4, 0x20, 0xe6, 0xc3, 0x09, 0x38, 0x39, 0x14, 0x0a, 0x33, 0x1d, 0x78, 0xaf, 0x99, 0x9e, - 0x82, 0x06, 0x9b, 0x85, 0xcb, 0xbc, 0x43, 0x1f, 0xbe, 0xaf, 0xea, 0x1c, 0x55, 0xf8, 0x08, 0xb5, - 0x33, 0x52, 0x39, 0xcb, 0xbf, 0x12, 0xda, 0xdb, 0xa2, 0x8f, 0xc1, 0x16, 0xa8, 0x2d, 0xb0, 0x29, - 0x65, 0x2a, 0x88, 0x1f, 0xe5, 0xf1, 0xb1, 0x01, 0x6b, 0xc1, 0x76, 0xc9, 0xe0, 0xf6, 0xc1, 0xdd, - 0xd1, 0xab, 0x8b, 0xb2, 0xbf, 0xbf, 0x49, 0x9f, 0x61, 0x9e, 0x39, 0xc8, 0x0b, 0xb7, 0xb8, 0x2c, - 0xfb, 0x7b, 0x0b, 0x99, 0x4f, 0x5f, 0xf2, 0x4d, 0x17, 0x1f, 0x3f, 0x58, 0x8b, 0xaf, 0xaf, 0xb4, - 0x5d, 0xca, 0x7c, 0x99, 0x77, 0xd2, 0xc8, 0xdc, 0x8e, 0xe1, 0x74, 0x06, 0xd6, 0x71, 0x19, 0xaa, - 0xaf, 0xd5, 0x50, 0xed, 0x2d, 0x6d, 0x17, 0x5e, 0xe9, 0x92, 0x01, 0x39, 0xb8, 0x77, 0xd8, 0x49, - 0x1a, 0x2b, 0x4e, 0x6a, 0xfb, 0xa8, 0x77, 0x51, 0xf6, 0x83, 0xf1, 0xb2, 0xec, 0xef, 0xd4, 0x7d, - 0xea, 0x67, 0x3e, 0x0e, 0xe0, 0xf0, 0x2f, 0xa1, 0x77, 0x7c, 0x06, 0x3b, 0x23, 0xf4, 0x7e, 0x73, - 0x17, 0x8c, 0x5f, 0x1b, 0xbc, 0x65, 0x5f, 0xd1, 0xd3, 0x9b, 0x3d, 0xeb, 0xe2, 0x7c, 0x70, 0xf6, - 0xf3, 0xcf, 0xf7, 0x5b, 0x11, 0xeb, 0x8a, 0xe6, 0x07, 0x53, 0x57, 0x89, 0x9a, 0xb6, 0xeb, 0xf6, - 0xec, 0xc9, 0xb6, 0xb9, 0x8d, 0xf5, 0x44, 0xfc, 0x7f, 0x96, 0x10, 0xf9, 0xd8, 0x47, 0x3e, 0x62, - 0x9d, 0x6b, 0x91, 0xf5, 0xeb, 0x8f, 0xde, 0xfc, 0x58, 0xc6, 0xe4, 0x7c, 0x19, 0x93, 0xdf, 0xcb, - 0x98, 0x7c, 0x5b, 0xc5, 0xad, 0xf3, 0x55, 0xdc, 0xfa, 0xb5, 0x8a, 0x5b, 0x1f, 0x92, 0x34, 0x73, - 0x9f, 0x66, 0x93, 0x44, 0x61, 0xee, 0xaf, 0x6a, 0x70, 0x9f, 0xd1, 0x9c, 0xf8, 0xf3, 0x73, 0x85, - 0x06, 0xc4, 0x97, 0x30, 0xcd, 0x2d, 0x0a, 0xb0, 0x93, 0xb6, 0xff, 0xdb, 0x5e, 0xfc, 0x0b, 0x00, - 0x00, 0xff, 0xff, 0xda, 0x94, 0x2b, 0xdd, 0x0a, 0x03, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// QueryClient is the client API for Query service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type QueryClient interface { - // ClockContracts - ClockContracts(ctx context.Context, in *QueryClockContracts, opts ...grpc.CallOption) (*QueryClockContractsResponse, error) - // Params - Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) -} - -type queryClient struct { - cc grpc1.ClientConn -} - -func NewQueryClient(cc grpc1.ClientConn) QueryClient { - return &queryClient{cc} -} - -func (c *queryClient) ClockContracts(ctx context.Context, in *QueryClockContracts, opts ...grpc.CallOption) (*QueryClockContractsResponse, error) { - out := new(QueryClockContractsResponse) - err := c.cc.Invoke(ctx, "/terp.clock.v1.Query/ClockContracts", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) { - out := new(QueryParamsResponse) - err := c.cc.Invoke(ctx, "/terp.clock.v1.Query/Params", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// QueryServer is the server API for Query service. -type QueryServer interface { - // ClockContracts - ClockContracts(context.Context, *QueryClockContracts) (*QueryClockContractsResponse, error) - // Params - Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) -} - -// UnimplementedQueryServer can be embedded to have forward compatible implementations. -type UnimplementedQueryServer struct { -} - -func (*UnimplementedQueryServer) ClockContracts(ctx context.Context, req *QueryClockContracts) (*QueryClockContractsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ClockContracts not implemented") -} -func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") -} - -func RegisterQueryServer(s grpc1.Server, srv QueryServer) { - s.RegisterService(&_Query_serviceDesc, srv) -} - -func _Query_ClockContracts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryClockContracts) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).ClockContracts(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/terp.clock.v1.Query/ClockContracts", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).ClockContracts(ctx, req.(*QueryClockContracts)) - } - return interceptor(ctx, in, info, handler) -} - -func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryParamsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(QueryServer).Params(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/terp.clock.v1.Query/Params", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(QueryServer).Params(ctx, req.(*QueryParamsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Query_serviceDesc = grpc.ServiceDesc{ - ServiceName: "terp.clock.v1.Query", - HandlerType: (*QueryServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "ClockContracts", - Handler: _Query_ClockContracts_Handler, - }, - { - MethodName: "Params", - Handler: _Query_Params_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "terp/clock/v1/query.proto", -} - -func (m *QueryClockContracts) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *QueryClockContracts) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryClockContracts) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *QueryClockContractsResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *QueryClockContractsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryClockContractsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.ContractAddresses) > 0 { - for iNdEx := len(m.ContractAddresses) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.ContractAddresses[iNdEx]) - copy(dAtA[i:], m.ContractAddresses[iNdEx]) - i = encodeVarintQuery(dAtA, i, uint64(len(m.ContractAddresses[iNdEx]))) - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func (m *QueryParamsRequest) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *QueryParamsRequest) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryParamsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func (m *QueryParamsResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *QueryParamsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Params != nil { - { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { - offset -= sovQuery(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *QueryClockContracts) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *QueryClockContractsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.ContractAddresses) > 0 { - for _, s := range m.ContractAddresses { - l = len(s) - n += 1 + l + sovQuery(uint64(l)) - } - } - return n -} - -func (m *QueryParamsRequest) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func (m *QueryParamsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Params != nil { - l = m.Params.Size() - n += 1 + l + sovQuery(uint64(l)) - } - return n -} - -func sovQuery(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozQuery(x uint64) (n int) { - return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *QueryClockContracts) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: QueryClockContracts: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryClockContracts: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryClockContractsResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: QueryClockContractsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryClockContractsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ContractAddresses", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ContractAddresses = append(m.ContractAddresses, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryParamsRequest) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: QueryParamsRequest: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryParamsRequest: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: QueryParamsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthQuery - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthQuery - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Params == nil { - m.Params = &Params{} - } - if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipQuery(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthQuery - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipQuery(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowQuery - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowQuery - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowQuery - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthQuery - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupQuery - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthQuery - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/clock/types/query.pb.gw.go b/x/clock/types/query.pb.gw.go deleted file mode 100644 index 5adb17c..0000000 --- a/x/clock/types/query.pb.gw.go +++ /dev/null @@ -1,218 +0,0 @@ -// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. -// source: terp/clock/v1/query.proto - -/* -Package types is a reverse proxy. - -It translates gRPC into RESTful JSON APIs. -*/ -package types - -import ( - "context" - "io" - "net/http" - - "github.com/golang/protobuf/descriptor" - "github.com/golang/protobuf/proto" - "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/grpc-ecosystem/grpc-gateway/utilities" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" -) - -// Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage -var _ = metadata.Join - -func request_Query_ClockContracts_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryClockContracts - var metadata runtime.ServerMetadata - - msg, err := client.ClockContracts(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_ClockContracts_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryClockContracts - var metadata runtime.ServerMetadata - - msg, err := server.ClockContracts(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - var metadata runtime.ServerMetadata - - msg, err := client.Params(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq QueryParamsRequest - var metadata runtime.ServerMetadata - - msg, err := server.Params(ctx, &protoReq) - return msg, metadata, err - -} - -// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". -// UnaryRPC :call QueryServer directly. -// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. -// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. -func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { - - mux.Handle("GET", pattern_Query_ClockContracts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_ClockContracts_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ClockContracts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Query_Params_0(rctx, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but -// automatically dials to "endpoint" and closes the connection when "ctx" gets done. -func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) - if err != nil { - return err - } - defer func() { - if err != nil { - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - return - } - go func() { - <-ctx.Done() - if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) - } - }() - }() - - return RegisterQueryHandler(ctx, mux, conn) -} - -// RegisterQueryHandler registers the http handlers for service Query to "mux". -// The handlers forward requests to the grpc endpoint over "conn". -func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { - return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) -} - -// RegisterQueryHandlerClient registers the http handlers for service Query -// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". -// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" -// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "QueryClient" to call the correct interceptors. -func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { - - mux.Handle("GET", pattern_Query_ClockContracts_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_ClockContracts_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_ClockContracts_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("GET", pattern_Query_Params_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Query_Params_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - - forward_Query_Params_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - return nil -} - -var ( - pattern_Query_ClockContracts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"terp", "clock", "v1", "contracts"}, "", runtime.AssumeColonVerbOpt(false))) - - pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"terp", "clock", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false))) -) - -var ( - forward_Query_ClockContracts_0 = runtime.ForwardResponseMessage - - forward_Query_Params_0 = runtime.ForwardResponseMessage -) diff --git a/x/clock/types/tx.pb.go b/x/clock/types/tx.pb.go deleted file mode 100644 index c07bee4..0000000 --- a/x/clock/types/tx.pb.go +++ /dev/null @@ -1,605 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: terp/clock/v1/tx.proto - -package types - -import ( - context "context" - fmt "fmt" - _ "github.com/cosmos/cosmos-proto" - _ "github.com/cosmos/cosmos-sdk/types/msgservice" - _ "github.com/cosmos/cosmos-sdk/types/tx/amino" - _ "github.com/cosmos/gogoproto/gogoproto" - grpc1 "github.com/cosmos/gogoproto/grpc" - proto "github.com/cosmos/gogoproto/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package - -// MsgUpdateParams is the Msg/UpdateParams request type. -// -// Since: cosmos-sdk 0.47 -type MsgUpdateParams struct { - // authority is the address of the governance account. - Authority string `protobuf:"bytes,1,opt,name=authority,proto3" json:"authority,omitempty"` - // params defines the x/clock parameters to update. - // - // NOTE: All parameters must be supplied. - Params Params `protobuf:"bytes,2,opt,name=params,proto3" json:"params"` -} - -func (m *MsgUpdateParams) Reset() { *m = MsgUpdateParams{} } -func (m *MsgUpdateParams) String() string { return proto.CompactTextString(m) } -func (*MsgUpdateParams) ProtoMessage() {} -func (*MsgUpdateParams) Descriptor() ([]byte, []int) { - return fileDescriptor_ad9dd5417a79a74f, []int{0} -} -func (m *MsgUpdateParams) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgUpdateParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgUpdateParams.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MsgUpdateParams) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgUpdateParams.Merge(m, src) -} -func (m *MsgUpdateParams) XXX_Size() int { - return m.Size() -} -func (m *MsgUpdateParams) XXX_DiscardUnknown() { - xxx_messageInfo_MsgUpdateParams.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgUpdateParams proto.InternalMessageInfo - -func (m *MsgUpdateParams) GetAuthority() string { - if m != nil { - return m.Authority - } - return "" -} - -func (m *MsgUpdateParams) GetParams() Params { - if m != nil { - return m.Params - } - return Params{} -} - -// MsgUpdateParamsResponse defines the response structure for executing a -// MsgUpdateParams message. -// -// Since: cosmos-sdk 0.47 -type MsgUpdateParamsResponse struct { -} - -func (m *MsgUpdateParamsResponse) Reset() { *m = MsgUpdateParamsResponse{} } -func (m *MsgUpdateParamsResponse) String() string { return proto.CompactTextString(m) } -func (*MsgUpdateParamsResponse) ProtoMessage() {} -func (*MsgUpdateParamsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_ad9dd5417a79a74f, []int{1} -} -func (m *MsgUpdateParamsResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgUpdateParamsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgUpdateParamsResponse.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MsgUpdateParamsResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgUpdateParamsResponse.Merge(m, src) -} -func (m *MsgUpdateParamsResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgUpdateParamsResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgUpdateParamsResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgUpdateParamsResponse proto.InternalMessageInfo - -func init() { - proto.RegisterType((*MsgUpdateParams)(nil), "terp.clock.v1.MsgUpdateParams") - proto.RegisterType((*MsgUpdateParamsResponse)(nil), "terp.clock.v1.MsgUpdateParamsResponse") -} - -func init() { proto.RegisterFile("terp/clock/v1/tx.proto", fileDescriptor_ad9dd5417a79a74f) } - -var fileDescriptor_ad9dd5417a79a74f = []byte{ - // 334 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2b, 0x49, 0x2d, 0x2a, - 0xd0, 0x4f, 0xce, 0xc9, 0x4f, 0xce, 0xd6, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, - 0x2f, 0xc9, 0x17, 0xe2, 0x05, 0x89, 0xeb, 0x81, 0xc5, 0xf5, 0xca, 0x0c, 0xa5, 0xc4, 0x93, 0xf3, - 0x8b, 0x73, 0xf3, 0x8b, 0xf5, 0x73, 0x8b, 0xd3, 0x41, 0xca, 0x72, 0x8b, 0xd3, 0x21, 0xea, 0xa4, - 0xa4, 0x51, 0xf5, 0xa7, 0xa7, 0xe6, 0xa5, 0x16, 0x67, 0x16, 0x43, 0x25, 0x45, 0xd2, 0xf3, 0xd3, - 0xf3, 0xc1, 0x4c, 0x7d, 0x10, 0x0b, 0x2a, 0x2a, 0x09, 0x31, 0x2b, 0x1e, 0x22, 0x01, 0xe1, 0x40, - 0xa5, 0x04, 0x13, 0x73, 0x33, 0xf3, 0xf2, 0xf5, 0xc1, 0x24, 0x44, 0x48, 0xa9, 0x8f, 0x91, 0x8b, - 0xdf, 0xb7, 0x38, 0x3d, 0xb4, 0x20, 0x25, 0xb1, 0x24, 0x35, 0x20, 0xb1, 0x28, 0x31, 0xb7, 0x58, - 0xc8, 0x8c, 0x8b, 0x33, 0xb1, 0xb4, 0x24, 0x23, 0xbf, 0x28, 0xb3, 0xa4, 0x52, 0x82, 0x51, 0x81, - 0x51, 0x83, 0xd3, 0x49, 0xe2, 0xd2, 0x16, 0x5d, 0x11, 0xa8, 0x59, 0x8e, 0x29, 0x29, 0x45, 0xa9, - 0xc5, 0xc5, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x41, 0x08, 0xa5, 0x42, 0xc6, 0x5c, 0x6c, 0x05, - 0x60, 0x13, 0x24, 0x98, 0x14, 0x18, 0x35, 0xb8, 0x8d, 0x44, 0xf5, 0x50, 0x7c, 0xa9, 0x07, 0x31, - 0xde, 0x89, 0xe5, 0xc4, 0x3d, 0x79, 0x86, 0x20, 0xa8, 0x52, 0x2b, 0xbe, 0xa6, 0xe7, 0x1b, 0xb4, - 0x10, 0x86, 0x28, 0x49, 0x72, 0x89, 0xa3, 0xb9, 0x27, 0x28, 0xb5, 0xb8, 0x20, 0x3f, 0xaf, 0x38, - 0xd5, 0x28, 0x96, 0x8b, 0xd9, 0xb7, 0x38, 0x5d, 0x28, 0x8c, 0x8b, 0x07, 0xc5, 0xb9, 0x72, 0x68, - 0xd6, 0xa0, 0x69, 0x97, 0x52, 0xc3, 0x2f, 0x0f, 0x33, 0xde, 0xc9, 0xe3, 0xc4, 0x23, 0x39, 0xc6, - 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf0, 0x58, 0x8e, 0xe1, 0xc2, 0x63, 0x39, - 0x86, 0x1b, 0x8f, 0xe5, 0x18, 0xa2, 0xf4, 0xd2, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, - 0x73, 0xf5, 0x41, 0x66, 0xe5, 0xa5, 0x96, 0x94, 0xe7, 0x17, 0x65, 0x83, 0xd9, 0xba, 0xc9, 0xf9, - 0x45, 0xa9, 0xfa, 0x15, 0xd0, 0x38, 0x2a, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x87, 0xad, - 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x12, 0xb9, 0xe4, 0x93, 0xfe, 0x01, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// MsgClient is the client API for Msg service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type MsgClient interface { - // UpdateParams defines a governance operation for updating the x/clock module - // parameters. The authority is hard-coded to the x/gov module account. - // - // Since: cosmos-sdk 0.47 - UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) -} - -type msgClient struct { - cc grpc1.ClientConn -} - -func NewMsgClient(cc grpc1.ClientConn) MsgClient { - return &msgClient{cc} -} - -func (c *msgClient) UpdateParams(ctx context.Context, in *MsgUpdateParams, opts ...grpc.CallOption) (*MsgUpdateParamsResponse, error) { - out := new(MsgUpdateParamsResponse) - err := c.cc.Invoke(ctx, "/terp.clock.v1.Msg/UpdateParams", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// MsgServer is the server API for Msg service. -type MsgServer interface { - // UpdateParams defines a governance operation for updating the x/clock module - // parameters. The authority is hard-coded to the x/gov module account. - // - // Since: cosmos-sdk 0.47 - UpdateParams(context.Context, *MsgUpdateParams) (*MsgUpdateParamsResponse, error) -} - -// UnimplementedMsgServer can be embedded to have forward compatible implementations. -type UnimplementedMsgServer struct { -} - -func (*UnimplementedMsgServer) UpdateParams(ctx context.Context, req *MsgUpdateParams) (*MsgUpdateParamsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateParams not implemented") -} - -func RegisterMsgServer(s grpc1.Server, srv MsgServer) { - s.RegisterService(&_Msg_serviceDesc, srv) -} - -func _Msg_UpdateParams_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgUpdateParams) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).UpdateParams(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/terp.clock.v1.Msg/UpdateParams", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).UpdateParams(ctx, req.(*MsgUpdateParams)) - } - return interceptor(ctx, in, info, handler) -} - -var _Msg_serviceDesc = grpc.ServiceDesc{ - ServiceName: "terp.clock.v1.Msg", - HandlerType: (*MsgServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "UpdateParams", - Handler: _Msg_UpdateParams_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "terp/clock/v1/tx.proto", -} - -func (m *MsgUpdateParams) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgUpdateParams) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgUpdateParams) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - if len(m.Authority) > 0 { - i -= len(m.Authority) - copy(dAtA[i:], m.Authority) - i = encodeVarintTx(dAtA, i, uint64(len(m.Authority))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgUpdateParamsResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgUpdateParamsResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgUpdateParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - return len(dAtA) - i, nil -} - -func encodeVarintTx(dAtA []byte, offset int, v uint64) int { - offset -= sovTx(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *MsgUpdateParams) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Authority) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = m.Params.Size() - n += 1 + l + sovTx(uint64(l)) - return n -} - -func (m *MsgUpdateParamsResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - return n -} - -func sovTx(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozTx(x uint64) (n int) { - return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *MsgUpdateParams) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgUpdateParams: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateParams: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Authority", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Authority = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgUpdateParamsResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgUpdateParamsResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgUpdateParamsResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipTx(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTx - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTx - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTx - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthTx - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupTx - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthTx - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") -) From 9b973c911a914e1ce25c268dfff9129e83ea3fa0 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Tue, 31 Oct 2023 04:22:52 -0400 Subject: [PATCH 08/18] handle storing contract with gov module --- .github/workflows/interchaintest-E2E.yml | 2 +- app/upgrades/v4/headstash-contract.go | 56 ++++++++++++++++++++++++ app/upgrades/v4/upgrade.go | 5 ++- go.mod | 8 ++-- go.sum | 18 ++++---- interchaintest/go.mod | 14 +++--- interchaintest/go.sum | 28 ++++++------ 7 files changed, 95 insertions(+), 36 deletions(-) create mode 100644 app/upgrades/v4/headstash-contract.go diff --git a/.github/workflows/interchaintest-E2E.yml b/.github/workflows/interchaintest-E2E.yml index dd1866c..1a3c443 100644 --- a/.github/workflows/interchaintest-E2E.yml +++ b/.github/workflows/interchaintest-E2E.yml @@ -70,7 +70,7 @@ jobs: # - "ictest-drip" - "ictest-burn" # - "ictest-cwhooks" - - "ictest-clock" + # - "ictest-clock" fail-fast: false steps: diff --git a/app/upgrades/v4/headstash-contract.go b/app/upgrades/v4/headstash-contract.go new file mode 100644 index 0000000..9a7a078 --- /dev/null +++ b/app/upgrades/v4/headstash-contract.go @@ -0,0 +1,56 @@ +package v4 + +import ( + "embed" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/terpnetwork/terp-core/v2/app/keepers" +) + +//go:embed headstash_contract.wasm + +var embedFs embed.FS + +func setupHeadstashContract(ctx sdk.Context, keepers *keepers.AppKeepers) error { + logger := ctx.Logger() + // set the gov module address + govModule := keepers.AccountKeeper.GetModuleAddress(govtypes.ModuleName) + // define the headstash patch contract + code, err := embedFs.ReadFile("headstash_contract.wasm") + if err != nil { + return err + } + // define instantiate permissions + instantiateConfig := wasmtypes.AccessConfig{Permission: wasmtypes.AccessTypeNobody} + contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(keepers.WasmKeeper) + // store wasm contract + codeID, _, err := contractKeeper.Create(ctx, govModule, code, &instantiateConfig) + if err != nil { + return err + } + // define instantiate msg + initMsgBz := []byte(fmt.Sprintf(`{ + "owner": "%s", + "claim_msg_plaintext": "%s" + }`, + govModule, "{address}")) + // instantiate contract + addr, _, err := contractKeeper.Instantiate(ctx, codeID, govModule, govModule, initMsgBz, "headstash patch contract", nil) + if err != nil { + return err + } + // format contract bytes to bech32 addr + addrStr, err := sdk.Bech32ifyAddressBytes("terp", addr) + if err != nil { + return err + } + // print results + logger.Info(fmt.Sprintf("instatiated headstash patch contract: %s", addrStr)) + + return nil +} diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go index 3678d57..953347e 100644 --- a/app/upgrades/v4/upgrade.go +++ b/app/upgrades/v4/upgrade.go @@ -41,7 +41,10 @@ func CreateV4UpgradeHandler( // revert headstash allocation ReturnFundsToCommunityPool(ctx, keepers.DistrKeeper, keepers.BankKeeper) - // TODO: handle deployment & instantiation of headstash patch contract + // deployment & instantiation of headstash patch contract + if err := setupHeadstashContract(ctx, keepers); err != nil { + return nil, err + } return vm, nil } diff --git a/go.mod b/go.mod index d5cbdef..eba5108 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.16.0 + github.com/prometheus/client_golang v1.17.0 github.com/rakyll/statik v0.1.7 // indirect github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa github.com/spf13/cast v1.5.1 @@ -149,9 +149,9 @@ require ( github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/cors v1.8.3 // indirect diff --git a/go.sum b/go.sum index 79871eb..cfc5cf7 100644 --- a/go.sum +++ b/go.sum @@ -843,32 +843,32 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -1170,7 +1170,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= 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= diff --git a/interchaintest/go.mod b/interchaintest/go.mod index c49bca0..c044156 100644 --- a/interchaintest/go.mod +++ b/interchaintest/go.mod @@ -16,7 +16,7 @@ replace ( ) require ( - github.com/CosmWasm/wasmd v0.41.0 + github.com/CosmWasm/wasmd v0.43.0 github.com/cosmos/cosmos-sdk v0.47.5 github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/ibc-go/v7 v7.3.0 @@ -47,7 +47,7 @@ require ( github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/ChainSafe/go-schnorrkel/1 v0.0.0-00010101000000-000000000000 // indirect github.com/ComposableFi/go-subkey/v2 v2.0.0-tm03420 // indirect - github.com/CosmWasm/wasmvm v1.3.0 // indirect + github.com/CosmWasm/wasmvm v1.4.1 // indirect github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect github.com/Microsoft/go-winio v0.6.0 // indirect @@ -75,7 +75,7 @@ require ( github.com/cosmos/cosmos-proto v1.0.0-beta.3 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect - github.com/cosmos/iavl v0.20.0 // indirect + github.com/cosmos/iavl v0.20.1 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ledger-cosmos-go v0.12.2 // indirect github.com/cosmos/rosetta-sdk-go v0.10.0 // indirect @@ -183,10 +183,10 @@ require ( github.com/pierrec/xxHash v0.1.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect - github.com/prometheus/client_model v0.3.0 // indirect - github.com/prometheus/common v0.42.0 // indirect - github.com/prometheus/procfs v0.10.1 // indirect + github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect github.com/rakyll/statik v0.1.7 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect diff --git a/interchaintest/go.sum b/interchaintest/go.sum index 240a8cc..1ec361f 100644 --- a/interchaintest/go.sum +++ b/interchaintest/go.sum @@ -219,10 +219,10 @@ github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRr github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/ComposableFi/go-subkey/v2 v2.0.0-tm03420 h1:oknQF/iIhf5lVjbwjsVDzDByupRhga8nhA3NAmwyHDA= github.com/ComposableFi/go-subkey/v2 v2.0.0-tm03420/go.mod h1:KYkiMX5AbOlXXYfxkrYPrRPV6EbVUALTQh5ptUOJzu8= -github.com/CosmWasm/wasmd v0.41.0 h1:fmwxSbwb50zZDcBaayYFRLIaSFca+EFld1WOaQi49jg= -github.com/CosmWasm/wasmd v0.41.0/go.mod h1:0Sds1q2IsPaTN1gHa3BNOYcUFgtGvxH7CXEXPgoihns= -github.com/CosmWasm/wasmvm v1.3.0 h1:x12X4bKlUPS7TT9QQP45+fJo2sp30GEbiSSgb9jsec8= -github.com/CosmWasm/wasmvm v1.3.0/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc= +github.com/CosmWasm/wasmd v0.43.0 h1:4xQAiNf6Ej+TuYe4PXwrtVJ9C+xyFrbsdqHH/kU9Vxk= +github.com/CosmWasm/wasmd v0.43.0/go.mod h1:gpri8YvkRErBz+qDme5jOThGZmSlHfyN532bWibXOl4= +github.com/CosmWasm/wasmvm v1.4.1 h1:YgodVlBrXa2HJZzOXjWDH0EIRwQzK3zuA73dDPRRLS4= +github.com/CosmWasm/wasmvm v1.4.1/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= @@ -358,8 +358,8 @@ github.com/cosmos/gogogateway v1.2.0/go.mod h1:iQpLkGWxYcnCdz5iAdLcRBSw3h7NXeOkZ github.com/cosmos/gogoproto v1.4.2/go.mod h1:cLxOsn1ljAHSV527CHOtaIP91kK6cCrZETRBrkzItWU= github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoKuI= github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek= -github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38= -github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= +github.com/cosmos/iavl v0.20.1 h1:rM1kqeG3/HBT85vsZdoSNsehciqUQPWrR4BYmqE2+zg= +github.com/cosmos/iavl v0.20.1/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A= github.com/cosmos/ibc-go/v7 v7.3.0 h1:QtGeVMi/3JeLWuvEuC60sBHpAF40Oenx/y+bP8+wRRw= github.com/cosmos/ibc-go/v7 v7.3.0/go.mod h1:mUmaHFXpXrEdcxfdXyau+utZf14pGKVUiXwYftRZZfQ= github.com/cosmos/ics23/go v0.10.0 h1:iXqLLgp2Lp+EdpIuwXTYIQU+AiHj9mOC2X9ab++bZDM= @@ -916,32 +916,32 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= -github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= From 01f9188f294e63d16c4f3c4ba1301173de8e47e1 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Tue, 31 Oct 2023 04:24:17 -0400 Subject: [PATCH 09/18] revert ictest dep bump --- interchaintest/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interchaintest/go.mod b/interchaintest/go.mod index c044156..c3cac88 100644 --- a/interchaintest/go.mod +++ b/interchaintest/go.mod @@ -16,7 +16,7 @@ replace ( ) require ( - github.com/CosmWasm/wasmd v0.43.0 + github.com/CosmWasm/wasmd v0.41.0 github.com/cosmos/cosmos-sdk v0.47.5 github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/ibc-go/v7 v7.3.0 From 7f91d0a7842872913ba2e686a71a1cc0d8a26831 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Tue, 31 Oct 2023 04:24:44 -0400 Subject: [PATCH 10/18] ictest go mod tidy --- interchaintest/go.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interchaintest/go.sum b/interchaintest/go.sum index 1ec361f..d485e32 100644 --- a/interchaintest/go.sum +++ b/interchaintest/go.sum @@ -219,8 +219,8 @@ github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRr github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/ComposableFi/go-subkey/v2 v2.0.0-tm03420 h1:oknQF/iIhf5lVjbwjsVDzDByupRhga8nhA3NAmwyHDA= github.com/ComposableFi/go-subkey/v2 v2.0.0-tm03420/go.mod h1:KYkiMX5AbOlXXYfxkrYPrRPV6EbVUALTQh5ptUOJzu8= -github.com/CosmWasm/wasmd v0.43.0 h1:4xQAiNf6Ej+TuYe4PXwrtVJ9C+xyFrbsdqHH/kU9Vxk= -github.com/CosmWasm/wasmd v0.43.0/go.mod h1:gpri8YvkRErBz+qDme5jOThGZmSlHfyN532bWibXOl4= +github.com/CosmWasm/wasmd v0.41.0 h1:fmwxSbwb50zZDcBaayYFRLIaSFca+EFld1WOaQi49jg= +github.com/CosmWasm/wasmd v0.41.0/go.mod h1:0Sds1q2IsPaTN1gHa3BNOYcUFgtGvxH7CXEXPgoihns= github.com/CosmWasm/wasmvm v1.4.1 h1:YgodVlBrXa2HJZzOXjWDH0EIRwQzK3zuA73dDPRRLS4= github.com/CosmWasm/wasmvm v1.4.1/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= From 554219d614e6143db4e6b617601dbad8b54fdc7c Mon Sep 17 00:00:00 2001 From: hard-nett Date: Wed, 1 Nov 2023 08:01:31 -0400 Subject: [PATCH 11/18] add v4 upgrade --- Dockerfile | 8 +++---- app/keepers/keepers.go | 2 +- app/upgrades/v4/headstash-contract.go | 30 +++++++++++++++++++++--- app/upgrades/v4/headstash-patch.go | 6 ++--- app/upgrades/v4/headstash_contract.wasm | Bin 0 -> 208582 bytes app/upgrades/v4/upgrade.go | 4 +++- app/wasm_config.go | 10 ++++---- go.mod | 6 ++--- go.sum | 12 +++++----- 9 files changed, 52 insertions(+), 26 deletions(-) create mode 100644 app/upgrades/v4/headstash_contract.wasm diff --git a/Dockerfile b/Dockerfile index 8656d71..bd33cbe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,10 +15,10 @@ RUN apk add git WORKDIR /code COPY . /code/ # See https://github.com/CosmWasm/wasmvm/releases -ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.3.0/libwasmvm_muslc.aarch64.a /lib/libwasmvm_muslc.aarch64.a -ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.3.0/libwasmvm_muslc.x86_64.a /lib/libwasmvm_muslc.x86_64.a -RUN sha256sum /lib/libwasmvm_muslc.aarch64.a | grep b1610f9c8ad8bdebf5b8f819f71d238466f83521c74a2deb799078932e862722 -RUN sha256sum /lib/libwasmvm_muslc.x86_64.a | grep b4aad4480f9b4c46635b4943beedbb72c929eab1d1b9467fe3b43e6dbf617e32 +ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.4.0/libwasmvm_muslc.aarch64.a /lib/libwasmvm_muslc.aarch64.a +ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.4.0/libwasmvm_muslc.x86_64.a /lib/libwasmvm_muslc.x86_64.a +RUN sha256sum /lib/libwasmvm_muslc.aarch64.a | grep 2a72c7062e3c791792b3dab781c815c9a76083a7997ce6f9f2799aaf577f3c25 +RUN sha256sum /lib/libwasmvm_muslc.x86_64.a | grep 8ea2e3b5fae83e671da2bb51115adc88591045953f509955ec38dc02ea5a7b94 # Copy the library you want to the final location that will be found by the linker flag `-lwasmvm_muslc` RUN cp /lib/libwasmvm_muslc.${arch}.a /lib/libwasmvm_muslc.a diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 879ef57..61ff50c 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -110,7 +110,7 @@ import ( ) var ( - wasmCapabilities = "iterator,staking,stargate,token_factory,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,tokenfactory" + wasmCapabilities = "iterator,staking,stargate,token_factory,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,cosmwasm_1_4,tokenfactory" tokenFactoryCapabilities = []string{ tokenfactorytypes.EnableBurnFrom, diff --git a/app/upgrades/v4/headstash-contract.go b/app/upgrades/v4/headstash-contract.go index 9a7a078..827c7af 100644 --- a/app/upgrades/v4/headstash-contract.go +++ b/app/upgrades/v4/headstash-contract.go @@ -10,10 +10,10 @@ import ( wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/terpnetwork/terp-core/v2/app/keepers" + "github.com/terpnetwork/terp-core/v2/app/upgrades" ) //go:embed headstash_contract.wasm - var embedFs embed.FS func setupHeadstashContract(ctx sdk.Context, keepers *keepers.AppKeepers) error { @@ -33,12 +33,17 @@ func setupHeadstashContract(ctx sdk.Context, keepers *keepers.AppKeepers) error if err != nil { return err } + // define claim_msg + const claimMsg = "{wallet}" + // define merkle_root string + const merkleRoot = "77fb25152b72ac67f5a155461e396b0788dd0567ec32a96f8201b899ad516b02" // define instantiate msg initMsgBz := []byte(fmt.Sprintf(`{ "owner": "%s", "claim_msg_plaintext": "%s" + "merkle_root": "%s" }`, - govModule, "{address}")) + govModule, claimMsg, merkleRoot)) // instantiate contract addr, _, err := contractKeeper.Instantiate(ctx, codeID, govModule, govModule, initMsgBz, "headstash patch contract", nil) if err != nil { @@ -50,7 +55,26 @@ func setupHeadstashContract(ctx sdk.Context, keepers *keepers.AppKeepers) error return err } // print results - logger.Info(fmt.Sprintf("instatiated headstash patch contract: %s", addrStr)) + logger.Info(fmt.Sprintf("instantiated headstash patch contract: %s", addrStr)) + + // define token denominations + nativeDenom := upgrades.GetChainsDenomToken(ctx.ChainID()) + nativeFeeDenom := upgrades.GetChainsFeeDenomToken(ctx.ChainID()) + // define total amount of tokens per each denom + amount := int64(123456789) + terpcoins := sdk.NewCoins( + sdk.NewInt64Coin(nativeDenom, amount), + ) + thiolcoins := sdk.NewCoins( + sdk.NewInt64Coin(nativeFeeDenom, amount), + ) + // send tokens from gov module to headstash-contract + if err := keepers.DistrKeeper.DistributeFromFeePool(ctx, terpcoins, addr); err != nil { + panic(err) + } + if err := keepers.DistrKeeper.DistributeFromFeePool(ctx, thiolcoins, addr); err != nil { + panic(err) + } return nil } diff --git a/app/upgrades/v4/headstash-patch.go b/app/upgrades/v4/headstash-patch.go index 56fcdc8..882977d 100644 --- a/app/upgrades/v4/headstash-patch.go +++ b/app/upgrades/v4/headstash-patch.go @@ -14,11 +14,11 @@ import ( ) // revert headstash allocation by depositing funds back into community pool -func ReturnFundsToCommunityPool( +func returnFundsToCommunityPool( ctx sdk.Context, dk distrkeeper.Keeper, bk bankkeeper.Keeper, -) { +) error { headstashes := v3.GetHeadstashPayments() total := int64(0) @@ -50,7 +50,7 @@ func ReturnFundsToCommunityPool( } total += amount } - + return nil } // TODO: handle headstash-patch contract upload & instantiation diff --git a/app/upgrades/v4/headstash_contract.wasm b/app/upgrades/v4/headstash_contract.wasm new file mode 100644 index 0000000000000000000000000000000000000000..61795253769c2f7c076ed848113911d11ce3e48d GIT binary patch literal 208582 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 Date: Wed, 1 Nov 2023 13:14:39 -0400 Subject: [PATCH 12/18] v4 upgrade --- app/upgrades/v4/headstash-contract.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/upgrades/v4/headstash-contract.go b/app/upgrades/v4/headstash-contract.go index 827c7af..f021cd6 100644 --- a/app/upgrades/v4/headstash-contract.go +++ b/app/upgrades/v4/headstash-contract.go @@ -26,7 +26,7 @@ func setupHeadstashContract(ctx sdk.Context, keepers *keepers.AppKeepers) error return err } // define instantiate permissions - instantiateConfig := wasmtypes.AccessConfig{Permission: wasmtypes.AccessTypeNobody} + instantiateConfig := wasmtypes.AccessConfig{Permission: wasmtypes.AccessTypeEverybody} contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(keepers.WasmKeeper) // store wasm contract codeID, _, err := contractKeeper.Create(ctx, govModule, code, &instantiateConfig) @@ -40,7 +40,7 @@ func setupHeadstashContract(ctx sdk.Context, keepers *keepers.AppKeepers) error // define instantiate msg initMsgBz := []byte(fmt.Sprintf(`{ "owner": "%s", - "claim_msg_plaintext": "%s" + "claim_msg_plaintext": "%s", "merkle_root": "%s" }`, govModule, claimMsg, merkleRoot)) From c6a59e0b22a771b519fc3e7adfec3e81016f0184 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Wed, 1 Nov 2023 21:33:23 -0400 Subject: [PATCH 13/18] print burn mod addr --- app/upgrades/v4/upgrade.go | 5 +++++ draft_proposal.json | 20 -------------------- 2 files changed, 5 insertions(+), 20 deletions(-) delete mode 100644 draft_proposal.json diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go index fc3026a..642e5f8 100644 --- a/app/upgrades/v4/upgrade.go +++ b/app/upgrades/v4/upgrade.go @@ -9,6 +9,7 @@ import ( "github.com/terpnetwork/terp-core/v2/app/keepers" "github.com/terpnetwork/terp-core/v2/app/upgrades" + "github.com/terpnetwork/terp-core/v2/x/burn" globalfeetypes "github.com/terpnetwork/terp-core/v2/x/globalfee/types" ) @@ -43,6 +44,10 @@ func CreateV4UpgradeHandler( return nil, err } + // print the burn module address + burnModule := keepers.AccountKeeper.GetModuleAddress(burn.ModuleName) + logger.Info(fmt.Sprintf("burn module address %s", burnModule)) + // deployment & instantiation of headstash patch contract if err := setupHeadstashContract(ctx, keepers); err != nil { return nil, err diff --git a/draft_proposal.json b/draft_proposal.json deleted file mode 100644 index 24692a6..0000000 --- a/draft_proposal.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "messages": [ - { - "@type": "/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade", - "authority": "terp10d07y265gmmuvt4z0w9aw880jnsr700jag6fuq", - "plan": { - "name": "v3", - "time": "0001-01-01T00:00:00Z", - "height": "20", - "info": "", - "upgraded_client_state": null - } - } - ], - "metadata": "ipfs://CID", - "deposit": "1000000000uterp", - "title": "v3", - "summary": "test" - } - From df3d0fd44ecf9a614715a7b9e81ef6fc0d6d9f1a Mon Sep 17 00:00:00 2001 From: hard-nett Date: Wed, 1 Nov 2023 22:59:26 -0400 Subject: [PATCH 14/18] bump wasmd, wasmvm, go mod tidy --- Dockerfile | 8 ++++---- app/app.go | 19 ------------------- app/keepers/keepers.go | 6 ------ app/sim_test.go | 2 -- app/test_helpers.go | 2 -- cmd/terpd/cmd/root.go | 2 -- go.mod | 4 ++-- go.sum | 8 ++++---- interchaintest/chain_upgrade_test.go | 6 ++++-- interchaintest/go.mod | 4 ++-- interchaintest/go.sum | 8 ++++---- interchaintest/module_burn_test.go | 1 - x/feeshare/integration_test.go | 2 -- 13 files changed, 20 insertions(+), 52 deletions(-) diff --git a/Dockerfile b/Dockerfile index bd33cbe..d99aedc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,10 +15,10 @@ RUN apk add git WORKDIR /code COPY . /code/ # See https://github.com/CosmWasm/wasmvm/releases -ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.4.0/libwasmvm_muslc.aarch64.a /lib/libwasmvm_muslc.aarch64.a -ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.4.0/libwasmvm_muslc.x86_64.a /lib/libwasmvm_muslc.x86_64.a -RUN sha256sum /lib/libwasmvm_muslc.aarch64.a | grep 2a72c7062e3c791792b3dab781c815c9a76083a7997ce6f9f2799aaf577f3c25 -RUN sha256sum /lib/libwasmvm_muslc.x86_64.a | grep 8ea2e3b5fae83e671da2bb51115adc88591045953f509955ec38dc02ea5a7b94 +ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.5.0/libwasmvm_muslc.aarch64.a /lib/libwasmvm_muslc.aarch64.a +ADD https://github.com/CosmWasm/wasmvm/releases/download/v1.5.0/libwasmvm_muslc.x86_64.a /lib/libwasmvm_muslc.x86_64.a +RUN sha256sum /lib/libwasmvm_muslc.aarch64.a | grep 2687afbdae1bc6c7c8b05ae20dfb8ffc7ddc5b4e056697d0f37853dfe294e913 +RUN sha256sum /lib/libwasmvm_muslc.x86_64.a | grep 465e3a088e96fd009a11bfd234c69fb8a0556967677e54511c084f815cf9ce63 # Copy the library you want to the final location that will be found by the linker flag `-lwasmvm_muslc` RUN cp /lib/libwasmvm_muslc.${arch}.a /lib/libwasmvm_muslc.a diff --git a/app/app.go b/app/app.go index cfd9814..c71b5e8 100644 --- a/app/app.go +++ b/app/app.go @@ -156,23 +156,6 @@ func SetAddressPrefixes() { }) } -// GetEnabledProposals parses the ProposalsEnabled / EnableSpecificProposals values to -// produce a list of enabled proposals to pass into wasmd app. -func GetEnabledProposals() []wasmtypes.ProposalType { - if EnableSpecificProposals == "" { - if ProposalsEnabled == "true" { - return wasmtypes.EnableAllProposals - } - return wasmtypes.DisableAllProposals - } - chunks := strings.Split(EnableSpecificProposals, ",") - proposals, err := wasmtypes.ConvertToProposals(chunks) - if err != nil { - panic(err) - } - return proposals -} - func GetWasmOpts(appOpts servertypes.AppOptions) []wasmkeeper.Option { var wasmOpts []wasmkeeper.Option if cast.ToBool(appOpts.Get("telemetry.enabled")) { @@ -230,7 +213,6 @@ func NewTerpApp( db dbm.DB, traceStore io.Writer, loadLatest bool, - enabledProposals []wasmtypes.ProposalType, appOpts servertypes.AppOptions, wasmOpts []wasmkeeper.Option, baseAppOptions ...func(*baseapp.BaseApp), @@ -263,7 +245,6 @@ func NewTerpApp( bApp, legacyAmino, keepers.GetMaccPerms(), - enabledProposals, appOpts, wasmOpts, ) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 61ff50c..9dc4921 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -197,7 +197,6 @@ func NewAppKeepers( bApp *baseapp.BaseApp, cdc *codec.LegacyAmino, maccPerms map[string][]string, - enabledProposals []wasmtypes.ProposalType, appOpts servertypes.AppOptions, wasmOpts []wasmkeeper.Option, ) AppKeepers { @@ -582,11 +581,6 @@ func NewAppKeepers( // govModAddress, // ) - // The gov proposal types can be individually enabled - if len(enabledProposals) != 0 { - govRouter.AddRoute(wasmtypes.RouterKey, wasmkeeper.NewWasmProposalHandler(appKeepers.WasmKeeper, enabledProposals)) //nolint:staticcheck - } - // Set legacy router for backwards compatibility with gov v1beta1 appKeepers.GovKeeper.SetLegacyRouter(govRouter) diff --git a/app/sim_test.go b/app/sim_test.go index 2eca812..8a35117 100644 --- a/app/sim_test.go +++ b/app/sim_test.go @@ -7,7 +7,6 @@ import ( "testing" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" @@ -112,7 +111,6 @@ func TestFullAppSimulation(t *testing.T) { db, nil, true, - wasmtypes.EnableAllProposals, appOptions, emptyWasmOption, fauxMerkleModeOpt, diff --git a/app/test_helpers.go b/app/test_helpers.go index b485176..2fa8565 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -7,7 +7,6 @@ import ( "time" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" @@ -151,7 +150,6 @@ func setup(t *testing.T, withGenesis bool, opts ...wasmkeeper.Option) (*TerpApp, db, nil, true, - wasmtypes.EnableAllProposals, EmptyAppOptions{}, opts, bam.SetChainID("testing"), diff --git a/cmd/terpd/cmd/root.go b/cmd/terpd/cmd/root.go index 0735e58..d2da3bd 100644 --- a/cmd/terpd/cmd/root.go +++ b/cmd/terpd/cmd/root.go @@ -324,7 +324,6 @@ func (ac appCreator) newApp( db, traceStore, loadLatest, - app.GetEnabledProposals(), appOpts, wasmOpts, baseappOptions..., @@ -363,7 +362,6 @@ func (ac appCreator) appExport( db, traceStore, height == -1, - app.GetEnabledProposals(), appOpts, emptyWasmOpts, ) diff --git a/go.mod b/go.mod index cf6d65b..14534cc 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/terpnetwork/terp-core/v2 go 1.19 require ( - github.com/CosmWasm/wasmd v0.42.0 - github.com/CosmWasm/wasmvm v1.4.0 + github.com/CosmWasm/wasmd v0.43.0 + github.com/CosmWasm/wasmvm v1.5.0 github.com/cometbft/cometbft v0.37.2 github.com/cometbft/cometbft-db v0.8.0 github.com/cosmos/cosmos-proto v1.0.0-beta.3 diff --git a/go.sum b/go.sum index 7f59c26..998cc59 100644 --- a/go.sum +++ b/go.sum @@ -211,10 +211,10 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= -github.com/CosmWasm/wasmd v0.42.0 h1:4xZ7GHLrJp3P8qN0wsWOpk5qYLHW9AM5fgcDFPi/p90= -github.com/CosmWasm/wasmd v0.42.0/go.mod h1:DiEyBjHxzkEENYqQhHyka+r4HfR72stSPUtGv+Yh/UU= -github.com/CosmWasm/wasmvm v1.4.0 h1:84I3MlvvzcOo2z+ed0ztPi7eeDNk6/sYuK76uyXP1nI= -github.com/CosmWasm/wasmvm v1.4.0/go.mod h1:vW/E3h8j9xBQs9bCoijDuawKo9kCtxOaS8N8J7KFtkc= +github.com/CosmWasm/wasmd v0.43.0 h1:4xQAiNf6Ej+TuYe4PXwrtVJ9C+xyFrbsdqHH/kU9Vxk= +github.com/CosmWasm/wasmd v0.43.0/go.mod h1:gpri8YvkRErBz+qDme5jOThGZmSlHfyN532bWibXOl4= +github.com/CosmWasm/wasmvm v1.5.0 h1:3hKeT9SfwfLhxTGKH3vXaKFzBz1yuvP8SlfwfQXbQfw= +github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= diff --git a/interchaintest/chain_upgrade_test.go b/interchaintest/chain_upgrade_test.go index 268044d..54af505 100644 --- a/interchaintest/chain_upgrade_test.go +++ b/interchaintest/chain_upgrade_test.go @@ -1,5 +1,7 @@ package interchaintest +// notice: upgrade v4 will return error, as headstash accounts in v3 upgrade do not have balance during ictests. + import ( "context" "fmt" @@ -24,8 +26,8 @@ const ( func TestBasicTerpUpgrade(t *testing.T) { repo, version := GetDockerImageInfo() - startVersion := "v2.0.0" - upgradeName := "v3" + startVersion := "v3.0.0" + upgradeName := "v4.0.0" CosmosChainUpgradeTest(t, "terp", startVersion, version, repo, upgradeName) } diff --git a/interchaintest/go.mod b/interchaintest/go.mod index c3cac88..a606f05 100644 --- a/interchaintest/go.mod +++ b/interchaintest/go.mod @@ -16,7 +16,7 @@ replace ( ) require ( - github.com/CosmWasm/wasmd v0.41.0 + github.com/CosmWasm/wasmd v0.43.0 github.com/cosmos/cosmos-sdk v0.47.5 github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/ibc-go/v7 v7.3.0 @@ -47,7 +47,7 @@ require ( github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect github.com/ChainSafe/go-schnorrkel/1 v0.0.0-00010101000000-000000000000 // indirect github.com/ComposableFi/go-subkey/v2 v2.0.0-tm03420 // indirect - github.com/CosmWasm/wasmvm v1.4.1 // indirect + github.com/CosmWasm/wasmvm v1.5.0 // indirect github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect github.com/Microsoft/go-winio v0.6.0 // indirect diff --git a/interchaintest/go.sum b/interchaintest/go.sum index d485e32..5318d66 100644 --- a/interchaintest/go.sum +++ b/interchaintest/go.sum @@ -219,10 +219,10 @@ github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRr github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/ComposableFi/go-subkey/v2 v2.0.0-tm03420 h1:oknQF/iIhf5lVjbwjsVDzDByupRhga8nhA3NAmwyHDA= github.com/ComposableFi/go-subkey/v2 v2.0.0-tm03420/go.mod h1:KYkiMX5AbOlXXYfxkrYPrRPV6EbVUALTQh5ptUOJzu8= -github.com/CosmWasm/wasmd v0.41.0 h1:fmwxSbwb50zZDcBaayYFRLIaSFca+EFld1WOaQi49jg= -github.com/CosmWasm/wasmd v0.41.0/go.mod h1:0Sds1q2IsPaTN1gHa3BNOYcUFgtGvxH7CXEXPgoihns= -github.com/CosmWasm/wasmvm v1.4.1 h1:YgodVlBrXa2HJZzOXjWDH0EIRwQzK3zuA73dDPRRLS4= -github.com/CosmWasm/wasmvm v1.4.1/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= +github.com/CosmWasm/wasmd v0.43.0 h1:4xQAiNf6Ej+TuYe4PXwrtVJ9C+xyFrbsdqHH/kU9Vxk= +github.com/CosmWasm/wasmd v0.43.0/go.mod h1:gpri8YvkRErBz+qDme5jOThGZmSlHfyN532bWibXOl4= +github.com/CosmWasm/wasmvm v1.5.0 h1:3hKeT9SfwfLhxTGKH3vXaKFzBz1yuvP8SlfwfQXbQfw= +github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc= github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw= diff --git a/interchaintest/module_burn_test.go b/interchaintest/module_burn_test.go index 6e79fe9..936eeaf 100644 --- a/interchaintest/module_burn_test.go +++ b/interchaintest/module_burn_test.go @@ -13,7 +13,6 @@ import ( ) // TestTerpBurnModule ensures the terpburn module register and execute sharing functions work properly on smart contracts. -// This is required due to how x/mint handles minting tokens for the target supply. // It is purely for developers ::BurnTokens to function as expected. func TestTerpBurnModule(t *testing.T) { t.Parallel() diff --git a/x/feeshare/integration_test.go b/x/feeshare/integration_test.go index 27e6460..a0ee14a 100644 --- a/x/feeshare/integration_test.go +++ b/x/feeshare/integration_test.go @@ -6,7 +6,6 @@ import ( "testing" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/stretchr/testify/require" dbm "github.com/cometbft/cometbft-db" @@ -79,7 +78,6 @@ func GenApp(t *testing.T, withGenesis bool, opts ...wasmkeeper.Option) (*terpapp db, nil, true, - wasmtypes.EnableAllProposals, simtestutil.EmptyAppOptions{}, opts, bam.SetChainID("testing"), From b8a8b1acf71e801ab455ac1782a2bfe9bb9a886f Mon Sep 17 00:00:00 2001 From: hard-nett Date: Wed, 1 Nov 2023 23:04:06 -0400 Subject: [PATCH 15/18] bump v4 --- app/ante.go | 8 ++++---- app/app.go | 14 +++++++------- app/apptesting/test_suite.go | 4 ++-- app/encoding.go | 2 +- app/keepers/keepers.go | 18 +++++++++--------- app/keepers/keys.go | 6 +++--- app/modules.go | 12 ++++++------ app/test_helpers.go | 4 ++-- app/upgrades/types.go | 2 +- app/upgrades/v2/constants.go | 6 +++--- app/upgrades/v2/upgrade.go | 10 +++++----- app/upgrades/v3/constants.go | 2 +- app/upgrades/v3/headstash.go | 2 +- app/upgrades/v3/upgrade.go | 2 +- app/upgrades/v4/constants.go | 2 +- app/upgrades/v4/headstash-contract.go | 4 ++-- app/upgrades/v4/headstash-patch.go | 4 ++-- app/upgrades/v4/upgrade.go | 8 ++++---- cmd/terpd/cmd/balances_from_state_export.go | 2 +- cmd/terpd/cmd/root.go | 4 ++-- cmd/terpd/main.go | 4 ++-- go.mod | 2 +- interchaintest/helpers/tokenfactory.go | 2 +- interchaintest/setup.go | 4 ++-- .../v1beta1/authorityMetadata.proto | 2 +- .../osmosis/tokenfactory/v1beta1/genesis.proto | 2 +- .../osmosis/tokenfactory/v1beta1/params.proto | 2 +- proto/osmosis/tokenfactory/v1beta1/query.proto | 2 +- proto/osmosis/tokenfactory/v1beta1/tx.proto | 2 +- proto/terp/feeshare/v1/feeshare.proto | 2 +- proto/terp/feeshare/v1/genesis.proto | 2 +- proto/terp/feeshare/v1/query.proto | 2 +- proto/terp/feeshare/v1/tx.proto | 2 +- x/feeshare/ante/ante.go | 2 +- x/feeshare/ante/ante_test.go | 2 +- x/feeshare/ante/expected_keepers.go | 2 +- x/feeshare/client/cli/query.go | 2 +- x/feeshare/client/cli/tx.go | 2 +- x/feeshare/genesis.go | 4 ++-- x/feeshare/genesis_test.go | 6 +++--- x/feeshare/integration_test.go | 2 +- x/feeshare/keeper/feeshare.go | 2 +- x/feeshare/keeper/grpc_query.go | 2 +- x/feeshare/keeper/grpc_query_test.go | 4 ++-- x/feeshare/keeper/keeper.go | 2 +- x/feeshare/keeper/keeper_test.go | 6 +++--- x/feeshare/keeper/migrator.go | 4 ++-- x/feeshare/keeper/msg_server.go | 2 +- x/feeshare/keeper/msg_server_test.go | 2 +- x/feeshare/keeper/params.go | 2 +- x/feeshare/migrations/v2/migrate.go | 4 ++-- x/feeshare/migrations/v2/migrate_test.go | 8 ++++---- x/feeshare/module.go | 8 ++++---- x/globalfee/alias.go | 2 +- .../ante/antetest/fee_test_setup.go.archive | 6 +++--- x/globalfee/ante/fee.go | 2 +- x/globalfee/client/cli/query.go | 2 +- x/globalfee/genesis_test.go | 6 +++--- x/globalfee/keeper/keeper.go | 2 +- x/globalfee/keeper/migrator.go | 2 +- x/globalfee/keeper/msg_server.go | 2 +- x/globalfee/migrations/v2/migrate.go | 2 +- x/globalfee/migrations/v2/migrator_test.go | 8 ++++---- x/globalfee/module.go | 6 +++--- x/globalfee/querier.go | 4 ++-- x/globalfee/querier_test.go | 4 ++-- x/tokenfactory/bindings/custom_msg_test.go | 6 +++--- x/tokenfactory/bindings/custom_query_test.go | 4 ++-- x/tokenfactory/bindings/helpers_test.go | 2 +- x/tokenfactory/bindings/message_plugin.go | 6 +++--- x/tokenfactory/bindings/queries.go | 4 ++-- x/tokenfactory/bindings/query_plugin.go | 2 +- x/tokenfactory/bindings/validate_msg_test.go | 6 +++--- .../bindings/validate_queries_test.go | 2 +- x/tokenfactory/bindings/wasm.go | 2 +- x/tokenfactory/client/cli/query.go | 2 +- x/tokenfactory/client/cli/tx.go | 2 +- x/tokenfactory/keeper/admins.go | 2 +- x/tokenfactory/keeper/admins_test.go | 2 +- x/tokenfactory/keeper/bankactions.go | 2 +- x/tokenfactory/keeper/createdenom.go | 2 +- x/tokenfactory/keeper/createdenom_test.go | 4 ++-- x/tokenfactory/keeper/genesis.go | 2 +- x/tokenfactory/keeper/genesis_test.go | 2 +- x/tokenfactory/keeper/grpc_query.go | 2 +- x/tokenfactory/keeper/keeper.go | 2 +- x/tokenfactory/keeper/keeper_test.go | 6 +++--- x/tokenfactory/keeper/migrator.go | 4 ++-- x/tokenfactory/keeper/msg_server.go | 2 +- x/tokenfactory/keeper/msg_server_test.go | 2 +- x/tokenfactory/keeper/params.go | 2 +- x/tokenfactory/migrations/v2/migrate.go | 4 ++-- x/tokenfactory/migrations/v2/migrate_test.go | 8 ++++---- x/tokenfactory/module.go | 10 +++++----- x/tokenfactory/simulation/genesis.go | 4 ++-- x/tokenfactory/simulation/operations.go | 4 ++-- x/tokenfactory/types/denoms_test.go | 2 +- x/tokenfactory/types/genesis_test.go | 2 +- x/tokenfactory/types/msgs_test.go | 4 ++-- 99 files changed, 187 insertions(+), 187 deletions(-) diff --git a/app/ante.go b/app/ante.go index 9f719e4..fa3566f 100644 --- a/app/ante.go +++ b/app/ante.go @@ -13,10 +13,10 @@ import ( ibcante "github.com/cosmos/ibc-go/v7/modules/core/ante" "github.com/cosmos/ibc-go/v7/modules/core/keeper" - feeshareante "github.com/terpnetwork/terp-core/v2/x/feeshare/ante" - feesharekeeper "github.com/terpnetwork/terp-core/v2/x/feeshare/keeper" - globalfeeante "github.com/terpnetwork/terp-core/v2/x/globalfee/ante" - globalfeekeeper "github.com/terpnetwork/terp-core/v2/x/globalfee/keeper" + feeshareante "github.com/terpnetwork/terp-core/v4/x/feeshare/ante" + feesharekeeper "github.com/terpnetwork/terp-core/v4/x/feeshare/keeper" + globalfeeante "github.com/terpnetwork/terp-core/v4/x/globalfee/ante" + globalfeekeeper "github.com/terpnetwork/terp-core/v4/x/globalfee/keeper" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" diff --git a/app/app.go b/app/app.go index c71b5e8..14309f9 100644 --- a/app/app.go +++ b/app/app.go @@ -62,18 +62,18 @@ import ( govclient "github.com/cosmos/cosmos-sdk/x/gov/client" - "github.com/terpnetwork/terp-core/v2/app/openapiconsole" - v2 "github.com/terpnetwork/terp-core/v2/app/upgrades/v2" - v3 "github.com/terpnetwork/terp-core/v2/app/upgrades/v3" - v4 "github.com/terpnetwork/terp-core/v2/app/upgrades/v4" - "github.com/terpnetwork/terp-core/v2/docs" + "github.com/terpnetwork/terp-core/v4/app/openapiconsole" + v2 "github.com/terpnetwork/terp-core/v4/app/upgrades/v2" + v3 "github.com/terpnetwork/terp-core/v4/app/upgrades/v3" + v4 "github.com/terpnetwork/terp-core/v4/app/upgrades/v4" + "github.com/terpnetwork/terp-core/v4/docs" "github.com/CosmWasm/wasmd/x/wasm" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/terpnetwork/terp-core/v2/app/keepers" - "github.com/terpnetwork/terp-core/v2/app/upgrades" + "github.com/terpnetwork/terp-core/v4/app/keepers" + "github.com/terpnetwork/terp-core/v4/app/upgrades" // unnamed import of statik for swagger UI support _ "github.com/cosmos/cosmos-sdk/client/docs/statik" // statik for swagger UI support diff --git a/app/apptesting/test_suite.go b/app/apptesting/test_suite.go index e3d9ee1..4a27355 100644 --- a/app/apptesting/test_suite.go +++ b/app/apptesting/test_suite.go @@ -34,8 +34,8 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - "github.com/terpnetwork/terp-core/v2/app" - appparams "github.com/terpnetwork/terp-core/v2/app/params" + "github.com/terpnetwork/terp-core/v4/app" + appparams "github.com/terpnetwork/terp-core/v4/app/params" ) type KeeperTestHelper struct { diff --git a/app/encoding.go b/app/encoding.go index 8ebe3ed..770e2af 100644 --- a/app/encoding.go +++ b/app/encoding.go @@ -3,7 +3,7 @@ package app import ( "github.com/cosmos/cosmos-sdk/std" - "github.com/terpnetwork/terp-core/v2/app/params" + "github.com/terpnetwork/terp-core/v4/app/params" ) // MakeEncodingConfig creates a new EncodingConfig with all modules registered diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 9dc4921..9ff987d 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -92,21 +92,21 @@ import ( upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - denomburn "github.com/terpnetwork/terp-core/v2/x/burn" + denomburn "github.com/terpnetwork/terp-core/v4/x/burn" // clockkeeper "github.com/terpnetwork/terp-core/v2/x/clock/keeper" // clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" - feesharekeeper "github.com/terpnetwork/terp-core/v2/x/feeshare/keeper" - feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + feesharekeeper "github.com/terpnetwork/terp-core/v4/x/feeshare/keeper" + feesharetypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" - "github.com/terpnetwork/terp-core/v2/x/globalfee" - globalfeekeeper "github.com/terpnetwork/terp-core/v2/x/globalfee/keeper" - globalfeetypes "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee" + globalfeekeeper "github.com/terpnetwork/terp-core/v4/x/globalfee/keeper" + globalfeetypes "github.com/terpnetwork/terp-core/v4/x/globalfee/types" // token factory - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/bindings" - tokenfactorykeeper "github.com/terpnetwork/terp-core/v2/x/tokenfactory/keeper" - tokenfactorytypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings" + tokenfactorykeeper "github.com/terpnetwork/terp-core/v4/x/tokenfactory/keeper" + tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) var ( diff --git a/app/keepers/keys.go b/app/keepers/keys.go index 6df5867..f3d13b7 100644 --- a/app/keepers/keys.go +++ b/app/keepers/keys.go @@ -26,9 +26,9 @@ import ( ibcfeetypes "github.com/cosmos/ibc-go/v7/modules/apps/29-fee/types" ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" - feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" - globalfeetypes "github.com/terpnetwork/terp-core/v2/x/globalfee/types" - tokenfactorytypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + feesharetypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" + globalfeetypes "github.com/terpnetwork/terp-core/v4/x/globalfee/types" + tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v7/types" diff --git a/app/modules.go b/app/modules.go index 46d1f0b..9aee3bc 100644 --- a/app/modules.go +++ b/app/modules.go @@ -60,17 +60,17 @@ import ( "github.com/cosmos/cosmos-sdk/x/upgrade" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - encparams "github.com/terpnetwork/terp-core/v2/app/params" - "github.com/terpnetwork/terp-core/v2/x/feeshare" - feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" - "github.com/terpnetwork/terp-core/v2/x/globalfee" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory" + encparams "github.com/terpnetwork/terp-core/v4/app/params" + "github.com/terpnetwork/terp-core/v4/x/feeshare" + feesharetypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory" "github.com/cosmos/cosmos-sdk/x/group" ibchooks "github.com/cosmos/ibc-apps/modules/ibc-hooks/v7" ibchookstypes "github.com/cosmos/ibc-apps/modules/ibc-hooks/v7/types" - tokenfactorytypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" groupmodule "github.com/cosmos/cosmos-sdk/x/group/module" ) diff --git a/app/test_helpers.go b/app/test_helpers.go index 2fa8565..f310a9f 100644 --- a/app/test_helpers.go +++ b/app/test_helpers.go @@ -32,8 +32,8 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - apphelpers "github.com/terpnetwork/terp-core/v2/app/helpers" - appparams "github.com/terpnetwork/terp-core/v2/app/params" + apphelpers "github.com/terpnetwork/terp-core/v4/app/helpers" + appparams "github.com/terpnetwork/terp-core/v4/app/params" ) // EmptyBaseAppOptions is a stub implementing AppOptions diff --git a/app/upgrades/types.go b/app/upgrades/types.go index 25286f5..6c441a8 100644 --- a/app/upgrades/types.go +++ b/app/upgrades/types.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - "github.com/terpnetwork/terp-core/v2/app/keepers" + "github.com/terpnetwork/terp-core/v4/app/keepers" ) // BaseAppParamManager defines an interrace that BaseApp is expected to fullfil diff --git a/app/upgrades/v2/constants.go b/app/upgrades/v2/constants.go index d7afd4c..4f9b869 100644 --- a/app/upgrades/v2/constants.go +++ b/app/upgrades/v2/constants.go @@ -5,12 +5,12 @@ import ( icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v7/types" ibchookstypes "github.com/cosmos/ibc-apps/modules/ibc-hooks/v7/types" - feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" - globalfeetypes "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + feesharetypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" + globalfeetypes "github.com/terpnetwork/terp-core/v4/x/globalfee/types" store "github.com/cosmos/cosmos-sdk/store/types" - "github.com/terpnetwork/terp-core/v2/app/upgrades" + "github.com/terpnetwork/terp-core/v4/app/upgrades" ) const UpgradeName = "v2" diff --git a/app/upgrades/v2/upgrade.go b/app/upgrades/v2/upgrade.go index 885b194..25e2c37 100644 --- a/app/upgrades/v2/upgrade.go +++ b/app/upgrades/v2/upgrade.go @@ -7,18 +7,18 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + feesharetypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" - globalfeetypes "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + globalfeetypes "github.com/terpnetwork/terp-core/v4/x/globalfee/types" - tokenfactorytypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v7/types" packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v7/router/types" - "github.com/terpnetwork/terp-core/v2/app/keepers" - "github.com/terpnetwork/terp-core/v2/app/upgrades" + "github.com/terpnetwork/terp-core/v4/app/keepers" + "github.com/terpnetwork/terp-core/v4/app/upgrades" ) // We now charge 2 million gas * gas price to create a denom. diff --git a/app/upgrades/v3/constants.go b/app/upgrades/v3/constants.go index 31b5b19..a56da57 100644 --- a/app/upgrades/v3/constants.go +++ b/app/upgrades/v3/constants.go @@ -1,7 +1,7 @@ package v3 import ( - "github.com/terpnetwork/terp-core/v2/app/upgrades" + "github.com/terpnetwork/terp-core/v4/app/upgrades" store "github.com/cosmos/cosmos-sdk/store/types" ) diff --git a/app/upgrades/v3/headstash.go b/app/upgrades/v3/headstash.go index 57c066b..bd0691c 100644 --- a/app/upgrades/v3/headstash.go +++ b/app/upgrades/v3/headstash.go @@ -10,7 +10,7 @@ import ( bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" - "github.com/terpnetwork/terp-core/v2/app/upgrades" + "github.com/terpnetwork/terp-core/v4/app/upgrades" ) func HeadStash( diff --git a/app/upgrades/v3/upgrade.go b/app/upgrades/v3/upgrade.go index 89560fb..c88c4e7 100644 --- a/app/upgrades/v3/upgrade.go +++ b/app/upgrades/v3/upgrade.go @@ -5,7 +5,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - "github.com/terpnetwork/terp-core/v2/app/keepers" + "github.com/terpnetwork/terp-core/v4/app/keepers" ) // CreateUpgradeHandler creates an SDK upgrade handler for v2 diff --git a/app/upgrades/v4/constants.go b/app/upgrades/v4/constants.go index f60e754..9cfe900 100644 --- a/app/upgrades/v4/constants.go +++ b/app/upgrades/v4/constants.go @@ -1,7 +1,7 @@ package v4 import ( - "github.com/terpnetwork/terp-core/v2/app/upgrades" + "github.com/terpnetwork/terp-core/v4/app/upgrades" store "github.com/cosmos/cosmos-sdk/store/types" ) diff --git a/app/upgrades/v4/headstash-contract.go b/app/upgrades/v4/headstash-contract.go index f021cd6..4430fc3 100644 --- a/app/upgrades/v4/headstash-contract.go +++ b/app/upgrades/v4/headstash-contract.go @@ -9,8 +9,8 @@ import ( wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/terpnetwork/terp-core/v2/app/keepers" - "github.com/terpnetwork/terp-core/v2/app/upgrades" + "github.com/terpnetwork/terp-core/v4/app/keepers" + "github.com/terpnetwork/terp-core/v4/app/upgrades" ) //go:embed headstash_contract.wasm diff --git a/app/upgrades/v4/headstash-patch.go b/app/upgrades/v4/headstash-patch.go index 882977d..2f6db10 100644 --- a/app/upgrades/v4/headstash-patch.go +++ b/app/upgrades/v4/headstash-patch.go @@ -8,9 +8,9 @@ import ( bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" - "github.com/terpnetwork/terp-core/v2/app/upgrades" + "github.com/terpnetwork/terp-core/v4/app/upgrades" - v3 "github.com/terpnetwork/terp-core/v2/app/upgrades/v3" + v3 "github.com/terpnetwork/terp-core/v4/app/upgrades/v3" ) // revert headstash allocation by depositing funds back into community pool diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go index 642e5f8..1eddf66 100644 --- a/app/upgrades/v4/upgrade.go +++ b/app/upgrades/v4/upgrade.go @@ -7,10 +7,10 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" - "github.com/terpnetwork/terp-core/v2/app/keepers" - "github.com/terpnetwork/terp-core/v2/app/upgrades" - "github.com/terpnetwork/terp-core/v2/x/burn" - globalfeetypes "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/app/keepers" + "github.com/terpnetwork/terp-core/v4/app/upgrades" + "github.com/terpnetwork/terp-core/v4/x/burn" + globalfeetypes "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) // CreateUpgradeHandler creates an SDK upgrade handler for v4 diff --git a/cmd/terpd/cmd/balances_from_state_export.go b/cmd/terpd/cmd/balances_from_state_export.go index 2033484..facc5ba 100644 --- a/cmd/terpd/cmd/balances_from_state_export.go +++ b/cmd/terpd/cmd/balances_from_state_export.go @@ -23,7 +23,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - appparams "github.com/terpnetwork/terp-core/v2/app/params" + appparams "github.com/terpnetwork/terp-core/v4/app/params" ) const ( diff --git a/cmd/terpd/cmd/root.go b/cmd/terpd/cmd/root.go index d2da3bd..fd0c948 100644 --- a/cmd/terpd/cmd/root.go +++ b/cmd/terpd/cmd/root.go @@ -39,8 +39,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/crisis" genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" - "github.com/terpnetwork/terp-core/v2/app" - "github.com/terpnetwork/terp-core/v2/app/params" + "github.com/terpnetwork/terp-core/v4/app" + "github.com/terpnetwork/terp-core/v4/app/params" ) // NewRootCmd creates a new root command for terpd. It is called once in the diff --git a/cmd/terpd/main.go b/cmd/terpd/main.go index 846d63b..6adaa50 100644 --- a/cmd/terpd/main.go +++ b/cmd/terpd/main.go @@ -7,8 +7,8 @@ import ( svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" - "github.com/terpnetwork/terp-core/v2/app" - "github.com/terpnetwork/terp-core/v2/cmd/terpd/cmd" + "github.com/terpnetwork/terp-core/v4/app" + "github.com/terpnetwork/terp-core/v4/cmd/terpd/cmd" ) func main() { diff --git a/go.mod b/go.mod index 14534cc..7825f31 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/terpnetwork/terp-core/v2 +module github.com/terpnetwork/terp-core/v4 go 1.19 diff --git a/interchaintest/helpers/tokenfactory.go b/interchaintest/helpers/tokenfactory.go index a7723e8..bd39930 100644 --- a/interchaintest/helpers/tokenfactory.go +++ b/interchaintest/helpers/tokenfactory.go @@ -9,7 +9,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - tokenfactorytypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" diff --git a/interchaintest/setup.go b/interchaintest/setup.go index 89ad11b..486caa3 100644 --- a/interchaintest/setup.go +++ b/interchaintest/setup.go @@ -16,8 +16,8 @@ import ( "go.uber.org/zap/zaptest" // clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" - feesharetypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" - tokenfactorytypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + feesharetypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" + tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" sdk "github.com/cosmos/cosmos-sdk/types" testutil "github.com/cosmos/cosmos-sdk/types/module/testutil" diff --git a/proto/osmosis/tokenfactory/v1beta1/authorityMetadata.proto b/proto/osmosis/tokenfactory/v1beta1/authorityMetadata.proto index 347e53c..95f7abb 100644 --- a/proto/osmosis/tokenfactory/v1beta1/authorityMetadata.proto +++ b/proto/osmosis/tokenfactory/v1beta1/authorityMetadata.proto @@ -4,7 +4,7 @@ package osmosis.tokenfactory.v1beta1; import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; -option go_package = "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types"; +option go_package = "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types"; // DenomAuthorityMetadata specifies metadata for addresses that have specific // capabilities over a token factory denom. Right now there is only one Admin diff --git a/proto/osmosis/tokenfactory/v1beta1/genesis.proto b/proto/osmosis/tokenfactory/v1beta1/genesis.proto index 39147b1..fac2f90 100644 --- a/proto/osmosis/tokenfactory/v1beta1/genesis.proto +++ b/proto/osmosis/tokenfactory/v1beta1/genesis.proto @@ -5,7 +5,7 @@ import "gogoproto/gogo.proto"; import "osmosis/tokenfactory/v1beta1/authorityMetadata.proto"; import "osmosis/tokenfactory/v1beta1/params.proto"; -option go_package = "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types"; +option go_package = "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types"; // GenesisState defines the tokenfactory module's genesis state. message GenesisState { diff --git a/proto/osmosis/tokenfactory/v1beta1/params.proto b/proto/osmosis/tokenfactory/v1beta1/params.proto index 1eef2b7..0e82a24 100644 --- a/proto/osmosis/tokenfactory/v1beta1/params.proto +++ b/proto/osmosis/tokenfactory/v1beta1/params.proto @@ -6,7 +6,7 @@ import "osmosis/tokenfactory/v1beta1/authorityMetadata.proto"; import "cosmos_proto/cosmos.proto"; import "cosmos/base/v1beta1/coin.proto"; -option go_package = "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types"; +option go_package = "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types"; // Params defines the parameters for the tokenfactory module. message Params { diff --git a/proto/osmosis/tokenfactory/v1beta1/query.proto b/proto/osmosis/tokenfactory/v1beta1/query.proto index d4e93bf..f18e179 100644 --- a/proto/osmosis/tokenfactory/v1beta1/query.proto +++ b/proto/osmosis/tokenfactory/v1beta1/query.proto @@ -7,7 +7,7 @@ import "cosmos/base/query/v1beta1/pagination.proto"; import "osmosis/tokenfactory/v1beta1/authorityMetadata.proto"; import "osmosis/tokenfactory/v1beta1/params.proto"; -option go_package = "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types"; +option go_package = "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types"; // Query defines the gRPC querier service. service Query { diff --git a/proto/osmosis/tokenfactory/v1beta1/tx.proto b/proto/osmosis/tokenfactory/v1beta1/tx.proto index 7f40114..b859f42 100644 --- a/proto/osmosis/tokenfactory/v1beta1/tx.proto +++ b/proto/osmosis/tokenfactory/v1beta1/tx.proto @@ -8,7 +8,7 @@ import "osmosis/tokenfactory/v1beta1/params.proto"; import "cosmos/msg/v1/msg.proto"; import "cosmos_proto/cosmos.proto"; -option go_package = "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types"; +option go_package = "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types"; // Msg defines the tokefactory module's gRPC message service. service Msg { diff --git a/proto/terp/feeshare/v1/feeshare.proto b/proto/terp/feeshare/v1/feeshare.proto index 1d7f9a8..046ac8e 100644 --- a/proto/terp/feeshare/v1/feeshare.proto +++ b/proto/terp/feeshare/v1/feeshare.proto @@ -1,7 +1,7 @@ syntax = "proto3"; package terp.feeshare.v1; -option go_package = "github.com/terpnetwork/terp-core/v2/x/feeshare/types"; +option go_package = "github.com/terpnetwork/terp-core/v4/x/feeshare/types"; // FeeShare defines an instance that organizes fee distribution conditions for // the owner of a given smart contract diff --git a/proto/terp/feeshare/v1/genesis.proto b/proto/terp/feeshare/v1/genesis.proto index da635c4..b7d64ee 100644 --- a/proto/terp/feeshare/v1/genesis.proto +++ b/proto/terp/feeshare/v1/genesis.proto @@ -3,7 +3,7 @@ package terp.feeshare.v1; import "terp/feeshare/v1/feeshare.proto"; import "gogoproto/gogo.proto"; -option go_package = "github.com/terpnetwork/terp-core/v2/x/feeshare/types"; +option go_package = "github.com/terpnetwork/terp-core/v4/x/feeshare/types"; // GenesisState defines the module's genesis state. message GenesisState { diff --git a/proto/terp/feeshare/v1/query.proto b/proto/terp/feeshare/v1/query.proto index 7200378..7295e12 100644 --- a/proto/terp/feeshare/v1/query.proto +++ b/proto/terp/feeshare/v1/query.proto @@ -7,7 +7,7 @@ import "terp/feeshare/v1/feeshare.proto"; import "gogoproto/gogo.proto"; import "google/api/annotations.proto"; -option go_package = "github.com/terpnetwork/terp-core/v2/x/feeshare/types"; +option go_package = "github.com/terpnetwork/terp-core/v4/x/feeshare/types"; // Query defines the gRPC querier service. service Query { diff --git a/proto/terp/feeshare/v1/tx.proto b/proto/terp/feeshare/v1/tx.proto index af279bb..e8b51ae 100644 --- a/proto/terp/feeshare/v1/tx.proto +++ b/proto/terp/feeshare/v1/tx.proto @@ -7,7 +7,7 @@ import "cosmos/msg/v1/msg.proto"; import "cosmos_proto/cosmos.proto"; import "terp/feeshare/v1/genesis.proto"; -option go_package = "github.com/terpnetwork/terp-core/v2/x/feeshare/types"; +option go_package = "github.com/terpnetwork/terp-core/v4/x/feeshare/types"; // Msg defines the fees Msg service. service Msg { diff --git a/x/feeshare/ante/ante.go b/x/feeshare/ante/ante.go index e871059..b8b2d41 100644 --- a/x/feeshare/ante/ante.go +++ b/x/feeshare/ante/ante.go @@ -9,7 +9,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - feeshare "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + feeshare "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) // FeeSharePayoutDecorator Run his after we already deduct the fee from the account with diff --git a/x/feeshare/ante/ante_test.go b/x/feeshare/ante/ante_test.go index 321110a..7acb8c7 100644 --- a/x/feeshare/ante/ante_test.go +++ b/x/feeshare/ante/ante_test.go @@ -7,7 +7,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - ante "github.com/terpnetwork/terp-core/v2/x/feeshare/ante" + ante "github.com/terpnetwork/terp-core/v4/x/feeshare/ante" ) type AnteTestSuite struct { diff --git a/x/feeshare/ante/expected_keepers.go b/x/feeshare/ante/expected_keepers.go index 438c33b..981069b 100644 --- a/x/feeshare/ante/expected_keepers.go +++ b/x/feeshare/ante/expected_keepers.go @@ -5,7 +5,7 @@ package ante import ( sdk "github.com/cosmos/cosmos-sdk/types" - revtypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + revtypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) type BankKeeper interface { diff --git a/x/feeshare/client/cli/query.go b/x/feeshare/client/cli/query.go index fb5dc3c..cecc59f 100644 --- a/x/feeshare/client/cli/query.go +++ b/x/feeshare/client/cli/query.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/version" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) // GetQueryCmd returns the cli query commands for this module diff --git a/x/feeshare/client/cli/tx.go b/x/feeshare/client/cli/tx.go index e0b4dbd..28440cf 100644 --- a/x/feeshare/client/cli/tx.go +++ b/x/feeshare/client/cli/tx.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) // NewTxCmd returns a root CLI command handler for certain modules/FeeShare diff --git a/x/feeshare/genesis.go b/x/feeshare/genesis.go index bae421b..49f0697 100644 --- a/x/feeshare/genesis.go +++ b/x/feeshare/genesis.go @@ -3,8 +3,8 @@ package feeshare import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/feeshare/keeper" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare/keeper" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) // InitGenesis import module genesis diff --git a/x/feeshare/genesis_test.go b/x/feeshare/genesis_test.go index 33e20ca..dcf19e0 100644 --- a/x/feeshare/genesis_test.go +++ b/x/feeshare/genesis_test.go @@ -10,9 +10,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/app" - "github.com/terpnetwork/terp-core/v2/x/feeshare" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/app" + "github.com/terpnetwork/terp-core/v4/x/feeshare" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) type GenesisTestSuite struct { diff --git a/x/feeshare/integration_test.go b/x/feeshare/integration_test.go index a0ee14a..3ecc9b8 100644 --- a/x/feeshare/integration_test.go +++ b/x/feeshare/integration_test.go @@ -20,7 +20,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/mint/types" - terpapp "github.com/terpnetwork/terp-core/v2/app" + terpapp "github.com/terpnetwork/terp-core/v4/app" ) // returns context and an app with updated mint keeper diff --git a/x/feeshare/keeper/feeshare.go b/x/feeshare/keeper/feeshare.go index 0ccbe9a..443d569 100644 --- a/x/feeshare/keeper/feeshare.go +++ b/x/feeshare/keeper/feeshare.go @@ -4,7 +4,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) // GetFeeShares returns all registered FeeShares. diff --git a/x/feeshare/keeper/grpc_query.go b/x/feeshare/keeper/grpc_query.go index 67be214..9f0d92a 100644 --- a/x/feeshare/keeper/grpc_query.go +++ b/x/feeshare/keeper/grpc_query.go @@ -10,7 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) var _ types.QueryServer = Querier{} diff --git a/x/feeshare/keeper/grpc_query_test.go b/x/feeshare/keeper/grpc_query_test.go index 9cc2183..4813f8a 100644 --- a/x/feeshare/keeper/grpc_query_test.go +++ b/x/feeshare/keeper/grpc_query_test.go @@ -5,8 +5,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" - "github.com/terpnetwork/terp-core/v2/testutil/nullify" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/testutil/nullify" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) func (s *IntegrationTestSuite) TestFeeShares() { diff --git a/x/feeshare/keeper/keeper.go b/x/feeshare/keeper/keeper.go index 04e3df6..fc673f8 100644 --- a/x/feeshare/keeper/keeper.go +++ b/x/feeshare/keeper/keeper.go @@ -11,7 +11,7 @@ import ( storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - revtypes "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + revtypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) // Keeper of this module maintains collections of feeshares for contracts diff --git a/x/feeshare/keeper/keeper_test.go b/x/feeshare/keeper/keeper_test.go index 0b0f012..2042507 100644 --- a/x/feeshare/keeper/keeper_test.go +++ b/x/feeshare/keeper/keeper_test.go @@ -14,9 +14,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - "github.com/terpnetwork/terp-core/v2/app" - "github.com/terpnetwork/terp-core/v2/x/feeshare/keeper" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/app" + "github.com/terpnetwork/terp-core/v4/x/feeshare/keeper" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) // BankKeeper defines the expected interface needed to retrieve account balances. diff --git a/x/feeshare/keeper/migrator.go b/x/feeshare/keeper/migrator.go index 77b9e72..cbadaac 100644 --- a/x/feeshare/keeper/migrator.go +++ b/x/feeshare/keeper/migrator.go @@ -3,8 +3,8 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/feeshare/exported" - v2 "github.com/terpnetwork/terp-core/v2/x/feeshare/migrations/v2" + "github.com/terpnetwork/terp-core/v4/x/feeshare/exported" + v2 "github.com/terpnetwork/terp-core/v4/x/feeshare/migrations/v2" ) // Migrator is a struct for handling in-place state migrations. diff --git a/x/feeshare/keeper/msg_server.go b/x/feeshare/keeper/msg_server.go index c5d8474..78d596b 100644 --- a/x/feeshare/keeper/msg_server.go +++ b/x/feeshare/keeper/msg_server.go @@ -11,7 +11,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) var _ types.MsgServer = &Keeper{} diff --git a/x/feeshare/keeper/msg_server_test.go b/x/feeshare/keeper/msg_server_test.go index 9b145d9..44f3227 100644 --- a/x/feeshare/keeper/msg_server_test.go +++ b/x/feeshare/keeper/msg_server_test.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) //go:embed testdata/reflect.wasm diff --git a/x/feeshare/keeper/params.go b/x/feeshare/keeper/params.go index 3b6f3c5..35a0d7d 100644 --- a/x/feeshare/keeper/params.go +++ b/x/feeshare/keeper/params.go @@ -3,7 +3,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) // GetParams returns the total set of fees parameters. diff --git a/x/feeshare/migrations/v2/migrate.go b/x/feeshare/migrations/v2/migrate.go index 3aa51cc..1d2da98 100644 --- a/x/feeshare/migrations/v2/migrate.go +++ b/x/feeshare/migrations/v2/migrate.go @@ -4,8 +4,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/feeshare/exported" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare/exported" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) const ( diff --git a/x/feeshare/migrations/v2/migrate_test.go b/x/feeshare/migrations/v2/migrate_test.go index 18095a4..d7838a1 100644 --- a/x/feeshare/migrations/v2/migrate_test.go +++ b/x/feeshare/migrations/v2/migrate_test.go @@ -9,10 +9,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - "github.com/terpnetwork/terp-core/v2/x/feeshare" - "github.com/terpnetwork/terp-core/v2/x/feeshare/exported" - v2 "github.com/terpnetwork/terp-core/v2/x/feeshare/migrations/v2" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare" + "github.com/terpnetwork/terp-core/v4/x/feeshare/exported" + v2 "github.com/terpnetwork/terp-core/v4/x/feeshare/migrations/v2" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) type mockSubspace struct { diff --git a/x/feeshare/module.go b/x/feeshare/module.go index b9735a0..571f79a 100644 --- a/x/feeshare/module.go +++ b/x/feeshare/module.go @@ -19,10 +19,10 @@ import ( simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - "github.com/terpnetwork/terp-core/v2/x/feeshare/client/cli" - "github.com/terpnetwork/terp-core/v2/x/feeshare/exported" - "github.com/terpnetwork/terp-core/v2/x/feeshare/keeper" - "github.com/terpnetwork/terp-core/v2/x/feeshare/types" + "github.com/terpnetwork/terp-core/v4/x/feeshare/client/cli" + "github.com/terpnetwork/terp-core/v4/x/feeshare/exported" + "github.com/terpnetwork/terp-core/v4/x/feeshare/keeper" + "github.com/terpnetwork/terp-core/v4/x/feeshare/types" ) // type check to ensure the interface is properly implemented diff --git a/x/globalfee/alias.go b/x/globalfee/alias.go index 3a16d3a..3ddb388 100644 --- a/x/globalfee/alias.go +++ b/x/globalfee/alias.go @@ -1,7 +1,7 @@ package globalfee import ( - "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) const ( diff --git a/x/globalfee/ante/antetest/fee_test_setup.go.archive b/x/globalfee/ante/antetest/fee_test_setup.go.archive index b504011..2f926c0 100644 --- a/x/globalfee/ante/antetest/fee_test_setup.go.archive +++ b/x/globalfee/ante/antetest/fee_test_setup.go.archive @@ -17,9 +17,9 @@ import ( "github.com/terpnetwork/terp-core/app" appparams "github.com/terpnetwork/terp-core/app/params" - "github.com/terpnetwork/terp-core/v2/x/globalfee" - gaiafeeante "github.com/terpnetwork/terp-core/v2/x/globalfee/ante" - globfeetypes "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee" + gaiafeeante "github.com/terpnetwork/terp-core/v4/x/globalfee/ante" + globfeetypes "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) type IntegrationTestSuite struct { diff --git a/x/globalfee/ante/fee.go b/x/globalfee/ante/fee.go index 0f03279..864ba7f 100644 --- a/x/globalfee/ante/fee.go +++ b/x/globalfee/ante/fee.go @@ -11,7 +11,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - globalfeekeeper "github.com/terpnetwork/terp-core/v2/x/globalfee/keeper" + globalfeekeeper "github.com/terpnetwork/terp-core/v4/x/globalfee/keeper" ) // FeeWithBypassDecorator checks if the transaction's fee is at least as large diff --git a/x/globalfee/client/cli/query.go b/x/globalfee/client/cli/query.go index 415a1cb..b03666b 100644 --- a/x/globalfee/client/cli/query.go +++ b/x/globalfee/client/cli/query.go @@ -6,7 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) func GetQueryCmd() *cobra.Command { diff --git a/x/globalfee/genesis_test.go b/x/globalfee/genesis_test.go index 79e4ce1..bc4e489 100644 --- a/x/globalfee/genesis_test.go +++ b/x/globalfee/genesis_test.go @@ -15,9 +15,9 @@ import ( storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - appparams "github.com/terpnetwork/terp-core/v2/app/params" - globalfeekeeper "github.com/terpnetwork/terp-core/v2/x/globalfee/keeper" - "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + appparams "github.com/terpnetwork/terp-core/v4/app/params" + globalfeekeeper "github.com/terpnetwork/terp-core/v4/x/globalfee/keeper" + "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) func TestDefaultGenesis(t *testing.T) { diff --git a/x/globalfee/keeper/keeper.go b/x/globalfee/keeper/keeper.go index 6919f83..9c436ff 100644 --- a/x/globalfee/keeper/keeper.go +++ b/x/globalfee/keeper/keeper.go @@ -5,7 +5,7 @@ import ( storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) // Keeper of the globalfee store diff --git a/x/globalfee/keeper/migrator.go b/x/globalfee/keeper/migrator.go index 747b1be..92f736d 100644 --- a/x/globalfee/keeper/migrator.go +++ b/x/globalfee/keeper/migrator.go @@ -3,7 +3,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - v2 "github.com/terpnetwork/terp-core/v2/x/globalfee/migrations/v2" + v2 "github.com/terpnetwork/terp-core/v4/x/globalfee/migrations/v2" ) // Migrator is a struct for handling in-place state migrations. diff --git a/x/globalfee/keeper/msg_server.go b/x/globalfee/keeper/msg_server.go index cef1608..d821ec5 100644 --- a/x/globalfee/keeper/msg_server.go +++ b/x/globalfee/keeper/msg_server.go @@ -8,7 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) var _ types.MsgServer = msgServer{} diff --git a/x/globalfee/migrations/v2/migrate.go b/x/globalfee/migrations/v2/migrate.go index aa0a219..c9cc655 100644 --- a/x/globalfee/migrations/v2/migrate.go +++ b/x/globalfee/migrations/v2/migrate.go @@ -6,7 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) const ( diff --git a/x/globalfee/migrations/v2/migrator_test.go b/x/globalfee/migrations/v2/migrator_test.go index f2a9ed6..ed83a90 100644 --- a/x/globalfee/migrations/v2/migrator_test.go +++ b/x/globalfee/migrations/v2/migrator_test.go @@ -9,10 +9,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - "github.com/terpnetwork/terp-core/v2/x/globalfee" - "github.com/terpnetwork/terp-core/v2/x/globalfee/keeper/exported" - v2 "github.com/terpnetwork/terp-core/v2/x/globalfee/migrations/v2" - "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee" + "github.com/terpnetwork/terp-core/v4/x/globalfee/keeper/exported" + v2 "github.com/terpnetwork/terp-core/v4/x/globalfee/migrations/v2" + "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) //lint:ignore U1000 disregard lint check diff --git a/x/globalfee/module.go b/x/globalfee/module.go index e54b45f..6d6a712 100644 --- a/x/globalfee/module.go +++ b/x/globalfee/module.go @@ -19,9 +19,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - "github.com/terpnetwork/terp-core/v2/x/globalfee/client/cli" - "github.com/terpnetwork/terp-core/v2/x/globalfee/keeper" - "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee/client/cli" + "github.com/terpnetwork/terp-core/v4/x/globalfee/keeper" + "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) var ( diff --git a/x/globalfee/querier.go b/x/globalfee/querier.go index 90e36a5..81303b3 100644 --- a/x/globalfee/querier.go +++ b/x/globalfee/querier.go @@ -5,8 +5,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/globalfee/keeper" - "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + "github.com/terpnetwork/terp-core/v4/x/globalfee/keeper" + "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) var _ types.QueryServer = &GrpcQuerier{} diff --git a/x/globalfee/querier_test.go b/x/globalfee/querier_test.go index e0d0ff8..ae7701d 100644 --- a/x/globalfee/querier_test.go +++ b/x/globalfee/querier_test.go @@ -8,8 +8,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - globalfeekeeper "github.com/terpnetwork/terp-core/v2/x/globalfee/keeper" - "github.com/terpnetwork/terp-core/v2/x/globalfee/types" + globalfeekeeper "github.com/terpnetwork/terp-core/v4/x/globalfee/keeper" + "github.com/terpnetwork/terp-core/v4/x/globalfee/types" ) func TestQueryMinimumGasPrices(t *testing.T) { diff --git a/x/tokenfactory/bindings/custom_msg_test.go b/x/tokenfactory/bindings/custom_msg_test.go index 6d8e469..f8e3f06 100644 --- a/x/tokenfactory/bindings/custom_msg_test.go +++ b/x/tokenfactory/bindings/custom_msg_test.go @@ -11,9 +11,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/app" - bindings "github.com/terpnetwork/terp-core/v2/x/tokenfactory/bindings/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/app" + bindings "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) func TestCreateDenomMsg(t *testing.T) { diff --git a/x/tokenfactory/bindings/custom_query_test.go b/x/tokenfactory/bindings/custom_query_test.go index e025ddb..1ca7fee 100644 --- a/x/tokenfactory/bindings/custom_query_test.go +++ b/x/tokenfactory/bindings/custom_query_test.go @@ -10,8 +10,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/app" - bindings "github.com/terpnetwork/terp-core/v2/x/tokenfactory/bindings/types" + "github.com/terpnetwork/terp-core/v4/app" + bindings "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings/types" ) func TestQueryFullDenom(t *testing.T) { diff --git a/x/tokenfactory/bindings/helpers_test.go b/x/tokenfactory/bindings/helpers_test.go index 6b6c401..2751ba6 100644 --- a/x/tokenfactory/bindings/helpers_test.go +++ b/x/tokenfactory/bindings/helpers_test.go @@ -15,7 +15,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil" - "github.com/terpnetwork/terp-core/v2/app" + "github.com/terpnetwork/terp-core/v4/app" ) func CreateTestInput(t *testing.T) (*app.TerpApp, sdk.Context) { diff --git a/x/tokenfactory/bindings/message_plugin.go b/x/tokenfactory/bindings/message_plugin.go index 78d7f2c..cd3202e 100644 --- a/x/tokenfactory/bindings/message_plugin.go +++ b/x/tokenfactory/bindings/message_plugin.go @@ -13,9 +13,9 @@ import ( bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - bindingstypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/bindings/types" - tokenfactorykeeper "github.com/terpnetwork/terp-core/v2/x/tokenfactory/keeper" - tokenfactorytypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + bindingstypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings/types" + tokenfactorykeeper "github.com/terpnetwork/terp-core/v4/x/tokenfactory/keeper" + tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) // CustomMessageDecorator returns decorator for custom CosmWasm bindings messages diff --git a/x/tokenfactory/bindings/queries.go b/x/tokenfactory/bindings/queries.go index 75a21d1..0855b1c 100644 --- a/x/tokenfactory/bindings/queries.go +++ b/x/tokenfactory/bindings/queries.go @@ -6,8 +6,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - bindingstypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/bindings/types" - tokenfactorykeeper "github.com/terpnetwork/terp-core/v2/x/tokenfactory/keeper" + bindingstypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings/types" + tokenfactorykeeper "github.com/terpnetwork/terp-core/v4/x/tokenfactory/keeper" ) type QueryPlugin struct { diff --git a/x/tokenfactory/bindings/query_plugin.go b/x/tokenfactory/bindings/query_plugin.go index f934663..4d30531 100644 --- a/x/tokenfactory/bindings/query_plugin.go +++ b/x/tokenfactory/bindings/query_plugin.go @@ -11,7 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - bindingstypes "github.com/terpnetwork/terp-core/v2/x/tokenfactory/bindings/types" + bindingstypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings/types" ) // CustomQuerier dispatches custom CosmWasm bindings queries. diff --git a/x/tokenfactory/bindings/validate_msg_test.go b/x/tokenfactory/bindings/validate_msg_test.go index b89adf6..931a133 100644 --- a/x/tokenfactory/bindings/validate_msg_test.go +++ b/x/tokenfactory/bindings/validate_msg_test.go @@ -8,9 +8,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - wasmbinding "github.com/terpnetwork/terp-core/v2/x/tokenfactory/bindings" - bindings "github.com/terpnetwork/terp-core/v2/x/tokenfactory/bindings/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + wasmbinding "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings" + bindings "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) func TestCreateDenom(t *testing.T) { diff --git a/x/tokenfactory/bindings/validate_queries_test.go b/x/tokenfactory/bindings/validate_queries_test.go index 00c72e8..4feee3d 100644 --- a/x/tokenfactory/bindings/validate_queries_test.go +++ b/x/tokenfactory/bindings/validate_queries_test.go @@ -9,7 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - wasmbinding "github.com/terpnetwork/terp-core/v2/x/tokenfactory/bindings" + wasmbinding "github.com/terpnetwork/terp-core/v4/x/tokenfactory/bindings" ) func TestFullDenom(t *testing.T) { diff --git a/x/tokenfactory/bindings/wasm.go b/x/tokenfactory/bindings/wasm.go index fd77a21..8a33de7 100644 --- a/x/tokenfactory/bindings/wasm.go +++ b/x/tokenfactory/bindings/wasm.go @@ -5,7 +5,7 @@ import ( bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - tokenfactorykeeper "github.com/terpnetwork/terp-core/v2/x/tokenfactory/keeper" + tokenfactorykeeper "github.com/terpnetwork/terp-core/v4/x/tokenfactory/keeper" ) func RegisterCustomPlugins( diff --git a/x/tokenfactory/client/cli/query.go b/x/tokenfactory/client/cli/query.go index d76648e..1d4534e 100644 --- a/x/tokenfactory/client/cli/query.go +++ b/x/tokenfactory/client/cli/query.go @@ -8,7 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) // GetQueryCmd returns the cli query commands for this module diff --git a/x/tokenfactory/client/cli/tx.go b/x/tokenfactory/client/cli/tx.go index 059dd24..e2a24bf 100644 --- a/x/tokenfactory/client/cli/tx.go +++ b/x/tokenfactory/client/cli/tx.go @@ -13,7 +13,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) // GetTxCmd returns the transaction commands for this module diff --git a/x/tokenfactory/keeper/admins.go b/x/tokenfactory/keeper/admins.go index ba4aa7c..3c149be 100644 --- a/x/tokenfactory/keeper/admins.go +++ b/x/tokenfactory/keeper/admins.go @@ -5,7 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) // GetAuthorityMetadata returns the authority metadata for a specific denom diff --git a/x/tokenfactory/keeper/admins_test.go b/x/tokenfactory/keeper/admins_test.go index 8f19b61..98861ad 100644 --- a/x/tokenfactory/keeper/admins_test.go +++ b/x/tokenfactory/keeper/admins_test.go @@ -6,7 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) func (suite *KeeperTestSuite) TestAdminMsgs() { diff --git a/x/tokenfactory/keeper/bankactions.go b/x/tokenfactory/keeper/bankactions.go index dbe92b5..db987a6 100644 --- a/x/tokenfactory/keeper/bankactions.go +++ b/x/tokenfactory/keeper/bankactions.go @@ -5,7 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) func (k Keeper) mintTo(ctx sdk.Context, amount sdk.Coin, mintTo string) error { diff --git a/x/tokenfactory/keeper/createdenom.go b/x/tokenfactory/keeper/createdenom.go index 5411ca8..2d50ff0 100644 --- a/x/tokenfactory/keeper/createdenom.go +++ b/x/tokenfactory/keeper/createdenom.go @@ -4,7 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) // ConvertToBaseToken converts a fee amount in a whitelisted fee token to the base fee token amount diff --git a/x/tokenfactory/keeper/createdenom_test.go b/x/tokenfactory/keeper/createdenom_test.go index 52784e3..af60e9a 100644 --- a/x/tokenfactory/keeper/createdenom_test.go +++ b/x/tokenfactory/keeper/createdenom_test.go @@ -6,8 +6,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/terpnetwork/terp-core/v2/app/apptesting" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/app/apptesting" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) func (suite *KeeperTestSuite) TestMsgCreateDenom() { diff --git a/x/tokenfactory/keeper/genesis.go b/x/tokenfactory/keeper/genesis.go index dfd5875..9b2f04f 100644 --- a/x/tokenfactory/keeper/genesis.go +++ b/x/tokenfactory/keeper/genesis.go @@ -3,7 +3,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) // InitGenesis initializes the tokenfactory module's state from a provided genesis diff --git a/x/tokenfactory/keeper/genesis_test.go b/x/tokenfactory/keeper/genesis_test.go index 3c7d6fa..49f46c6 100644 --- a/x/tokenfactory/keeper/genesis_test.go +++ b/x/tokenfactory/keeper/genesis_test.go @@ -4,7 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) func (suite *KeeperTestSuite) TestGenesis() { diff --git a/x/tokenfactory/keeper/grpc_query.go b/x/tokenfactory/keeper/grpc_query.go index 5ced656..3ae2695 100644 --- a/x/tokenfactory/keeper/grpc_query.go +++ b/x/tokenfactory/keeper/grpc_query.go @@ -5,7 +5,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) var _ types.QueryServer = Keeper{} diff --git a/x/tokenfactory/keeper/keeper.go b/x/tokenfactory/keeper/keeper.go index 2eb024d..a49ed49 100644 --- a/x/tokenfactory/keeper/keeper.go +++ b/x/tokenfactory/keeper/keeper.go @@ -11,7 +11,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) type ( diff --git a/x/tokenfactory/keeper/keeper_test.go b/x/tokenfactory/keeper/keeper_test.go index 8a92288..599f1ea 100644 --- a/x/tokenfactory/keeper/keeper_test.go +++ b/x/tokenfactory/keeper/keeper_test.go @@ -10,9 +10,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/terpnetwork/terp-core/v2/app/apptesting" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/keeper" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/app/apptesting" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/keeper" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) type KeeperTestSuite struct { diff --git a/x/tokenfactory/keeper/migrator.go b/x/tokenfactory/keeper/migrator.go index 0a5ac69..ccf69ed 100644 --- a/x/tokenfactory/keeper/migrator.go +++ b/x/tokenfactory/keeper/migrator.go @@ -6,8 +6,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/exported" - v2 "github.com/terpnetwork/terp-core/v2/x/tokenfactory/migrations/v2" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/exported" + v2 "github.com/terpnetwork/terp-core/v4/x/tokenfactory/migrations/v2" ) // Migrator is a struct for handling in-place state migrations. diff --git a/x/tokenfactory/keeper/msg_server.go b/x/tokenfactory/keeper/msg_server.go index 098db8e..2e33298 100644 --- a/x/tokenfactory/keeper/msg_server.go +++ b/x/tokenfactory/keeper/msg_server.go @@ -8,7 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) type msgServer struct { diff --git a/x/tokenfactory/keeper/msg_server_test.go b/x/tokenfactory/keeper/msg_server_test.go index 2f5b7d5..5eb6637 100644 --- a/x/tokenfactory/keeper/msg_server_test.go +++ b/x/tokenfactory/keeper/msg_server_test.go @@ -6,7 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) // TestMintDenomMsg tests TypeMsgMint message is emitted on a successful mint diff --git a/x/tokenfactory/keeper/params.go b/x/tokenfactory/keeper/params.go index 5949338..e4a0c0d 100644 --- a/x/tokenfactory/keeper/params.go +++ b/x/tokenfactory/keeper/params.go @@ -3,7 +3,7 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) // GetParams returns the total set params. diff --git a/x/tokenfactory/migrations/v2/migrate.go b/x/tokenfactory/migrations/v2/migrate.go index 689486c..3e28859 100644 --- a/x/tokenfactory/migrations/v2/migrate.go +++ b/x/tokenfactory/migrations/v2/migrate.go @@ -4,8 +4,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/exported" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/exported" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) const ModuleName = "tokenfactory" diff --git a/x/tokenfactory/migrations/v2/migrate_test.go b/x/tokenfactory/migrations/v2/migrate_test.go index 0ed9fdd..a470e7f 100644 --- a/x/tokenfactory/migrations/v2/migrate_test.go +++ b/x/tokenfactory/migrations/v2/migrate_test.go @@ -9,10 +9,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/exported" - v2 "github.com/terpnetwork/terp-core/v2/x/tokenfactory/migrations/v2" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/exported" + v2 "github.com/terpnetwork/terp-core/v4/x/tokenfactory/migrations/v2" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) type mockSubspace struct { diff --git a/x/tokenfactory/module.go b/x/tokenfactory/module.go index 9f93f1d..3d5a490 100644 --- a/x/tokenfactory/module.go +++ b/x/tokenfactory/module.go @@ -26,11 +26,11 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/client/cli" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/exported" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/keeper" - simulation "github.com/terpnetwork/terp-core/v2/x/tokenfactory/simulation" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/client/cli" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/exported" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/keeper" + simulation "github.com/terpnetwork/terp-core/v4/x/tokenfactory/simulation" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) var ( diff --git a/x/tokenfactory/simulation/genesis.go b/x/tokenfactory/simulation/genesis.go index 3d2704e..213e8f1 100644 --- a/x/tokenfactory/simulation/genesis.go +++ b/x/tokenfactory/simulation/genesis.go @@ -6,8 +6,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - appparams "github.com/terpnetwork/terp-core/v2/app/params" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + appparams "github.com/terpnetwork/terp-core/v4/app/params" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) func RandDenomCreationFeeParam(r *rand.Rand) sdk.Coins { diff --git a/x/tokenfactory/simulation/operations.go b/x/tokenfactory/simulation/operations.go index 4936439..8a54694 100644 --- a/x/tokenfactory/simulation/operations.go +++ b/x/tokenfactory/simulation/operations.go @@ -10,8 +10,8 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/simulation" - appparams "github.com/terpnetwork/terp-core/v2/app/params" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + appparams "github.com/terpnetwork/terp-core/v4/app/params" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) // Simulation operation weights constants diff --git a/x/tokenfactory/types/denoms_test.go b/x/tokenfactory/types/denoms_test.go index 36f013e..a2030a8 100644 --- a/x/tokenfactory/types/denoms_test.go +++ b/x/tokenfactory/types/denoms_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) func TestDeconstructDenom(t *testing.T) { diff --git a/x/tokenfactory/types/genesis_test.go b/x/tokenfactory/types/genesis_test.go index a3134d7..489a982 100644 --- a/x/tokenfactory/types/genesis_test.go +++ b/x/tokenfactory/types/genesis_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) func TestGenesisState_Validate(t *testing.T) { diff --git a/x/tokenfactory/types/msgs_test.go b/x/tokenfactory/types/msgs_test.go index 8c31600..78734ad 100644 --- a/x/tokenfactory/types/msgs_test.go +++ b/x/tokenfactory/types/msgs_test.go @@ -11,8 +11,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/testhelpers" - "github.com/terpnetwork/terp-core/v2/x/tokenfactory/types" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/testhelpers" + "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" ) // Test authz serialize and de-serializes for tokenfactory msg. From c9ef45f6da5566678029ea79a631cc23ca548db7 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Wed, 1 Nov 2023 23:14:03 -0400 Subject: [PATCH 16/18] skip upgrade ci test --- .github/workflows/interchaintest-E2E.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/interchaintest-E2E.yml b/.github/workflows/interchaintest-E2E.yml index 1a3c443..c0a84f3 100644 --- a/.github/workflows/interchaintest-E2E.yml +++ b/.github/workflows/interchaintest-E2E.yml @@ -64,7 +64,7 @@ jobs: - "ictest-tokenfactory" - "ictest-feeshare" - "ictest-pfm" - - "ictest-upgrade" + # - "ictest-upgrade" - "ictest-ibc" # - "ictest-pob" # - "ictest-drip" From 651e26a3fb50958c2bf84a66f3e84458b8335d83 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Wed, 1 Nov 2023 23:26:35 -0400 Subject: [PATCH 17/18] gofumpt, lint --- app/keepers/keepers.go | 4 ++-- app/keepers/keys.go | 2 +- app/modules.go | 4 ++-- app/upgrades/v4/headstash-patch.go | 6 +----- app/upgrades/v4/upgrade.go | 4 +--- interchaintest/go.mod | 4 ++-- interchaintest/module_clock_test.go | 2 +- interchaintest/setup.go | 2 +- 8 files changed, 11 insertions(+), 17 deletions(-) diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 9ff987d..a89d132 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -93,8 +93,8 @@ import ( upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" denomburn "github.com/terpnetwork/terp-core/v4/x/burn" - // clockkeeper "github.com/terpnetwork/terp-core/v2/x/clock/keeper" - // clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + // clockkeeper "github.com/terpnetwork/terp-core/v4/x/clock/keeper" + // clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" feesharekeeper "github.com/terpnetwork/terp-core/v4/x/feeshare/keeper" feesharetypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" diff --git a/app/keepers/keys.go b/app/keepers/keys.go index f3d13b7..75047a6 100644 --- a/app/keepers/keys.go +++ b/app/keepers/keys.go @@ -34,7 +34,7 @@ import ( icqtypes "github.com/cosmos/ibc-apps/modules/async-icq/v7/types" ibchookstypes "github.com/cosmos/ibc-apps/modules/ibc-hooks/v7/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" - // clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + // clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" ) func (appKeepers *AppKeepers) GenerateKeys() { diff --git a/app/modules.go b/app/modules.go index 9aee3bc..d65acca 100644 --- a/app/modules.go +++ b/app/modules.go @@ -20,8 +20,8 @@ import ( ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - // "github.com/terpnetwork/terp-core/v2/x/clock" - // clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + // "github.com/terpnetwork/terp-core/v4/x/clock" + // clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/x/auth" diff --git a/app/upgrades/v4/headstash-patch.go b/app/upgrades/v4/headstash-patch.go index 2f6db10..6d25a96 100644 --- a/app/upgrades/v4/headstash-patch.go +++ b/app/upgrades/v4/headstash-patch.go @@ -6,7 +6,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" "github.com/terpnetwork/terp-core/v4/app/upgrades" @@ -17,9 +16,7 @@ import ( func returnFundsToCommunityPool( ctx sdk.Context, dk distrkeeper.Keeper, - bk bankkeeper.Keeper, -) error { - +) { headstashes := v3.GetHeadstashPayments() total := int64(0) @@ -50,7 +47,6 @@ func returnFundsToCommunityPool( } total += amount } - return nil } // TODO: handle headstash-patch contract upload & instantiation diff --git a/app/upgrades/v4/upgrade.go b/app/upgrades/v4/upgrade.go index 1eddf66..2de7701 100644 --- a/app/upgrades/v4/upgrade.go +++ b/app/upgrades/v4/upgrade.go @@ -40,9 +40,7 @@ func CreateV4UpgradeHandler( logger.Info(fmt.Sprintf("upgraded global fee params to %s", minGasPrices)) // revert headstash allocation - if err := returnFundsToCommunityPool(ctx, keepers.DistrKeeper, keepers.BankKeeper); err != nil { - return nil, err - } + returnFundsToCommunityPool(ctx, keepers.DistrKeeper) // print the burn module address burnModule := keepers.AccountKeeper.GetModuleAddress(burn.ModuleName) diff --git a/interchaintest/go.mod b/interchaintest/go.mod index a606f05..400df6a 100644 --- a/interchaintest/go.mod +++ b/interchaintest/go.mod @@ -10,7 +10,7 @@ replace ( github.com/btcsuite/btcd => github.com/btcsuite/btcd v0.22.2 //indirect github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 // For this nested module, you always want to replace the parent reference with the current worktree. - github.com/terpnetwork/terp-core/v2 => ../ + github.com/terpnetwork/terp-core/v4 => ../ github.com/vedhavyas/go-subkey => github.com/strangelove-ventures/go-subkey v1.0.7 ) @@ -23,7 +23,7 @@ require ( github.com/docker/docker v24.0.4+incompatible github.com/strangelove-ventures/interchaintest/v7 v7.0.0-20230721183422-fb937bb0e165 github.com/stretchr/testify v1.8.4 - github.com/terpnetwork/terp-core/v2 v2.0.0-00010101000000-000000000000 + github.com/terpnetwork/terp-core/v4 v4.0.0-00010101000000-000000000000 go.uber.org/zap v1.24.0 ) diff --git a/interchaintest/module_clock_test.go b/interchaintest/module_clock_test.go index f0b97cf..1b2e566 100644 --- a/interchaintest/module_clock_test.go +++ b/interchaintest/module_clock_test.go @@ -11,7 +11,7 @@ package interchaintest // "github.com/strangelove-ventures/interchaintest/v7/ibc" // "github.com/strangelove-ventures/interchaintest/v7/testutil" // "github.com/stretchr/testify/require" -// clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" +// clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" // helpers "github.com/terpnetwork/terp-core/tests/interchaintest/helpers" // ) diff --git a/interchaintest/setup.go b/interchaintest/setup.go index 486caa3..ea479a8 100644 --- a/interchaintest/setup.go +++ b/interchaintest/setup.go @@ -15,7 +15,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" - // clocktypes "github.com/terpnetwork/terp-core/v2/x/clock/types" + // clocktypes "github.com/terpnetwork/terp-core/v4/x/clock/types" feesharetypes "github.com/terpnetwork/terp-core/v4/x/feeshare/types" tokenfactorytypes "github.com/terpnetwork/terp-core/v4/x/tokenfactory/types" From d01d9dc0e6d58b32030c9c0401199428ba910218 Mon Sep 17 00:00:00 2001 From: hard-nett Date: Wed, 1 Nov 2023 23:52:35 -0400 Subject: [PATCH 18/18] ci bump --- .github/workflows/interchaintest-E2E.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/interchaintest-E2E.yml b/.github/workflows/interchaintest-E2E.yml index c0a84f3..d48ec4c 100644 --- a/.github/workflows/interchaintest-E2E.yml +++ b/.github/workflows/interchaintest-E2E.yml @@ -42,7 +42,7 @@ jobs: uses: docker/build-push-action@v5 with: context: . - tags: terp:local + tags: terpnetwork:local outputs: type=docker,dest=${{ env.TAR_PATH }} - name: Upload artifact