From 3d2896a2e43eeb8ad9d157ab12c13936a54cd906 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 20 Jan 2021 10:26:39 +0100 Subject: [PATCH 01/40] Update changelog after 0.40.1 release (#8394) --- CHANGELOG.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cab64e9c93..f2bc793c05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,16 +38,29 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements -* (x/bank) [\#8302](https://github.com/cosmos/cosmos-sdk/issues/8302) Add gRPC and CLI queries for client denomination metadata. -* (tendermint) [\#8316](https://github.com/cosmos/cosmos-sdk/pull/8316) Bump Tendermint version to [v0.34.2](https://github.com/tendermint/tendermint/releases/tag/v0.34.2) ### Bug Fixes -* (x/bank) [\#8317](https://github.com/cosmos/cosmos-sdk/pull/8317) Fix panic when querying for a not found client denomination metadata. + +## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 + +### Improvements + +* (x/bank) [\#8302](https://github.com/cosmos/cosmos-sdk/issues/8302) Add gRPC and CLI queries for client denomination metadata. +* (tendermint) Bump Tendermint version to [v0.34.3](https://github.com/tendermint/tendermint/releases/tag/v0.34.3). + +### Bug Fixes + +* [\#8085](https://github.com/cosmos/cosmos-sdk/pull/8058) fix zero time checks +* [\#8280](https://github.com/cosmos/cosmos-sdk/pull/8280) fix GET /upgrade/current query * (x/auth) [\#8287](https://github.com/cosmos/cosmos-sdk/pull/8287) Fix `tx sign --signature-only` to return correct sequence value in signature. -* (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. +* (build) [\8300](https://github.com/cosmos/cosmos-sdk/pull/8300), [\8301](https://github.com/cosmos/cosmos-sdk/pull/8301) Fix reproducible builds * (types/errors) [\#8355][https://github.com/cosmos/cosmos-sdk/pull/8355] Fix errorWrap `Is` method. -* (x/ibc) [\#8359](https://github.com/cosmos/cosmos-sdk/pull/8359) Add missing UnpackInterfaces functions to IBC Query Responses. Fixes 'cannot unpack Any' error for IBC types. +* (x/ibc) [\#8341](https://github.com/cosmos/cosmos-sdk/pull/8341) Fix query latest consensus state. +* (proto) [\#8350][https://github.com/cosmos/cosmos-sdk/pull/8350], [\#8361](https://github.com/cosmos/cosmos-sdk/pull/8361) Update gogo proto deps with v1.3.2 security fixes +* (x/ibc) [\#8359](https://github.com/cosmos/cosmos-sdk/pull/8359) Add missing UnpackInterfaces functions to IBC Query Responses. Fixes 'cannot unpack Any' error for IBC types. +* (x/bank) [\#8317](https://github.com/cosmos/cosmos-sdk/pull/8317) Fix panic when querying for a not found client denomination metadata. + ## [v0.40.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0) - 2021-01-08 From d4e63ffe60b63c466dce741624353374f2916144 Mon Sep 17 00:00:00 2001 From: Aditya Date: Wed, 20 Jan 2021 09:25:32 -0500 Subject: [PATCH 02/40] IBC Upgrade docs (#8298) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * start upgrade guide and some organization * add client developer guide * remove top-level upgrade doc * Apply suggestions from code review Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> * address @colin-axner suggestions * add order and synopsis * address @fedekunze review * address final @colin-axner comments Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: Christopher Goes Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/ibc/upgrades/README.md | 14 ++++++++ docs/ibc/upgrades/developer-guide.md | 50 ++++++++++++++++++++++++++ docs/ibc/upgrades/quick-guide.md | 54 ++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 docs/ibc/upgrades/README.md create mode 100644 docs/ibc/upgrades/developer-guide.md create mode 100644 docs/ibc/upgrades/quick-guide.md diff --git a/docs/ibc/upgrades/README.md b/docs/ibc/upgrades/README.md new file mode 100644 index 0000000000..11ccabe237 --- /dev/null +++ b/docs/ibc/upgrades/README.md @@ -0,0 +1,14 @@ + + +### Upgrading IBC Chains Overview + +This directory contains information on how to upgrade an IBC chain without breaking counterparty clients and connections. + +IBC-connnected chains must be able to upgrade without breaking connections to other chains. Otherwise there would be a massive disincentive towards upgrading and disrupting high-value IBC connections, thus preventing chains in the IBC ecosystem from evolving and improving. Many chain upgrades may be irrelevant to IBC, however some upgrades could potentially break counterparty clients if not handled correctly. Thus, any IBC chain that wishes to perform a IBC-client-breaking upgrade must perform an IBC upgrade in order to allow counterparty clients to securely upgrade to the new light client. + +1. The [quick-guide](./quick-guide.md) describes how IBC-connected chains can perform client-breaking upgrades and how relayers can securely upgrade counterparty clients using the SDK. +2. The [developer-guide](./developer-guide.md) is a guide for developers intending to develop IBC client implementations with upgrade functionality. diff --git a/docs/ibc/upgrades/developer-guide.md b/docs/ibc/upgrades/developer-guide.md new file mode 100644 index 0000000000..998cb276e7 --- /dev/null +++ b/docs/ibc/upgrades/developer-guide.md @@ -0,0 +1,50 @@ + + +# IBC Client Developer Guide to Upgrades + +Learn how to implement upgrade functionality for your custom IBC client. {synopsis} + +As mentioned in the [README](./README.md), it is vital that high-value IBC clients can upgrade along with their underlying chains to avoid disruption to the IBC ecosystem. Thus, IBC client developers will want to implement upgrade functionality to enable clients to maintain connections and channels even across chain upgrades. + +The IBC protocol allows client implementations to provide a path to upgrading clients given the upgraded client state, upgraded consensus state and proofs for each. + +```go +// Upgrade functions +// NOTE: proof heights are not included as upgrade to a new revision is expected to pass only on the last +// height committed by the current revision. Clients are responsible for ensuring that the planned last +// height of the current revision is somehow encoded in the proof verification process. +// This is to ensure that no premature upgrades occur, since upgrade plans committed to by the counterparty +// may be cancelled or modified before the last planned height. +VerifyUpgradeAndUpdateState( + ctx sdk.Context, + cdc codec.BinaryMarshaler, + store sdk.KVStore, + newClient ClientState, + newConsState ConsensusState, + proofUpgradeClient, + proofUpgradeConsState []byte, +) (upgradedClient ClientState, upgradedConsensus ConsensusState, err error) +``` + +Note that the clients should have prior knowledge of the merkle path that the upgraded client and upgraded consensus states will use. The height at which the upgrade has occurred should also be encoded in the proof. The Tendermint client implementation accomplishes this by including an `UpgradePath` in the ClientState itself, which is used along with the upgrade height to construct the merkle path under which the client state and consensus state are committed. + +Developers must ensure that the `UpgradeClientMsg` does not pass until the last height of the old chain has been committed, and after the chain upgrades, the `UpgradeClientMsg` should pass once and only once on all counterparty clients. + +Developers must ensure that the new client adopts all of the new Client parameters that must be uniform across every valid light client of a chain (chain-chosen parameters), while maintaining the Client parameters that are customizable by each individual client (client-chosen parameters) from the previous version of the client. + +Upgrades must adhere to the IBC Security Model. IBC does not rely on the assumption of honest relayers for correctness. Thus users should not have to rely on relayers to maintain client correctness and security (though honest relayers must exist to maintain relayer liveness). While relayers may choose any set of client parameters while creating a new `ClientState`, this still holds under the security model since users can always choose a relayer-created client that suits their security and correctness needs or create a Client with their desired parameters if no such client exists. + +However, when upgrading an existing client, one must keep in mind that there are already many users who depend on this client's particular parameters. We cannot give the upgrading relayer free choice over these parameters once they have already been chosen. This would violate the security model since users who rely on the client would have to rely on the upgrading relayer to maintain the same level of security. Thus, developers must make sure that their upgrade mechanism allows clients to upgrade the chain-specified parameters whenever a chain upgrade changes these parameters (examples in the Tendermint client include `UnbondingPeriod`, `ChainID`, `UpgradePath`, etc.), while ensuring that the relayer submitting the `UpgradeClientMsg` cannot alter the client-chosen parameters that the users are relying upon (examples in Tendermint client include `TrustingPeriod`, `TrustLevel`, `MaxClockDrift`, etc). + +Developers should maintain the distinction between Client parameters that are uniform across every valid light client of a chain (chain-chosen parameters), and Client parameters that are customizable by each individual client (client-chosen parameters); since this distinction is necessary to implement the `ZeroCustomFields` method in the `ClientState` interface: + +```go +// Utility function that zeroes out any client customizable fields in client state +// Ledger enforced fields are maintained while all custom fields are zero values +// Used to verify upgrades +ZeroCustomFields() ClientState +``` + +Counterparty clients can upgrade securely by using all of the chain-chosen parameters from the chain-committed `UpgradedClient` and preserving all of the old client-chosen parameters. This enables chains to securely upgrade without relying on an honest relayer, however it can in some cases lead to an invalid final `ClientState` if the new chain-chosen parameters clash with the old client-chosen parameter. This can happen in the Tendermint client case if the upgrading chain lowers the `UnbondingPeriod` (chain-chosen) to a duration below that of a counterparty client's `TrustingPeriod` (client-chosen). Such cases should be clearly documented by developers, so that chains know which upgrades should be avoided to prevent this problem. The final upgraded client should also be validated in `VerifyUpgradeAndUpdateState` before returning to ensure that the client does not upgrade to an invalid `ClientState`. diff --git a/docs/ibc/upgrades/quick-guide.md b/docs/ibc/upgrades/quick-guide.md new file mode 100644 index 0000000000..4717e52f44 --- /dev/null +++ b/docs/ibc/upgrades/quick-guide.md @@ -0,0 +1,54 @@ + + +# How to Upgrade IBC Chains and their Clients + +Learn how to upgrade your chain and counterparty clients. {synopsis} + +The information in this doc for upgrading chains is relevant to SDK chains. However, the guide for counterparty clients is relevant to any Tendermint client that enables upgrades. + +### IBC Client Breaking Upgrades + +IBC-connected chains must perform an IBC upgrade if their upgrade will break counterparty IBC clients. The current IBC protocol supports upgrading tendermint chains for a specific subset of IBC-client-breaking upgrades. Here is the exhaustive list of IBC client-breaking upgrades and whether the IBC protocol currently supports such upgrades. + +IBC currently does **NOT** support unplanned upgrades. All of the following upgrades must be planned and committed to in advance by the upgrading chain, in order for counterparty clients to maintain their connections securely. + +Note: Since upgrades are only implemented for Tendermint clients, this doc only discusses upgrades on Tendermint chains that would break counterparty IBC Tendermint Clients. + +1. Changing the Chain-ID: **Supported** +2. Changing the UnbondingPeriod: **Partially Supported**, chains may increase the unbonding period with no issues. However, decreasing the unbonding period may irreversibly break some counterparty clients. Thus, it is **not recommended** that chains reduce the unbonding period. +3. Changing the height (resetting to 0): **Supported**, so long as chains remember to increment the revision number in their chain-id. +4. Changing the ProofSpecs: **Supported**, this should be changed if the proof structure needed to verify IBC proofs is changed across the upgrade. Ex: Switching from an IAVL store, to a SimpleTree Store +5. Changing the UpgradePath: **Supported**, this might involve changing the key under which upgraded clients and consensus states are stored in the upgrade store, or even migrating the upgrade store itself. +6. Migrating the IBC store: **Unsupported**, as the IBC store location is negotiated by the connection. +7. Upgrading to a backwards compatible version of IBC: Supported +8. Upgrading to a non-backwards compatible version of IBC: **Unsupported**, as IBC version is negotiated on connection handshake. +9. Changing the Tendermint LightClient algorithm: **Partially Supported**. Changes to the light client algorithm that do not change the ClientState or ConsensusState struct may be supported, provided that the counterparty is also upgraded to support the new light client algorithm. Changes that require updating the ClientState and ConsensusState structs themselves are theoretically possible by providing a path to translate an older ClientState struct into the new ClientState struct; however this is not currently implemented. + +### Step-by-Step Upgrade Process for SDK chains + +If the IBC-connected chain is conducting an upgrade that will break counterparty clients, it must ensure that the upgrade is first supported by IBC using the list above and then execute the upgrade process described below in order to prevent counterparty clients from breaking. + +1. Create a `SoftwareUpgradeProposal` with an `UpgradePlan` that includes the new IBC ClientState in the `UpgradedClientState`. Note that the `UpgradePlan` must specify an upgrade height **only** (no upgrade time), and the `ClientState` should only include the fields common to all valid clients and zero out any client-customizable fields (such as TrustingPeriod). +2. Vote on and pass the `SoftwareUpgradeProposal` + +Upon the `SoftwareUpgradeProposal` passing, the upgrade module will commit the UpgradedClient under the key: `upgrade/UpgradedIBCState/{upgradeHeight}/upgradedClient`. On the block right before the upgrade height, the upgrade module will also commit an initial consensus state for the next chain under the key: `upgrade/UpgradedIBCState/{upgradeHeight}/upgradedConsState`. + +Once the chain reaches the upgrade height and halts, a relayer can upgrade the counterparty clients to the last block of the old chain. They can then submit the proofs of the `UpgradedClient` and `UpgradedConsensusState` against this last block and upgrade the counterparty client. + +### Step-by-Step Upgrade Process for Relayers Upgrading Counterparty Clients + +Once the upgrading chain has committed to upgrading, relayers must wait till the chain halts at the upgrade height before upgrading counterparty clients. This is because chains may reschedule or cancel upgrade plans before they occur. Thus, relayers must wait till the chain reaches the upgrade height and halts before they can be sure the upgrade will take place. + +Thus, the upgrade process for relayers trying to upgrade the counterparty clients is as follows: + +1. Wait for the upgrading chain to reach the upgrade height and halt +2. Query a full node for the proofs of `UpgradedClient` and `UpgradedConsensusState` at the last height of the old chain. +3. Update the counterparty client to the last height of the old chain using the `UpdateClient` msg. +4. Submit an `UpgradeClient` msg to the counterparty chain with the `UpgradedClient`, `UpgradedConsensusState` and their respective proofs. +5. Submit an `UpdateClient` msg to the counterparty chain with a header from the new upgraded chain. + +The Tendermint client on the counterparty chain will verify that the upgrading chain did indeed commit to the upgraded client and upgraded consensus state at the upgrade height (since the upgrade height is included in the key). If the proofs are verified against the upgrade height, then the client will upgrade to the new client while retaining all of its client-customized fields. Thus, it will retain its old TrustingPeriod, TrustLevel, MaxClockDrift, etc; while adopting the new chain-specified fields such as UnbondingPeriod, ChainId, UpgradePath, etc. Note, this can lead to an invalid client since the old client-chosen fields may no longer be valid given the new chain-chosen fields. Upgrading chains should try to avoid these situations by not altering parameters that can break old clients. For an example, see the UnbondingPeriod example in the supported upgrades section. + +The upgraded consensus state will serve purely as a basis of trust for future `UpdateClientMsgs` and will not contain a consensus root to perform proof verification against. Thus, relayers must submit an `UpdateClientMsg` with a header from the new chain so that the connection can be used for proof verification again. \ No newline at end of file From d226254578d8b3fd1b5bff1a4e5d40e40d3041c7 Mon Sep 17 00:00:00 2001 From: Cyrus Goh Date: Thu, 21 Jan 2021 00:42:42 -0800 Subject: [PATCH 03/40] docs: add enhanceApp.js to .vuepress for redirects (#8354) --- docs/.vuepress/enhanceApp.js | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/.vuepress/enhanceApp.js diff --git a/docs/.vuepress/enhanceApp.js b/docs/.vuepress/enhanceApp.js new file mode 100644 index 0000000000..79974546e9 --- /dev/null +++ b/docs/.vuepress/enhanceApp.js @@ -0,0 +1,6 @@ +export default ({ router }) => { + router.addRoutes([ + { path: '/master/spec/*', redirect: '/master/modules/' }, + { path: '/master/spec/governance/', redirect: '/master/modules/gov/' }, + ]) +} \ No newline at end of file From 57f5e965708fe9acdd3e96cb5fd586f383e17824 Mon Sep 17 00:00:00 2001 From: SaReN Date: Thu, 21 Jan 2021 15:03:02 +0530 Subject: [PATCH 04/40] Rosetta API implementation (#7695) Ref: #7492 Co-authored-by: Jonathan Gimeno Co-authored-by: Alessio Treglia Co-authored-by: Frojdi Dymylja <33157909+fdymylja@users.noreply.github.com> Co-authored-by: Robert Zaremba Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- .github/workflows/test.yml | 17 + Makefile | 17 + contrib/rosetta/README.md | 24 + contrib/rosetta/configuration/bootstrap.json | 12 + contrib/rosetta/configuration/data.sh | 58 +++ contrib/rosetta/configuration/faucet.py | 25 + contrib/rosetta/configuration/rosetta.json | 51 ++ contrib/rosetta/configuration/run_tests.sh | 29 ++ contrib/rosetta/configuration/send_funds.sh | 5 + contrib/rosetta/configuration/staking.json | 30 ++ contrib/rosetta/configuration/staking.ros | 147 ++++++ contrib/rosetta/configuration/transfer.ros | 109 +++++ contrib/rosetta/docker-compose.yaml | 39 ++ contrib/rosetta/node/Dockerfile | 32 ++ contrib/rosetta/node/data.tar.gz | Bin 0 -> 34626 bytes contrib/rosetta/rosetta-cli/Dockerfile | 18 + .../adr-035-rosetta-api-support.md | 292 +++++------- docs/run-node/README.md | 1 + docs/run-node/rosetta.md | 83 ++++ go.mod | 10 +- go.sum | 116 ++++- server/config/config.go | 40 ++ server/config/toml.go | 24 + server/rosetta.go | 42 ++ server/rosetta/client_offline.go | 221 +++++++++ server/rosetta/client_online.go | 447 ++++++++++++++++++ server/rosetta/codec.go | 22 + server/rosetta/config.go | 203 ++++++++ server/rosetta/conv_from_rosetta.go | 211 +++++++++ server/rosetta/conv_to_rosetta.go | 95 ++++ server/rosetta/types.go | 41 ++ server/rosetta/util.go | 112 +++++ server/start.go | 45 +- simapp/simd/cmd/root.go | 3 + types/tx/types.go | 31 ++ x/auth/client/cli/cli_test.go | 2 +- x/auth/client/cli/validate_sigs.go | 4 +- x/bank/types/msgs.go | 84 ++++ x/distribution/types/msg.go | 50 ++ x/genutil/client/cli/gentx_test.go | 2 +- x/ibc/core/03-connection/types/msgs_test.go | 4 +- x/slashing/client/rest/rest.go | 3 +- x/staking/client/rest/rest.go | 3 +- x/staking/types/msg.go | 274 +++++++++++ x/staking/types/tx.pb.go | 9 +- x/upgrade/client/rest/rest.go | 3 +- 46 files changed, 2887 insertions(+), 203 deletions(-) create mode 100644 contrib/rosetta/README.md create mode 100644 contrib/rosetta/configuration/bootstrap.json create mode 100644 contrib/rosetta/configuration/data.sh create mode 100644 contrib/rosetta/configuration/faucet.py create mode 100644 contrib/rosetta/configuration/rosetta.json create mode 100755 contrib/rosetta/configuration/run_tests.sh create mode 100644 contrib/rosetta/configuration/send_funds.sh create mode 100644 contrib/rosetta/configuration/staking.json create mode 100644 contrib/rosetta/configuration/staking.ros create mode 100644 contrib/rosetta/configuration/transfer.ros create mode 100644 contrib/rosetta/docker-compose.yaml create mode 100644 contrib/rosetta/node/Dockerfile create mode 100644 contrib/rosetta/node/data.tar.gz create mode 100644 contrib/rosetta/rosetta-cli/Dockerfile create mode 100644 docs/run-node/rosetta.md create mode 100644 server/rosetta.go create mode 100644 server/rosetta/client_offline.go create mode 100644 server/rosetta/client_online.go create mode 100644 server/rosetta/codec.go create mode 100644 server/rosetta/config.go create mode 100644 server/rosetta/conv_from_rosetta.go create mode 100644 server/rosetta/conv_to_rosetta.go create mode 100644 server/rosetta/types.go create mode 100644 server/rosetta/util.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2cbcb1477a..d8f051e60c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -188,6 +188,23 @@ jobs: name: "${{ github.sha }}-${{ matrix.part }}-race-output" path: ./${{ matrix.part }}-race-output.txt + test-rosetta: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v2 + - uses: technote-space/get-diff-action@v4 + id: git_diff + with: + PATTERNS: | + **/**.go + go.mod + go.sum + - name: test rosetta + run: | + make test-rosetta + # if: env.GIT_DIFF + race-detector-report: runs-on: ubuntu-latest needs: [test-race, install-tparse] diff --git a/Makefile b/Makefile index 6f498b36b3..0f4cf9e80f 100644 --- a/Makefile +++ b/Makefile @@ -309,6 +309,11 @@ test-cover: @export VERSION=$(VERSION); bash -x contrib/test_cover.sh .PHONY: test-cover +test-rosetta: + docker build -t rosetta-ci:latest -f contrib/rosetta/node/Dockerfile . + docker-compose -f contrib/rosetta/docker-compose.yaml up --abort-on-container-exit --exit-code-from test_rosetta --build +.PHONY: test-rosetta + benchmark: @go test -mod=readonly -bench=. $(PACKAGES_NOSIMULATION) .PHONY: benchmark @@ -463,3 +468,15 @@ localnet-stop: docker-compose down .PHONY: localnet-start localnet-stop + +############################################################################### +### rosetta ### +############################################################################### +# builds rosetta test data dir +rosetta-data: + -docker container rm data_dir_build + docker build -t rosetta-ci:latest -f contrib/rosetta/node/Dockerfile . + docker run --name data_dir_build -t rosetta-ci:latest sh /rosetta/data.sh + docker cp data_dir_build:/tmp/data.tar.gz "$(CURDIR)/contrib/rosetta/node/data.tar.gz" + docker container rm data_dir_build +.PHONY: rosetta-data \ No newline at end of file diff --git a/contrib/rosetta/README.md b/contrib/rosetta/README.md new file mode 100644 index 0000000000..b1d33659fe --- /dev/null +++ b/contrib/rosetta/README.md @@ -0,0 +1,24 @@ +# rosetta + +This directory contains the files required to run the rosetta CI. It builds `simapp` based on the current codebase. + +## docker-compose.yaml + +Builds: +- cosmos-sdk simapp node, with prefixed data directory, keys etc. This is required to test historical balances. +- faucet is required so we can test construction API, it was literally impossible to put there a deterministic address to request funds for +- rosetta is the rosetta node used by rosetta-cli to interact with the cosmos-sdk app +- test_rosetta runs the rosetta-cli test against construction API and data API + +## configuration + +Contains the required files to set up rosetta cli and make it work against its workflows + +## node + +Contains the files for a deterministic network, with fixed keys and some actions on there, to test parsing of msgs and historical balances. + +## Notes + +- Keyring password is 12345678 +- data.sh creates node data, it's required in case consensus breaking changes are made to quickly recreate replicable node data for rosetta diff --git a/contrib/rosetta/configuration/bootstrap.json b/contrib/rosetta/configuration/bootstrap.json new file mode 100644 index 0000000000..15b75b5508 --- /dev/null +++ b/contrib/rosetta/configuration/bootstrap.json @@ -0,0 +1,12 @@ +[ + { + "account_identifier": { + "address":"cosmos1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjjqfl87e" + }, + "currency":{ + "symbol":"stake", + "decimals":0 + }, + "value": "999900000000" + } +] \ No newline at end of file diff --git a/contrib/rosetta/configuration/data.sh b/contrib/rosetta/configuration/data.sh new file mode 100644 index 0000000000..dc4f2cb59a --- /dev/null +++ b/contrib/rosetta/configuration/data.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +set -e + +wait_simd() { + timeout 30 sh -c 'until nc -z $0 $1; do sleep 1; done' localhost 9090 +} +# this script is used to recreate the data dir +echo clearing /root/.simapp +rm -rf /root/.simapp +echo initting new chain +# init config files +simd init simd --chain-id testing + +# create accounts +simd keys add fd --keyring-backend=test + +addr=$(simd keys show fd -a --keyring-backend=test) + +# give the accounts some money +simd add-genesis-account "$addr" 1000000000000stake --keyring-backend=test + +# save configs for the daemon +simd gentx fd --chain-id testing --keyring-backend=test + +# input genTx to the genesis file +simd collect-gentxs +# verify genesis file is fine +simd validate-genesis +echo changing network settings +sed -i 's/127.0.0.1/0.0.0.0/g' /root/.simapp/config/config.toml + +# start simd +echo starting simd... +simd start --pruning=nothing & +pid=$! +echo simd started with PID $pid + +echo awaiting for simd to be ready +wait_simd +echo simd is ready +sleep 10 + + +# send transaction to deterministic address +echo sending transaction with addr $addr +simd tx bank send "$addr" cosmos1wjmt63j4fv9nqda92nsrp2jp2vsukcke4va3pt 100stake --yes --keyring-backend=test --broadcast-mode=block --chain-id=testing + +sleep 10 + +echo stopping simd... +kill -9 $pid + +echo zipping data dir and saving to /tmp/data.tar.gz + +tar -czvf /tmp/data.tar.gz /root/.simapp + +echo new address for bootstrap.json "$addr" diff --git a/contrib/rosetta/configuration/faucet.py b/contrib/rosetta/configuration/faucet.py new file mode 100644 index 0000000000..44536a84bb --- /dev/null +++ b/contrib/rosetta/configuration/faucet.py @@ -0,0 +1,25 @@ +from http.server import HTTPServer, BaseHTTPRequestHandler +import subprocess + +import os + + +class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): + + def do_POST(self): + try: + content_len = int(self.headers.get('Content-Length')) + addr = self.rfile.read(content_len).decode("utf-8") + print("sending funds to " + addr) + subprocess.call(['sh', './send_funds.sh', addr]) + self.send_response(200) + self.end_headers() + except Exception as e: + print("failed " + str(e)) + os._exit(1) + + +if __name__ == "__main__": + print("starting faucet server...") + httpd = HTTPServer(('0.0.0.0', 8000), SimpleHTTPRequestHandler) + httpd.serve_forever() diff --git a/contrib/rosetta/configuration/rosetta.json b/contrib/rosetta/configuration/rosetta.json new file mode 100644 index 0000000000..39a0bb3811 --- /dev/null +++ b/contrib/rosetta/configuration/rosetta.json @@ -0,0 +1,51 @@ +{ + "network": { + "blockchain": "app", + "network": "network" + }, + "online_url": "http://rosetta:8080", + "data_directory": "", + "http_timeout": 300, + "max_retries": 5, + "retry_elapsed_time": 0, + "max_online_connections": 0, + "max_sync_concurrency": 0, + "tip_delay": 60, + "log_configuration": true, + "construction": { + "offline_url": "http://rosetta:8080", + "max_offline_connections": 0, + "stale_depth": 0, + "broadcast_limit": 0, + "ignore_broadcast_failures": false, + "clear_broadcasts": false, + "broadcast_behind_tip": false, + "block_broadcast_limit": 0, + "rebroadcast_all": false, + "constructor_dsl_file": "transfer.ros", + "end_conditions": { + "create_account": 1, + "transfer": 3 + } + }, + "data": { + "active_reconciliation_concurrency": 0, + "inactive_reconciliation_concurrency": 0, + "inactive_reconciliation_frequency": 0, + "log_blocks": false, + "log_transactions": false, + "log_balance_changes": false, + "log_reconciliations": false, + "ignore_reconciliation_error": false, + "exempt_accounts": "", + "bootstrap_balances": "bootstrap.json", + "interesting_accounts": "", + "reconciliation_disabled": false, + "inactive_discrepency_search_disabled": false, + "balance_tracking_disabled": false, + "coin_tracking_disabled": false, + "end_conditions": { + "tip": true + } + } +} \ No newline at end of file diff --git a/contrib/rosetta/configuration/run_tests.sh b/contrib/rosetta/configuration/run_tests.sh new file mode 100755 index 0000000000..cd7af92acd --- /dev/null +++ b/contrib/rosetta/configuration/run_tests.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +set -e + +addr="abcd" + +send_tx() { + echo '12345678' | simd tx bank send $addr "$1" "$2" +} + +detect_account() { + line=$1 +} + +wait_for_rosetta() { + timeout 30 sh -c 'until nc -z $0 $1; do sleep 1; done' rosetta 8080 +} + +echo "waiting for rosetta instance to be up" +wait_for_rosetta + +echo "checking data API" +rosetta-cli check:data --configuration-file ./config/rosetta.json + +echo "checking construction API" +rosetta-cli check:construction --configuration-file ./config/rosetta.json + +echo "checking staking API" +rosetta-cli check:construction --configuration-file ./config/staking.json diff --git a/contrib/rosetta/configuration/send_funds.sh b/contrib/rosetta/configuration/send_funds.sh new file mode 100644 index 0000000000..3a897539d2 --- /dev/null +++ b/contrib/rosetta/configuration/send_funds.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e +addr=$(simd keys show fd -a --keyring-backend=test) +echo "12345678" | simd tx bank send "$addr" "$1" 100stake --chain-id="testing" --node tcp://cosmos:26657 --yes --keyring-backend=test \ No newline at end of file diff --git a/contrib/rosetta/configuration/staking.json b/contrib/rosetta/configuration/staking.json new file mode 100644 index 0000000000..9c5e5da3ba --- /dev/null +++ b/contrib/rosetta/configuration/staking.json @@ -0,0 +1,30 @@ +{ + "network": { + "blockchain": "app", + "network": "network" + }, + "online_url": "http://rosetta:8080", + "data_directory": "", + "http_timeout": 300, + "max_retries": 5, + "retry_elapsed_time": 0, + "max_online_connections": 0, + "max_sync_concurrency": 0, + "tip_delay": 60, + "log_configuration": true, + "construction": { + "offline_url": "http://rosetta:8080", + "max_offline_connections": 0, + "stale_depth": 0, + "broadcast_limit": 0, + "ignore_broadcast_failures": false, + "clear_broadcasts": false, + "broadcast_behind_tip": false, + "block_broadcast_limit": 0, + "rebroadcast_all": false, + "constructor_dsl_file": "staking.ros", + "end_conditions": { + "staking": 3 + } + } +} \ No newline at end of file diff --git a/contrib/rosetta/configuration/staking.ros b/contrib/rosetta/configuration/staking.ros new file mode 100644 index 0000000000..1d9de1d180 --- /dev/null +++ b/contrib/rosetta/configuration/staking.ros @@ -0,0 +1,147 @@ +request_funds(1){ + find_account{ + currency = {"symbol":"stake", "decimals":0}; + random_account = find_balance({ + "minimum_balance":{ + "value": "0", + "currency": {{currency}} + }, + "create_limit":1 + }); + }, + send_funds{ + account_identifier = {{random_account.account_identifier}}; + address = {{account_identifier.address}}; + idk = http_request({ + "method": "POST", + "url": "http:\/\/faucet:8000", + "timeout": 10, + "body": {{random_account.account_identifier.address}} + }); + }, + // Create a separate scenario to request funds so that + // the address we are using to request funds does not + // get rolled back if funds do not yet exist. + request{ + loaded_account = find_balance({ + "account_identifier": {{random_account.account_identifier}}, + "minimum_balance":{ + "value": "100", + "currency": {{currency}} + } + }); + } +} +create_account(1){ + create{ + network = {"network":"network", "blockchain":"app"}; + key = generate_key({"curve_type": "secp256k1"}); + account = derive({ + "network_identifier": {{network}}, + "public_key": {{key.public_key}} + }); + // If the account is not saved, the key will be lost! + save_account({ + "account_identifier": {{account.account_identifier}}, + "keypair": {{key}} + }); + } +} + +staking(1){ + stake{ + stake.network = {"network":"network", "blockchain":"app"}; + currency = {"symbol":"stake", "decimals":0}; + sender = find_balance({ + "minimum_balance":{ + "value": "100", + "currency": {{currency}} + } + }); + // Set the recipient_amount as some value <= sender.balance-max_fee + max_fee = "0"; + fee_amount = "1"; + fee_value = 0 - {{fee_amount}}; + available_amount = {{sender.balance.value}} - {{max_fee}}; + recipient_amount = "1"; + print_message({"recipient_amount":{{recipient_amount}}}); + // Find recipient and construct operations + recipient = {{sender.account_identifier}}; + sender_amount = 0 - {{recipient_amount}}; + stake.confirmation_depth = "1"; + stake.operations = [ + { + "operation_identifier":{"index":0}, + "type":"fee", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{fee_value}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":1}, + "type":"cosmos.staking.v1beta1.MsgDelegate", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{sender_amount}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":2}, + "type":"cosmos.staking.v1beta1.MsgDelegate", + "account": { + "address": "staking_account", + "sub_account": { + "address" : "cosmosvaloper1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjj9atjj2" + } + }, + "amount":{ + "value":{{recipient_amount}}, + "currency":{{currency}} + } + } + ]; + }, + undelegate{ + print_message({"undelegate":{{sender}}}); + + undelegate.network = {"network":"network", "blockchain":"app"}; + undelegate.confirmation_depth = "1"; + undelegate.operations = [ + { + "operation_identifier":{"index":0}, + "type":"fee", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{fee_value}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":1}, + "type":"cosmos.staking.v1beta1.MsgUndelegate", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{recipient_amount}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":2}, + "type":"cosmos.staking.v1beta1.MsgUndelegate", + "account": { + "address": "staking_account", + "sub_account": { + "address" : "cosmosvaloper1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjj9atjj2" + } + }, + "amount":{ + "value":{{sender_amount}}, + "currency":{{currency}} + } + } + ]; + } +} diff --git a/contrib/rosetta/configuration/transfer.ros b/contrib/rosetta/configuration/transfer.ros new file mode 100644 index 0000000000..a1cb3f8caf --- /dev/null +++ b/contrib/rosetta/configuration/transfer.ros @@ -0,0 +1,109 @@ +request_funds(1){ + find_account{ + currency = {"symbol":"stake", "decimals":0}; + random_account = find_balance({ + "minimum_balance":{ + "value": "0", + "currency": {{currency}} + }, + "create_limit":1 + }); + }, + send_funds{ + account_identifier = {{random_account.account_identifier}}; + address = {{account_identifier.address}}; + idk = http_request({ + "method": "POST", + "url": "http:\/\/faucet:8000", + "timeout": 10, + "body": {{random_account.account_identifier.address}} + }); + }, + // Create a separate scenario to request funds so that + // the address we are using to request funds does not + // get rolled back if funds do not yet exist. + request{ + loaded_account = find_balance({ + "account_identifier": {{random_account.account_identifier}}, + "minimum_balance":{ + "value": "100", + "currency": {{currency}} + } + }); + } +} +create_account(1){ + create{ + network = {"network":"network", "blockchain":"app"}; + key = generate_key({"curve_type": "secp256k1"}); + account = derive({ + "network_identifier": {{network}}, + "public_key": {{key.public_key}} + }); + // If the account is not saved, the key will be lost! + save_account({ + "account_identifier": {{account.account_identifier}}, + "keypair": {{key}} + }); + } +} +transfer(3){ + transfer{ + transfer.network = {"network":"network", "blockchain":"app"}; + currency = {"symbol":"stake", "decimals":0}; + sender = find_balance({ + "minimum_balance":{ + "value": "100", + "currency": {{currency}} + } + }); + // Set the recipient_amount as some value <= sender.balance-max_fee + max_fee = "0"; + fee_amount = "1"; + fee_value = 0 - {{fee_amount}}; + available_amount = {{sender.balance.value}} - {{max_fee}}; + recipient_amount = random_number({"minimum": "1", "maximum": {{available_amount}}}); + print_message({"recipient_amount":{{recipient_amount}}}); + // Find recipient and construct operations + sender_amount = 0 - {{recipient_amount}}; + recipient = find_balance({ + "not_account_identifier":[{{sender.account_identifier}}], + "minimum_balance":{ + "value": "0", + "currency": {{currency}} + }, + "create_limit": 100, + "create_probability": 50 + }); + transfer.confirmation_depth = "1"; + transfer.operations = [ + { + "operation_identifier":{"index":0}, + "type":"fee", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{fee_value}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":1}, + "type":"cosmos.bank.v1beta1.MsgSend", + "account":{{sender.account_identifier}}, + "amount":{ + "value":{{sender_amount}}, + "currency":{{currency}} + } + }, + { + "operation_identifier":{"index":2}, + "type":"cosmos.bank.v1beta1.MsgSend", + "account":{{recipient.account_identifier}}, + "amount":{ + "value":{{recipient_amount}}, + "currency":{{currency}} + } + } + ]; + } +} diff --git a/contrib/rosetta/docker-compose.yaml b/contrib/rosetta/docker-compose.yaml new file mode 100644 index 0000000000..0a9e82de8a --- /dev/null +++ b/contrib/rosetta/docker-compose.yaml @@ -0,0 +1,39 @@ +version: "3" + +services: + cosmos: + image: rosetta-ci:latest + command: ["simd", "start", "--pruning", "nothing", "--grpc-web.enable", "true", "--grpc-web.address", "0.0.0.0:9091"] + ports: + - 9090:9090 + - 26657:26657 + logging: + driver: "none" + + rosetta: + image: rosetta-ci:latest + command: [ + "simd", + "rosetta", + "--blockchain", "app", + "--network", "network", + "--tendermint", "cosmos:26657", + "--grpc", "cosmos:9090", + "--addr", ":8080", + ] + ports: + - 8080:8080 + + faucet: + image: rosetta-ci:latest + working_dir: /rosetta + command: ["python3", "faucet.py"] + expose: + - 8080 + + test_rosetta: + image: tendermintdev/rosetta-cli:v0.6.6 + volumes: + - ./configuration:/rosetta/config:z + command: ["./config/run_tests.sh"] + working_dir: /rosetta diff --git a/contrib/rosetta/node/Dockerfile b/contrib/rosetta/node/Dockerfile new file mode 100644 index 0000000000..0887f522f6 --- /dev/null +++ b/contrib/rosetta/node/Dockerfile @@ -0,0 +1,32 @@ +FROM golang:1.15-alpine as build + +RUN apk add --no-cache tar + +# prepare node data +WORKDIR /node +COPY ./contrib/rosetta/node/data.tar.gz data.tar.gz +RUN tar -zxvf data.tar.gz -C . + +# build simd +WORKDIR /simd +COPY . ./ +RUN go build -o simd ./simapp/simd/ + +FROM alpine +RUN apk add gcc libc-dev python3 --no-cache + +ENV PATH=$PATH:/bin + +COPY --from=build /simd/simd /bin/simd + +WORKDIR /rosetta +COPY ./contrib/rosetta/configuration ./ +RUN chmod +x run_tests.sh +RUN chmod +x send_funds.sh +RUN chmod +x faucet.py + +COPY --from=build /node/root /root/ +WORKDIR /root/.simapp + +RUN chmod -R 0777 ./ + diff --git a/contrib/rosetta/node/data.tar.gz b/contrib/rosetta/node/data.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..a7bed60579ea098baa390af3a29e05b08d16dcc8 GIT binary patch literal 34626 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 O?DZF9r!))zMgjoC3=_)$ literal 0 HcmV?d00001 diff --git a/contrib/rosetta/rosetta-cli/Dockerfile b/contrib/rosetta/rosetta-cli/Dockerfile new file mode 100644 index 0000000000..e0bc3c961f --- /dev/null +++ b/contrib/rosetta/rosetta-cli/Dockerfile @@ -0,0 +1,18 @@ +FROM golang:1.15-alpine as build + +RUN apk add git gcc libc-dev --no-cache + +ARG ROSETTA_VERSION="v0.5.23" + +# build rosetta CLI +WORKDIR /rosetta +RUN git clone https://github.com/coinbase/rosetta-cli . +RUN git checkout tags/$ROSETTA_VERSION +RUN go build -o rosetta-cli ./main.go + +FROM alpine +RUN apk add gcc libc-dev python3 --no-cache + +ENV PATH=$PATH:/bin + +COPY --from=build /rosetta/rosetta-cli /bin/rosetta-cli diff --git a/docs/architecture/adr-035-rosetta-api-support.md b/docs/architecture/adr-035-rosetta-api-support.md index 2da663f572..b7807ce1d2 100644 --- a/docs/architecture/adr-035-rosetta-api-support.md +++ b/docs/architecture/adr-035-rosetta-api-support.md @@ -5,6 +5,7 @@ - Jonathan Gimeno (@jgimeno) - David Grierson (@senormonito) - Alessio Treglia (@alessio) +- Frojdy Dymylja (@fdymylja) ## Context @@ -35,9 +36,11 @@ We will achieve these delivering on these principles by the following: 1. There will be an external repo called [cosmos-rosetta-gateway](https://github.com/tendermint/cosmos-rosetta-gateway) for the implementation of the core Rosetta API features, particularly: - a. The types and interfaces. This separates design from implementation detail. - b. Some core implementations: specifically, the `Service` functionality as this is independent of the Cosmos SDK version. -2. Due to differences between the Cosmos release series, each series will have its own specific API implementations of `Network` struct and `Adapter` interface. + a. The types and interfaces (`Client`, `OfflineClient`...), this separates design from implementation detail. + b. The `Server` functionality as this is independent of the Cosmos SDK version. + c. The `Online/OfflineNetwork`, which is not exported, and implements the rosetta API using the `Client` interface to query the node, build tx and so on. + d. The `errors` package to extend rosetta errors. +2. Due to differences between the Cosmos release series, each series will have its own specific implementation of `Client` interface. 3. There will be two options for starting an API service in applications: a. API shares the application process b. API-specific process. @@ -49,143 +52,130 @@ We will achieve these delivering on these principles by the following: As section will describe the proposed external library, including the service implementation, plus the defined types and interfaces. -#### Service +#### Server -`Service` is a simple `struct` that is started and listens to the port specified in the options. This is meant to be used across all the Cosmos SDK versions that are actively supported. +`Server` is a simple `struct` that is started and listens to the port specified in the settings. This is meant to be used across all the Cosmos SDK versions that are actively supported. The constructor follows: -`func New(options Options, network Network) (*Service, error)` +`func NewServer(settings Settings) (Server, error)` + +`Settings`, which are used to construct a new server, are the following: +```go +// Settings define the rosetta server settings +type Settings struct { + // Network contains the information regarding the network + Network *types.NetworkIdentifier + // Client is the online API handler + Client crgtypes.Client + // Listen is the address the handler will listen at + Listen string + // Offline defines if the rosetta service should be exposed in offline mode + Offline bool + // Retries is the number of readiness checks that will be attempted when instantiating the handler + // valid only for online API + Retries int + // RetryWait is the time that will be waited between retries + RetryWait time.Duration +} +``` #### Types -`Service` accepts an `Options` `struct` that holds service configuration values, such as the port the service would be listening to: +Package types uses a mixture of rosetta types and custom defined type wrappers, that the client must parse and return while executing operations. -```golang -type Options struct { - ListenAddress string + +##### Interfaces + +Every SDK version uses a different format to connect (rpc, gRPC, etc), query and build transactions, we have abstracted this in what is the `Client` interface. +The client uses rosetta types, whilst the `Online/OfflineNetwork` takes care of returning correctly parsed rosetta responses and errors. + +Each Cosmos SDK release series will have their own `Client` implementations. +Developers can implement their own custom `Client`s as required. + +```go +// Client defines the API the client implementation should provide. +type Client interface { + // Needed if the client needs to perform some action before connecting. + Bootstrap() error + // Ready checks if the servicer constraints for queries are satisfied + // for example the node might still not be ready, it's useful in process + // when the rosetta instance might come up before the node itself + // the servicer must return nil if the node is ready + Ready() error + + // Data API + + // Balances fetches the balance of the given address + // if height is not nil, then the balance will be displayed + // at the provided height, otherwise last block balance will be returned + Balances(ctx context.Context, addr string, height *int64) ([]*types.Amount, error) + // BlockByHashAlt gets a block and its transaction at the provided height + BlockByHash(ctx context.Context, hash string) (BlockResponse, error) + // BlockByHeightAlt gets a block given its height, if height is nil then last block is returned + BlockByHeight(ctx context.Context, height *int64) (BlockResponse, error) + // BlockTransactionsByHash gets the block, parent block and transactions + // given the block hash. + BlockTransactionsByHash(ctx context.Context, hash string) (BlockTransactionsResponse, error) + // BlockTransactionsByHash gets the block, parent block and transactions + // given the block hash. + BlockTransactionsByHeight(ctx context.Context, height *int64) (BlockTransactionsResponse, error) + // GetTx gets a transaction given its hash + GetTx(ctx context.Context, hash string) (*types.Transaction, error) + // GetUnconfirmedTx gets an unconfirmed Tx given its hash + // NOTE(fdymylja): NOT IMPLEMENTED YET! + GetUnconfirmedTx(ctx context.Context, hash string) (*types.Transaction, error) + // Mempool returns the list of the current non confirmed transactions + Mempool(ctx context.Context) ([]*types.TransactionIdentifier, error) + // Peers gets the peers currently connected to the node + Peers(ctx context.Context) ([]*types.Peer, error) + // Status returns the node status, such as sync data, version etc + Status(ctx context.Context) (*types.SyncStatus, error) + + // Construction API + + // PostTx posts txBytes to the node and returns the transaction identifier plus metadata related + // to the transaction itself. + PostTx(txBytes []byte) (res *types.TransactionIdentifier, meta map[string]interface{}, err error) + // ConstructionMetadataFromOptions + ConstructionMetadataFromOptions(ctx context.Context, options map[string]interface{}) (meta map[string]interface{}, err error) + OfflineClient +} + +// OfflineClient defines the functionalities supported without having access to the node +type OfflineClient interface { + NetworkInformationProvider + // SignedTx returns the signed transaction given the tx bytes (msgs) plus the signatures + SignedTx(ctx context.Context, txBytes []byte, sigs []*types.Signature) (signedTxBytes []byte, err error) + // TxOperationsAndSignersAccountIdentifiers returns the operations related to a transaction and the account + // identifiers if the transaction is signed + TxOperationsAndSignersAccountIdentifiers(signed bool, hexBytes []byte) (ops []*types.Operation, signers []*types.AccountIdentifier, err error) + // ConstructionPayload returns the construction payload given the request + ConstructionPayload(ctx context.Context, req *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) + // PreprocessOperationsToOptions returns the options given the preprocess operations + PreprocessOperationsToOptions(ctx context.Context, req *types.ConstructionPreprocessRequest) (options map[string]interface{}, err error) + // AccountIdentifierFromPublicKey returns the account identifier given the public key + AccountIdentifierFromPublicKey(pubKey *types.PublicKey) (*types.AccountIdentifier, error) } ``` -The `Network` type holds network-specific properties (i.e. configuration values) and adapters. Pre-configured concrete types will be available for each Cosmos SDK release. Applications can also create their own custom types. - -```golang -type Network struct { - Properties rosetta.NetworkProperties - Adapter rosetta.Adapter -} -``` - -A `NetworkProperties` `struct` comprises basic values that are required by a Rosetta API `Service`: - -```golang -type NetworkProperties struct { - // Mandatory properties - Blockchain string - Network string - SupportedOperations []string -} -``` - -Rosetta API services use `Blockchain` and `Network` as identifiers, e.g. the developers of _gaia_, the application that powers the Cosmos Hub, may want to set those to `Cosmos Hub` and `cosmos-hub-3` respectively. - -`SupportedOperations` contains the transaction types that are supported by the library. At the present time, -only `cosmos-sdk/MsgSend` is supported in Launchpad. Additional operations will be added in due time. - -For Launchpad we will map the amino type name to the operation supported, in Stargate we will use the protoc one. - -#### Interfaces - -Every SDK version uses a different format to connect (rpc, gRpc, etc), we have abstracted this in what is called the -Adapter. This is an interface that defines the methods an adapter implementation must provide in order to be used -in the `Network` interface. - -Each Cosmos SDK release series will have their own Adapter implementations. -Developers can implement their own custom adapters as required. - -```golang -type Adapter interface { - DataAPI - ConstructionAPI -} - -type DataAPI interface { - server.NetworkAPIServicer - server.AccountAPIServicer - server.MempoolAPIServicer - server.BlockAPIServicer - server.ConstructionAPIServicer -} - -type ConstructionAPI interface { - server.ConstructionAPIServicer -} -``` - -Example in pseudo-code of an Adapter interface: - -```golang -type SomeAdapter struct { - cosmosClient client - tendermintClient client -} - -func NewSomeAdapter(cosmosClient client, tendermintClient client) rosetta.Adapter { - return &SomeAdapter{cosmosClient: cosmosClient, tendermintClient: tendermintClient} -} - -func (s SomeAdapter) NetworkStatus(ctx context.Context, request *types.NetworkRequest) (*types.NetworkStatusResponse, *types.Error) { - resp := s.tendermintClient.CallStatus() - // ... Parse status Response - // build NetworkStatusResponse - return networkStatusResp, nil -} - -func (s SomeAdapter) AccountBalance(ctx context.Context, request *types.AccountBalanceRequest) (*types.AccountBalanceResponse, *types.Error) { - resp := s.cosmosClient.Account() - // ... Parse cosmos specific account response - // build AccountBalanceResponse - return AccountBalanceResponse, nil -} - -// And we repeat for all the methods defined in the interface. -``` - -For further information about the `Servicer` interfaces, please refer to the [Coinbase's rosetta-sdk-go's documentation](https://pkg.go.dev/github.com/coinbase/rosetta-sdk-go@v0.5.9/server). - ### 2. Cosmos SDK Implementation -As described, each Cosmos SDK release series will have version specific implementations of `Network` and `Adapter`, as -well as a `NewNetwork` constructor. +The cosmos sdk implementation, based on version, takes care of satisfying the `Client` interface. +In Stargate, Launchpad and 0.37, we have introduced the concept of rosetta.Msg, this message is not in the shared repository as the sdk.Msg type differs between cosmos-sdk versions. -Due to separation of interface and implementation, application developers have the option to override as needed, -using this code as reference. +The rosetta.Msg interface follows: -```golang -// NewNetwork returns the default application configuration. -func NewNetwork(options Options) service.Network { - cosmosClient := cosmos.NewClient(fmt.Sprintf("http://%s", options.CosmosEndpoint)) - tendermintClient := tendermint.NewClient(fmt.Sprintf("http://%s", options.TendermintEndpoint)) - - return service.Network{ - Properties: rosetta.NetworkProperties{ - Blockchain: options.Blockchain, - Network: options.Network, - SupportedOperations: []string{OperationTransfer}, - }, - Adapter: newAdapter( - cosmosClient, - tendermintClient, - properties{ - Blockchain: options.Blockchain, - Network: options.Network, - OfflineMode: options.OfflineMode, - }, - ), - } +```go +// Msg represents a cosmos-sdk message that can be converted from and to a rosetta operation. +type Msg interface { + sdk.Msg + ToOperations(withStatus, hasError bool) []*types.Operation + FromOperations(ops []*types.Operation) (sdk.Msg, error) } ``` +Hence developers who want to extend the rosetta set of supported operations just need to extend their module's sdk.Msgs with the `ToOperations` and `FromOperations` methods. ### 3. API service invocation As stated at the start, application developers will have two methods for invocation of the Rosetta API service: @@ -195,67 +185,13 @@ As stated at the start, application developers will have two methods for invocat #### Shared Process (Only Stargate) -Rosetta API service could run within the same execution process as the application. New configuration option and -command line flags would be provided to support this: +Rosetta API service could run within the same execution process as the application. This would be enabled via app.toml settings, and if gRPC is not enabled the rosetta instance would be spinned in offline mode (tx building capabilities only). -```golang - if config.Rosetta.Enable { - .... - get contecxt, flags, etc - ... - - h, err := service.New( - service.Options{ListenAddress: config.Rosetta.ListenAddress}, - rosetta.NewNetwork(cdc, options), - ) - if err != nil { - } - - ... - - go func() { - if err := h.Start(config); err != nil { - errCh <- err - } - }() - } - -``` #### Separate API service -Client application developers can write a new command to launch a Rosetta API server as a separate process too: +Client application developers can write a new command to launch a Rosetta API server as a separate process too, using the rosetta command contained in the `/server/rosetta` package. Construction of the command depends on cosmos sdk version. Examples can be found inside `simd` for stargate, and `contrib/rosetta/simapp` for other release series. -```golang -func RosettaCommand(cdc *codec.Codec) *cobra.Command { - - ... - cmd := &cobra.Command{ - Use: "rosetta", - .... - - RunE: func(cmd *cobra.Command, args []string) error { - .... - get contecxt, flags, etc - ... - - h, err := service.New( - service.Options{Endpoint: endpoint}, - rosetta.NewNetwork(cdc, options), - ) - if err != nil { - return err - } - - ... - - h.Start() - } - } - ... - -} -``` ## Status diff --git a/docs/run-node/README.md b/docs/run-node/README.md index 0a2f24b879..27ee972650 100644 --- a/docs/run-node/README.md +++ b/docs/run-node/README.md @@ -13,3 +13,4 @@ This folder contains documentation on how to run a node and interact with it. 1. [Interacting with a Node](./interact-node.md) 1. [Generating, Signing and Broadcasting Transactions](./txs.md) 1. [Cosmos Upgrade Manager](./cosmovisor.md) +1. [Rosetta API](./rosetta.md) diff --git a/docs/run-node/rosetta.md b/docs/run-node/rosetta.md new file mode 100644 index 0000000000..b10bc21e79 --- /dev/null +++ b/docs/run-node/rosetta.md @@ -0,0 +1,83 @@ +# Rosetta + +Package rosetta implements the rosetta API for the current cosmos sdk release series. + +The client satisfies [cosmos-rosetta-gateway](https://github.com/tendermint/cosmos-rosetta-gateway) `Client` interface implementation. + +## Extension + +There are two ways in which you can customize and extend the implementation with your custom settings. + +### Message extension + +In order to make an `sdk.Msg` understandable by rosetta the only thing which is required is adding the methods to your message that satisfy the `rosetta.Msg` interface. +Examples on how to do so can be found in the staking types such as `MsgDelegate`, or in bank types such as `MsgSend`. + +### Client interface override + +In case more customization is required, it's possible to embed the Client type and override the methods which require customizations. + +Example: +```go +package custom_client +import ( + +"context" +"github.com/coinbase/rosetta-sdk-go/types" +"github.com/cosmos/cosmos-sdk/server/rosetta" +) + +// CustomClient embeds the standard cosmos client +// which means that it implements the cosmos-rosetta-gateway Client +// interface while at the same time allowing to customize certain methods +type CustomClient struct { + *rosetta.Client +} + +func (c *CustomClient) ConstructionPayload(_ context.Context, request *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) { + // provide custom signature bytes + panic("implement me") +} +``` + +### Error extension + +Since rosetta requires to provide 'returned' errors to network options. In order to declare a new rosetta error, we use the `errors` package in cosmos-rosetta-gateway. + +Example: + +```go +package custom_errors +import crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + +var customErrRetriable = true +var CustomError = crgerrs.RegisterError(100, "custom message", customErrRetriable, "description") +``` + +Note: errors must be registered before cosmos-rosetta-gateway's `Server`.`Start` method is called. Otherwise the registration will be ignored. Errors with same code will be ignored too. + +## Integration in app.go + +To integrate rosetta as a command in your application, in app.go, in your root command simply use the `server.RosettaCommand` method. + +Example: + +```go +package app +import ( + +"github.com/cosmos/cosmos-sdk/server" +"github.com/spf13/cobra" +) + +func buildAppCommand(rootCmd *cobra.Command) { + // more app.go init stuff + // ... + // add rosetta command + rootCmd.AddCommand(server.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler)) +} +``` + +A full implementation example can be found in `simapp` package. + +NOTE: when using a customized client, the command cannot be used as the constructors required **may** differ, so it's required to create a new one. We intend to provide a way to init a customized client without writing extra code in the future. \ No newline at end of file diff --git a/go.mod b/go.mod index 323f13ebc4..3e2c956f35 100644 --- a/go.mod +++ b/go.mod @@ -4,18 +4,16 @@ module github.com/cosmos/cosmos-sdk require ( github.com/99designs/keyring v1.1.6 - github.com/DataDog/zstd v1.4.5 // indirect github.com/armon/go-metrics v0.3.6 github.com/bgentry/speakeasy v0.1.0 github.com/btcsuite/btcd v0.21.0-beta github.com/btcsuite/btcutil v1.0.2 + github.com/coinbase/rosetta-sdk-go v0.5.9 github.com/confio/ics23/go v0.6.3 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/iavl v0.15.3 github.com/cosmos/ledger-cosmos-go v0.11.1 github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect - github.com/dgraph-io/ristretto v0.0.3 // indirect - github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 github.com/gogo/gateway v1.1.0 github.com/gogo/protobuf v1.3.3 @@ -31,7 +29,7 @@ require ( github.com/magiconair/properties v1.8.4 github.com/mattn/go-isatty v0.0.12 github.com/otiai10/copy v1.4.2 - github.com/pelletier/go-toml v1.8.0 // indirect + github.com/pelletier/go-toml v1.8.1 // indirect github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.8.0 github.com/prometheus/common v0.15.0 @@ -41,11 +39,12 @@ require ( github.com/spf13/afero v1.3.4 // indirect github.com/spf13/cast v1.3.1 github.com/spf13/cobra v1.1.1 - github.com/spf13/jwalterweatherman v1.1.0 // indirect; indirects + github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.7.0 github.com/tendermint/btcd v0.1.1 + github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 github.com/tendermint/tendermint v0.34.3 @@ -54,6 +53,7 @@ require ( google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f google.golang.org/grpc v1.35.0 google.golang.org/protobuf v1.25.0 + gopkg.in/ini.v1 v1.61.0 // indirect gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 21ae47248e..c99dd6b24c 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,19 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/99designs/keyring v1.1.6 h1:kVDC2uCgVwecxCk+9zoCt2uEL6dt+dfVzMvGgnVcIuM= github.com/99designs/keyring v1.1.6/go.mod h1:16e0ds7LGQQcT59QqkTg72Hh5ShM51Byv5PEmW6uoRU= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -26,6 +39,8 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= @@ -37,9 +52,11 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -48,6 +65,7 @@ github.com/armon/go-metrics v0.3.6/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -57,6 +75,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= @@ -76,6 +95,7 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= @@ -83,9 +103,13 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coinbase/rosetta-sdk-go v0.5.8/go.mod h1:xd4wYUhV3LkY78SPH8BUhc88rXfn2jYgN9BfiSjbcvM= +github.com/coinbase/rosetta-sdk-go v0.5.9 h1:CuGQE3HFmYwdEACJnuOtVI9cofqPsGvq6FdFIzaOPKI= +github.com/coinbase/rosetta-sdk-go v0.5.9/go.mod h1:xd4wYUhV3LkY78SPH8BUhc88rXfn2jYgN9BfiSjbcvM= github.com/confio/ics23/go v0.0.0-20200817220745-f173e6211efb/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/confio/ics23/go v0.6.3 h1:PuGK2V1NJWZ8sSkNDq91jgT/cahFEW9RGp4Y5jxulf0= github.com/confio/ics23/go v0.6.3/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= @@ -120,6 +144,7 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= @@ -134,29 +159,39 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ= github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= +github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4pn2T/hjXMbvwTr1Cvy5THHrQkbeY9HRk= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.9.23 h1:SIKhg/z4Q7AbvqcxuPYvMxf36che/Rq/Pp0IdYEkbtw= +github.com/ethereum/go-ethereum v1.9.23/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -164,6 +199,7 @@ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -175,6 +211,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -207,6 +245,7 @@ github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -218,9 +257,13 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -241,8 +284,10 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.1/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= @@ -293,13 +338,18 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/improbable-eng/grpc-web v0.13.0 h1:7XqtaBWaOCH0cVGKHyvhtcuo6fgW32Y10yRKrDHFHOc= github.com/improbable-eng/grpc-web v0.13.0/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -317,8 +367,10 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -331,23 +383,36 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY= github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -365,6 +430,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -374,6 +441,8 @@ github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ib github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= @@ -389,6 +458,8 @@ github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtb github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -420,11 +491,13 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw= -github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= +github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= @@ -472,6 +545,7 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= @@ -482,11 +556,14 @@ github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzy github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs= github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo= @@ -497,6 +574,7 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0 github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y= github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -535,6 +613,9 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -545,6 +626,7 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -556,6 +638,8 @@ github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzH github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= +github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1 h1:UEkXlFMcWdQWPOA/Rf8nV4WruMK7JO2U8iX7rMTuC24= +github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1/go.mod h1:gBPw8WV2Erm4UGHlBRiM3zaEBst4bsuihmMCNQdgP/s= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= @@ -568,13 +652,21 @@ github.com/tendermint/tendermint v0.34.3/go.mod h1:h57vnXeOlrdvvNFCqPBSaOrpOivl+ github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3 h1:ZkhQcKnB8/2jr5EaZwGndN4owkPsGezW2fSisS9zGbg= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= +github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0= +github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= +github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/sjson v1.1.2/go.mod h1:SEzaDwxiPzKzNfUEO4HbYF/m4UCSJDsGgNqsS1LvdoY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vmihailenco/msgpack/v5 v5.0.0-beta.9/go.mod h1:HVxBVPUK/+fZMonk4bi1islLa8V3cfnBug0+4dykPzo= +github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -623,6 +715,7 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= @@ -636,15 +729,18 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -669,6 +765,7 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -681,6 +778,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -692,6 +790,7 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -713,12 +812,16 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -754,6 +857,7 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -818,9 +922,14 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.61.0 h1:LBCdW4FmFYL4s/vDZD1RQYX7oAR6IjujCYgMdbHBR10= +gopkg.in/ini.v1 v1.61.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -834,6 +943,9 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/server/config/config.go b/server/config/config.go index 68f6cf4352..8f1c47e88d 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -101,6 +101,29 @@ type APIConfig struct { // Ref: https://github.com/cosmos/cosmos-sdk/issues/6420 } +// RosettaConfig defines the Rosetta API listener configuration. +type RosettaConfig struct { + // Address defines the API server to listen on + Address string `mapstructure:"address"` + + // Blockchain defines the blockchain name + // defaults to DefaultBlockchain + Blockchain string `mapstructure:"blockchain"` + + // Network defines the network name + Network string `mapstructure:"network"` + + // Retries defines the maximum number of retries + // rosetta will do before quitting + Retries int `mapstructure:"retries"` + + // Enable defines if the API server should be enabled. + Enable bool `mapstructure:"enable"` + + // Offline defines if the server must be run in offline mode + Offline bool `mapstructure:"offline"` +} + // GRPCConfig defines configuration for the gRPC server. type GRPCConfig struct { // Enable defines if the gRPC server should be enabled. @@ -138,6 +161,7 @@ type Config struct { Telemetry telemetry.Config `mapstructure:"telemetry"` API APIConfig `mapstructure:"api"` GRPC GRPCConfig `mapstructure:"grpc"` + Rosetta RosettaConfig `mapstructure:"rosetta"` GRPCWeb GRPCWebConfig `mapstructure:"grpc-web"` StateSync StateSyncConfig `mapstructure:"state-sync"` } @@ -198,6 +222,14 @@ func DefaultConfig() *Config { Enable: true, Address: DefaultGRPCAddress, }, + Rosetta: RosettaConfig{ + Enable: false, + Address: ":8080", + Blockchain: "app", + Network: "network", + Retries: 3, + Offline: false, + }, GRPCWeb: GRPCWebConfig{ Enable: true, Address: DefaultGRPCWebAddress, @@ -252,6 +284,14 @@ func GetConfig(v *viper.Viper) Config { RPCMaxBodyBytes: v.GetUint("api.rpc-max-body-bytes"), EnableUnsafeCORS: v.GetBool("api.enabled-unsafe-cors"), }, + Rosetta: RosettaConfig{ + Enable: v.GetBool("rosetta.enable"), + Address: v.GetString("rosetta.address"), + Blockchain: v.GetString("rosetta.blockchain"), + Network: v.GetString("rosetta.network"), + Retries: v.GetInt("rosetta.retries"), + Offline: v.GetBool("rosetta.offline"), + }, GRPC: GRPCConfig{ Enable: v.GetBool("grpc.enable"), Address: v.GetString("grpc.address"), diff --git a/server/config/toml.go b/server/config/toml.go index 58dc7bfed2..88197defe9 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -135,6 +135,30 @@ rpc-max-body-bytes = {{ .API.RPCMaxBodyBytes }} # EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk). enabled-unsafe-cors = {{ .API.EnableUnsafeCORS }} +############################################################################### +### Rosetta Configuration ### +############################################################################### + +[rosetta] + +# Enable defines if the Rosetta API server should be enabled. +enable = {{ .Rosetta.Enable }} + +# Address defines the Rosetta API server to listen on. +address = "{{ .Rosetta.Address }}" + +# Network defines the name of the blockchain that will be returned by Rosetta. +blockchain = "{{ .Rosetta.Blockchain }}" + +# Network defines the name of the network that will be returned by Rosetta. +network = "{{ .Rosetta.Network }}" + +# Retries defines the number of retries when connecting to the node before failing. +retries = {{ .Rosetta.Retries }} + +# Offline defines if Rosetta server should run in offline mode. +offline = {{ .Rosetta.Offline }} + ############################################################################### ### gRPC Configuration ### ############################################################################### diff --git a/server/rosetta.go b/server/rosetta.go new file mode 100644 index 0000000000..c6a928d062 --- /dev/null +++ b/server/rosetta.go @@ -0,0 +1,42 @@ +package server + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/server/rosetta" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" +) + +// RosettaCommand builds the rosetta root command given +// a protocol buffers serializer/deserializer +func RosettaCommand(ir codectypes.InterfaceRegistry, cdc codec.Marshaler) *cobra.Command { + cmd := &cobra.Command{ + Use: "rosetta", + Short: "spin up a rosetta server", + RunE: func(cmd *cobra.Command, args []string) error { + conf, err := rosetta.FromFlags(cmd.Flags()) + if err != nil { + return err + } + + protoCodec, ok := cdc.(*codec.ProtoCodec) + if !ok { + return fmt.Errorf("exoected *codec.ProtoMarshaler, got: %T", cdc) + } + conf.WithCodec(ir, protoCodec) + + rosettaSrv, err := rosetta.ServerFromConfig(conf) + if err != nil { + return err + } + return rosettaSrv.Start() + }, + } + rosetta.SetFlags(cmd.Flags()) + + return cmd +} diff --git a/server/rosetta/client_offline.go b/server/rosetta/client_offline.go new file mode 100644 index 0000000000..f619bfc6d2 --- /dev/null +++ b/server/rosetta/client_offline.go @@ -0,0 +1,221 @@ +package rosetta + +import ( + "context" + "encoding/hex" + "strings" + + "github.com/btcsuite/btcd/btcec" + "github.com/coinbase/rosetta-sdk-go/types" + crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" +) + +func (c *Client) OperationStatuses() []*types.OperationStatus { + return []*types.OperationStatus{ + { + Status: StatusSuccess, + Successful: true, + }, + { + Status: StatusReverted, + Successful: false, + }, + } +} + +func (c *Client) Version() string { + return c.version +} + +func (c *Client) SupportedOperations() []string { + var supportedOperations []string + for _, ii := range c.ir.ListImplementations("cosmos.base.v1beta1.Msg") { + resolve, err := c.ir.Resolve(ii) + if err != nil { + continue + } + + if _, ok := resolve.(Msg); ok { + supportedOperations = append(supportedOperations, strings.TrimLeft(ii, "/")) + } + } + + supportedOperations = append(supportedOperations, OperationFee) + + return supportedOperations +} + +func (c *Client) SignedTx(ctx context.Context, txBytes []byte, signatures []*types.Signature) (signedTxBytes []byte, err error) { + TxConfig := c.getTxConfig() + rawTx, err := TxConfig.TxDecoder()(txBytes) + if err != nil { + return nil, err + } + + txBldr, err := TxConfig.WrapTxBuilder(rawTx) + if err != nil { + return nil, err + } + + var sigs = make([]signing.SignatureV2, len(signatures)) + for i, signature := range signatures { + if signature.PublicKey.CurveType != types.Secp256k1 { + return nil, crgerrs.ErrUnsupportedCurve + } + + cmp, err := btcec.ParsePubKey(signature.PublicKey.Bytes, btcec.S256()) + if err != nil { + return nil, err + } + + compressedPublicKey := make([]byte, secp256k1.PubKeySize) + copy(compressedPublicKey, cmp.SerializeCompressed()) + pubKey := &secp256k1.PubKey{Key: compressedPublicKey} + + accountInfo, err := c.accountInfo(ctx, sdk.AccAddress(pubKey.Address()).String(), nil) + if err != nil { + return nil, err + } + + sig := signing.SignatureV2{ + PubKey: pubKey, + Data: &signing.SingleSignatureData{ + SignMode: signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, + Signature: signature.Bytes, + }, + Sequence: accountInfo.GetSequence(), + } + sigs[i] = sig + } + + if err = txBldr.SetSignatures(sigs...); err != nil { + return nil, err + } + + txBytes, err = c.getTxConfig().TxEncoder()(txBldr.GetTx()) + if err != nil { + return nil, err + } + + return txBytes, nil +} + +func (c *Client) ConstructionPayload(_ context.Context, request *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) { + // check if there is at least one operation + if len(request.Operations) < 1 { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidOperation, "expected at least one operation") + } + + // convert rosetta operations to sdk msgs and fees (if present) + msgs, fee, err := opsToMsgsAndFees(c.ir, request.Operations) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidOperation, err.Error()) + } + + metadata, err := getMetadataFromPayloadReq(request) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error()) + } + + txFactory := tx.Factory{}.WithAccountNumber(metadata.AccountNumber).WithChainID(metadata.ChainID). + WithGas(metadata.Gas).WithSequence(metadata.Sequence).WithMemo(metadata.Memo).WithFees(fee.String()) + + TxConfig := c.getTxConfig() + txFactory = txFactory.WithTxConfig(TxConfig) + + txBldr, err := tx.BuildUnsignedTx(txFactory, msgs...) + if err != nil { + return nil, err + } + + // Sign_mode_legacy_amino is being used as default here, as sign_mode_direct + // needs the signer infos to be set before hand but rosetta doesn't have a way + // to do this yet. To be revisited in future versions of sdk and rosetta + if txFactory.SignMode() == signing.SignMode_SIGN_MODE_UNSPECIFIED { + txFactory = txFactory.WithSignMode(signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON) + } + + signerData := authsigning.SignerData{ + ChainID: txFactory.ChainID(), + AccountNumber: txFactory.AccountNumber(), + Sequence: txFactory.Sequence(), + } + + signBytes, err := TxConfig.SignModeHandler().GetSignBytes(txFactory.SignMode(), signerData, txBldr.GetTx()) + if err != nil { + return nil, err + } + + txBytes, err := TxConfig.TxEncoder()(txBldr.GetTx()) + if err != nil { + return nil, err + } + + accIdentifiers := getAccountIdentifiersByMsgs(msgs) + + payloads := make([]*types.SigningPayload, len(accIdentifiers)) + for i, accID := range accIdentifiers { + payloads[i] = &types.SigningPayload{ + AccountIdentifier: accID, + Bytes: crypto.Sha256(signBytes), + SignatureType: types.Ecdsa, + } + } + + return &types.ConstructionPayloadsResponse{ + UnsignedTransaction: hex.EncodeToString(txBytes), + Payloads: payloads, + }, nil +} + +func getAccountIdentifiersByMsgs(msgs []sdk.Msg) []*types.AccountIdentifier { + var accIdentifiers []*types.AccountIdentifier + for _, msg := range msgs { + for _, signer := range msg.GetSigners() { + accIdentifiers = append(accIdentifiers, &types.AccountIdentifier{Address: signer.String()}) + } + } + + return accIdentifiers +} + +func (c *Client) PreprocessOperationsToOptions(_ context.Context, req *types.ConstructionPreprocessRequest) (options map[string]interface{}, err error) { + operations := req.Operations + if len(operations) < 1 { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, "invalid number of operations") + } + + msgs, err := opsToMsgs(c.ir, operations) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidOperation, err.Error()) + } + + if len(msgs) < 1 || len(msgs[0].GetSigners()) < 1 { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidOperation, "operation produced no msg or signers") + } + + memo, ok := req.Metadata["memo"] + if !ok { + memo = "" + } + + defaultGas := float64(200000) + + gas := req.SuggestedFeeMultiplier + if gas == nil { + gas = &defaultGas + } + + return map[string]interface{}{ + OptionAddress: msgs[0].GetSigners()[0], + OptionMemo: memo, + OptionGas: gas, + }, nil +} diff --git a/server/rosetta/client_online.go b/server/rosetta/client_online.go new file mode 100644 index 0000000000..110430bb18 --- /dev/null +++ b/server/rosetta/client_online.go @@ -0,0 +1,447 @@ +package rosetta + +import ( + "bytes" + "context" + "encoding/hex" + "fmt" + "strconv" + "time" + + "github.com/cosmos/cosmos-sdk/version" + + abcitypes "github.com/tendermint/tendermint/abci/types" + + "github.com/tendermint/btcd/btcec" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + + "github.com/coinbase/rosetta-sdk-go/types" + "google.golang.org/grpc/metadata" + + "github.com/tendermint/tendermint/rpc/client/http" + tmtypes "github.com/tendermint/tendermint/rpc/core/types" + "google.golang.org/grpc" + + crgerrs "github.com/tendermint/cosmos-rosetta-gateway/errors" + crgtypes "github.com/tendermint/cosmos-rosetta-gateway/types" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" + authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + auth "github.com/cosmos/cosmos-sdk/x/auth/types" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// interface assertion +var _ crgtypes.Client = (*Client)(nil) + +const tmWebsocketPath = "/websocket" +const defaultNodeTimeout = 15 * time.Second + +// Client implements a single network client to interact with cosmos based chains +type Client struct { + config *Config + + auth auth.QueryClient + bank bank.QueryClient + + ir codectypes.InterfaceRegistry + + clientCtx client.Context + + version string +} + +func (c *Client) AccountIdentifierFromPublicKey(pubKey *types.PublicKey) (*types.AccountIdentifier, error) { + if pubKey.CurveType != "secp256k1" { + return nil, crgerrs.WrapError(crgerrs.ErrUnsupportedCurve, "only secp256k1 supported") + } + + cmp, err := btcec.ParsePubKey(pubKey.Bytes, btcec.S256()) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrBadArgument, err.Error()) + } + + compressedPublicKey := make([]byte, secp256k1.PubKeySize) + copy(compressedPublicKey, cmp.SerializeCompressed()) + + pk := secp256k1.PubKey{Key: compressedPublicKey} + + return &types.AccountIdentifier{ + Address: sdk.AccAddress(pk.Address()).String(), + }, nil +} + +// NewClient instantiates a new online servicer +func NewClient(cfg *Config) (*Client, error) { + info := version.NewInfo() + + v := info.Version + if v == "" { + v = "unknown" + } + + return &Client{ + config: cfg, + ir: cfg.InterfaceRegistry, + version: fmt.Sprintf("%s/%s", info.AppName, v), + }, nil +} + +func (c *Client) accountInfo(ctx context.Context, addr string, height *int64) (auth.AccountI, error) { + if height != nil { + strHeight := strconv.FormatInt(*height, 10) + ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, strHeight) + } + + accountInfo, err := c.auth.Account(ctx, &auth.QueryAccountRequest{ + Address: addr, + }) + if err != nil { + return nil, crgerrs.FromGRPCToRosettaError(err) + } + + var account auth.AccountI + err = c.ir.UnpackAny(accountInfo.Account, &account) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + + return account, nil +} + +func (c *Client) Balances(ctx context.Context, addr string, height *int64) ([]*types.Amount, error) { + if height != nil { + strHeight := strconv.FormatInt(*height, 10) + ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, strHeight) + } + + balance, err := c.bank.AllBalances(ctx, &bank.QueryAllBalancesRequest{ + Address: addr, + }) + if err != nil { + return nil, crgerrs.FromGRPCToRosettaError(err) + } + + availableCoins, err := c.coins(ctx) + if err != nil { + return nil, err + } + + return sdkCoinsToRosettaAmounts(balance.Balances, availableCoins), nil +} + +func (c *Client) BlockByHash(ctx context.Context, hash string) (crgtypes.BlockResponse, error) { + bHash, err := hex.DecodeString(hash) + if err != nil { + return crgtypes.BlockResponse{}, fmt.Errorf("invalid block hash: %s", err) + } + + block, err := c.clientCtx.Client.BlockByHash(ctx, bHash) + if err != nil { + return crgtypes.BlockResponse{}, err + } + + return buildBlockResponse(block), nil +} + +func (c *Client) BlockByHeight(ctx context.Context, height *int64) (crgtypes.BlockResponse, error) { + block, err := c.clientCtx.Client.Block(ctx, height) + if err != nil { + return crgtypes.BlockResponse{}, err + } + + return buildBlockResponse(block), nil +} + +func buildBlockResponse(block *tmtypes.ResultBlock) crgtypes.BlockResponse { + return crgtypes.BlockResponse{ + Block: TMBlockToRosettaBlockIdentifier(block), + ParentBlock: TMBlockToRosettaParentBlockIdentifier(block), + MillisecondTimestamp: timeToMilliseconds(block.Block.Time), + TxCount: int64(len(block.Block.Txs)), + } +} + +func (c *Client) BlockTransactionsByHash(ctx context.Context, hash string) (crgtypes.BlockTransactionsResponse, error) { + blockResp, err := c.BlockByHash(ctx, hash) + if err != nil { + return crgtypes.BlockTransactionsResponse{}, err + } + + txs, err := c.listTransactionsInBlock(ctx, blockResp.Block.Index) + if err != nil { + return crgtypes.BlockTransactionsResponse{}, err + } + + return crgtypes.BlockTransactionsResponse{ + BlockResponse: blockResp, + Transactions: sdkTxsWithHashToRosettaTxs(txs), + }, nil +} + +func (c *Client) BlockTransactionsByHeight(ctx context.Context, height *int64) (crgtypes.BlockTransactionsResponse, error) { + blockResp, err := c.BlockByHeight(ctx, height) + if err != nil { + return crgtypes.BlockTransactionsResponse{}, err + } + + txs, err := c.listTransactionsInBlock(ctx, blockResp.Block.Index) + if err != nil { + return crgtypes.BlockTransactionsResponse{}, err + } + + return crgtypes.BlockTransactionsResponse{ + BlockResponse: blockResp, + Transactions: sdkTxsWithHashToRosettaTxs(txs), + }, nil +} + +// Coins fetches the existing coins in the application +func (c *Client) coins(ctx context.Context) (sdk.Coins, error) { + supply, err := c.bank.TotalSupply(ctx, &bank.QueryTotalSupplyRequest{}) + if err != nil { + return nil, crgerrs.FromGRPCToRosettaError(err) + } + return supply.Supply, nil +} + +// listTransactionsInBlock returns the list of the transactions in a block given its height +func (c *Client) listTransactionsInBlock(ctx context.Context, height int64) ([]*sdkTxWithHash, error) { + txQuery := fmt.Sprintf(`tx.height=%d`, height) + txList, err := c.clientCtx.Client.TxSearch(ctx, txQuery, true, nil, nil, "") + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + + sdkTxs, err := tmResultTxsToSdkTxsWithHash(c.clientCtx.TxConfig.TxDecoder(), txList.Txs) + if err != nil { + return nil, err + } + return sdkTxs, nil +} + +func (c *Client) TxOperationsAndSignersAccountIdentifiers(signed bool, txBytes []byte) (ops []*types.Operation, signers []*types.AccountIdentifier, err error) { + txConfig := c.getTxConfig() + rawTx, err := txConfig.TxDecoder()(txBytes) + if err != nil { + return nil, nil, err + } + + txBldr, err := txConfig.WrapTxBuilder(rawTx) + if err != nil { + return nil, nil, err + } + + var accountIdentifierSigners []*types.AccountIdentifier + if signed { + addrs := txBldr.GetTx().GetSigners() + for _, addr := range addrs { + signer := &types.AccountIdentifier{ + Address: addr.String(), + } + accountIdentifierSigners = append(accountIdentifierSigners, signer) + } + } + + return sdkTxToOperations(txBldr.GetTx(), false, false), accountIdentifierSigners, nil +} + +// GetTx returns a transaction given its hash +func (c *Client) GetTx(_ context.Context, hash string) (*types.Transaction, error) { + txResp, err := authclient.QueryTx(c.clientCtx, hash) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + var sdkTx sdk.Tx + err = c.ir.UnpackAny(txResp.Tx, &sdkTx) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrCodec, err.Error()) + } + return sdkTxWithHashToOperations(&sdkTxWithHash{ + HexHash: txResp.TxHash, + Code: txResp.Code, + Log: txResp.RawLog, + Tx: sdkTx, + }), nil +} + +// GetUnconfirmedTx gets an unconfirmed transaction given its hash +func (c *Client) GetUnconfirmedTx(ctx context.Context, hash string) (*types.Transaction, error) { + res, err := c.clientCtx.Client.UnconfirmedTxs(ctx, nil) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrNotFound, "unconfirmed tx not found") + } + + hashAsBytes, err := hex.DecodeString(hash) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrInterpreting, "invalid hash") + } + + for _, tx := range res.Txs { + if bytes.Equal(tx.Hash(), hashAsBytes) { + sdkTx, err := tmTxToSdkTx(c.clientCtx.TxConfig.TxDecoder(), tx) + if err != nil { + return nil, err + } + + return &types.Transaction{ + TransactionIdentifier: TmTxToRosettaTxsIdentifier(tx), + Operations: sdkTxToOperations(sdkTx, false, false), + Metadata: nil, + }, nil + } + } + + return nil, crgerrs.WrapError(crgerrs.ErrNotFound, "transaction not found in mempool") +} + +// Mempool returns the unconfirmed transactions in the mempool +func (c *Client) Mempool(ctx context.Context) ([]*types.TransactionIdentifier, error) { + txs, err := c.clientCtx.Client.UnconfirmedTxs(ctx, nil) + if err != nil { + return nil, err + } + + return TMTxsToRosettaTxsIdentifiers(txs.Txs), nil +} + +// Peers gets the number of peers +func (c *Client) Peers(ctx context.Context) ([]*types.Peer, error) { + netInfo, err := c.clientCtx.Client.NetInfo(ctx) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + return TmPeersToRosettaPeers(netInfo.Peers), nil +} + +func (c *Client) Status(ctx context.Context) (*types.SyncStatus, error) { + status, err := c.clientCtx.Client.Status(ctx) + if err != nil { + return nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + return TMStatusToRosettaSyncStatus(status), err +} + +func (c *Client) getTxConfig() client.TxConfig { + return c.clientCtx.TxConfig +} + +func (c *Client) PostTx(txBytes []byte) (*types.TransactionIdentifier, map[string]interface{}, error) { + // sync ensures it will go through checkTx + res, err := c.clientCtx.BroadcastTxSync(txBytes) + if err != nil { + return nil, nil, crgerrs.WrapError(crgerrs.ErrUnknown, err.Error()) + } + // check if tx was broadcast successfully + if res.Code != abcitypes.CodeTypeOK { + return nil, nil, crgerrs.WrapError(crgerrs.ErrUnknown, fmt.Sprintf("transaction broadcast failure: (%d) %s ", res.Code, res.RawLog)) + } + + return &types.TransactionIdentifier{ + Hash: res.TxHash, + }, + map[string]interface{}{ + Log: res.RawLog, + }, nil +} + +func (c *Client) ConstructionMetadataFromOptions(ctx context.Context, options map[string]interface{}) (meta map[string]interface{}, err error) { + if len(options) == 0 { + return nil, crgerrs.ErrBadArgument + } + + addr, ok := options[OptionAddress] + if !ok { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidAddress, "no address provided") + } + + addrString, ok := addr.(string) + if !ok { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidAddress, "address is not a string") + } + + accountInfo, err := c.accountInfo(ctx, addrString, nil) + if err != nil { + return nil, err + } + + gas, ok := options[OptionGas] + if !ok { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidAddress, "gas not set") + } + + memo, ok := options[OptionMemo] + if !ok { + return nil, crgerrs.WrapError(crgerrs.ErrInvalidMemo, "memo not set") + } + + status, err := c.clientCtx.Client.Status(ctx) + if err != nil { + return nil, err + } + + return map[string]interface{}{ + OptionAccountNumber: accountInfo.GetAccountNumber(), + OptionSequence: accountInfo.GetSequence(), + OptionChainID: status.NodeInfo.Network, + OptionGas: gas, + OptionMemo: memo, + }, nil +} + +func (c *Client) Ready() error { + ctx, cancel := context.WithTimeout(context.Background(), defaultNodeTimeout) + defer cancel() + _, err := c.clientCtx.Client.Health(ctx) + if err != nil { + return err + } + _, err = c.bank.TotalSupply(ctx, &bank.QueryTotalSupplyRequest{}) + if err != nil { + return err + } + return nil +} + +func (c *Client) Bootstrap() error { + grpcConn, err := grpc.Dial(c.config.GRPCEndpoint, grpc.WithInsecure()) + if err != nil { + return err + } + + tmRPC, err := http.New(c.config.TendermintRPC, tmWebsocketPath) + if err != nil { + return err + } + + authClient := auth.NewQueryClient(grpcConn) + bankClient := bank.NewQueryClient(grpcConn) + + // NodeURI and Client are set from here otherwise + // WitNodeURI will require to create a new client + // it's done here because WithNodeURI panics if + // connection to tendermint node fails + clientCtx := client.Context{ + Client: tmRPC, + NodeURI: c.config.TendermintRPC, + } + clientCtx = clientCtx. + WithJSONMarshaler(c.config.Codec). + WithInterfaceRegistry(c.config.InterfaceRegistry). + WithTxConfig(authtx.NewTxConfig(c.config.Codec, authtx.DefaultSignModes)). + WithAccountRetriever(auth.AccountRetriever{}). + WithBroadcastMode(flags.BroadcastBlock) + + c.auth = authClient + c.bank = bankClient + c.clientCtx = clientCtx + c.ir = c.config.InterfaceRegistry + + return nil +} diff --git a/server/rosetta/codec.go b/server/rosetta/codec.go new file mode 100644 index 0000000000..96242a9e04 --- /dev/null +++ b/server/rosetta/codec.go @@ -0,0 +1,22 @@ +package rosetta + +import ( + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + authcodec "github.com/cosmos/cosmos-sdk/x/auth/types" + bankcodec "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +// MakeCodec generates the codec required to interact +// with the cosmos APIs used by the rosetta gateway +func MakeCodec() (*codec.ProtoCodec, codectypes.InterfaceRegistry) { + ir := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(ir) + + authcodec.RegisterInterfaces(ir) + bankcodec.RegisterInterfaces(ir) + cryptocodec.RegisterInterfaces(ir) + + return cdc, ir +} diff --git a/server/rosetta/config.go b/server/rosetta/config.go new file mode 100644 index 0000000000..a6a8166939 --- /dev/null +++ b/server/rosetta/config.go @@ -0,0 +1,203 @@ +package rosetta + +import ( + "fmt" + "strings" + "time" + + "github.com/coinbase/rosetta-sdk-go/types" + "github.com/spf13/pflag" + crg "github.com/tendermint/cosmos-rosetta-gateway/server" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" +) + +// configuration defaults constants +const ( + // DefaultBlockchain defines the default blockchain identifier name + DefaultBlockchain = "app" + // DefaultAddr defines the default rosetta binding address + DefaultAddr = ":8080" + // DefaultRetries is the default number of retries + DefaultRetries = 5 + // DefaultTendermintEndpoint is the default value for the tendermint endpoint + DefaultTendermintEndpoint = "localhost:26657" + // DefaultGRPCEndpoint is the default value for the gRPC endpoint + DefaultGRPCEndpoint = "localhost:9090" + // DefaultNetwork defines the default network name + DefaultNetwork = "network" + // DefaultOffline defines the default offline value + DefaultOffline = false +) + +// configuration flags +const ( + FlagBlockchain = "blockchain" + FlagNetwork = "network" + FlagTendermintEndpoint = "tendermint" + FlagGRPCEndpoint = "grpc" + FlagAddr = "addr" + FlagRetries = "retries" + FlagOffline = "offline" +) + +// Config defines the configuration of the rosetta server +type Config struct { + // Blockchain defines the blockchain name + // defaults to DefaultBlockchain + Blockchain string + // Network defines the network name + Network string + // TendermintRPC defines the endpoint to connect to + // tendermint RPC, specifying 'tcp://' before is not + // required, usually it's at port 26657 of the + TendermintRPC string + // GRPCEndpoint defines the cosmos application gRPC endpoint + // usually it is located at 9090 port + GRPCEndpoint string + // Addr defines the default address to bind the rosetta server to + // defaults to DefaultAddr + Addr string + // Retries defines the maximum number of retries + // rosetta will do before quitting + Retries int + // Offline defines if the server must be run in offline mode + Offline bool + // Codec overrides the default data and construction api client codecs + Codec *codec.ProtoCodec + // InterfaceRegistry overrides the default data and construction api interface registry + InterfaceRegistry codectypes.InterfaceRegistry +} + +// NetworkIdentifier returns the network identifier given the configuration +func (c *Config) NetworkIdentifier() *types.NetworkIdentifier { + return &types.NetworkIdentifier{ + Blockchain: c.Blockchain, + Network: c.Network, + } +} + +// validate validates a configuration and sets +// its defaults in case they were not provided +func (c *Config) validate() error { + if (c.Codec == nil) != (c.InterfaceRegistry == nil) { + return fmt.Errorf("codec and interface registry must be both different from nil or nil") + } + + if c.Addr == "" { + c.Addr = DefaultAddr + } + if c.Blockchain == "" { + c.Blockchain = DefaultBlockchain + } + if c.Retries == 0 { + c.Retries = DefaultRetries + } + // these are must + if c.Network == "" { + return fmt.Errorf("network not provided") + } + if c.Offline { + return fmt.Errorf("offline mode is not supported for stargate implementation due to how sigv2 works") + } + + // these are optional but it must be online + if c.GRPCEndpoint == "" { + return fmt.Errorf("grpc endpoint not provided") + } + if c.TendermintRPC == "" { + return fmt.Errorf("tendermint rpc not provided") + } + if !strings.HasPrefix(c.TendermintRPC, "tcp://") { + c.TendermintRPC = fmt.Sprintf("tcp://%s", c.TendermintRPC) + } + + return nil +} + +// WithCodec extends the configuration with a predefined Codec +func (c *Config) WithCodec(ir codectypes.InterfaceRegistry, cdc *codec.ProtoCodec) { + c.Codec = cdc + c.InterfaceRegistry = ir +} + +// FromFlags gets the configuration from flags +func FromFlags(flags *pflag.FlagSet) (*Config, error) { + blockchain, err := flags.GetString(FlagBlockchain) + if err != nil { + return nil, err + } + network, err := flags.GetString(FlagNetwork) + if err != nil { + return nil, err + } + tendermintRPC, err := flags.GetString(FlagTendermintEndpoint) + if err != nil { + return nil, err + } + gRPCEndpoint, err := flags.GetString(FlagGRPCEndpoint) + if err != nil { + return nil, err + } + addr, err := flags.GetString(FlagAddr) + if err != nil { + return nil, err + } + retries, err := flags.GetInt(FlagRetries) + if err != nil { + return nil, err + } + offline, err := flags.GetBool(FlagOffline) + if err != nil { + return nil, err + } + conf := &Config{ + Blockchain: blockchain, + Network: network, + TendermintRPC: tendermintRPC, + GRPCEndpoint: gRPCEndpoint, + Addr: addr, + Retries: retries, + Offline: offline, + } + err = conf.validate() + if err != nil { + return nil, err + } + return conf, nil +} + +func ServerFromConfig(conf *Config) (crg.Server, error) { + err := conf.validate() + if err != nil { + return crg.Server{}, err + } + client, err := NewClient(conf) + if err != nil { + return crg.Server{}, err + } + return crg.NewServer( + crg.Settings{ + Network: &types.NetworkIdentifier{ + Blockchain: conf.Blockchain, + Network: conf.Network, + }, + Client: client, + Listen: conf.Addr, + Offline: conf.Offline, + Retries: conf.Retries, + RetryWait: 15 * time.Second, + }) +} + +// SetFlags sets the configuration flags to the given flagset +func SetFlags(flags *pflag.FlagSet) { + flags.String(FlagBlockchain, DefaultBlockchain, "the blockchain type") + flags.String(FlagNetwork, DefaultNetwork, "the network name") + flags.String(FlagTendermintEndpoint, DefaultTendermintEndpoint, "the tendermint rpc endpoint, without tcp://") + flags.String(FlagGRPCEndpoint, DefaultGRPCEndpoint, "the app gRPC endpoint") + flags.String(FlagAddr, DefaultAddr, "the address rosetta will bind to") + flags.Int(FlagRetries, DefaultRetries, "the number of retries that will be done before quitting") + flags.Bool(FlagOffline, DefaultOffline, "run rosetta only with construction API") +} diff --git a/server/rosetta/conv_from_rosetta.go b/server/rosetta/conv_from_rosetta.go new file mode 100644 index 0000000000..da9ea5b2ed --- /dev/null +++ b/server/rosetta/conv_from_rosetta.go @@ -0,0 +1,211 @@ +package rosetta + +import ( + "fmt" + "time" + + "github.com/coinbase/rosetta-sdk-go/types" + tmcoretypes "github.com/tendermint/tendermint/rpc/core/types" + tmtypes "github.com/tendermint/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// timeToMilliseconds converts time to milliseconds timestamp +func timeToMilliseconds(t time.Time) int64 { + return t.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond)) +} + +// sdkCoinsToRosettaAmounts converts []sdk.Coin to rosetta amounts +// availableCoins keeps track of current available coins vs the coins +// owned by an address. This is required to support historical balances +// as rosetta expects them to be set to 0, if an address does not own them +func sdkCoinsToRosettaAmounts(ownedCoins []sdk.Coin, availableCoins sdk.Coins) []*types.Amount { + amounts := make([]*types.Amount, len(availableCoins)) + ownedCoinsMap := make(map[string]sdk.Int, len(availableCoins)) + + for _, ownedCoin := range ownedCoins { + ownedCoinsMap[ownedCoin.Denom] = ownedCoin.Amount + } + + for i, coin := range availableCoins { + value, owned := ownedCoinsMap[coin.Denom] + if !owned { + amounts[i] = &types.Amount{ + Value: sdk.NewInt(0).String(), + Currency: &types.Currency{ + Symbol: coin.Denom, + }, + } + continue + } + amounts[i] = &types.Amount{ + Value: value.String(), + Currency: &types.Currency{ + Symbol: coin.Denom, + }, + } + } + + return amounts +} + +// sdkTxsWithHashToRosettaTxs converts sdk transactions wrapped with their hash to rosetta transactions +func sdkTxsWithHashToRosettaTxs(txs []*sdkTxWithHash) []*types.Transaction { + converted := make([]*types.Transaction, len(txs)) + for i, tx := range txs { + converted[i] = sdkTxWithHashToOperations(tx) + } + + return converted +} + +func sdkTxWithHashToOperations(tx *sdkTxWithHash) *types.Transaction { + hasError := tx.Code != 0 + return &types.Transaction{ + TransactionIdentifier: &types.TransactionIdentifier{Hash: tx.HexHash}, + Operations: sdkTxToOperations(tx.Tx, true, hasError), + Metadata: map[string]interface{}{ + Log: tx.Log, + }, + } +} + +// sdkTxToOperations converts an sdk.Tx to rosetta operations +func sdkTxToOperations(tx sdk.Tx, withStatus, hasError bool) []*types.Operation { + var operations []*types.Operation + + msgOps := sdkMsgsToRosettaOperations(tx.GetMsgs(), withStatus, hasError) + operations = append(operations, msgOps...) + + feeTx := tx.(sdk.FeeTx) + feeOps := sdkFeeTxToOperations(feeTx, withStatus, len(msgOps)) + operations = append(operations, feeOps...) + + return operations +} + +// sdkFeeTxToOperations converts sdk.FeeTx to rosetta operations +func sdkFeeTxToOperations(feeTx sdk.FeeTx, withStatus bool, previousOps int) []*types.Operation { + feeCoins := feeTx.GetFee() + var ops []*types.Operation + if feeCoins != nil { + var feeOps = rosettaFeeOperationsFromCoins(feeCoins, feeTx.FeePayer().String(), withStatus, previousOps) + ops = append(ops, feeOps...) + } + + return ops +} + +// rosettaFeeOperationsFromCoins returns the list of rosetta fee operations given sdk coins +func rosettaFeeOperationsFromCoins(coins sdk.Coins, account string, withStatus bool, previousOps int) []*types.Operation { + feeOps := make([]*types.Operation, 0) + var status string + if withStatus { + status = StatusSuccess + } + + for i, coin := range coins { + op := &types.Operation{ + OperationIdentifier: &types.OperationIdentifier{ + Index: int64(previousOps + i), + }, + Type: OperationFee, + Status: status, + Account: &types.AccountIdentifier{ + Address: account, + }, + Amount: &types.Amount{ + Value: "-" + coin.Amount.String(), + Currency: &types.Currency{ + Symbol: coin.Denom, + }, + }, + } + + feeOps = append(feeOps, op) + } + + return feeOps +} + +// sdkMsgsToRosettaOperations converts sdk messages to rosetta operations +func sdkMsgsToRosettaOperations(msgs []sdk.Msg, withStatus bool, hasError bool) []*types.Operation { + var operations []*types.Operation + for _, msg := range msgs { + if rosettaMsg, ok := msg.(Msg); ok { + operations = append(operations, rosettaMsg.ToOperations(withStatus, hasError)...) + } + } + + return operations +} + +// TMTxsToRosettaTxsIdentifiers converts a tendermint raw transactions into an array of rosetta tx identifiers +func TMTxsToRosettaTxsIdentifiers(txs []tmtypes.Tx) []*types.TransactionIdentifier { + converted := make([]*types.TransactionIdentifier, len(txs)) + for i, tx := range txs { + converted[i] = TmTxToRosettaTxsIdentifier(tx) + } + + return converted +} + +// TmTxToRosettaTxsIdentifier converts a tendermint raw transaction into a rosetta tx identifier +func TmTxToRosettaTxsIdentifier(tx tmtypes.Tx) *types.TransactionIdentifier { + return &types.TransactionIdentifier{Hash: fmt.Sprintf("%x", tx.Hash())} +} + +// TMBlockToRosettaBlockIdentifier converts a tendermint result block to a rosetta block identifier +func TMBlockToRosettaBlockIdentifier(block *tmcoretypes.ResultBlock) *types.BlockIdentifier { + return &types.BlockIdentifier{ + Index: block.Block.Height, + Hash: block.Block.Hash().String(), + } +} + +// TmPeersToRosettaPeers converts tendermint peers to rosetta ones +func TmPeersToRosettaPeers(peers []tmcoretypes.Peer) []*types.Peer { + converted := make([]*types.Peer, len(peers)) + + for i, peer := range peers { + converted[i] = &types.Peer{ + PeerID: peer.NodeInfo.Moniker, + Metadata: map[string]interface{}{ + "addr": peer.NodeInfo.ListenAddr, + }, + } + } + + return converted +} + +// TMStatusToRosettaSyncStatus converts a tendermint status to rosetta sync status +func TMStatusToRosettaSyncStatus(status *tmcoretypes.ResultStatus) *types.SyncStatus { + // determine sync status + var stage = StageSynced + if status.SyncInfo.CatchingUp { + stage = StageSyncing + } + + return &types.SyncStatus{ + CurrentIndex: status.SyncInfo.LatestBlockHeight, + TargetIndex: nil, // sync info does not allow us to get target height + Stage: &stage, + } +} + +// TMBlockToRosettaParentBlockIdentifier returns the parent block identifier from the last block +func TMBlockToRosettaParentBlockIdentifier(block *tmcoretypes.ResultBlock) *types.BlockIdentifier { + if block.Block.Height == 1 { + return &types.BlockIdentifier{ + Index: 1, + Hash: fmt.Sprintf("%X", block.BlockID.Hash.Bytes()), + } + } + + return &types.BlockIdentifier{ + Index: block.Block.Height - 1, + Hash: fmt.Sprintf("%X", block.Block.LastBlockID.Hash.Bytes()), + } +} diff --git a/server/rosetta/conv_to_rosetta.go b/server/rosetta/conv_to_rosetta.go new file mode 100644 index 0000000000..09146eed4f --- /dev/null +++ b/server/rosetta/conv_to_rosetta.go @@ -0,0 +1,95 @@ +package rosetta + +import ( + "fmt" + "strconv" + "strings" + + "github.com/gogo/protobuf/jsonpb" + + "github.com/coinbase/rosetta-sdk-go/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// opsToMsgsAndFees converts rosetta operations to sdk.Msg and fees represented as sdk.Coins +func opsToMsgsAndFees(interfaceRegistry jsonpb.AnyResolver, ops []*types.Operation) ([]sdk.Msg, sdk.Coins, error) { + var feeAmnt []*types.Amount + var newOps []*types.Operation + var msgType string + // find the fee operation and put it aside + for _, op := range ops { + switch op.Type { + case OperationFee: + amount := op.Amount + feeAmnt = append(feeAmnt, amount) + default: + // check if operation matches the one already used + // as, at the moment, we only support operations + // that represent a single cosmos-sdk message + switch { + // if msgType was not set then set it + case msgType == "": + msgType = op.Type + // if msgType does not match op.Type then it means we're trying to send multiple messages in a single tx + case msgType != op.Type: + return nil, nil, fmt.Errorf("only single message operations are supported: %s - %s", msgType, op.Type) + } + // append operation to new ops list + newOps = append(newOps, op) + } + } + // convert all operations, except fee op to sdk.Msgs + msgs, err := opsToMsgs(interfaceRegistry, newOps) + if err != nil { + return nil, nil, err + } + + return msgs, amountsToCoins(feeAmnt), nil +} + +// amountsToCoins converts rosetta amounts to sdk coins +func amountsToCoins(amounts []*types.Amount) sdk.Coins { + var feeCoins sdk.Coins + + for _, amount := range amounts { + absValue := strings.Trim(amount.Value, "-") + value, err := strconv.ParseInt(absValue, 10, 64) + if err != nil { + return nil + } + coin := sdk.NewCoin(amount.Currency.Symbol, sdk.NewInt(value)) + feeCoins = append(feeCoins, coin) + } + + return feeCoins +} + +func opsToMsgs(interfaceRegistry jsonpb.AnyResolver, ops []*types.Operation) ([]sdk.Msg, error) { + var msgs []sdk.Msg + var operationsByType = make(map[string][]*types.Operation) + for _, op := range ops { + operationsByType[op.Type] = append(operationsByType[op.Type], op) + } + + for opName, operations := range operationsByType { + if opName == OperationFee { + continue + } + + msgType, err := interfaceRegistry.Resolve("/" + opName) // Types are registered as /proto-name in the interface registry. + if err != nil { + return nil, err + } + + if rosettaMsg, ok := msgType.(Msg); ok { + m, err := rosettaMsg.FromOperations(operations) + if err != nil { + return nil, err + } + msgs = append(msgs, m) + } + } + + return msgs, nil +} diff --git a/server/rosetta/types.go b/server/rosetta/types.go new file mode 100644 index 0000000000..626e7470ab --- /dev/null +++ b/server/rosetta/types.go @@ -0,0 +1,41 @@ +package rosetta + +import ( + "github.com/coinbase/rosetta-sdk-go/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// statuses +const ( + StatusSuccess = "Success" + StatusReverted = "Reverted" + StageSynced = "synced" + StageSyncing = "syncing" +) + +// misc +const ( + Log = "log" +) + +// operations +const ( + OperationFee = "fee" +) + +// options +const ( + OptionAccountNumber = "account_number" + OptionAddress = "address" + OptionChainID = "chain_id" + OptionSequence = "sequence" + OptionMemo = "memo" + OptionGas = "gas" +) + +type Msg interface { + sdk.Msg + ToOperations(withStatus, hasError bool) []*types.Operation + FromOperations(ops []*types.Operation) (sdk.Msg, error) +} diff --git a/server/rosetta/util.go b/server/rosetta/util.go new file mode 100644 index 0000000000..29e4a1587d --- /dev/null +++ b/server/rosetta/util.go @@ -0,0 +1,112 @@ +package rosetta + +import ( + "fmt" + + "github.com/coinbase/rosetta-sdk-go/types" + + tmcoretypes "github.com/tendermint/tendermint/rpc/core/types" + tmtypes "github.com/tendermint/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// tmResultTxsToSdkTxsWithHash converts tendermint result txs to cosmos sdk.Tx +func tmResultTxsToSdkTxsWithHash(decode sdk.TxDecoder, txs []*tmcoretypes.ResultTx) ([]*sdkTxWithHash, error) { + converted := make([]*sdkTxWithHash, len(txs)) + for i, tx := range txs { + sdkTx, err := decode(tx.Tx) + if err != nil { + return nil, err + } + converted[i] = &sdkTxWithHash{ + HexHash: fmt.Sprintf("%X", tx.Tx.Hash()), + Code: tx.TxResult.Code, + Log: tx.TxResult.Log, + Tx: sdkTx, + } + } + + return converted, nil +} + +func tmTxToSdkTx(decode sdk.TxDecoder, tx tmtypes.Tx) (sdk.Tx, error) { + sdkTx, err := decode(tx) + if err != nil { + return nil, err + } + + return sdkTx, err +} + +type sdkTxWithHash struct { + HexHash string + Code uint32 + Log string + Tx sdk.Tx +} + +type PayloadReqMetadata struct { + ChainID string + Sequence uint64 + AccountNumber uint64 + Gas uint64 + Memo string +} + +// getMetadataFromPayloadReq obtains the metadata from the request to /construction/payloads endpoint. +func getMetadataFromPayloadReq(req *types.ConstructionPayloadsRequest) (*PayloadReqMetadata, error) { + chainID, ok := req.Metadata[OptionChainID].(string) + if !ok { + return nil, fmt.Errorf("chain_id metadata was not provided") + } + + sequence, ok := req.Metadata[OptionSequence] + if !ok { + return nil, fmt.Errorf("sequence metadata was not provided") + } + + seqNum, ok := sequence.(float64) + if !ok { + return nil, fmt.Errorf("invalid sequence value") + } + + accountNum, ok := req.Metadata[OptionAccountNumber] + if !ok { + return nil, fmt.Errorf("account_number metadata was not provided") + } + + accNum, ok := accountNum.(float64) + if !ok { + fmt.Printf("this is type %T", accountNum) + return nil, fmt.Errorf("invalid account_number value") + } + + gasNum, ok := req.Metadata[OptionGas] + if !ok { + return nil, fmt.Errorf("gas metadata was not provided") + } + + gasF64, ok := gasNum.(float64) + if !ok { + return nil, fmt.Errorf("invalid gas value") + } + + memo, ok := req.Metadata[OptionMemo] + if !ok { + memo = "" + } + + memoStr, ok := memo.(string) + if !ok { + return nil, fmt.Errorf("invalid memo") + } + + return &PayloadReqMetadata{ + ChainID: chainID, + Sequence: uint64(seqNum), + AccountNumber: uint64(accNum), + Gas: uint64(gasF64), + Memo: memoStr, + }, nil +} diff --git a/server/start.go b/server/start.go index 84c4dc8586..447497f087 100644 --- a/server/start.go +++ b/server/start.go @@ -9,7 +9,14 @@ import ( "runtime/pprof" "time" + "github.com/cosmos/cosmos-sdk/server/rosetta" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/spf13/cobra" + "google.golang.org/grpc" + + crgserver "github.com/tendermint/cosmos-rosetta-gateway/server" "github.com/tendermint/tendermint/abci/server" tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands" tmos "github.com/tendermint/tendermint/libs/os" @@ -18,7 +25,6 @@ import ( pvm "github.com/tendermint/tendermint/privval" "github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/rpc/client/local" - "google.golang.org/grpc" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -280,7 +286,6 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } var apiSrv *api.Server - if config.API.Enable { genDoc, err := genDocProvider() if err != nil { @@ -326,6 +331,42 @@ func startInProcess(ctx *Context, clientCtx client.Context, appCreator types.App } } + var rosettaSrv crgserver.Server + if config.Rosetta.Enable { + offlineMode := config.Rosetta.Offline + if !config.GRPC.Enable { // If GRPC is not enabled rosetta cannot work in online mode, so it works in offline mode. + offlineMode = true + } + + conf := &rosetta.Config{ + Blockchain: config.Rosetta.Blockchain, + Network: config.Rosetta.Network, + TendermintRPC: ctx.Config.RPC.ListenAddress, + GRPCEndpoint: config.GRPC.Address, + Addr: config.Rosetta.Address, + Retries: config.Rosetta.Retries, + Offline: offlineMode, + } + conf.WithCodec(clientCtx.InterfaceRegistry, clientCtx.JSONMarshaler.(*codec.ProtoCodec)) + + rosettaSrv, err = rosetta.ServerFromConfig(conf) + if err != nil { + return err + } + errCh := make(chan error) + go func() { + if err := rosettaSrv.Start(); err != nil { + errCh <- err + } + }() + + select { + case err := <-errCh: + return err + case <-time.After(5 * time.Second): // assume server started successfully + } + } + defer func() { if tmNode.IsRunning() { _ = tmNode.Stop() diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index e7713a2845..f76948d59c 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -90,6 +90,9 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) { txCommand(), keys.Commands(simapp.DefaultNodeHome), ) + + // add rosetta + rootCmd.AddCommand(server.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler)) } func addModuleInitFlags(startCmd *cobra.Command) { diff --git a/types/tx/types.go b/types/tx/types.go index 0392b2fcfd..a0b05b5dce 100644 --- a/types/tx/types.go +++ b/types/tx/types.go @@ -132,6 +132,37 @@ func (t *Tx) GetSigners() []sdk.AccAddress { return signers } +func (t *Tx) GetGas() uint64 { + return t.AuthInfo.Fee.GasLimit +} +func (t *Tx) GetFee() sdk.Coins { + return t.AuthInfo.Fee.Amount +} +func (t *Tx) FeePayer() sdk.AccAddress { + feePayer := t.AuthInfo.Fee.Payer + if feePayer != "" { + payerAddr, err := sdk.AccAddressFromBech32(feePayer) + if err != nil { + panic(err) + } + return payerAddr + } + // use first signer as default if no payer specified + return t.GetSigners()[0] +} + +func (t *Tx) FeeGranter() sdk.AccAddress { + feePayer := t.AuthInfo.Fee.Granter + if feePayer != "" { + granterAddr, err := sdk.AccAddressFromBech32(feePayer) + if err != nil { + panic(err) + } + return granterAddr + } + return nil +} + // UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method func (t *Tx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { if t.Body != nil { diff --git a/x/auth/client/cli/cli_test.go b/x/auth/client/cli/cli_test.go index fdd558b797..d8913d1ac0 100644 --- a/x/auth/client/cli/cli_test.go +++ b/x/auth/client/cli/cli_test.go @@ -435,7 +435,7 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() { // Write the output to disk signedTxFile := testutil.WriteToNewTempFile(s.T(), signedTx.String()) - // Validate Signature + // validate Signature res, err = authtest.TxValidateSignaturesExec(val1.ClientCtx, signedTxFile.Name()) s.Require().NoError(err) s.Require().True(strings.Contains(res.String(), "[OK]")) diff --git a/x/auth/client/cli/validate_sigs.go b/x/auth/client/cli/validate_sigs.go index 52290ed8e9..d8d6283a79 100644 --- a/x/auth/client/cli/validate_sigs.go +++ b/x/auth/client/cli/validate_sigs.go @@ -16,7 +16,7 @@ import ( func GetValidateSignaturesCommand() *cobra.Command { cmd := &cobra.Command{ Use: "validate-signatures [file]", - Short: "Validate transactions signatures", + Short: "validate transactions signatures", Long: `Print the addresses that must sign the transaction, those who have already signed it, and make sure that signatures are in the correct order. @@ -96,7 +96,7 @@ func printAndValidateSigs( success = false } - // Validate the actual signature over the transaction bytes since we can + // validate the actual signature over the transaction bytes since we can // reach out to a full node to query accounts. if !offline && success { accNum, accSeq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, sigAddr) diff --git a/x/bank/types/msgs.go b/x/bank/types/msgs.go index 22fdc30b38..dd41975468 100644 --- a/x/bank/types/msgs.go +++ b/x/bank/types/msgs.go @@ -1,6 +1,13 @@ package types import ( + "fmt" + "strconv" + "strings" + + "github.com/coinbase/rosetta-sdk-go/types" + "github.com/gogo/protobuf/proto" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -62,6 +69,83 @@ func (msg MsgSend) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{from} } +// Rosetta interface +func (msg *MsgSend) ToOperations(withStatus bool, hasError bool) []*types.Operation { + var operations []*types.Operation + + fromAddress := msg.FromAddress + toAddress := msg.ToAddress + amounts := msg.Amount + if len(amounts) == 0 { + return []*types.Operation{} + } + + coin := amounts[0] + sendOp := func(account, amount string, index int) *types.Operation { + var status string + if withStatus { + status = "Success" + if hasError { + status = "Reverted" + } + } + return &types.Operation{ + OperationIdentifier: &types.OperationIdentifier{ + Index: int64(index), + }, + Type: proto.MessageName(msg), + Status: status, + Account: &types.AccountIdentifier{ + Address: account, + }, + Amount: &types.Amount{ + Value: amount, + Currency: &types.Currency{ + Symbol: coin.Denom, + }, + }, + } + } + operations = append(operations, + sendOp(fromAddress, "-"+coin.Amount.String(), 0), + sendOp(toAddress, coin.Amount.String(), 1), + ) + + return operations +} + +func (msg MsgSend) FromOperations(ops []*types.Operation) (sdk.Msg, error) { + var ( + from, to sdk.AccAddress + sendAmt sdk.Coin + err error + ) + + for _, op := range ops { + if strings.HasPrefix(op.Amount.Value, "-") { + from, err = sdk.AccAddressFromBech32(op.Account.Address) + if err != nil { + return nil, err + } + continue + } + + to, err = sdk.AccAddressFromBech32(op.Account.Address) + if err != nil { + return nil, err + } + + amount, err := strconv.ParseInt(op.Amount.Value, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid amount") + } + + sendAmt = sdk.NewCoin(op.Amount.Currency.Symbol, sdk.NewInt(amount)) + } + + return NewMsgSend(from, to, sdk.NewCoins(sendAmt)), nil +} + var _ sdk.Msg = &MsgMultiSend{} // NewMsgMultiSend - construct arbitrary multi-in, multi-out send msg. diff --git a/x/distribution/types/msg.go b/x/distribution/types/msg.go index 8dc72081e9..62c8bfc2ab 100644 --- a/x/distribution/types/msg.go +++ b/x/distribution/types/msg.go @@ -2,6 +2,12 @@ package types import ( + "fmt" + + rosettatypes "github.com/coinbase/rosetta-sdk-go/types" + "github.com/gogo/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/server/rosetta" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -90,6 +96,50 @@ func (msg MsgWithdrawDelegatorReward) ValidateBasic() error { return nil } +func (msg *MsgWithdrawDelegatorReward) ToOperations(withStatus, hasError bool) []*rosettatypes.Operation { + + var status string + if withStatus { + status = rosetta.StatusSuccess + if hasError { + status = rosetta.StatusReverted + } + } + + op := &rosettatypes.Operation{ + OperationIdentifier: &rosettatypes.OperationIdentifier{ + Index: 0, + }, + RelatedOperations: nil, + Type: proto.MessageName(msg), + Status: status, + Account: &rosettatypes.AccountIdentifier{ + Address: msg.DelegatorAddress, + SubAccount: &rosettatypes.SubAccountIdentifier{ + Address: msg.ValidatorAddress, + }, + }, + } + return []*rosettatypes.Operation{op} +} + +func (msg *MsgWithdrawDelegatorReward) FromOperations(ops []*rosettatypes.Operation) (sdk.Msg, error) { + if len(ops) != 1 { + return nil, fmt.Errorf("expected one operation") + } + op := ops[0] + if op.Account == nil { + return nil, fmt.Errorf("account identifier must be specified") + } + if op.Account.SubAccount == nil { + return nil, fmt.Errorf("account identifier subaccount must be specified") + } + return &MsgWithdrawDelegatorReward{ + DelegatorAddress: op.Account.Address, + ValidatorAddress: op.Account.SubAccount.Address, + }, nil +} + func NewMsgWithdrawValidatorCommission(valAddr sdk.ValAddress) *MsgWithdrawValidatorCommission { return &MsgWithdrawValidatorCommission{ ValidatorAddress: valAddr.String(), diff --git a/x/genutil/client/cli/gentx_test.go b/x/genutil/client/cli/gentx_test.go index d15ee88962..b573367595 100644 --- a/x/genutil/client/cli/gentx_test.go +++ b/x/genutil/client/cli/gentx_test.go @@ -72,7 +72,7 @@ func (s *IntegrationTestSuite) TestGenTxCmd() { err := cmd.ExecuteContext(ctx) s.Require().NoError(err) - // Validate generated transaction. + // validate generated transaction. open, err := os.Open(genTxFile) s.Require().NoError(err) diff --git a/x/ibc/core/03-connection/types/msgs_test.go b/x/ibc/core/03-connection/types/msgs_test.go index 57c1925f66..6aff3b0904 100644 --- a/x/ibc/core/03-connection/types/msgs_test.go +++ b/x/ibc/core/03-connection/types/msgs_test.go @@ -138,7 +138,7 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenTry() { {"invalid counterparty client ID", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "test/conn1", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, {"invalid nil counterparty client", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", nil, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, {"invalid client unpacking", &types.MsgConnectionOpenTry{connectionID, "clienttotesta", invalidAny, counterparty, 500, []*types.Version{ibctesting.ConnectionVersion}, clientHeight, suite.proof, suite.proof, suite.proof, clientHeight, signer.String()}, false}, - {"counterparty failed Validate", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", invalidClient, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, + {"counterparty failed validate", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", invalidClient, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, {"empty counterparty prefix", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, emptyPrefix, []*types.Version{ibctesting.ConnectionVersion}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, {"empty counterpartyVersions", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{}, 500, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, {"empty proofInit", types.NewMsgConnectionOpenTry(connectionID, "clienttotesta", "connectiontotest", "clienttotest", clientState, prefix, []*types.Version{ibctesting.ConnectionVersion}, 500, emptyProof, suite.proof, suite.proof, clientHeight, clientHeight, signer), false}, @@ -188,7 +188,7 @@ func (suite *MsgTestSuite) TestNewMsgConnectionOpenAck() { {"invalid counterparty connection ID", types.NewMsgConnectionOpenAck(connectionID, "test/conn1", clientState, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, {"invalid nil counterparty client", types.NewMsgConnectionOpenAck(connectionID, connectionID, nil, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, {"invalid unpacking counterparty client", &types.MsgConnectionOpenAck{connectionID, connectionID, ibctesting.ConnectionVersion, invalidAny, clientHeight, suite.proof, suite.proof, suite.proof, clientHeight, signer.String()}, false}, - {"counterparty client failed Validate", types.NewMsgConnectionOpenAck(connectionID, connectionID, invalidClient, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, + {"counterparty client failed validate", types.NewMsgConnectionOpenAck(connectionID, connectionID, invalidClient, suite.proof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, {"empty proofTry", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, emptyProof, suite.proof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, {"empty proofClient", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, emptyProof, suite.proof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, {"empty proofConsensus", types.NewMsgConnectionOpenAck(connectionID, connectionID, clientState, suite.proof, suite.proof, emptyProof, clientHeight, clientHeight, ibctesting.ConnectionVersion, signer), false}, diff --git a/x/slashing/client/rest/rest.go b/x/slashing/client/rest/rest.go index a3a8854590..059cb17c6b 100644 --- a/x/slashing/client/rest/rest.go +++ b/x/slashing/client/rest/rest.go @@ -3,9 +3,8 @@ package rest import ( "github.com/gorilla/mux" - "github.com/cosmos/cosmos-sdk/client/rest" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/rest" ) func RegisterHandlers(clientCtx client.Context, rtr *mux.Router) { diff --git a/x/staking/client/rest/rest.go b/x/staking/client/rest/rest.go index 35bb8da681..6f9b7e1e2a 100644 --- a/x/staking/client/rest/rest.go +++ b/x/staking/client/rest/rest.go @@ -3,9 +3,8 @@ package rest import ( "github.com/gorilla/mux" - "github.com/cosmos/cosmos-sdk/client/rest" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/rest" ) func RegisterHandlers(clientCtx client.Context, rtr *mux.Router) { diff --git a/x/staking/types/msg.go b/x/staking/types/msg.go index 2525aa6646..52ab1750b8 100644 --- a/x/staking/types/msg.go +++ b/x/staking/types/msg.go @@ -2,9 +2,17 @@ package types import ( "bytes" + "fmt" + "strconv" + "strings" + + "github.com/gogo/protobuf/proto" + + rosettatypes "github.com/coinbase/rosetta-sdk-go/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/server/rosetta" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -249,6 +257,90 @@ func (msg MsgDelegate) ValidateBasic() error { return nil } +// Rosetta Msg interface. +func (msg *MsgDelegate) ToOperations(withStatus bool, hasError bool) []*rosettatypes.Operation { + var operations []*rosettatypes.Operation + delAddr := msg.DelegatorAddress + valAddr := msg.ValidatorAddress + coin := msg.Amount + delOp := func(account *rosettatypes.AccountIdentifier, amount string, index int) *rosettatypes.Operation { + var status string + if withStatus { + status = rosetta.StatusSuccess + if hasError { + status = rosetta.StatusReverted + } + } + return &rosettatypes.Operation{ + OperationIdentifier: &rosettatypes.OperationIdentifier{ + Index: int64(index), + }, + Type: proto.MessageName(msg), + Status: status, + Account: account, + Amount: &rosettatypes.Amount{ + Value: amount, + Currency: &rosettatypes.Currency{ + Symbol: coin.Denom, + }, + }, + } + } + delAcc := &rosettatypes.AccountIdentifier{ + Address: delAddr, + } + valAcc := &rosettatypes.AccountIdentifier{ + Address: "staking_account", + SubAccount: &rosettatypes.SubAccountIdentifier{ + Address: valAddr, + }, + } + operations = append(operations, + delOp(delAcc, "-"+coin.Amount.String(), 0), + delOp(valAcc, coin.Amount.String(), 1), + ) + return operations +} + +func (msg *MsgDelegate) FromOperations(ops []*rosettatypes.Operation) (sdk.Msg, error) { + var ( + delAddr sdk.AccAddress + valAddr sdk.ValAddress + sendAmt sdk.Coin + err error + ) + + for _, op := range ops { + if strings.HasPrefix(op.Amount.Value, "-") { + if op.Account == nil { + return nil, fmt.Errorf("account identifier must be specified") + } + delAddr, err = sdk.AccAddressFromBech32(op.Account.Address) + if err != nil { + return nil, err + } + continue + } + + if op.Account.SubAccount == nil { + return nil, fmt.Errorf("account identifier subaccount must be specified") + } + valAddr, err = sdk.ValAddressFromBech32(op.Account.SubAccount.Address) + if err != nil { + return nil, err + } + + amount, err := strconv.ParseInt(op.Amount.Value, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid amount: %w", err) + } + + sendAmt = sdk.NewCoin(op.Amount.Currency.Symbol, sdk.NewInt(amount)) + } + + return NewMsgDelegate(delAddr, valAddr, sendAmt), nil +} + // NewMsgBeginRedelegate creates a new MsgBeginRedelegate instance. //nolint:interfacer func NewMsgBeginRedelegate( @@ -304,6 +396,103 @@ func (msg MsgBeginRedelegate) ValidateBasic() error { return nil } +// Rosetta Msg interface. +func (msg *MsgBeginRedelegate) ToOperations(withStatus bool, hasError bool) []*rosettatypes.Operation { + var operations []*rosettatypes.Operation + delAddr := msg.DelegatorAddress + srcValAddr := msg.ValidatorSrcAddress + destValAddr := msg.ValidatorDstAddress + coin := msg.Amount + delOp := func(account *rosettatypes.AccountIdentifier, amount string, index int) *rosettatypes.Operation { + var status string + if withStatus { + status = rosetta.StatusSuccess + if hasError { + status = rosetta.StatusReverted + } + } + return &rosettatypes.Operation{ + OperationIdentifier: &rosettatypes.OperationIdentifier{ + Index: int64(index), + }, + Type: proto.MessageName(msg), + Status: status, + Account: account, + Amount: &rosettatypes.Amount{ + Value: amount, + Currency: &rosettatypes.Currency{ + Symbol: coin.Denom, + }, + }, + } + } + srcValAcc := &rosettatypes.AccountIdentifier{ + Address: delAddr, + SubAccount: &rosettatypes.SubAccountIdentifier{ + Address: srcValAddr, + }, + } + destValAcc := &rosettatypes.AccountIdentifier{ + Address: "staking_account", + SubAccount: &rosettatypes.SubAccountIdentifier{ + Address: destValAddr, + }, + } + operations = append(operations, + delOp(srcValAcc, "-"+coin.Amount.String(), 0), + delOp(destValAcc, coin.Amount.String(), 1), + ) + return operations +} + +func (msg *MsgBeginRedelegate) FromOperations(ops []*rosettatypes.Operation) (sdk.Msg, error) { + var ( + delAddr sdk.AccAddress + srcValAddr sdk.ValAddress + destValAddr sdk.ValAddress + sendAmt sdk.Coin + err error + ) + + for _, op := range ops { + if strings.HasPrefix(op.Amount.Value, "-") { + if op.Account == nil { + return nil, fmt.Errorf("account identifier must be specified") + } + delAddr, err = sdk.AccAddressFromBech32(op.Account.Address) + if err != nil { + return nil, err + } + + if op.Account.SubAccount == nil { + return nil, fmt.Errorf("account identifier subaccount must be specified") + } + srcValAddr, err = sdk.ValAddressFromBech32(op.Account.SubAccount.Address) + if err != nil { + return nil, err + } + continue + } + + if op.Account.SubAccount == nil { + return nil, fmt.Errorf("account identifier subaccount must be specified") + } + destValAddr, err = sdk.ValAddressFromBech32(op.Account.SubAccount.Address) + if err != nil { + return nil, err + } + + amount, err := strconv.ParseInt(op.Amount.Value, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid amount: %w", err) + } + + sendAmt = sdk.NewCoin(op.Amount.Currency.Symbol, sdk.NewInt(amount)) + } + + return NewMsgBeginRedelegate(delAddr, srcValAddr, destValAddr, sendAmt), nil +} + // NewMsgUndelegate creates a new MsgUndelegate instance. //nolint:interfacer func NewMsgUndelegate(delAddr sdk.AccAddress, valAddr sdk.ValAddress, amount sdk.Coin) *MsgUndelegate { @@ -351,3 +540,88 @@ func (msg MsgUndelegate) ValidateBasic() error { return nil } + +// Rosetta Msg interface. +func (msg *MsgUndelegate) ToOperations(withStatus bool, hasError bool) []*rosettatypes.Operation { + var operations []*rosettatypes.Operation + delAddr := msg.DelegatorAddress + valAddr := msg.ValidatorAddress + coin := msg.Amount + delOp := func(account *rosettatypes.AccountIdentifier, amount string, index int) *rosettatypes.Operation { + var status string + if withStatus { + status = rosetta.StatusSuccess + if hasError { + status = rosetta.StatusReverted + } + } + return &rosettatypes.Operation{ + OperationIdentifier: &rosettatypes.OperationIdentifier{ + Index: int64(index), + }, + Type: proto.MessageName(msg), + Status: status, + Account: account, + Amount: &rosettatypes.Amount{ + Value: amount, + Currency: &rosettatypes.Currency{ + Symbol: coin.Denom, + }, + }, + } + } + delAcc := &rosettatypes.AccountIdentifier{ + Address: delAddr, + } + valAcc := &rosettatypes.AccountIdentifier{ + Address: "staking_account", + SubAccount: &rosettatypes.SubAccountIdentifier{ + Address: valAddr, + }, + } + operations = append(operations, + delOp(valAcc, "-"+coin.Amount.String(), 0), + delOp(delAcc, coin.Amount.String(), 1), + ) + return operations +} + +func (msg *MsgUndelegate) FromOperations(ops []*rosettatypes.Operation) (sdk.Msg, error) { + var ( + delAddr sdk.AccAddress + valAddr sdk.ValAddress + undelAmt sdk.Coin + err error + ) + + for _, op := range ops { + if strings.HasPrefix(op.Amount.Value, "-") { + if op.Account.SubAccount == nil { + return nil, fmt.Errorf("account identifier subaccount must be specified") + } + valAddr, err = sdk.ValAddressFromBech32(op.Account.SubAccount.Address) + if err != nil { + return nil, err + } + continue + } + + if op.Account == nil { + return nil, fmt.Errorf("account identifier must be specified") + } + + delAddr, err = sdk.AccAddressFromBech32(op.Account.Address) + if err != nil { + return nil, err + } + + amount, err := strconv.ParseInt(op.Amount.Value, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid amount") + } + + undelAmt = sdk.NewCoin(op.Amount.Currency.Symbol, sdk.NewInt(amount)) + } + + return NewMsgUndelegate(delAddr, valAddr, undelAmt), nil +} diff --git a/x/staking/types/tx.pb.go b/x/staking/types/tx.pb.go index 50e1765ff6..fad3a8c75e 100644 --- a/x/staking/types/tx.pb.go +++ b/x/staking/types/tx.pb.go @@ -6,6 +6,11 @@ package types import ( context "context" fmt "fmt" + io "io" + math "math" + math_bits "math/bits" + time "time" + types "github.com/cosmos/cosmos-sdk/codec/types" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types1 "github.com/cosmos/cosmos-sdk/types" @@ -18,10 +23,6 @@ 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" - time "time" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/x/upgrade/client/rest/rest.go b/x/upgrade/client/rest/rest.go index 3192083f8d..8f10485249 100644 --- a/x/upgrade/client/rest/rest.go +++ b/x/upgrade/client/rest/rest.go @@ -3,9 +3,8 @@ package rest import ( "github.com/gorilla/mux" - "github.com/cosmos/cosmos-sdk/client/rest" - "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/rest" ) // RegisterRoutes registers REST routes for the upgrade module under the path specified by routeName. From 78703f1b6ea1b173fbacb68462e41ca301bbf3d8 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 21 Jan 2021 13:35:40 +0100 Subject: [PATCH 05/40] remove any.ClearCachedValue method (#8402) * remove any.ClearCachedValue method This method is in a public interface but used only for tests. It shouldn't be used - `Any` values shouldn't be manipulated. This could lead to bugs. * rename any_test.go Co-authored-by: Alessio Treglia --- codec/types/any.go | 5 --- codec/types/any_internal_test.go | 53 ++++++++++++++++++++++++++++++++ codec/types/types_test.go | 11 ++----- 3 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 codec/types/any_internal_test.go diff --git a/codec/types/any.go b/codec/types/any.go index eebf13ca6c..c33931f0e2 100644 --- a/codec/types/any.go +++ b/codec/types/any.go @@ -113,8 +113,3 @@ func (any *Any) pack(x proto.Message) error { func (any *Any) GetCachedValue() interface{} { return any.cachedValue } - -// ClearCachedValue clears the cached value from the Any -func (any *Any) ClearCachedValue() { - any.cachedValue = nil -} diff --git a/codec/types/any_internal_test.go b/codec/types/any_internal_test.go new file mode 100644 index 0000000000..fda205f591 --- /dev/null +++ b/codec/types/any_internal_test.go @@ -0,0 +1,53 @@ +package types + +import ( + "testing" + + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/require" +) + +type Dog struct { + Name string `protobuf:"bytes,1,opt,name=size,proto3" json:"size,omitempty"` +} + +func (d Dog) Greet() string { return d.Name } + +// We implement a minimal proto.Message interface +func (d *Dog) Reset() { d.Name = "" } +func (d *Dog) String() string { return d.Name } +func (d *Dog) ProtoMessage() {} +func (d *Dog) XXX_MessageName() string { return "tests/dog" } + +type Animal interface { + Greet() string +} + +var _ Animal = (*Dog)(nil) +var _ proto.Message = (*Dog)(nil) + +func TestAnyPackUnpack(t *testing.T) { + registry := NewInterfaceRegistry() + registry.RegisterInterface("Animal", (*Animal)(nil)) + registry.RegisterImplementations( + (*Animal)(nil), + &Dog{}, + ) + + spot := &Dog{Name: "Spot"} + var animal Animal + + // with cache + any, err := NewAnyWithValue(spot) + require.NoError(t, err) + require.Equal(t, spot, any.GetCachedValue()) + err = registry.UnpackAny(any, &animal) + require.NoError(t, err) + require.Equal(t, spot, animal) + + // without cache + any.cachedValue = nil + err = registry.UnpackAny(any, &animal) + require.NoError(t, err) + require.Equal(t, spot, animal) +} diff --git a/codec/types/types_test.go b/codec/types/types_test.go index b2d0142695..43f8537550 100644 --- a/codec/types/types_test.go +++ b/codec/types/types_test.go @@ -9,16 +9,15 @@ import ( "github.com/gogo/protobuf/grpc" "github.com/gogo/protobuf/jsonpb" "github.com/gogo/protobuf/proto" - grpc2 "google.golang.org/grpc" - "github.com/stretchr/testify/require" + grpc2 "google.golang.org/grpc" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/testutil/testdata" ) -func TestPackUnpack(t *testing.T) { +func TestAnyPackUnpack(t *testing.T) { registry := testdata.NewTestInterfaceRegistry() spot := &testdata.Dog{Name: "Spot"} @@ -31,12 +30,6 @@ func TestPackUnpack(t *testing.T) { err = registry.UnpackAny(any, &animal) require.NoError(t, err) require.Equal(t, spot, animal) - - // without cache - any.ClearCachedValue() - err = registry.UnpackAny(any, &animal) - require.NoError(t, err) - require.Equal(t, spot, animal) } type TestI interface { From f9ee39f0b2b9c548ea74c207567e9a2643d2c9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Thu, 21 Jan 2021 16:10:07 +0100 Subject: [PATCH 06/40] Reorder IBC channel callbacks (#8404) * reorder chan callbacks * add changelog * Update CHANGELOG.md Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- CHANGELOG.md | 1 + x/ibc/core/keeper/msg_server.go | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2bc793c05..3cfe96782b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. ### Bug Fixes diff --git a/x/ibc/core/keeper/msg_server.go b/x/ibc/core/keeper/msg_server.go index 5ea590fea9..dcddcaed16 100644 --- a/x/ibc/core/keeper/msg_server.go +++ b/x/ibc/core/keeper/msg_server.go @@ -326,15 +326,15 @@ func (k Keeper) ChannelOpenAck(goCtx context.Context, msg *channeltypes.MsgChann return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) } - if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion); err != nil { - return nil, sdkerrors.Wrap(err, "channel open ack callback failed") - } - _, err = channel.HandleMsgChannelOpenAck(ctx, k.ChannelKeeper, cap, msg) if err != nil { return nil, err } + if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion); err != nil { + return nil, sdkerrors.Wrap(err, "channel open ack callback failed") + } + return &channeltypes.MsgChannelOpenAckResponse{}, nil } @@ -354,15 +354,15 @@ func (k Keeper) ChannelOpenConfirm(goCtx context.Context, msg *channeltypes.MsgC return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module) } - if err = cbs.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil { - return nil, sdkerrors.Wrap(err, "channel open confirm callback failed") - } - _, err = channel.HandleMsgChannelOpenConfirm(ctx, k.ChannelKeeper, cap, msg) if err != nil { return nil, err } + if err = cbs.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil { + return nil, sdkerrors.Wrap(err, "channel open confirm callback failed") + } + return &channeltypes.MsgChannelOpenConfirmResponse{}, nil } From 5ed11519e0193396a05dec49871a6db3a0942086 Mon Sep 17 00:00:00 2001 From: Frojdi Dymylja <33157909+fdymylja@users.noreply.github.com> Date: Fri, 22 Jan 2021 05:12:22 +0100 Subject: [PATCH 07/40] [appd] fix: gRPC web address default flag value (#8399) * fix: flags grpc web default address * chore: update CHANGELOG.md Co-authored-by: SaReN Co-authored-by: Alessio Treglia --- CHANGELOG.md | 1 + server/start.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cfe96782b..eade483816 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value ## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 diff --git a/server/start.go b/server/start.go index 447497f087..764a67be52 100644 --- a/server/start.go +++ b/server/start.go @@ -160,7 +160,7 @@ which accepts a path for the resulting pprof file. cmd.Flags().String(flagGRPCAddress, config.DefaultGRPCAddress, "the gRPC server address to listen on") cmd.Flags().Bool(flagGRPCWebEnable, true, "Define if the gRPC-Web server should be enabled. (Note: gRPC must also be enabled.)") - cmd.Flags().String(flagGRPCWebAddress, config.DefaultGRPCAddress, "The gRPC-Web server address to listen on") + cmd.Flags().String(flagGRPCWebAddress, config.DefaultGRPCWebAddress, "The gRPC-Web server address to listen on") cmd.Flags().Uint64(FlagStateSyncSnapshotInterval, 0, "State sync snapshot interval") cmd.Flags().Uint32(FlagStateSyncSnapshotKeepRecent, 2, "State sync snapshot to keep") From 31fdee0228bd6f3e787489c8e4434aabc8facb7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Jan 2021 10:36:46 -0300 Subject: [PATCH 08/40] build(deps): bump github.com/tendermint/cosmos-rosetta-gateway (#8408) Bumps [github.com/tendermint/cosmos-rosetta-gateway](https://github.com/tendermint/cosmos-rosetta-gateway) from 0.3.0-rc1 to 0.3.0-rc2. - [Release notes](https://github.com/tendermint/cosmos-rosetta-gateway/releases) - [Changelog](https://github.com/tendermint/cosmos-rosetta-gateway/blob/develop/CHANGELOG.md) - [Commits](https://github.com/tendermint/cosmos-rosetta-gateway/compare/v0.3.0-rc1...v0.3.0-rc2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3e2c956f35..1b56715dee 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.7.0 github.com/tendermint/btcd v0.1.1 - github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1 + github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 github.com/tendermint/tendermint v0.34.3 diff --git a/go.sum b/go.sum index c99dd6b24c..b36fb8fad5 100644 --- a/go.sum +++ b/go.sum @@ -638,8 +638,8 @@ github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzH github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= -github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1 h1:UEkXlFMcWdQWPOA/Rf8nV4WruMK7JO2U8iX7rMTuC24= -github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc1/go.mod h1:gBPw8WV2Erm4UGHlBRiM3zaEBst4bsuihmMCNQdgP/s= +github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2 h1:crekJuQ57yIBDuKd3/dMJ00ZvOHURuv9RGJSi2hWTW4= +github.com/tendermint/cosmos-rosetta-gateway v0.3.0-rc2/go.mod h1:gBPw8WV2Erm4UGHlBRiM3zaEBst4bsuihmMCNQdgP/s= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= From 7d4f7f93febb442f13ca6a1486e841a9df9e3453 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Fri, 22 Jan 2021 21:44:54 -0300 Subject: [PATCH 09/40] x/bank: balance and metadata validation (#8417) * x/bank: balance validation * metadata validation * minor change * balance and metadata tests * changelog * check for empty coins * genesis test --- CHANGELOG.md | 3 +- x/bank/module.go | 2 +- x/bank/types/balance.go | 93 ++++++++++++++++++++ x/bank/types/balance_test.go | 80 ++++++++++++++++++ x/bank/types/genesis.go | 84 ++++++++---------- x/bank/types/genesis_test.go | 152 +++++++++++++++++++++++++++------ x/bank/types/metadata.go | 56 ++++++++++++ x/bank/types/metadata_test.go | 155 ++++++++++++++++++++++++++++++++++ x/bank/types/supply.go | 4 +- 9 files changed, 547 insertions(+), 82 deletions(-) create mode 100644 x/bank/types/balance.go create mode 100644 x/bank/types/balance_test.go create mode 100644 x/bank/types/metadata.go create mode 100644 x/bank/types/metadata_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index eade483816..96b8f5629e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,10 +38,11 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements -* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. +* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. ### Bug Fixes +* (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value ## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 diff --git a/x/bank/module.go b/x/bank/module.go index bc998634c1..f271fa2197 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -58,7 +58,7 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, _ client.TxEncodi return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) } - return types.ValidateGenesis(data) + return data.Validate() } // RegisterRESTRoutes registers the REST routes for the bank module. diff --git a/x/bank/types/balance.go b/x/bank/types/balance.go new file mode 100644 index 0000000000..93517a1d92 --- /dev/null +++ b/x/bank/types/balance.go @@ -0,0 +1,93 @@ +package types + +import ( + "bytes" + "encoding/json" + fmt "fmt" + "sort" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/bank/exported" +) + +var _ exported.GenesisBalance = (*Balance)(nil) + +// GetAddress returns the account address of the Balance object. +func (b Balance) GetAddress() sdk.AccAddress { + addr, _ := sdk.AccAddressFromBech32(b.Address) + return addr +} + +// GetCoins returns the account coins of the Balance object. +func (b Balance) GetCoins() sdk.Coins { + return b.Coins +} + +// Validate checks for address and coins correctness. +func (b Balance) Validate() error { + _, err := sdk.AccAddressFromBech32(b.Address) + if err != nil { + return err + } + + if len(b.Coins) == 0 { + return fmt.Errorf("empty or nil coins for address %s", b.Address) + } + + seenDenoms := make(map[string]bool) + + // NOTE: we perform a custom validation since the coins.Validate function + // errors on zero balance coins + for _, coin := range b.Coins { + if seenDenoms[coin.Denom] { + return fmt.Errorf("duplicate denomination %s", coin.Denom) + } + + if err := sdk.ValidateDenom(coin.Denom); err != nil { + return err + } + + if coin.IsNegative() { + return fmt.Errorf("coin %s amount is cannot be negative", coin.Denom) + } + + seenDenoms[coin.Denom] = true + } + + // sort the coins post validation + b.Coins = b.Coins.Sort() + + return nil +} + +// SanitizeGenesisBalances sorts addresses and coin sets. +func SanitizeGenesisBalances(balances []Balance) []Balance { + sort.Slice(balances, func(i, j int) bool { + addr1, _ := sdk.AccAddressFromBech32(balances[i].Address) + addr2, _ := sdk.AccAddressFromBech32(balances[j].Address) + return bytes.Compare(addr1.Bytes(), addr2.Bytes()) < 0 + }) + + for _, balance := range balances { + balance.Coins = balance.Coins.Sort() + } + + return balances +} + +// GenesisBalancesIterator implements genesis account iteration. +type GenesisBalancesIterator struct{} + +// IterateGenesisBalances iterates over all the genesis balances found in +// appGenesis and invokes a callback on each genesis account. If any call +// returns true, iteration stops. +func (GenesisBalancesIterator) IterateGenesisBalances( + cdc codec.JSONMarshaler, appState map[string]json.RawMessage, cb func(exported.GenesisBalance) (stop bool), +) { + for _, balance := range GetGenesisStateFromAppState(cdc, appState).Balances { + if cb(balance) { + break + } + } +} diff --git a/x/bank/types/balance_test.go b/x/bank/types/balance_test.go new file mode 100644 index 0000000000..73e4d8eff3 --- /dev/null +++ b/x/bank/types/balance_test.go @@ -0,0 +1,80 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestBalanceValidate(t *testing.T) { + + testCases := []struct { + name string + balance Balance + expErr bool + }{ + { + "valid balance", + Balance{ + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, + }, + false, + }, + {"empty balance", Balance{}, true}, + { + "nil balance coins", + Balance{ + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + }, + true, + }, + { + "dup coins", + Balance{ + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{ + sdk.NewInt64Coin("uatom", 1), + sdk.NewInt64Coin("uatom", 1), + }, + }, + true, + }, + { + "invalid coin denom", + Balance{ + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{ + sdk.Coin{Denom: "", Amount: sdk.OneInt()}, + }, + }, + true, + }, + { + "negative coin", + Balance{ + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{ + sdk.Coin{Denom: "uatom", Amount: sdk.NewInt(-1)}, + }, + }, + true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + + err := tc.balance.Validate() + + if tc.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/bank/types/genesis.go b/x/bank/types/genesis.go index ccf35be862..4adc758f3b 100644 --- a/x/bank/types/genesis.go +++ b/x/bank/types/genesis.go @@ -1,51 +1,49 @@ package types import ( - "bytes" "encoding/json" - "sort" + "fmt" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/bank/exported" ) -var _ exported.GenesisBalance = (*Balance)(nil) - -// GetAddress returns the account address of the Balance object. -func (b Balance) GetAddress() sdk.AccAddress { - addr1, _ := sdk.AccAddressFromBech32(b.Address) - return addr1 -} - -// GetAddress returns the account coins of the Balance object. -func (b Balance) GetCoins() sdk.Coins { - return b.Coins -} - -// SanitizeGenesisAccounts sorts addresses and coin sets. -func SanitizeGenesisBalances(balances []Balance) []Balance { - sort.Slice(balances, func(i, j int) bool { - addr1, _ := sdk.AccAddressFromBech32(balances[i].Address) - addr2, _ := sdk.AccAddressFromBech32(balances[j].Address) - return bytes.Compare(addr1.Bytes(), addr2.Bytes()) < 0 - }) - - for _, balance := range balances { - balance.Coins = balance.Coins.Sort() - } - - return balances -} - -// ValidateGenesis performs basic validation of supply genesis data returning an +// Validate performs basic validation of supply genesis data returning an // error for any failed validation criteria. -func ValidateGenesis(data GenesisState) error { - if err := data.Params.Validate(); err != nil { +func (gs GenesisState) Validate() error { + if err := gs.Params.Validate(); err != nil { return err } - return NewSupply(data.Supply).ValidateBasic() + seenBalances := make(map[string]bool) + seenMetadatas := make(map[string]bool) + + for _, balance := range gs.Balances { + if seenBalances[balance.Address] { + return fmt.Errorf("duplicate balance for address %s", balance.Address) + } + + if err := balance.Validate(); err != nil { + return err + } + + seenBalances[balance.Address] = true + } + + for _, metadata := range gs.DenomMetadata { + if seenMetadatas[metadata.Base] { + return fmt.Errorf("duplicate client metadata for denom %s", metadata.Base) + } + + if err := metadata.Validate(); err != nil { + return err + } + + seenMetadatas[metadata.Base] = true + } + + // NOTE: this errors if supply for any given coin is zero + return NewSupply(gs.Supply).ValidateBasic() } // NewGenesisState creates a new genesis state. @@ -74,19 +72,3 @@ func GetGenesisStateFromAppState(cdc codec.JSONMarshaler, appState map[string]js return &genesisState } - -// GenesisAccountIterator implements genesis account iteration. -type GenesisBalancesIterator struct{} - -// IterateGenesisAccounts iterates over all the genesis accounts found in -// appGenesis and invokes a callback on each genesis account. If any call -// returns true, iteration stops. -func (GenesisBalancesIterator) IterateGenesisBalances( - cdc codec.JSONMarshaler, appState map[string]json.RawMessage, cb func(exported.GenesisBalance) (stop bool), -) { - for _, balance := range GetGenesisStateFromAppState(cdc, appState).Balances { - if cb(balance) { - break - } - } -} diff --git a/x/bank/types/genesis_test.go b/x/bank/types/genesis_test.go index 5f612aed72..634b247e01 100644 --- a/x/bank/types/genesis_test.go +++ b/x/bank/types/genesis_test.go @@ -1,52 +1,150 @@ -package types_test +package types import ( "testing" "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/x/bank/types" + sdk "github.com/cosmos/cosmos-sdk/types" ) -func TestMarshalJSONMetaData(t *testing.T) { - cdc := codec.NewLegacyAmino() +func TestGenesisStateValidate(t *testing.T) { testCases := []struct { - name string - input []types.Metadata - strOutput string + name string + genesisState GenesisState + expErr bool }{ - {"nil metadata", nil, `null`}, - {"empty metadata", []types.Metadata{}, `[]`}, - {"non-empty coins", []types.Metadata{{ - Description: "The native staking token of the Cosmos Hub.", - DenomUnits: []*types.DenomUnit{ - {"uatom", uint32(0), []string{"microatom"}}, // The default exponent value 0 is omitted in the json - {"matom", uint32(3), []string{"milliatom"}}, - {"atom", uint32(6), nil}, + { + "valid genesisState", + GenesisState{ + Params: DefaultParams(), + Balances: []Balance{ + { + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, + }, + }, + Supply: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, + DenomMetadata: []Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + }, }, - Base: "uatom", - Display: "atom", + false, }, + {"empty genesisState", GenesisState{}, false}, + { + "invalid params ", + GenesisState{ + Params: Params{ + SendEnabled: []*SendEnabled{ + {"", true}, + }, + }, + }, + true, + }, + { + "dup balances", + GenesisState{ + Balances: []Balance{ + { + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, + }, + { + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + Coins: sdk.Coins{sdk.NewInt64Coin("uatom", 1)}, + }, + }, + }, + true, + }, + { + "invalid balance", + GenesisState{ + Balances: []Balance{ + { + Address: "cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t", + }, + }, + }, + true, + }, + { + "dup Metadata", + GenesisState{ + DenomMetadata: []Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + }, + }, + true, + }, + { + "invalid Metadata", + GenesisState{ + DenomMetadata: []Metadata{ + { + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "", + Display: "", + }, + }, + }, + true, + }, + { + "invalid supply", + GenesisState{ + Supply: sdk.Coins{sdk.Coin{Denom: "", Amount: sdk.OneInt()}}, + }, + true, }, - `[{"description":"The native staking token of the Cosmos Hub.","denom_units":[{"denom":"uatom","aliases":["microatom"]},{"denom":"matom","exponent":3,"aliases":["milliatom"]},{"denom":"atom","exponent":6}],"base":"uatom","display":"atom"}]`}, } for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { - bz, err := cdc.MarshalJSON(tc.input) - require.NoError(t, err) - require.Equal(t, tc.strOutput, string(bz)) - var newMetadata []types.Metadata - require.NoError(t, cdc.UnmarshalJSON(bz, &newMetadata)) + err := tc.genesisState.Validate() - if len(tc.input) == 0 { - require.Nil(t, newMetadata) + if tc.expErr { + require.Error(t, err) } else { - require.Equal(t, tc.input, newMetadata) + require.NoError(t, err) } }) } diff --git a/x/bank/types/metadata.go b/x/bank/types/metadata.go new file mode 100644 index 0000000000..5106964e99 --- /dev/null +++ b/x/bank/types/metadata.go @@ -0,0 +1,56 @@ +package types + +import ( + "fmt" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// Validate performs a basic validation of the coin metadata fields +func (m Metadata) Validate() error { + if err := sdk.ValidateDenom(m.Base); err != nil { + return fmt.Errorf("invalid metadata base denom: %w", err) + } + + if err := sdk.ValidateDenom(m.Display); err != nil { + return fmt.Errorf("invalid metadata display denom: %w", err) + } + + seenUnits := make(map[string]bool) + for _, denomUnit := range m.DenomUnits { + if seenUnits[denomUnit.Denom] { + return fmt.Errorf("duplicate denomination unit %s", denomUnit.Denom) + } + + if err := denomUnit.Validate(); err != nil { + return err + } + + seenUnits[denomUnit.Denom] = true + } + + return nil +} + +// Validate performs a basic validation of the denomination unit fields +func (du DenomUnit) Validate() error { + if err := sdk.ValidateDenom(du.Denom); err != nil { + return fmt.Errorf("invalid denom unit: %w", err) + } + + seenAliases := make(map[string]bool) + for _, alias := range du.Aliases { + if seenAliases[alias] { + return fmt.Errorf("duplicate denomination unit alias %s", alias) + } + + if strings.TrimSpace(alias) == "" { + return fmt.Errorf("alias for denom unit %s cannot be blank", du.Denom) + } + + seenAliases[alias] = true + } + + return nil +} diff --git a/x/bank/types/metadata_test.go b/x/bank/types/metadata_test.go new file mode 100644 index 0000000000..29f4d220f9 --- /dev/null +++ b/x/bank/types/metadata_test.go @@ -0,0 +1,155 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func TestMetadataValidate(t *testing.T) { + testCases := []struct { + name string + metadata types.Metadata + expErr bool + }{ + { + "non-empty coins", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + false, + }, + {"empty metadata", types.Metadata{}, true}, + { + "invalid base denom", + types.Metadata{ + Base: "", + }, + true, + }, + { + "invalid display denom", + types.Metadata{ + Base: "uatom", + Display: "", + }, + true, + }, + { + "duplicate denom unit", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"uatom", uint32(0), []string{"microatom"}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "invalid denom unit", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"", uint32(0), []string{"microatom"}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "invalid denom unit alias", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{""}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "duplicate denom unit alias", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom", "microatom"}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + + err := tc.metadata.Validate() + + if tc.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMarshalJSONMetaData(t *testing.T) { + cdc := codec.NewLegacyAmino() + + testCases := []struct { + name string + input []types.Metadata + strOutput string + }{ + {"nil metadata", nil, `null`}, + {"empty metadata", []types.Metadata{}, `[]`}, + {"non-empty coins", []types.Metadata{{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, // The default exponent value 0 is omitted in the json + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + }, + `[{"description":"The native staking token of the Cosmos Hub.","denom_units":[{"denom":"uatom","aliases":["microatom"]},{"denom":"matom","exponent":3,"aliases":["milliatom"]},{"denom":"atom","exponent":6}],"base":"uatom","display":"atom"}]`}, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + bz, err := cdc.MarshalJSON(tc.input) + require.NoError(t, err) + require.Equal(t, tc.strOutput, string(bz)) + + var newMetadata []types.Metadata + require.NoError(t, cdc.UnmarshalJSON(bz, &newMetadata)) + + if len(tc.input) == 0 { + require.Nil(t, newMetadata) + } else { + require.Equal(t, tc.input, newMetadata) + } + }) + } +} diff --git a/x/bank/types/supply.go b/x/bank/types/supply.go index 558c852c2b..c5c14b15bc 100644 --- a/x/bank/types/supply.go +++ b/x/bank/types/supply.go @@ -50,8 +50,8 @@ func (supply Supply) String() string { // ValidateBasic validates the Supply coins and returns error if invalid func (supply Supply) ValidateBasic() error { - if !supply.Total.IsValid() { - return fmt.Errorf("invalid total supply: %s", supply.Total.String()) + if err := supply.Total.Validate(); err != nil { + return fmt.Errorf("invalid total supply: %w", err) } return nil From bdd7fa9712cc47d41746877069d430a4704641ed Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Sun, 24 Jan 2021 11:33:27 -0300 Subject: [PATCH 10/40] simapp: increase supply balance when adding genaccount (#8418) * simapp: increase supply balance when adding genaccount * changelog --- CHANGELOG.md | 1 + simapp/simd/cmd/genaccounts.go | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96b8f5629e..f7bf603d78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account * (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value diff --git a/simapp/simd/cmd/genaccounts.go b/simapp/simd/cmd/genaccounts.go index dc6925120e..57de144c36 100644 --- a/simapp/simd/cmd/genaccounts.go +++ b/simapp/simd/cmd/genaccounts.go @@ -151,6 +151,7 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa bankGenState := banktypes.GetGenesisStateFromAppState(depCdc, appState) bankGenState.Balances = append(bankGenState.Balances, balances) bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances) + bankGenState.Supply = bankGenState.Supply.Add(balances.Coins...) bankGenStateBz, err := cdc.MarshalJSON(bankGenState) if err != nil { From c95de9c4177442dee4c69d96917efc955b5d19d9 Mon Sep 17 00:00:00 2001 From: MD Aleem <72057206+aleem1314@users.noreply.github.com> Date: Mon, 25 Jan 2021 22:11:30 +0530 Subject: [PATCH 11/40] implement x/authz module (#7629) * WIP: Msg authorization module added * fixing errors * fixed errors * fixed module.go * Add msg_tests * fixes compile issues * fix test * fix test * Add msg types tests * Fix Getmsgs * fixed codec issue * Fix syntax issues * Fix keeper * fixed proto issues * Fix keeper tests * fixed router in keeper * Fix query proto * Fix cli txs * Add grpc query client implementation * Add grpc-keeper test * Add grpc query tests Add revoke and exec authorization cli commands * Fix linting issues * Fix cli query * fix lint errors * Add Genesis state * Fix query authorization * Review changes * Fix grant authorization handler * Add cli tests * Add cli tests * Fix genesis test * Fix issues * update module to use proto msg services * Add simultion tests * Fix lint * fix lint * WIP simulations * WIP simulations * add msg tests * Fix simulation * Fix errors * fix genesis import export * fix sim tests * fix sim * fix test * Register RegisterMsgServer * WIP * WIP * Update keeper test * change msg_authorization module name to authz * changed type conversion for serviceMsg * serviceMsg change to any * Fix issues * fix msg tests * fix errors * proto format * remove LegacyQuerierHandler * Use MsgServiceRouter * fix keeper-test * fix query authorizations * fix NewCmdSendAs * fix simtests * fix error * fix lint * fix lint * add tests for generic authorization * fix imports * format * Update error message * remove println * add query all grants * Add pagination for queries * format * fix lint * review changes * fix grpc tests * add pagination to cli query * review changes * replace panic with error * lint * fix errors * fix tests * remove gogoproto extensions * update function doc * review changes * fix errors * fix query flags * fix grpc query test * init service-msg * remove unsed field * add proto-codec for simulations * fix codec issue * update authz simulations * change msgauth to authz * add check for invalid msg-type * change expiration flag to Unix * doc * update module.go * fix sims * fix grant-authorization sims * fix error * fix error * add build flag * fix codec issue * rename * review changes * format * review changes * go.mod * refactor * proto-gen * Update x/authz/keeper/grpc_query_test.go Co-authored-by: Amaury * Update x/authz/keeper/grpc_query_test.go Co-authored-by: Amaury * Update x/authz/keeper/grpc_query_test.go Co-authored-by: Amaury * Fix review comments * fix protogen * Follow Msg...Request style for msg requests * update comment * Fix error codes * fix review comment * improve msg validations * Handle error in casting msgs * rename actor => grantStoreKey * add godoc * add godoc * Fix simulations * Fix cli, cli_tests * Fix simulations * rename to GetOrRevokeAuthorization * Move events to keeper * Fix fmt * Update x/authz/client/cli/tx.go Co-authored-by: Amaury * rename actor * fix lint Co-authored-by: atheesh Co-authored-by: atheeshp <59333759+atheeshp@users.noreply.github.com> Co-authored-by: Amaury Martiny Co-authored-by: MD Aleem <72057206+aleem1413@users.noreply.github.com> Co-authored-by: Anil Kumar Kammari --- docs/core/proto-docs.md | 901 ++++++++---- proto/cosmos/authz/v1beta1/authz.proto | 37 + proto/cosmos/authz/v1beta1/genesis.proto | 24 + proto/cosmos/authz/v1beta1/query.proto | 54 + proto/cosmos/authz/v1beta1/tx.proto | 62 + simapp/app.go | 14 +- simapp/sim_test.go | 2 + types/errors/errors.go | 3 + types/msgservice/service_msg_client.go | 50 + types/simulation/types.go | 13 +- x/authz/client/cli/cli_test.go | 727 ++++++++++ x/authz/client/cli/query.go | 138 ++ x/authz/client/cli/tx.go | 222 +++ x/authz/client/rest/grpc_query_test.go | 235 ++++ x/authz/client/testutil/test_helpers.go | 34 + x/authz/exported/keeper.go | 26 + x/authz/genesis.go | 47 + x/authz/genesis_test.go | 59 + x/authz/keeper/grpc_query.go | 120 ++ x/authz/keeper/grpc_query_test.go | 157 +++ x/authz/keeper/keeper.go | 210 +++ x/authz/keeper/keeper_test.go | 218 +++ x/authz/keeper/msg_server.go | 75 + x/authz/module.go | 194 +++ x/authz/simulation/decoder.go | 26 + x/authz/simulation/decoder_test.go | 50 + x/authz/simulation/genesis.go | 38 + x/authz/simulation/genesis_test.go | 40 + x/authz/simulation/operations.go | 291 ++++ x/authz/simulation/operations_test.go | 197 +++ x/authz/types/authorizations.go | 63 + x/authz/types/authz.pb.go | 759 ++++++++++ x/authz/types/codec.go | 25 + x/authz/types/errors.go | 10 + x/authz/types/events.go | 14 + x/authz/types/expected_keepers.go | 16 + x/authz/types/generic_authorization.go | 28 + x/authz/types/genesis.go | 41 + x/authz/types/genesis.pb.go | 680 +++++++++ x/authz/types/keys.go | 41 + x/authz/types/keys_test.go | 20 + x/authz/types/msgs.go | 215 +++ x/authz/types/msgs_test.go | 103 ++ x/authz/types/query.pb.go | 1278 +++++++++++++++++ x/authz/types/query.pb.gw.go | 362 +++++ x/authz/types/send_authorization.go | 45 + x/authz/types/tx.pb.go | 1609 ++++++++++++++++++++++ x/bank/client/testutil/cli_helpers.go | 39 +- x/bank/simulation/operations.go | 4 +- x/distribution/simulation/operations.go | 8 +- x/gov/simulation/operations.go | 6 +- x/slashing/simulation/operations.go | 10 +- x/staking/simulation/operations.go | 10 +- x/staking/types/tx.pb.go | 9 +- 54 files changed, 9322 insertions(+), 337 deletions(-) create mode 100644 proto/cosmos/authz/v1beta1/authz.proto create mode 100644 proto/cosmos/authz/v1beta1/genesis.proto create mode 100644 proto/cosmos/authz/v1beta1/query.proto create mode 100644 proto/cosmos/authz/v1beta1/tx.proto create mode 100644 types/msgservice/service_msg_client.go create mode 100644 x/authz/client/cli/cli_test.go create mode 100644 x/authz/client/cli/query.go create mode 100644 x/authz/client/cli/tx.go create mode 100644 x/authz/client/rest/grpc_query_test.go create mode 100644 x/authz/client/testutil/test_helpers.go create mode 100644 x/authz/exported/keeper.go create mode 100644 x/authz/genesis.go create mode 100644 x/authz/genesis_test.go create mode 100644 x/authz/keeper/grpc_query.go create mode 100644 x/authz/keeper/grpc_query_test.go create mode 100644 x/authz/keeper/keeper.go create mode 100644 x/authz/keeper/keeper_test.go create mode 100644 x/authz/keeper/msg_server.go create mode 100644 x/authz/module.go create mode 100644 x/authz/simulation/decoder.go create mode 100644 x/authz/simulation/decoder_test.go create mode 100644 x/authz/simulation/genesis.go create mode 100644 x/authz/simulation/genesis_test.go create mode 100644 x/authz/simulation/operations.go create mode 100644 x/authz/simulation/operations_test.go create mode 100644 x/authz/types/authorizations.go create mode 100644 x/authz/types/authz.pb.go create mode 100644 x/authz/types/codec.go create mode 100644 x/authz/types/errors.go create mode 100644 x/authz/types/events.go create mode 100644 x/authz/types/expected_keepers.go create mode 100644 x/authz/types/generic_authorization.go create mode 100644 x/authz/types/genesis.go create mode 100644 x/authz/types/genesis.pb.go create mode 100644 x/authz/types/keys.go create mode 100644 x/authz/types/keys_test.go create mode 100644 x/authz/types/msgs.go create mode 100644 x/authz/types/msgs_test.go create mode 100644 x/authz/types/query.pb.go create mode 100644 x/authz/types/query.pb.gw.go create mode 100644 x/authz/types/send_authorization.go create mode 100644 x/authz/types/tx.pb.go diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index d49cf8634b..ec30ba730b 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -26,6 +26,49 @@ - [DecProto](#cosmos.base.v1beta1.DecProto) - [IntProto](#cosmos.base.v1beta1.IntProto) +- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) + - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) + - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) + - [SendAuthorization](#cosmos.authz.v1beta1.SendAuthorization) + +- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) + - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) + - [Attribute](#cosmos.base.abci.v1beta1.Attribute) + - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) + - [MsgData](#cosmos.base.abci.v1beta1.MsgData) + - [Result](#cosmos.base.abci.v1beta1.Result) + - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) + - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) + - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) + - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) + - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) + +- [cosmos/authz/v1beta1/tx.proto](#cosmos/authz/v1beta1/tx.proto) + - [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) + - [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) + - [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) + - [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) + - [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) + - [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) + + - [Msg](#cosmos.authz.v1beta1.Msg) + +- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) + - [GenesisState](#cosmos.authz.v1beta1.GenesisState) + - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) + +- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) + - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) + - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) + +- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto) + - [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) + - [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) + - [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) + - [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) + + - [Query](#cosmos.authz.v1beta1.Query) + - [cosmos/bank/v1beta1/bank.proto](#cosmos/bank/v1beta1/bank.proto) - [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) - [Input](#cosmos.bank.v1beta1.Input) @@ -39,10 +82,6 @@ - [Balance](#cosmos.bank.v1beta1.Balance) - [GenesisState](#cosmos.bank.v1beta1.GenesisState) -- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) - - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) - - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) - - [cosmos/bank/v1beta1/query.proto](#cosmos/bank/v1beta1/query.proto) - [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) - [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) @@ -69,18 +108,6 @@ - [Msg](#cosmos.bank.v1beta1.Msg) -- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) - - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) - - [Attribute](#cosmos.base.abci.v1beta1.Attribute) - - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) - - [MsgData](#cosmos.base.abci.v1beta1.MsgData) - - [Result](#cosmos.base.abci.v1beta1.Result) - - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) - - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) - - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) - - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) - - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) - - [cosmos/base/kv/v1beta1/kv.proto](#cosmos/base/kv/v1beta1/kv.proto) - [Pair](#cosmos.base.kv.v1beta1.Pair) - [Pairs](#cosmos.base.kv.v1beta1.Pairs) @@ -960,6 +987,589 @@ IntProto defines a Protobuf wrapper around an Int object. + +

    Top

    + +## cosmos/authz/v1beta1/authz.proto + + + + + +### AuthorizationGrant +AuthorizationGrant gives permissions to execute +the provide method with expiration time. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + + + + + + + + +### GenericAuthorization +GenericAuthorization gives the grantee unrestricted permissions to execute +the provided method on behalf of the granter's account. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `method_name` | [string](#string) | | method name to grant unrestricted permissions to execute Note: MethodName() is already a method on `GenericAuthorization` type, we need some custom naming here so using `MessageName` | + + + + + + + + +### SendAuthorization +SendAuthorization allows the grantee to spend up to spend_limit coins from +the granter's account. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/base/abci/v1beta1/abci.proto + + + + + +### ABCIMessageLog +ABCIMessageLog defines a structure containing an indexed tx ABCI message log. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `msg_index` | [uint32](#uint32) | | | +| `log` | [string](#string) | | | +| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | + + + + + + + + +### Attribute +Attribute defines an attribute wrapper where the key and value are +strings instead of raw bytes. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | + + + + + + + + +### GasInfo +GasInfo defines tx execution gas context. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | +| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | + + + + + + + + +### MsgData +MsgData defines the data returned in a Result object during message +execution. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `msg_type` | [string](#string) | | | +| `data` | [bytes](#bytes) | | | + + + + + + + + +### Result +Result is the union of ResponseFormat and ResponseCheckTx. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | +| `log` | [string](#string) | | Log contains the log information from message or handler execution. | +| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | + + + + + + + + +### SearchTxsResult +SearchTxsResult defines a structure for querying txs pageable + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `total_count` | [uint64](#uint64) | | Count of all txs | +| `count` | [uint64](#uint64) | | Count of txs in current page | +| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | +| `page_total` | [uint64](#uint64) | | Count of total pages | +| `limit` | [uint64](#uint64) | | Max count txs per page | +| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | + + + + + + + + +### SimulationResponse +SimulationResponse defines the response generated when a transaction is +successfully simulated. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | +| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | + + + + + + + + +### StringEvent +StringEvent defines en Event object wrapper where all the attributes +contain key/value pairs that are strings instead of raw bytes. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `type` | [string](#string) | | | +| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | + + + + + + + + +### TxMsgData +TxMsgData defines a list of MsgData. A transaction will have a MsgData object +for each message. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | + + + + + + + + +### TxResponse +TxResponse defines a structure containing relevant tx data and metadata. The +tags are stringified and the log is JSON decoded. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | The block height | +| `txhash` | [string](#string) | | The transaction hash. | +| `codespace` | [string](#string) | | Namespace for the Code | +| `code` | [uint32](#uint32) | | Response code. | +| `data` | [string](#string) | | Result bytes, if any. | +| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | +| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | +| `info` | [string](#string) | | Additional information. May be non-deterministic. | +| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | +| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | +| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | +| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/authz/v1beta1/tx.proto + + + + + +### MsgExecAuthorizedRequest +MsgExecAuthorizedRequest attempts to execute the provided messages using +authorizations granted to the grantee. Each message should have only +one signer corresponding to the granter of the authorization. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `grantee` | [string](#string) | | | +| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | + + + + + + + + +### MsgExecAuthorizedResponse +MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | + + + + + + + + +### MsgGrantAuthorizationRequest +MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +account with the provided expiration time. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + + + + + + + + +### MsgGrantAuthorizationResponse +MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. + + + + + + + + +### MsgRevokeAuthorizationRequest +MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the +granter's account with that has been granted to the grantee. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | + + + + + + + + +### MsgRevokeAuthorizationResponse +MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. + + + + + + + + + + + + + + +### Msg +Msg defines the authz Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `GrantAuthorization` | [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) | [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) | GrantAuthorization grants the provided authorization to the grantee on the granter's account with the provided expiration time. | | +| `ExecAuthorized` | [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) | [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) | ExecAuthorized attempts to execute the provided messages using authorizations granted to the grantee. Each message should have only one signer corresponding to the granter of the authorization. | | +| `RevokeAuthorization` | [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) | [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) | RevokeAuthorization revokes any authorization corresponding to the provided method name on the granter's account that has been granted to the grantee. | | + + + + + + +

    Top

    + +## cosmos/authz/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the authz module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | + + + + + + + + +### GrantAuthorization +GrantAuthorization defines the GenesisState/GrantAuthorization type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/base/query/v1beta1/pagination.proto + + + + + +### PageRequest +PageRequest is to be embedded in gRPC request messages for efficient +pagination. Ex: + + message SomeRequest { + Foo some_parameter = 1; + PageRequest pagination = 2; + } + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | +| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | +| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | +| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | + + + + + + + + +### PageResponse +PageResponse is to be embedded in gRPC response messages where the +corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | +| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/authz/v1beta1/query.proto + + + + + +### QueryAuthorizationRequest +QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | + + + + + + + + +### QueryAuthorizationResponse +QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | + + + + + + + + +### QueryAuthorizationsRequest +QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | + + + + + + + + +### QueryAuthorizationsResponse +QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authorizations` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | repeated | authorizations is a list of grants granted for grantee by granter. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Authorization` | [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) | [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) | Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the provided msg type. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant| +| `Authorizations` | [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) | [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants| + + + + +

    Top

    @@ -1135,68 +1745,6 @@ GenesisState defines the bank module's genesis state. - - - - - - - - - - - -

    Top

    - -## cosmos/base/query/v1beta1/pagination.proto - - - - - -### PageRequest -PageRequest is to be embedded in gRPC request messages for efficient -pagination. Ex: - - message SomeRequest { - Foo some_parameter = 1; - PageRequest pagination = 2; - } - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | -| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | -| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | -| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | - - - - - - - - -### PageResponse -PageResponse is to be embedded in gRPC response messages where the -corresponding request message has used PageRequest. - - message SomeResponse { - repeated Bar results = 1; - PageResponse page = 2; - } - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | -| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | - - - - - @@ -1528,203 +2076,6 @@ Msg defines the bank Msg service. - -

    Top

    - -## cosmos/base/abci/v1beta1/abci.proto - - - - - -### ABCIMessageLog -ABCIMessageLog defines a structure containing an indexed tx ABCI message log. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `msg_index` | [uint32](#uint32) | | | -| `log` | [string](#string) | | | -| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | - - - - - - - - -### Attribute -Attribute defines an attribute wrapper where the key and value are -strings instead of raw bytes. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | - - - - - - - - -### GasInfo -GasInfo defines tx execution gas context. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | -| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | - - - - - - - - -### MsgData -MsgData defines the data returned in a Result object during message -execution. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `msg_type` | [string](#string) | | | -| `data` | [bytes](#bytes) | | | - - - - - - - - -### Result -Result is the union of ResponseFormat and ResponseCheckTx. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | -| `log` | [string](#string) | | Log contains the log information from message or handler execution. | -| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | - - - - - - - - -### SearchTxsResult -SearchTxsResult defines a structure for querying txs pageable - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `total_count` | [uint64](#uint64) | | Count of all txs | -| `count` | [uint64](#uint64) | | Count of txs in current page | -| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | -| `page_total` | [uint64](#uint64) | | Count of total pages | -| `limit` | [uint64](#uint64) | | Max count txs per page | -| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | - - - - - - - - -### SimulationResponse -SimulationResponse defines the response generated when a transaction is -successfully simulated. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | -| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | - - - - - - - - -### StringEvent -StringEvent defines en Event object wrapper where all the attributes -contain key/value pairs that are strings instead of raw bytes. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `type` | [string](#string) | | | -| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | - - - - - - - - -### TxMsgData -TxMsgData defines a list of MsgData. A transaction will have a MsgData object -for each message. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | - - - - - - - - -### TxResponse -TxResponse defines a structure containing relevant tx data and metadata. The -tags are stringified and the log is JSON decoded. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | The block height | -| `txhash` | [string](#string) | | The transaction hash. | -| `codespace` | [string](#string) | | Namespace for the Code | -| `code` | [uint32](#uint32) | | Response code. | -| `data` | [string](#string) | | Result bytes, if any. | -| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | -| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | -| `info` | [string](#string) | | Additional information. May be non-deterministic. | -| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | -| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | -| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | -| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | - - - - - - - - - - - - - - -

    Top

    diff --git a/proto/cosmos/authz/v1beta1/authz.proto b/proto/cosmos/authz/v1beta1/authz.proto new file mode 100644 index 0000000000..56c403a79f --- /dev/null +++ b/proto/cosmos/authz/v1beta1/authz.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos_proto/cosmos.proto"; +import "google/protobuf/timestamp.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz/types"; + +// SendAuthorization allows the grantee to spend up to spend_limit coins from +// the granter's account. +message SendAuthorization { + option (cosmos_proto.implements_interface) = "Authorization"; + + repeated cosmos.base.v1beta1.Coin spend_limit = 1 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; +} + +// GenericAuthorization gives the grantee unrestricted permissions to execute +// the provided method on behalf of the granter's account. +message GenericAuthorization { + option (cosmos_proto.implements_interface) = "Authorization"; + + // method name to grant unrestricted permissions to execute + // Note: MethodName() is already a method on `GenericAuthorization` type, + // we need some custom naming here so using `MessageName` + string method_name = 1 [(gogoproto.customname) = "MessageName"]; +} + +// AuthorizationGrant gives permissions to execute +// the provide method with expiration time. +message AuthorizationGrant { + google.protobuf.Any authorization = 1 [(cosmos_proto.accepts_interface) = "Authorization"]; + google.protobuf.Timestamp expiration = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; +} diff --git a/proto/cosmos/authz/v1beta1/genesis.proto b/proto/cosmos/authz/v1beta1/genesis.proto new file mode 100644 index 0000000000..940d42e1f2 --- /dev/null +++ b/proto/cosmos/authz/v1beta1/genesis.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/any.proto"; +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/authz/v1beta1/tx.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz/types"; + +// GenesisState defines the authz module's genesis state. +message GenesisState { + repeated GrantAuthorization authorization = 1 [(gogoproto.nullable) = false]; +} + +// GrantAuthorization defines the GenesisState/GrantAuthorization type. +message GrantAuthorization { + string granter = 1; + string grantee = 2; + + google.protobuf.Any authorization = 3 [(cosmos_proto.accepts_interface) = "Authorization"]; + google.protobuf.Timestamp expiration = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} diff --git a/proto/cosmos/authz/v1beta1/query.proto b/proto/cosmos/authz/v1beta1/query.proto new file mode 100644 index 0000000000..8c7d50a8d7 --- /dev/null +++ b/proto/cosmos/authz/v1beta1/query.proto @@ -0,0 +1,54 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "google/api/annotations.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "cosmos/authz/v1beta1/authz.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/authz/types"; + +// Query defines the gRPC querier service. +service Query { + // Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the + // provided msg type. + rpc Authorization(QueryAuthorizationRequest) returns (QueryAuthorizationResponse) { + option (google.api.http).get = "/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant"; + } + + // Returns list of `Authorization`, granted to the grantee by the granter. + rpc Authorizations(QueryAuthorizationsRequest) returns (QueryAuthorizationsResponse) { + option (google.api.http).get = "/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants"; + } +} + +// QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. +message QueryAuthorizationRequest { + string granter = 1; + string grantee = 2; + string method_name = 3; +} + +// QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. +message QueryAuthorizationResponse { + // authorization is a authorization granted for grantee by granter. + cosmos.authz.v1beta1.AuthorizationGrant authorization = 1; +} + +// QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. +message QueryAuthorizationsRequest { + string granter = 1; + string grantee = 2; + // pagination defines an pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 3; +} + +// QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. +message QueryAuthorizationsResponse { + // authorizations is a list of grants granted for grantee by granter. + repeated cosmos.authz.v1beta1.AuthorizationGrant authorizations = 1; + // pagination defines an pagination for the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/proto/cosmos/authz/v1beta1/tx.proto b/proto/cosmos/authz/v1beta1/tx.proto new file mode 100644 index 0000000000..69e3e6f1fb --- /dev/null +++ b/proto/cosmos/authz/v1beta1/tx.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; +package cosmos.authz.v1beta1; + +import "cosmos_proto/cosmos.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/any.proto"; +import "cosmos/base/abci/v1beta1/abci.proto"; +option go_package = "github.com/cosmos/cosmos-sdk/x/authz/types"; + +// Msg defines the authz Msg service. +service Msg { + // GrantAuthorization grants the provided authorization to the grantee on the granter's + // account with the provided expiration time. + rpc GrantAuthorization(MsgGrantAuthorizationRequest) returns (MsgGrantAuthorizationResponse); + + // ExecAuthorized attempts to execute the provided messages using + // authorizations granted to the grantee. Each message should have only + // one signer corresponding to the granter of the authorization. + rpc ExecAuthorized(MsgExecAuthorizedRequest) returns (MsgExecAuthorizedResponse); + + // RevokeAuthorization revokes any authorization corresponding to the provided method name on the + // granter's account that has been granted to the grantee. + rpc RevokeAuthorization(MsgRevokeAuthorizationRequest) returns (MsgRevokeAuthorizationResponse); +} + +// MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +// account with the provided expiration time. +message MsgGrantAuthorizationRequest { + string granter = 1; + string grantee = 2; + + google.protobuf.Any authorization = 3 [(cosmos_proto.accepts_interface) = "Authorization"]; + google.protobuf.Timestamp expiration = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} + +// MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. +message MsgExecAuthorizedResponse { + cosmos.base.abci.v1beta1.Result result = 1; +} + +// MsgExecAuthorizedRequest attempts to execute the provided messages using +// authorizations granted to the grantee. Each message should have only +// one signer corresponding to the granter of the authorization. +message MsgExecAuthorizedRequest { + string grantee = 1; + repeated google.protobuf.Any msgs = 2; +} + +// MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. +message MsgGrantAuthorizationResponse {} + +// MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the +// granter's account with that has been granted to the grantee. +message MsgRevokeAuthorizationRequest { + string granter = 1; + string grantee = 2; + string method_name = 3; +} + +// MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. +message MsgRevokeAuthorizationResponse {} diff --git a/simapp/app.go b/simapp/app.go index b73538df03..5e9c3e29e1 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -44,6 +44,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/capability" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + "github.com/cosmos/cosmos-sdk/x/crisis" crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper" crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" @@ -87,6 +88,10 @@ import ( upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + authz "github.com/cosmos/cosmos-sdk/x/authz" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" + authztypes "github.com/cosmos/cosmos-sdk/x/authz/types" + // unnamed import of statik for swagger UI support _ "github.com/cosmos/cosmos-sdk/client/docs/statik" ) @@ -118,6 +123,7 @@ var ( upgrade.AppModuleBasic{}, evidence.AppModuleBasic{}, transfer.AppModuleBasic{}, + authz.AppModuleBasic{}, vesting.AppModuleBasic{}, ) @@ -171,6 +177,7 @@ type SimApp struct { CrisisKeeper crisiskeeper.Keeper UpgradeKeeper upgradekeeper.Keeper ParamsKeeper paramskeeper.Keeper + AuthzKeeper authzkeeper.Keeper IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly EvidenceKeeper evidencekeeper.Keeper TransferKeeper ibctransferkeeper.Keeper @@ -217,6 +224,7 @@ func NewSimApp( minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, + authztypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -282,6 +290,8 @@ func NewSimApp( appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, scopedIBCKeeper, ) + app.AuthzKeeper = authzkeeper.NewKeeper(keys[authztypes.StoreKey], appCodec, app.BaseApp.MsgServiceRouter()) + // register the proposal types govRouter := govtypes.NewRouter() govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). @@ -346,6 +356,7 @@ func NewSimApp( evidence.NewAppModule(app.EvidenceKeeper), ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), + authz.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), transferModule, ) @@ -367,7 +378,7 @@ func NewSimApp( app.mm.SetOrderInitGenesis( capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, - ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, ibctransfertypes.ModuleName, + ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authztypes.ModuleName, ibctransfertypes.ModuleName, ) app.mm.RegisterInvariants(&app.CrisisKeeper) @@ -392,6 +403,7 @@ func NewSimApp( slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), params.NewAppModule(app.ParamsKeeper), evidence.NewAppModule(app.EvidenceKeeper), + authz.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), ibc.NewAppModule(app.IBCKeeper), transferModule, ) diff --git a/simapp/sim_test.go b/simapp/sim_test.go index cc1a7cada4..1c0609c1b8 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -19,6 +19,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + authztypes "github.com/cosmos/cosmos-sdk/x/authz/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" @@ -177,6 +178,7 @@ func TestAppImportExport(t *testing.T) { {app.keys[capabilitytypes.StoreKey], newApp.keys[capabilitytypes.StoreKey], [][]byte{}}, {app.keys[ibchost.StoreKey], newApp.keys[ibchost.StoreKey], [][]byte{}}, {app.keys[ibctransfertypes.StoreKey], newApp.keys[ibctransfertypes.StoreKey], [][]byte{}}, + {app.keys[authztypes.StoreKey], newApp.keys[authztypes.StoreKey], [][]byte{}}, } for _, skp := range storeKeysPrefixes { diff --git a/types/errors/errors.go b/types/errors/errors.go index 1aa68816cc..6c540a1d61 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -135,6 +135,9 @@ var ( // supported. ErrNotSupported = Register(RootCodespace, 37, "feature not supported") + // ErrNotFound defines an error when requested entity doesn't exist in the state. + ErrNotFound = Register(RootCodespace, 38, "not found") + // ErrPanic is only set when we recover from a panic, so we know to // redact potentially sensitive system info ErrPanic = Register(UndefinedCodespace, 111222, "panic") diff --git a/types/msgservice/service_msg_client.go b/types/msgservice/service_msg_client.go new file mode 100644 index 0000000000..de3be89094 --- /dev/null +++ b/types/msgservice/service_msg_client.go @@ -0,0 +1,50 @@ +package msgservice + +import ( + "context" + "fmt" + + gogogrpc "github.com/gogo/protobuf/grpc" + grpc "google.golang.org/grpc" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ gogogrpc.ClientConn = &ServiceMsgClientConn{} + +// ServiceMsgClientConn is an instance of grpc.ClientConn that is used to test building +// transactions with MsgClient's. It is intended to be replaced by the work in +// https://github.com/cosmos/cosmos-sdk/issues/7541 when that is ready. +type ServiceMsgClientConn struct { + msgs []sdk.Msg +} + +// Invoke implements the grpc ClientConn.Invoke method +func (t *ServiceMsgClientConn) Invoke(_ context.Context, method string, args, _ interface{}, _ ...grpc.CallOption) error { + req, ok := args.(sdk.MsgRequest) + if !ok { + return fmt.Errorf("%T should implement %T", args, (*sdk.MsgRequest)(nil)) + } + + err := req.ValidateBasic() + if err != nil { + return err + } + + t.msgs = append(t.msgs, sdk.ServiceMsg{ + MethodName: method, + Request: req, + }) + + return nil +} + +// NewStream implements the grpc ClientConn.NewStream method +func (t *ServiceMsgClientConn) NewStream(context.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { + return nil, fmt.Errorf("not supported") +} + +// GetMsgs returns ServiceMsgClientConn.msgs +func (t *ServiceMsgClientConn) GetMsgs() []sdk.Msg { + return t.msgs +} diff --git a/types/simulation/types.go b/types/simulation/types.go index f541b1d764..46ede62a35 100644 --- a/types/simulation/types.go +++ b/types/simulation/types.go @@ -2,7 +2,9 @@ package simulation import ( "encoding/json" + "fmt" "math/rand" + "reflect" "time" "github.com/cosmos/cosmos-sdk/baseapp" @@ -75,7 +77,16 @@ func NewOperationMsgBasic(route, name, comment string, ok bool, msg []byte) Oper } // NewOperationMsg - create a new operation message from sdk.Msg -func NewOperationMsg(msg sdk.Msg, ok bool, comment string) OperationMsg { +func NewOperationMsg(msg sdk.Msg, ok bool, comment string, cdc *codec.ProtoCodec) OperationMsg { + if reflect.TypeOf(msg) == reflect.TypeOf(sdk.ServiceMsg{}) { + srvMsg, ok := msg.(sdk.ServiceMsg) + if !ok { + panic(fmt.Sprintf("Expecting %T to implement sdk.ServiceMsg", msg)) + } + bz := cdc.MustMarshalJSON(srvMsg.Request) + + return NewOperationMsgBasic(srvMsg.MethodName, srvMsg.MethodName, comment, ok, bz) + } return NewOperationMsgBasic(msg.Route(), msg.Type(), comment, ok, msg.GetSignBytes()) } diff --git a/x/authz/client/cli/cli_test.go b/x/authz/client/cli/cli_test.go new file mode 100644 index 0000000000..fb6fb1a177 --- /dev/null +++ b/x/authz/client/cli/cli_test.go @@ -0,0 +1,727 @@ +// +build norace + +package cli_test + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/gogo/protobuf/proto" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + tmcli "github.com/tendermint/tendermint/libs/cli" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/testutil" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/client/cli" + govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli" + govtestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + + "github.com/cosmos/cosmos-sdk/x/authz/types" + bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network + grantee sdk.AccAddress +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := network.DefaultConfig() + cfg.NumValidators = 1 + + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + val := s.network.Validators[0] + + // Create new account in the keyring. + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + newAddr := sdk.AccAddress(info.GetPubKey().Address()) + + // Send some funds to the new account. + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + val.Address, + newAddr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + s.grantee = newAddr + + // create a proposal with deposit + _, err = govtestutil.MsgSubmitProposal(val.ClientCtx, val.Address.String(), + "Text Proposal 1", "Where is the title!?", govtypes.ProposalTypeText, + fmt.Sprintf("--%s=%s", govcli.FlagDeposit, sdk.NewCoin(s.cfg.BondDenom, govtypes.DefaultMinDepositTokens).String())) + s.Require().NoError(err) + + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +var typeMsgSend = types.SendAuthorization{}.MethodName() +var typeMsgVote = "/cosmos.gov.v1beta1.Msg/Vote" + +func (s *IntegrationTestSuite) TestQueryAuthorizations() { + val := s.network.Validators[0] + + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + testCases := []struct { + name string + args []string + expectErr bool + expErrMsg string + }{ + { + "Error: Invalid grantee", + []string{ + val.Address.String(), + "invalid grantee", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + "decoding bech32 failed: invalid character in string: ' '", + }, + { + "Error: Invalid granter", + []string{ + "invalid granter", + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + "decoding bech32 failed: invalid character in string: ' '", + }, + { + "Valid txn (json)", + []string{ + val.Address.String(), + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + false, + ``, + }, + } + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryAuthorizations() + clientCtx := val.ClientCtx + resp, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + s.Require().Contains(string(resp.Bytes()), tc.expErrMsg) + } else { + s.Require().NoError(err) + var grants types.QueryAuthorizationsResponse + err = val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp.Bytes(), &grants) + s.Require().NoError(err) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryAuthorization() { + val := s.network.Validators[0] + + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + testCases := []struct { + name string + args []string + expectErr bool + expectedOutput string + }{ + { + "Error: Invalid grantee", + []string{ + val.Address.String(), + "invalid grantee", + typeMsgSend, + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + "", + }, + { + "Error: Invalid granter", + []string{ + "invalid granter", + grantee.String(), + typeMsgSend, + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + "", + }, + { + "no authorization found", + []string{ + val.Address.String(), + grantee.String(), + "typeMsgSend", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, + "", + }, + { + "Valid txn (json)", + []string{ + val.Address.String(), + grantee.String(), + typeMsgSend, + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + false, + `{"@type":"/cosmos.authz.v1beta1.SendAuthorization","spend_limit":[{"denom":"steak","amount":"100"}]}`, + }, + } + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryAuthorization() + clientCtx := val.ClientCtx + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().Contains(strings.TrimSpace(out.String()), tc.expectedOutput) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCLITxGrantAuthorization() { + val := s.network.Validators[0] + grantee := s.grantee + + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + pastHour := time.Now().Add(time.Minute * time.Duration(-60)).Unix() + + testCases := []struct { + name string + args []string + respType proto.Message + expectedCode uint32 + expectErr bool + }{ + { + "Invalid granter Address", + []string{ + "grantee_addr", + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=%s", flags.FlagFrom, "granter"), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + }, + nil, + 0, + true, + }, + { + "Invalid grantee Address", + []string{ + "grantee_addr", + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + }, + nil, 0, + true, + }, + { + "Invalid expiration time", + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, pastHour), + }, + nil, 0, + true, + }, + { + "fail with error invalid msg-type", + []string{ + grantee.String(), + "generic", + fmt.Sprintf("--%s=invalid-msg-type", cli.FlagMsgType), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 29, + false, + }, + { + "Valid tx send authorization", + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + { + "Valid tx generic authorization", + []string{ + grantee.String(), + "generic", + fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + clientCtx := val.ClientCtx + out, err := execGrantAuthorization( + val, + tc.args, + ) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func execGrantAuthorization(val *network.Validator, args []string) (testutil.BufferWriter, error) { + cmd := cli.NewCmdGrantAuthorization() + clientCtx := val.ClientCtx + return clitestutil.ExecTestCLICmd(clientCtx, cmd, args) +} + +func (s *IntegrationTestSuite) TestCmdRevokeAuthorizations() { + val := s.network.Validators[0] + + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + // send-authorization + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=100steak", cli.FlagSpendLimit), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + // generic-authorization + _, err = execGrantAuthorization( + val, + []string{ + grantee.String(), + "generic", + fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + testCases := []struct { + name string + args []string + respType proto.Message + expectedCode uint32 + expectErr bool + }{ + { + "invalid grantee address", + []string{ + "invlid grantee", + typeMsgSend, + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + }, + nil, + 0, + true, + }, + { + "invalid granter address", + []string{ + grantee.String(), + typeMsgSend, + fmt.Sprintf("--%s=%s", flags.FlagFrom, "granter"), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + }, + nil, + 0, + true, + }, + { + "Valid tx send authorization", + []string{ + grantee.String(), + typeMsgSend, + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + { + "Valid tx generic authorization", + []string{ + grantee.String(), + typeMsgVote, + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + &sdk.TxResponse{}, 0, + false, + }, + } + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.NewCmdRevokeAuthorization() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestExecAuthorizationWithExpiration() { + val := s.network.Validators[0] + grantee := s.grantee + tenSeconds := time.Now().Add(time.Second * time.Duration(10)).Unix() + + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "generic", + fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, tenSeconds), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + // msg vote + voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1beta1.Msg/Vote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String()) + execMsg := testutil.WriteToNewTempFile(s.T(), voteTx) + + // waiting for authorization to expires + time.Sleep(12 * time.Second) + + cmd := cli.NewCmdExecAuthorization() + clientCtx := val.ClientCtx + + res, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, []string{ + execMsg.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + }) + s.Require().NoError(err) + s.Require().Contains(res.String(), "authorization not found") +} + +func (s *IntegrationTestSuite) TestNewExecGenericAuthorized() { + val := s.network.Validators[0] + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "generic", + fmt.Sprintf("--%s=%s", cli.FlagMsgType, typeMsgVote), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + + // msg vote + voteTx := fmt.Sprintf(`{"body":{"messages":[{"@type":"/cosmos.gov.v1beta1.Msg/Vote","proposal_id":"1","voter":"%s","option":"VOTE_OPTION_YES"}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, val.Address.String()) + execMsg := testutil.WriteToNewTempFile(s.T(), voteTx) + + testCases := []struct { + name string + args []string + respType proto.Message + expectedCode uint32 + expectErr bool + }{ + { + "fail invalid grantee", + []string{ + execMsg.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, "grantee"), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + }, + nil, + 0, + true, + }, + { + "fail invalid json path", + []string{ + "/invalid/file.txt", + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + }, + nil, + 0, + true, + }, + { + "valid txn", + []string{ + execMsg.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + }, + &sdk.TxResponse{}, + 0, + false, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + + cmd := cli.NewCmdExecAuthorization() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestNewExecGrantAuthorized() { + val := s.network.Validators[0] + grantee := s.grantee + twoHours := time.Now().Add(time.Minute * time.Duration(120)).Unix() + + _, err := execGrantAuthorization( + val, + []string{ + grantee.String(), + "send", + fmt.Sprintf("--%s=12%stoken", cli.FlagSpendLimit, val.Moniker), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, twoHours), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + }, + ) + s.Require().NoError(err) + tokens := sdk.NewCoins( + sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), sdk.NewInt(12)), + ) + normalGeneratedTx, err := bankcli.ServiceMsgSendExec( + val.ClientCtx, + val.Address, + grantee, + tokens, + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + ) + s.Require().NoError(err) + execMsg := testutil.WriteToNewTempFile(s.T(), normalGeneratedTx.String()) + testCases := []struct { + name string + args []string + respType proto.Message + expectedCode uint32 + expectErr bool + }{ + { + "fail invalid grantee", + []string{ + execMsg.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, "grantee"), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagGenerateOnly), + }, + nil, + 0, + true, + }, + { + "fail invalid json path", + []string{ + "/invalid/file.txt", + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + }, + nil, + 0, + true, + }, + { + "valid txn", + []string{ + execMsg.Name(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, grantee.String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + }, + &sdk.TxResponse{}, + 0, + false, + }, + } + + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + cmd := cli.NewCmdExecAuthorization() + clientCtx := val.ClientCtx + + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/authz/client/cli/query.go b/x/authz/client/cli/query.go new file mode 100644 index 0000000000..ef7f326f71 --- /dev/null +++ b/x/authz/client/cli/query.go @@ -0,0 +1,138 @@ +package cli + +import ( + "context" + "fmt" + "strings" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd() *cobra.Command { + authorizationQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the authz module", + Long: "", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + authorizationQueryCmd.AddCommand( + GetCmdQueryAuthorization(), + GetCmdQueryAuthorizations(), + ) + + return authorizationQueryCmd +} + +// GetCmdQueryAuthorizations implements the query authorizations command. +func GetCmdQueryAuthorizations() *cobra.Command { + cmd := &cobra.Command{ + Use: "authorizations [granter-addr] [grantee-addr]", + Args: cobra.ExactArgs(2), + Short: "query list of authorizations for a granter-grantee pair", + Long: strings.TrimSpace( + fmt.Sprintf(`Query list of authorizations for a granter-grantee pair: +Example: +$ %s query %s authorizations cosmos1skj.. cosmos1skjwj.. +`, version.AppName, types.ModuleName), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + granterAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + granteeAddr, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + res, err := queryClient.Authorizations( + context.Background(), + &types.QueryAuthorizationsRequest{ + Granter: granterAddr.String(), + Grantee: granteeAddr.String(), + Pagination: pageReq, + }, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "authorizations") + return cmd +} + +// GetCmdQueryAuthorization implements the query authorization command. +func GetCmdQueryAuthorization() *cobra.Command { + cmd := &cobra.Command{ + Use: "authorization [granter-addr] [grantee-addr] [msg-type]", + Args: cobra.ExactArgs(3), + Short: "query authorization for a granter-grantee pair", + Long: strings.TrimSpace( + fmt.Sprintf(`Query authorization for a granter-grantee pair that matches the given msg-type: +Example: +$ %s query %s authorization cosmos1skjw.. cosmos1skjwj.. %s +`, version.AppName, types.ModuleName, types.SendAuthorization{}.MethodName()), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + granter, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + grantee, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + msgAuthorized := args[2] + + res, err := queryClient.Authorization( + context.Background(), + &types.QueryAuthorizationRequest{ + Granter: granter.String(), + Grantee: grantee.String(), + MethodName: msgAuthorized, + }, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res.Authorization) + }, + } + flags.AddQueryFlagsToCmd(cmd) + return cmd +} diff --git a/x/authz/client/cli/tx.go b/x/authz/client/cli/tx.go new file mode 100644 index 0000000000..ba2fd21012 --- /dev/null +++ b/x/authz/client/cli/tx.go @@ -0,0 +1,222 @@ +package cli + +import ( + "context" + "errors" + "fmt" + "strings" + "time" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + "github.com/cosmos/cosmos-sdk/version" + authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +const FlagSpendLimit = "spend-limit" +const FlagMsgType = "msg-type" +const FlagExpiration = "expiration" + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd() *cobra.Command { + AuthorizationTxCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Authorization transactions subcommands", + Long: "Authorize and revoke access to execute transactions on behalf of your address", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + AuthorizationTxCmd.AddCommand( + NewCmdGrantAuthorization(), + NewCmdRevokeAuthorization(), + NewCmdExecAuthorization(), + ) + + return AuthorizationTxCmd +} + +func NewCmdGrantAuthorization() *cobra.Command { + cmd := &cobra.Command{ + Use: "grant --from ", + Short: "Grant authorization to an address", + Long: strings.TrimSpace( + fmt.Sprintf(`Grant authorization to an address to execute a transaction on your behalf: + +Examples: + $ %s tx %s grant cosmos1skjw.. send %s --spend-limit=1000stake --from=cosmos1skl.. + $ %s tx %s grant cosmos1skjw.. generic --msg-type=/cosmos.gov.v1beta1.Msg/Vote --from=cosmos1sk.. + `, version.AppName, types.ModuleName, types.SendAuthorization{}.MethodName(), version.AppName, types.ModuleName), + ), + Args: cobra.RangeArgs(2, 3), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + grantee, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + var authorization types.Authorization + switch args[1] { + case "send": + limit, err := cmd.Flags().GetString(FlagSpendLimit) + if err != nil { + return err + } + + spendLimit, err := sdk.ParseCoinsNormalized(limit) + if err != nil { + return err + } + + if !spendLimit.IsAllPositive() { + return fmt.Errorf("spend-limit should be greater than zero") + } + + authorization = &types.SendAuthorization{ + SpendLimit: spendLimit, + } + case "generic": + msgType, err := cmd.Flags().GetString(FlagMsgType) + if err != nil { + return err + } + + authorization = types.NewGenericAuthorization(msgType) + default: + return fmt.Errorf("invalid authorization type, %s", args[1]) + } + + exp, err := cmd.Flags().GetInt64(FlagExpiration) + if err != nil { + return err + } + + msg, err := types.NewMsgGrantAuthorization(clientCtx.GetFromAddress(), grantee, authorization, time.Unix(exp, 0)) + if err != nil { + return err + } + + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.GrantAuthorization(context.Background(), msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) + }, + } + flags.AddTxFlagsToCmd(cmd) + cmd.Flags().String(FlagMsgType, "", "The Msg method name for which we are creating a GenericAuthorization") + cmd.Flags().String(FlagSpendLimit, "", "SpendLimit for Send Authorization, an array of Coins allowed spend") + cmd.Flags().Int64(FlagExpiration, time.Now().AddDate(1, 0, 0).Unix(), "The Unix timestamp. Default is one year.") + return cmd +} + +func NewCmdRevokeAuthorization() *cobra.Command { + cmd := &cobra.Command{ + Use: "revoke [grantee_address] [msg_type] --from=[granter_address]", + Short: "revoke authorization", + Long: strings.TrimSpace( + fmt.Sprintf(`revoke authorization from a granter to a grantee: +Example: + $ %s tx %s revoke cosmos1skj.. %s --from=cosmos1skj.. + `, version.AppName, types.ModuleName, types.SendAuthorization{}.MethodName()), + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + grantee, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + granter := clientCtx.GetFromAddress() + + msgAuthorized := args[1] + + msg := types.NewMsgRevokeAuthorization(granter, grantee, msgAuthorized) + + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.RevokeAuthorization(context.Background(), &msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) + }, + } + flags.AddTxFlagsToCmd(cmd) + return cmd +} + +func NewCmdExecAuthorization() *cobra.Command { + cmd := &cobra.Command{ + Use: "exec [msg_tx_json_file] --from [grantee]", + Short: "execute tx on behalf of granter account", + Long: strings.TrimSpace( + fmt.Sprintf(`execute tx on behalf of granter account: +Example: + $ %s tx %s exec tx.json --from grantee + $ %s tx bank send --from --chain-id --generate-only > tx.json && %s tx %s exec tx.json --from grantee + `, version.AppName, types.ModuleName, version.AppName, version.AppName, types.ModuleName), + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + grantee := clientCtx.GetFromAddress() + + if offline, _ := cmd.Flags().GetBool(flags.FlagOffline); offline { + return errors.New("cannot broadcast tx during offline mode") + } + + theTx, err := authclient.ReadTxFromFile(clientCtx, args[0]) + if err != nil { + return err + } + msgs := theTx.GetMsgs() + serviceMsgs := make([]sdk.ServiceMsg, len(msgs)) + for i, msg := range msgs { + srvMsg, ok := msg.(sdk.ServiceMsg) + if !ok { + return fmt.Errorf("tx contains %T which is not a sdk.ServiceMsg", msg) + } + serviceMsgs[i] = srvMsg + } + + msg := types.NewMsgExecAuthorized(grantee, serviceMsgs) + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.ExecAuthorized(context.Background(), &msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/authz/client/rest/grpc_query_test.go b/x/authz/client/rest/grpc_query_test.go new file mode 100644 index 0000000000..8ed8e857c6 --- /dev/null +++ b/x/authz/client/rest/grpc_query_test.go @@ -0,0 +1,235 @@ +// +build norace + +package rest_test + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + authztestutil "github.com/cosmos/cosmos-sdk/x/authz/client/testutil" + types "github.com/cosmos/cosmos-sdk/x/authz/types" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" +) + +type IntegrationTestSuite struct { + suite.Suite + cfg network.Config + network *network.Network + grantee sdk.AccAddress +} + +var typeMsgSend = types.SendAuthorization{}.MethodName() + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := network.DefaultConfig() + + cfg.NumValidators = 1 + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + val := s.network.Validators[0] + // Create new account in the keyring. + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + newAddr := sdk.AccAddress(info.GetPubKey().Address()) + + // Send some funds to the new account. + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + val.Address, + newAddr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + + // grant authorization + _, err = authztestutil.MsgGrantAuthorizationExec(val.ClientCtx, val.Address.String(), newAddr.String(), typeMsgSend, "100stake") + s.Require().NoError(err) + + s.grantee = newAddr + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestQueryAuthorizationGRPC() { + val := s.network.Validators[0] + baseURL := val.APIAddress + testCases := []struct { + name string + url string + expectErr bool + errorMsg string + }{ + { + "fail invalid granter address", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, "invalid_granter", s.grantee.String(), typeMsgSend), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + }, + { + "fail invalid grantee address", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, val.Address.String(), "invalid_grantee", typeMsgSend), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + }, + { + "fail with empty granter", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, "", s.grantee.String(), typeMsgSend), + true, + "Not Implemented", + }, + { + "fail with empty grantee", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, val.Address.String(), "", typeMsgSend), + true, + "Not Implemented", + }, + { + "fail invalid msg-type", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, val.Address.String(), s.grantee.String(), "invalidMsg"), + true, + "rpc error: code = NotFound desc = no authorization found for invalidMsg type: key not found", + }, + { + "valid query", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grant?msg_type=%s", baseURL, val.Address.String(), s.grantee.String(), typeMsgSend), + false, + "", + }, + } + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + resp, _ := rest.GetRequest(tc.url) + if tc.expectErr { + s.Require().Contains(string(resp), tc.errorMsg) + } else { + var authorization types.QueryAuthorizationResponse + err := val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, &authorization) + s.Require().NoError(err) + authorization.Authorization.UnpackInterfaces(val.ClientCtx.InterfaceRegistry) + auth := authorization.Authorization.GetAuthorizationGrant() + s.Require().Equal(auth.MethodName(), types.SendAuthorization{}.MethodName()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryAuthorizationsGRPC() { + val := s.network.Validators[0] + baseURL := val.APIAddress + testCases := []struct { + name string + url string + expectErr bool + errMsg string + preRun func() + postRun func(*types.QueryAuthorizationsResponse) + }{ + { + "fail invalid granter address", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, "invalid_granter", s.grantee.String()), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + func() {}, + func(_ *types.QueryAuthorizationsResponse) {}, + }, + { + "fail invalid grantee address", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, val.Address.String(), "invalid_grantee"), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + func() {}, + func(_ *types.QueryAuthorizationsResponse) {}, + }, + { + "fail empty grantee address", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, "", "invalid_grantee"), + true, + "Not Implemented", + func() {}, + func(_ *types.QueryAuthorizationsResponse) {}, + }, + { + "valid query: expect single grant", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, val.Address.String(), s.grantee.String()), + false, + "", + func() { + }, + func(authorizations *types.QueryAuthorizationsResponse) { + s.Require().Equal(len(authorizations.Authorizations), 1) + }, + }, + { + "valid query: expect two grants", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants", baseURL, val.Address.String(), s.grantee.String()), + false, + "", + func() { + _, err := authztestutil.MsgGrantAuthorizationExec(val.ClientCtx, val.Address.String(), s.grantee.String(), "/cosmos.gov.v1beta1.Msg/Vote", "") + s.Require().NoError(err) + }, + func(authorizations *types.QueryAuthorizationsResponse) { + s.Require().Equal(len(authorizations.Authorizations), 2) + }, + }, + { + "valid query: expect single grant with pagination", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants?pagination.limit=1", baseURL, val.Address.String(), s.grantee.String()), + false, + "", + func() {}, + func(authorizations *types.QueryAuthorizationsResponse) { + s.Require().Equal(len(authorizations.Authorizations), 1) + }, + }, + { + "valid query: expect two grants with pagination", + fmt.Sprintf("%s/cosmos/authz/v1beta1/granters/%s/grantees/%s/grants?pagination.limit=2", baseURL, val.Address.String(), s.grantee.String()), + false, + "", + func() {}, + func(authorizations *types.QueryAuthorizationsResponse) { + s.Require().Equal(len(authorizations.Authorizations), 2) + }, + }, + } + for _, tc := range testCases { + tc := tc + s.Run(tc.name, func() { + tc.preRun() + resp, _ := rest.GetRequest(tc.url) + if tc.expectErr { + s.Require().Contains(string(resp), tc.errMsg) + } else { + var authorizations types.QueryAuthorizationsResponse + err := val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, &authorizations) + s.Require().NoError(err) + tc.postRun(&authorizations) + } + + }) + } +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/authz/client/testutil/test_helpers.go b/x/authz/client/testutil/test_helpers.go new file mode 100644 index 0000000000..a56429a4d9 --- /dev/null +++ b/x/authz/client/testutil/test_helpers.go @@ -0,0 +1,34 @@ +package testutil + +import ( + "fmt" + "time" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/testutil" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + sdk "github.com/cosmos/cosmos-sdk/types" + authzcli "github.com/cosmos/cosmos-sdk/x/authz/client/cli" +) + +var commonArgs = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), +} + +func MsgGrantAuthorizationExec(clientCtx client.Context, granter, grantee, msgName, limit string, extraArgs ...string) (testutil.BufferWriter, error) { + args := []string{ + grantee, + msgName, + } + if limit != "" { + args = append(args, limit) + } + + args = append(args, fmt.Sprintf("--%s=%s", flags.FlagFrom, granter)) + args = append(args, fmt.Sprintf("--%s=%d", authzcli.FlagExpiration, time.Now().Add(time.Minute*time.Duration(120)).Unix())) + args = append(args, commonArgs...) + return clitestutil.ExecTestCLICmd(clientCtx, authzcli.NewCmdGrantAuthorization(), args) +} diff --git a/x/authz/exported/keeper.go b/x/authz/exported/keeper.go new file mode 100644 index 0000000000..9858ba8217 --- /dev/null +++ b/x/authz/exported/keeper.go @@ -0,0 +1,26 @@ +package exported + +import ( + "time" + + "github.com/cosmos/cosmos-sdk/x/authz/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type Keeper interface { + // DispatchActions executes the provided messages via authorization grants from the message signer to the grantee + DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, msgs []sdk.ServiceMsg) sdk.Result + + // Grants the provided authorization to the grantee on the granter's account with the provided expiration time + // If there is an existing authorization grant for the same sdk.Msg type, this grant overwrites that. + Grant(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, authorization types.Authorization, expiration time.Time) error + + // Revokes any authorization for the provided message type granted to the grantee by the granter. + Revoke(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) + + // Returns any Authorization (or nil), with the expiration time, + // granted to the grantee by the granter for the provided msg type. + // If the Authorization is expired already, it will revoke the authorization and return nil + GetOrRevokeAuthorization(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) (cap types.Authorization, expiration time.Time) +} diff --git a/x/authz/genesis.go b/x/authz/genesis.go new file mode 100644 index 0000000000..e84ddf5987 --- /dev/null +++ b/x/authz/genesis.go @@ -0,0 +1,47 @@ +package authz + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/keeper" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +// InitGenesis new authz genesis +func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, data *types.GenesisState) { + for _, entry := range data.Authorization { + grantee, err := sdk.AccAddressFromBech32(entry.Grantee) + if err != nil { + panic(err) + } + granter, err := sdk.AccAddressFromBech32(entry.Granter) + if err != nil { + panic(err) + } + authorization, ok := entry.Authorization.GetCachedValue().(types.Authorization) + if !ok { + panic("expected authorization") + } + + err = keeper.Grant(ctx, grantee, granter, authorization, entry.Expiration) + if err != nil { + panic(err) + } + } +} + +// ExportGenesis returns a GenesisState for a given context and keeper. +func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { + var entries []types.GrantAuthorization + keeper.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant types.AuthorizationGrant) bool { + exp := grant.Expiration + entries = append(entries, types.GrantAuthorization{ + Granter: granter.String(), + Grantee: grantee.String(), + Expiration: exp, + Authorization: grant.Authorization, + }) + return false + }) + + return types.NewGenesisState(entries) +} diff --git a/x/authz/genesis_test.go b/x/authz/genesis_test.go new file mode 100644 index 0000000000..2d770d4c52 --- /dev/null +++ b/x/authz/genesis_test.go @@ -0,0 +1,59 @@ +package authz_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + authz "github.com/cosmos/cosmos-sdk/x/authz" + "github.com/cosmos/cosmos-sdk/x/authz/keeper" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +type GenesisTestSuite struct { + suite.Suite + + ctx sdk.Context + keeper keeper.Keeper +} + +func (suite *GenesisTestSuite) SetupTest() { + checkTx := false + app := simapp.Setup(checkTx) + + suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1}) + suite.keeper = app.AuthzKeeper +} + +var ( + granteePub = secp256k1.GenPrivKey().PubKey() + granterPub = secp256k1.GenPrivKey().PubKey() + granteeAddr = sdk.AccAddress(granteePub.Address()) + granterAddr = sdk.AccAddress(granterPub.Address()) +) + +func (suite *GenesisTestSuite) TestImportExportGenesis() { + coins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1_000))) + + now := suite.ctx.BlockHeader().Time + grant := &types.SendAuthorization{SpendLimit: coins} + err := suite.keeper.Grant(suite.ctx, granteeAddr, granterAddr, grant, now.Add(time.Hour)) + suite.Require().NoError(err) + genesis := authz.ExportGenesis(suite.ctx, suite.keeper) + + // Clear keeper + suite.keeper.Revoke(suite.ctx, granteeAddr, granterAddr, grant.MethodName()) + + authz.InitGenesis(suite.ctx, suite.keeper, genesis) + newGenesis := authz.ExportGenesis(suite.ctx, suite.keeper) + suite.Require().Equal(genesis, newGenesis) +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} diff --git a/x/authz/keeper/grpc_query.go b/x/authz/keeper/grpc_query.go new file mode 100644 index 0000000000..7b1fcb1995 --- /dev/null +++ b/x/authz/keeper/grpc_query.go @@ -0,0 +1,120 @@ +package keeper + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + proto "github.com/gogo/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +var _ types.QueryServer = Keeper{} + +// Authorizations implements the Query/Authorizations gRPC method. +func (k Keeper) Authorizations(c context.Context, req *types.QueryAuthorizationsRequest) (*types.QueryAuthorizationsResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + granter, err := sdk.AccAddressFromBech32(req.Granter) + + if err != nil { + return nil, err + } + grantee, err := sdk.AccAddressFromBech32(req.Grantee) + + if err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) + + store := ctx.KVStore(k.storeKey) + key := types.GetAuthorizationStoreKey(grantee, granter, "") + authStore := prefix.NewStore(store, key) + var authorizations []*types.AuthorizationGrant + pageRes, err := query.FilteredPaginate(authStore, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) { + auth, err := unmarshalAuthorization(k.cdc, value) + if err != nil { + return false, err + } + auth1 := auth.GetAuthorizationGrant() + if accumulate { + msg, ok := auth1.(proto.Message) + if !ok { + return false, status.Errorf(codes.Internal, "can't protomarshal %T", msg) + } + + authorizationAny, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return false, status.Errorf(codes.Internal, err.Error()) + } + authorizations = append(authorizations, &types.AuthorizationGrant{ + Authorization: authorizationAny, + Expiration: auth.Expiration, + }) + } + return true, nil + }) + if err != nil { + return nil, err + } + + return &types.QueryAuthorizationsResponse{ + Authorizations: authorizations, + Pagination: pageRes, + }, nil +} + +// unmarshal an authorization from a store value +func unmarshalAuthorization(cdc codec.BinaryMarshaler, value []byte) (v types.AuthorizationGrant, err error) { + err = cdc.UnmarshalBinaryBare(value, &v) + return v, err +} + +// Authorization implements the Query/Authorization gRPC method. +func (k Keeper) Authorization(c context.Context, req *types.QueryAuthorizationRequest) (*types.QueryAuthorizationResponse, error) { + if req == nil { + return nil, status.Errorf(codes.InvalidArgument, "empty request") + } + + if req.MethodName == "" { + return nil, status.Errorf(codes.InvalidArgument, "empty method-name") + } + + granter, err := sdk.AccAddressFromBech32(req.Granter) + + if err != nil { + return nil, err + } + grantee, err := sdk.AccAddressFromBech32(req.Grantee) + + if err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(c) + + authorization, expiration := k.GetOrRevokeAuthorization(ctx, grantee, granter, req.MethodName) + if authorization == nil { + return nil, status.Errorf(codes.NotFound, "no authorization found for %s type", req.MethodName) + } + + authorizationAny, err := codectypes.NewAnyWithValue(authorization) + if err != nil { + return nil, status.Errorf(codes.Internal, err.Error()) + } + + return &types.QueryAuthorizationResponse{ + Authorization: &types.AuthorizationGrant{ + Authorization: authorizationAny, + Expiration: expiration, + }, + }, nil +} diff --git a/x/authz/keeper/grpc_query_test.go b/x/authz/keeper/grpc_query_test.go new file mode 100644 index 0000000000..cc301fbca1 --- /dev/null +++ b/x/authz/keeper/grpc_query_test.go @@ -0,0 +1,157 @@ +package keeper_test + +import ( + gocontext "context" + "fmt" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +func (suite *TestSuite) TestGRPCQueryAuthorization() { + app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs + var ( + req *types.QueryAuthorizationRequest + expAuthorization types.Authorization + ) + testCases := []struct { + msg string + malleate func() + expPass bool + postTest func(res *types.QueryAuthorizationResponse) + }{ + { + "fail invalid granter addr", + func() { + req = &types.QueryAuthorizationRequest{} + }, + false, + func(res *types.QueryAuthorizationResponse) {}, + }, + { + "fail invalid grantee addr", + func() { + req = &types.QueryAuthorizationRequest{ + Granter: addrs[0].String(), + } + }, + false, + func(res *types.QueryAuthorizationResponse) {}, + }, + { + "fail invalid msg-type", + func() { + req = &types.QueryAuthorizationRequest{ + Granter: addrs[0].String(), + Grantee: addrs[1].String(), + } + }, + false, + func(res *types.QueryAuthorizationResponse) {}, + }, + { + "Success", + func() { + now := ctx.BlockHeader().Time + newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) + expAuthorization = &types.SendAuthorization{SpendLimit: newCoins} + err := app.AuthzKeeper.Grant(ctx, addrs[0], addrs[1], expAuthorization, now.Add(time.Hour)) + suite.Require().NoError(err) + req = &types.QueryAuthorizationRequest{ + Granter: addrs[1].String(), + Grantee: addrs[0].String(), + MethodName: expAuthorization.MethodName(), + } + }, + true, + func(res *types.QueryAuthorizationResponse) { + var auth types.Authorization + err := suite.app.InterfaceRegistry().UnpackAny(res.Authorization.Authorization, &auth) + suite.Require().NoError(err) + suite.Require().NotNil(auth) + suite.Require().Equal(auth.String(), expAuthorization.String()) + }, + }, + } + for _, testCase := range testCases { + suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { + testCase.malleate() + result, err := queryClient.Authorization(gocontext.Background(), req) + if testCase.expPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + testCase.postTest(result) + }) + } +} + +func (suite *TestSuite) TestGRPCQueryAuthorizations() { + app, ctx, queryClient, addrs := suite.app, suite.ctx, suite.queryClient, suite.addrs + var ( + req *types.QueryAuthorizationsRequest + expAuthorization types.Authorization + ) + testCases := []struct { + msg string + malleate func() + expPass bool + postTest func(res *types.QueryAuthorizationsResponse) + }{ + { + "fail invalid granter addr", + func() { + req = &types.QueryAuthorizationsRequest{} + }, + false, + func(res *types.QueryAuthorizationsResponse) {}, + }, + { + "fail invalid grantee addr", + func() { + req = &types.QueryAuthorizationsRequest{ + Granter: addrs[0].String(), + } + }, + false, + func(res *types.QueryAuthorizationsResponse) {}, + }, + { + "Success", + func() { + now := ctx.BlockHeader().Time + newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) + expAuthorization = &types.SendAuthorization{SpendLimit: newCoins} + err := app.AuthzKeeper.Grant(ctx, addrs[0], addrs[1], expAuthorization, now.Add(time.Hour)) + suite.Require().NoError(err) + req = &types.QueryAuthorizationsRequest{ + Granter: addrs[1].String(), + Grantee: addrs[0].String(), + } + }, + true, + func(res *types.QueryAuthorizationsResponse) { + var auth types.Authorization + suite.Require().Equal(1, len(res.Authorizations)) + err := suite.app.InterfaceRegistry().UnpackAny(res.Authorizations[0].Authorization, &auth) + suite.Require().NoError(err) + suite.Require().NotNil(auth) + suite.Require().Equal(auth.String(), expAuthorization.String()) + }, + }, + } + for _, testCase := range testCases { + suite.Run(fmt.Sprintf("Case %s", testCase.msg), func() { + testCase.malleate() + result, err := queryClient.Authorizations(gocontext.Background(), req) + if testCase.expPass { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + testCase.postTest(result) + }) + } +} diff --git a/x/authz/keeper/keeper.go b/x/authz/keeper/keeper.go new file mode 100644 index 0000000000..2888e17449 --- /dev/null +++ b/x/authz/keeper/keeper.go @@ -0,0 +1,210 @@ +package keeper + +import ( + "fmt" + "time" + + "github.com/gogo/protobuf/proto" + + "github.com/tendermint/tendermint/libs/log" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +type Keeper struct { + storeKey sdk.StoreKey + cdc codec.BinaryMarshaler + router *baseapp.MsgServiceRouter +} + +// NewKeeper constructs a message authorization Keeper +func NewKeeper(storeKey sdk.StoreKey, cdc codec.BinaryMarshaler, router *baseapp.MsgServiceRouter) Keeper { + return Keeper{ + storeKey: storeKey, + cdc: cdc, + router: router, + } +} + +// Logger returns a module-specific logger. +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +// getAuthorizationGrant returns grant between granter and grantee for the given msg type +func (k Keeper) getAuthorizationGrant(ctx sdk.Context, grantStoreKey []byte) (grant types.AuthorizationGrant, found bool) { + store := ctx.KVStore(k.storeKey) + bz := store.Get(grantStoreKey) + if bz == nil { + return grant, false + } + k.cdc.MustUnmarshalBinaryBare(bz, &grant) + return grant, true +} + +func (k Keeper) update(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, updated types.Authorization) error { + grantStoreKey := types.GetAuthorizationStoreKey(grantee, granter, updated.MethodName()) + grant, found := k.getAuthorizationGrant(ctx, grantStoreKey) + if !found { + return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "authorization not found") + } + + msg, ok := updated.(proto.Message) + if !ok { + sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", updated) + } + + any, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return err + } + + grant.Authorization = any + store := ctx.KVStore(k.storeKey) + store.Set(grantStoreKey, k.cdc.MustMarshalBinaryBare(&grant)) + return nil +} + +// DispatchActions attempts to execute the provided messages via authorization +// grants from the message signer to the grantee. +func (k Keeper) DispatchActions(ctx sdk.Context, grantee sdk.AccAddress, serviceMsgs []sdk.ServiceMsg) (*sdk.Result, error) { + var msgResult *sdk.Result + var err error + for _, serviceMsg := range serviceMsgs { + signers := serviceMsg.GetSigners() + if len(signers) != 1 { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "authorization can be given to msg with only one signer") + } + granter := signers[0] + if !granter.Equals(grantee) { + authorization, _ := k.GetOrRevokeAuthorization(ctx, grantee, granter, serviceMsg.MethodName) + if authorization == nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "authorization not found") + } + allow, updated, del := authorization.Accept(serviceMsg, ctx.BlockHeader()) + if !allow { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "requested amount is more than spend limit") + } + if del { + k.Revoke(ctx, grantee, granter, serviceMsg.Type()) + } else if updated != nil { + err = k.update(ctx, grantee, granter, updated) + if err != nil { + return nil, err + } + } + } + handler := k.router.Handler(serviceMsg.Route()) + + if handler == nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s", serviceMsg.Route()) + } + + msgResult, err = handler(ctx, serviceMsg.Request) + if err != nil { + return nil, sdkerrors.Wrapf(err, "failed to execute message; message %s", serviceMsg.MethodName) + } + } + + return msgResult, nil +} + +// Grant method grants the provided authorization to the grantee on the granter's account with the provided expiration +// time. If there is an existing authorization grant for the same `sdk.Msg` type, this grant +// overwrites that. +func (k Keeper) Grant(ctx sdk.Context, grantee, granter sdk.AccAddress, authorization types.Authorization, expiration time.Time) error { + store := ctx.KVStore(k.storeKey) + + grant, err := types.NewAuthorizationGrant(authorization, expiration) + if err != nil { + return err + } + + bz := k.cdc.MustMarshalBinaryBare(&grant) + grantStoreKey := types.GetAuthorizationStoreKey(grantee, granter, authorization.MethodName()) + store.Set(grantStoreKey, bz) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventGrantAuthorization, + sdk.NewAttribute(types.AttributeKeyGrantType, authorization.MethodName()), + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(types.AttributeKeyGranterAddress, granter.String()), + sdk.NewAttribute(types.AttributeKeyGranteeAddress, grantee.String()), + ), + ) + return nil +} + +// Revoke method revokes any authorization for the provided message type granted to the grantee by the granter. +func (k Keeper) Revoke(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) error { + store := ctx.KVStore(k.storeKey) + grantStoreKey := types.GetAuthorizationStoreKey(grantee, granter, msgType) + _, found := k.getAuthorizationGrant(ctx, grantStoreKey) + if !found { + return sdkerrors.Wrap(sdkerrors.ErrNotFound, "authorization not found") + } + store.Delete(grantStoreKey) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventRevokeAuthorization, + sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory), + sdk.NewAttribute(types.AttributeKeyGrantType, msgType), + sdk.NewAttribute(types.AttributeKeyGranterAddress, granter.String()), + sdk.NewAttribute(types.AttributeKeyGranteeAddress, grantee.String()), + ), + ) + return nil +} + +// GetAuthorizations Returns list of `Authorizations` granted to the grantee by the granter. +func (k Keeper) GetAuthorizations(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress) (authorizations []types.Authorization) { + store := ctx.KVStore(k.storeKey) + key := types.GetAuthorizationStoreKey(grantee, granter, "") + iter := sdk.KVStorePrefixIterator(store, key) + defer iter.Close() + var authorization types.AuthorizationGrant + for ; iter.Valid(); iter.Next() { + k.cdc.MustUnmarshalBinaryBare(iter.Value(), &authorization) + authorizations = append(authorizations, authorization.GetAuthorizationGrant()) + } + return authorizations +} + +// GetOrRevokeAuthorization Returns any `Authorization` (or `nil`), with the expiration time, +// granted to the grantee by the granter for the provided msg type. +// If the Authorization is expired already, it will revoke the authorization and return nil +func (k Keeper) GetOrRevokeAuthorization(ctx sdk.Context, grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) (cap types.Authorization, expiration time.Time) { + grant, found := k.getAuthorizationGrant(ctx, types.GetAuthorizationStoreKey(grantee, granter, msgType)) + if !found { + return nil, time.Time{} + } + if grant.Expiration.Before(ctx.BlockHeader().Time) { + k.Revoke(ctx, grantee, granter, msgType) + return nil, time.Time{} + } + + return grant.GetAuthorizationGrant(), grant.Expiration +} + +// IterateGrants iterates over all authorization grants +func (k Keeper) IterateGrants(ctx sdk.Context, + handler func(granterAddr sdk.AccAddress, granteeAddr sdk.AccAddress, grant types.AuthorizationGrant) bool) { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.GrantKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + var grant types.AuthorizationGrant + granterAddr, granteeAddr := types.ExtractAddressesFromGrantKey(iter.Key()) + k.cdc.MustUnmarshalBinaryBare(iter.Value(), &grant) + if handler(granterAddr, granteeAddr, grant) { + break + } + } +} diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go new file mode 100644 index 0000000000..5a544a04af --- /dev/null +++ b/x/authz/keeper/keeper_test.go @@ -0,0 +1,218 @@ +package keeper_test + +import ( + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/baseapp" + proto "github.com/gogo/protobuf/proto" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmtime "github.com/tendermint/tendermint/types/time" + + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/stretchr/testify/suite" +) + +type TestSuite struct { + suite.Suite + + app *simapp.SimApp + ctx sdk.Context + addrs []sdk.AccAddress + queryClient types.QueryClient +} + +func (s *TestSuite) SetupTest() { + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + now := tmtime.Now() + ctx = ctx.WithBlockHeader(tmproto.Header{Time: now}) + queryHelper := baseapp.NewQueryServerTestHelper(ctx, app.InterfaceRegistry()) + types.RegisterQueryServer(queryHelper, app.AuthzKeeper) + queryClient := types.NewQueryClient(queryHelper) + s.queryClient = queryClient + + s.app = app + s.ctx = ctx + s.queryClient = queryClient + s.addrs = simapp.AddTestAddrsIncremental(app, ctx, 3, sdk.NewInt(30000000)) + +} + +func (s *TestSuite) TestKeeper() { + app, ctx, addrs := s.app, s.ctx, s.addrs + + granterAddr := addrs[0] + granteeAddr := addrs[1] + recipientAddr := addrs[2] + err := app.BankKeeper.SetBalances(ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000))) + s.Require().Nil(err) + s.Require().True(app.BankKeeper.GetBalance(ctx, granterAddr, "steak").IsEqual(sdk.NewCoin("steak", sdk.NewInt(10000)))) + + s.T().Log("verify that no authorization returns nil") + authorization, expiration := app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Nil(authorization) + s.Require().Equal(expiration, time.Time{}) + now := s.ctx.BlockHeader().Time + s.Require().NotNil(now) + + newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) + s.T().Log("verify if expired authorization is rejected") + x := &types.SendAuthorization{SpendLimit: newCoins} + err = app.AuthzKeeper.Grant(ctx, granterAddr, granteeAddr, x, now.Add(-1*time.Hour)) + s.Require().NoError(err) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Nil(authorization) + + s.T().Log("verify if authorization is accepted") + x = &types.SendAuthorization{SpendLimit: newCoins} + err = app.AuthzKeeper.Grant(ctx, granteeAddr, granterAddr, x, now.Add(time.Hour)) + s.Require().NoError(err) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().NotNil(authorization) + s.Require().Equal(authorization.MethodName(), types.SendAuthorization{}.MethodName()) + + s.T().Log("verify fetching authorization with wrong msg type fails") + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, proto.MessageName(&banktypes.MsgMultiSend{})) + s.Require().Nil(authorization) + + s.T().Log("verify fetching authorization with wrong grantee fails") + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, recipientAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Nil(authorization) + + s.T().Log("verify revoke fails with wrong information") + err = app.AuthzKeeper.Revoke(ctx, recipientAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Error(err) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, recipientAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Nil(authorization) + + s.T().Log("verify revoke executes with correct information") + err = app.AuthzKeeper.Revoke(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().NoError(err) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().Nil(authorization) + +} + +func (s *TestSuite) TestKeeperIter() { + app, ctx, addrs := s.app, s.ctx, s.addrs + + granterAddr := addrs[0] + granteeAddr := addrs[1] + + err := app.BankKeeper.SetBalances(ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000))) + s.Require().Nil(err) + s.Require().True(app.BankKeeper.GetBalance(ctx, granterAddr, "steak").IsEqual(sdk.NewCoin("steak", sdk.NewInt(10000)))) + + s.T().Log("verify that no authorization returns nil") + authorization, expiration := app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, "Abcd") + s.Require().Nil(authorization) + s.Require().Equal(time.Time{}, expiration) + now := s.ctx.BlockHeader().Time + s.Require().NotNil(now) + + newCoins := sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) + s.T().Log("verify if expired authorization is rejected") + x := &types.SendAuthorization{SpendLimit: newCoins} + err = app.AuthzKeeper.Grant(ctx, granteeAddr, granterAddr, x, now.Add(-1*time.Hour)) + s.Require().NoError(err) + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(ctx, granteeAddr, granterAddr, "abcd") + s.Require().Nil(authorization) + + app.AuthzKeeper.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant types.AuthorizationGrant) bool { + s.Require().Equal(granter, granterAddr) + s.Require().Equal(grantee, granteeAddr) + return true + }) + +} + +func (s *TestSuite) TestKeeperFees() { + app, addrs := s.app, s.addrs + + granterAddr := addrs[0] + granteeAddr := addrs[1] + recipientAddr := addrs[2] + err := app.BankKeeper.SetBalances(s.ctx, granterAddr, sdk.NewCoins(sdk.NewInt64Coin("steak", 10000))) + s.Require().Nil(err) + s.Require().True(app.BankKeeper.GetBalance(s.ctx, granterAddr, "steak").IsEqual(sdk.NewCoin("steak", sdk.NewInt(10000)))) + + now := s.ctx.BlockHeader().Time + s.Require().NotNil(now) + + smallCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 20)) + someCoin := sdk.NewCoins(sdk.NewInt64Coin("steak", 123)) + + msgs := types.NewMsgExecAuthorized(granteeAddr, []sdk.ServiceMsg{ + { + MethodName: types.SendAuthorization{}.MethodName(), + Request: &banktypes.MsgSend{ + Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)), + FromAddress: granterAddr.String(), + ToAddress: recipientAddr.String(), + }, + }, + }) + + s.Require().NoError(msgs.UnpackInterfaces(app.AppCodec())) + + s.T().Log("verify dispatch fails with invalid authorization") + executeMsgs, err := msgs.GetServiceMsgs() + s.Require().NoError(err) + result, err := app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) + + s.Require().Nil(result) + s.Require().NotNil(err) + + s.T().Log("verify dispatch executes with correct information") + // grant authorization + err = app.AuthzKeeper.Grant(s.ctx, granteeAddr, granterAddr, &types.SendAuthorization{SpendLimit: smallCoin}, now) + s.Require().NoError(err) + authorization, _ := app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().NotNil(authorization) + + s.Require().Equal(authorization.MethodName(), types.SendAuthorization{}.MethodName()) + + executeMsgs, err = msgs.GetServiceMsgs() + s.Require().NoError(err) + + result, err = app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) + s.Require().NotNil(result) + s.Require().Nil(err) + + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().NotNil(authorization) + + s.T().Log("verify dispatch fails with overlimit") + // grant authorization + + msgs = types.NewMsgExecAuthorized(granteeAddr, []sdk.ServiceMsg{ + { + MethodName: types.SendAuthorization{}.MethodName(), + Request: &banktypes.MsgSend{ + Amount: someCoin, + FromAddress: granterAddr.String(), + ToAddress: recipientAddr.String(), + }, + }, + }) + + s.Require().NoError(msgs.UnpackInterfaces(app.AppCodec())) + executeMsgs, err = msgs.GetServiceMsgs() + s.Require().NoError(err) + + result, err = app.AuthzKeeper.DispatchActions(s.ctx, granteeAddr, executeMsgs) + s.Require().Nil(result) + s.Require().NotNil(err) + + authorization, _ = app.AuthzKeeper.GetOrRevokeAuthorization(s.ctx, granteeAddr, granterAddr, types.SendAuthorization{}.MethodName()) + s.Require().NotNil(authorization) +} + +func TestTestSuite(t *testing.T) { + suite.Run(t, new(TestSuite)) +} diff --git a/x/authz/keeper/msg_server.go b/x/authz/keeper/msg_server.go new file mode 100644 index 0000000000..53beb129df --- /dev/null +++ b/x/authz/keeper/msg_server.go @@ -0,0 +1,75 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +var _ types.MsgServer = Keeper{} + +// GrantAuthorization implements the MsgServer.GrantAuthorization method. +func (k Keeper) GrantAuthorization(goCtx context.Context, msg *types.MsgGrantAuthorizationRequest) (*types.MsgGrantAuthorizationResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return nil, err + } + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return nil, err + } + + authorization := msg.GetGrantAuthorization() + // If the granted service Msg doesn't exist, we throw an error. + if k.router.Handler(authorization.MethodName()) == nil { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "%s doesn't exist.", authorization.MethodName()) + } + + err = k.Grant(ctx, grantee, granter, authorization, msg.Expiration) + if err != nil { + return nil, err + } + + return &types.MsgGrantAuthorizationResponse{}, nil +} + +// RevokeAuthorization implements the MsgServer.RevokeAuthorization method. +func (k Keeper) RevokeAuthorization(goCtx context.Context, msg *types.MsgRevokeAuthorizationRequest) (*types.MsgRevokeAuthorizationResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return nil, err + } + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return nil, err + } + + err = k.Revoke(ctx, grantee, granter, msg.MethodName) + if err != nil { + return nil, err + } + + return &types.MsgRevokeAuthorizationResponse{}, nil +} + +// ExecAuthorized implements the MsgServer.ExecAuthorized method. +func (k Keeper) ExecAuthorized(goCtx context.Context, msg *types.MsgExecAuthorizedRequest) (*types.MsgExecAuthorizedResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return nil, err + } + msgs, err := msg.GetServiceMsgs() + if err != nil { + return nil, err + } + result, err := k.DispatchActions(ctx, grantee, msgs) + if err != nil { + return nil, err + } + return &types.MsgExecAuthorizedResponse{Result: result}, nil +} diff --git a/x/authz/module.go b/x/authz/module.go new file mode 100644 index 0000000000..1bcd388e4d --- /dev/null +++ b/x/authz/module.go @@ -0,0 +1,194 @@ +package authz + +import ( + "context" + "encoding/json" + "math/rand" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" + + sdkclient "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/authz/keeper" + "github.com/cosmos/cosmos-sdk/x/authz/types" + + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/cosmos/cosmos-sdk/x/authz/client/cli" + "github.com/cosmos/cosmos-sdk/x/authz/simulation" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleSimulation = AppModule{} +) + +// AppModuleBasic defines the basic application module used by the authz module. +type AppModuleBasic struct { + cdc codec.Marshaler +} + +// Name returns the authz module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterServices registers a gRPC query service to respond to the +// module-specific gRPC queries. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) + types.RegisterMsgServer(cfg.MsgServer(), am.keeper) +} + +// RegisterLegacyAminoCodec registers the authz module's types for the given codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {} + +// RegisterInterfaces registers the authz module's interface types +func (AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// DefaultGenesis returns default genesis state as raw bytes for the authz +// module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the authz module. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, config sdkclient.TxEncodingConfig, bz json.RawMessage) error { + var data types.GenesisState + if err := cdc.UnmarshalJSON(bz, &data); err != nil { + return sdkerrors.Wrapf(err, "failed to unmarshal %s genesis state", types.ModuleName) + } + + return types.ValidateGenesis(data) +} + +// RegisterRESTRoutes registers the REST routes for the authz module. +func (AppModuleBasic) RegisterRESTRoutes(clientCtx sdkclient.Context, r *mux.Router) { +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the authz module. +func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx sdkclient.Context, mux *runtime.ServeMux) { + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetQueryCmd returns the cli query commands for the authz module +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +// GetTxCmd returns the transaction commands for the authz module +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// AppModule implements the sdk.AppModule interface +type AppModule struct { + AppModuleBasic + keeper keeper.Keeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + registry cdctypes.InterfaceRegistry +} + +// NewAppModule creates a new AppModule object +func NewAppModule(cdc codec.Marshaler, keeper keeper.Keeper, ak types.AccountKeeper, bk types.BankKeeper, registry cdctypes.InterfaceRegistry) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{cdc: cdc}, + keeper: keeper, + accountKeeper: ak, + bankKeeper: bk, + registry: registry, + } +} + +// Name returns the authz module's name. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterInvariants does nothing, there are no invariants to enforce +func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// Route returns the message routing key for the staking module. +func (am AppModule) Route() sdk.Route { + return sdk.NewRoute(types.RouterKey, nil) +} + +func (am AppModule) NewHandler() sdk.Handler { + return nil +} + +// QuerierRoute returns the route we respond to for abci queries +func (AppModule) QuerierRoute() string { return "" } + +// LegacyQuerierHandler returns the authz module sdk.Querier. +func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { + return nil +} + +// InitGenesis performs genesis initialization for the authz module. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, data json.RawMessage) []abci.ValidatorUpdate { + var genesisState types.GenesisState + cdc.MustUnmarshalJSON(data, &genesisState) + InitGenesis(ctx, am.keeper, &genesisState) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the exported genesis state as raw bytes for the authz +// module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { + gs := ExportGenesis(ctx, am.keeper) + return cdc.MustMarshalJSON(gs) +} + +func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {} + +// EndBlock does nothing +func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// ____________________________________________________________________________ + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the authz module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalContents returns all the authz content functions used to +// simulate governance proposals. +func (am AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams creates randomized authz param changes for the simulator. +func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { + return nil +} + +// RegisterStoreDecoder registers a decoder for authz module's types +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { + sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) +} + +// WeightedOperations returns the all the gov module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + protoCdc := codec.NewProtoCodec(am.registry) + return simulation.WeightedOperations( + simState.AppParams, simState.Cdc, + am.accountKeeper, am.bankKeeper, am.keeper, am.cdc, protoCdc, + ) +} diff --git a/x/authz/simulation/decoder.go b/x/authz/simulation/decoder.go new file mode 100644 index 0000000000..c87f7a70c1 --- /dev/null +++ b/x/authz/simulation/decoder.go @@ -0,0 +1,26 @@ +package simulation + +import ( + "bytes" + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +// NewDecodeStore returns a decoder function closure that umarshals the KVPair's +// Value to the corresponding authz type. +func NewDecodeStore(cdc codec.Marshaler) func(kvA, kvB kv.Pair) string { + return func(kvA, kvB kv.Pair) string { + switch { + case bytes.Equal(kvA.Key[:1], types.GrantKey): + var grantA, grantB types.AuthorizationGrant + cdc.MustUnmarshalBinaryBare(kvA.Value, &grantA) + cdc.MustUnmarshalBinaryBare(kvB.Value, &grantB) + return fmt.Sprintf("%v\n%v", grantA, grantB) + default: + panic(fmt.Sprintf("invalid authz key %X", kvA.Key)) + } + } +} diff --git a/x/authz/simulation/decoder_test.go b/x/authz/simulation/decoder_test.go new file mode 100644 index 0000000000..86c2dfd6ab --- /dev/null +++ b/x/authz/simulation/decoder_test.go @@ -0,0 +1,50 @@ +package simulation_test + +import ( + "fmt" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/cosmos/cosmos-sdk/x/authz/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +func TestDecodeStore(t *testing.T) { + cdc := simapp.MakeTestEncodingConfig().Marshaler + dec := simulation.NewDecodeStore(cdc) + + grant, _ := types.NewAuthorizationGrant(types.NewSendAuthorization(sdk.NewCoins(sdk.NewInt64Coin("foo", 123))), time.Now().UTC()) + grantBz, err := cdc.MarshalBinaryBare(&grant) + require.NoError(t, err) + kvPairs := kv.Pairs{ + Pairs: []kv.Pair{ + {Key: []byte(types.GrantKey), Value: grantBz}, + {Key: []byte{0x99}, Value: []byte{0x99}}, + }, + } + + tests := []struct { + name string + expectedLog string + }{ + {"Grant", fmt.Sprintf("%v\n%v", grant, grant)}, + {"other", ""}, + } + + for i, tt := range tests { + i, tt := i, tt + t.Run(tt.name, func(t *testing.T) { + switch i { + case len(tests) - 1: + require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) + default: + require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) + } + }) + } +} diff --git a/x/authz/simulation/genesis.go b/x/authz/simulation/genesis.go new file mode 100644 index 0000000000..ea674e24ea --- /dev/null +++ b/x/authz/simulation/genesis.go @@ -0,0 +1,38 @@ +package simulation + +import ( + "encoding/json" + "fmt" + "math/rand" + + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +// Simulation parameter constant. +const authz = "authz" + +// GenAuthorizationGrant returns an empty slice of authorization grants. +func GenAuthorizationGrant(_ *rand.Rand, _ []simtypes.Account) []types.GrantAuthorization { + return []types.GrantAuthorization{} +} + +// RandomizedGenState generates a random GenesisState for authz. +func RandomizedGenState(simState *module.SimulationState) { + var grants []types.GrantAuthorization + + simState.AppParams.GetOrGenerate( + simState.Cdc, authz, &grants, simState.Rand, + func(r *rand.Rand) { grants = GenAuthorizationGrant(r, simState.Accounts) }, + ) + authzGrantsGenesis := types.NewGenesisState(grants) + + bz, err := json.MarshalIndent(&authzGrantsGenesis, "", " ") + if err != nil { + panic(err) + } + + fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, bz) + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(authzGrantsGenesis) +} diff --git a/x/authz/simulation/genesis_test.go b/x/authz/simulation/genesis_test.go new file mode 100644 index 0000000000..4672d195ec --- /dev/null +++ b/x/authz/simulation/genesis_test.go @@ -0,0 +1,40 @@ +package simulation_test + +import ( + "encoding/json" + "math/rand" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +func TestRandomizedGenState(t *testing.T) { + interfaceRegistry := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + s := rand.NewSource(1) + r := rand.New(s) + + simState := module.SimulationState{ + AppParams: make(simtypes.AppParams), + Cdc: cdc, + Rand: r, + NumBonded: 3, + Accounts: simtypes.RandomAccounts(r, 3), + InitialStake: 1000, + GenState: make(map[string]json.RawMessage), + } + + simulation.RandomizedGenState(&simState) + var authzGenesis types.GenesisState + simState.Cdc.MustUnmarshalJSON(simState.GenState[types.ModuleName], &authzGenesis) + + require.Len(t, authzGenesis.Authorization, 0) +} diff --git a/x/authz/simulation/operations.go b/x/authz/simulation/operations.go new file mode 100644 index 0000000000..5533d9fa69 --- /dev/null +++ b/x/authz/simulation/operations.go @@ -0,0 +1,291 @@ +package simulation + +import ( + "context" + "math/rand" + "strings" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/simapp/helpers" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/keeper" + "github.com/cosmos/cosmos-sdk/x/authz/types" + banktype "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/simulation" +) + +// authz message types +const ( + TypeMsgGrantAuthorization = "/cosmos.authz.v1beta1.Msg/GrantAuthorization" + TypeMsgRevokeAuthorization = "/cosmos.authz.v1beta1.Msg/RevokeAuthorization" + TypeMsgExecDelegated = "/cosmos.authz.v1beta1.Msg/ExecAuthorized" +) + +// Simulation operation weights constants +const ( + OpWeightMsgGrantAuthorization = "op_weight_msg_grant_authorization" + OpWeightRevokeAuthorization = "op_weight_msg_revoke_authorization" + OpWeightExecAuthorized = "op_weight_msg_execute_authorized" +) + +// WeightedOperations returns all the operations from the module with their respective weights +func WeightedOperations( + appParams simtypes.AppParams, cdc codec.JSONMarshaler, ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, appCdc cdctypes.AnyUnpacker, protoCdc *codec.ProtoCodec) simulation.WeightedOperations { + + var ( + weightMsgGrantAuthorization int + weightRevokeAuthorization int + weightExecAuthorized int + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgGrantAuthorization, &weightMsgGrantAuthorization, nil, + func(_ *rand.Rand) { + weightMsgGrantAuthorization = simappparams.DefaultWeightMsgDelegate + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightRevokeAuthorization, &weightRevokeAuthorization, nil, + func(_ *rand.Rand) { + weightRevokeAuthorization = simappparams.DefaultWeightMsgUndelegate + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightExecAuthorized, &weightExecAuthorized, nil, + func(_ *rand.Rand) { + weightExecAuthorized = simappparams.DefaultWeightMsgSend + }, + ) + + return simulation.WeightedOperations{ + simulation.NewWeightedOperation( + weightMsgGrantAuthorization, + SimulateMsgGrantAuthorization(ak, bk, k, protoCdc), + ), + simulation.NewWeightedOperation( + weightRevokeAuthorization, + SimulateMsgRevokeAuthorization(ak, bk, k, protoCdc), + ), + simulation.NewWeightedOperation( + weightExecAuthorized, + SimulateMsgExecuteAuthorized(ak, bk, k, appCdc, protoCdc), + ), + } +} + +// SimulateMsgGrantAuthorization generates a MsgGrantAuthorization with random values. +// nolint: funlen +func SimulateMsgGrantAuthorization(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, + protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + granter := accs[0] + grantee := accs[1] + + account := ak.GetAccount(ctx, granter.Address) + + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, err.Error()), nil, err + } + + blockTime := ctx.BlockTime() + msg, err := types.NewMsgGrantAuthorization(granter.Address, grantee.Address, + types.NewSendAuthorization(spendableCoins.Sub(fees)), blockTime.AddDate(1, 0, 0)) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, err.Error()), nil, err + } + txGen := simappparams.MakeTestEncodingConfig().TxConfig + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.GrantAuthorization(context.Background(), msg) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, err.Error()), nil, err + } + tx, err := helpers.GenTx( + txGen, + svcMsgClientConn.GetMsgs(), + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + granter.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantAuthorization, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, svcMsgClientConn.GetMsgs()[0].Type(), "unable to deliver tx"), nil, err + } + return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "", protoCdc), nil, err + } +} + +// SimulateMsgRevokeAuthorization generates a MsgRevokeAuthorization with random values. +// nolint: funlen +func SimulateMsgRevokeAuthorization(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + hasGrant := false + var targetGrant types.AuthorizationGrant + var granterAddr sdk.AccAddress + var granteeAddr sdk.AccAddress + k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant types.AuthorizationGrant) bool { + targetGrant = grant + granterAddr = granter + granteeAddr = grantee + hasGrant = true + return true + }) + + if !hasGrant { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeAuthorization, "no grants"), nil, nil + } + + granter, ok := simtypes.FindAccount(accs, granterAddr) + if !ok { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeAuthorization, "Account not found"), nil, nil + } + account := ak.GetAccount(ctx, granter.Address) + + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeAuthorization, "fee error"), nil, err + } + auth := targetGrant.GetAuthorizationGrant() + msg := types.NewMsgRevokeAuthorization(granterAddr, granteeAddr, auth.MethodName()) + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.RevokeAuthorization(context.Background(), &msg) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeAuthorization, err.Error()), nil, err + } + tx, err := helpers.GenTx( + txGen, + svcMsgClientConn.GetMsgs(), + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + granter.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeAuthorization, err.Error()), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "", protoCdc), nil, err + } +} + +// SimulateMsgExecuteAuthorized generates a MsgExecuteAuthorized with random values. +// nolint: funlen +func SimulateMsgExecuteAuthorized(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, cdc cdctypes.AnyUnpacker, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + hasGrant := false + var targetGrant types.AuthorizationGrant + var granterAddr sdk.AccAddress + var granteeAddr sdk.AccAddress + k.IterateGrants(ctx, func(granter, grantee sdk.AccAddress, grant types.AuthorizationGrant) bool { + targetGrant = grant + granterAddr = granter + granteeAddr = grantee + hasGrant = true + return true + }) + + if !hasGrant { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "Not found"), nil, nil + } + + grantee, _ := simtypes.FindAccount(accs, granteeAddr) + granterAccount := ak.GetAccount(ctx, granterAddr) + granteeAccount := ak.GetAccount(ctx, granteeAddr) + + granterspendableCoins := bk.SpendableCoins(ctx, granterAccount.GetAddress()) + if granterspendableCoins.Empty() { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "no coins"), nil, nil + } + + if targetGrant.Expiration.Before(ctx.BlockHeader().Time) { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "grant expired"), nil, nil + } + + granteespendableCoins := bk.SpendableCoins(ctx, granteeAccount.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, granteespendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "fee error"), nil, err + } + sendCoins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(10))) + + execMsg := sdk.ServiceMsg{ + MethodName: types.SendAuthorization{}.MethodName(), + Request: banktype.NewMsgSend( + granterAddr, + granteeAddr, + sendCoins, + ), + } + + msg := types.NewMsgExecAuthorized(grantee.Address, []sdk.ServiceMsg{execMsg}) + sendGrant := targetGrant.Authorization.GetCachedValue().(*types.SendAuthorization) + allow, _, _ := sendGrant.Accept(execMsg, ctx.BlockHeader()) + if !allow { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "not allowed"), nil, nil + } + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + authzMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = authzMsgClient.ExecAuthorized(context.Background(), &msg) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, err.Error()), nil, err + } + tx, err := helpers.GenTx( + txGen, + svcMsgClientConn.GetMsgs(), + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{granteeAccount.GetAccountNumber()}, + []uint64{granteeAccount.GetSequence()}, + grantee.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, err.Error()), nil, err + } + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + if strings.Contains(err.Error(), "insufficient fee") { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "insufficient fee"), nil, nil + } + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, err.Error()), nil, err + } + msg.UnpackInterfaces(cdc) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgExecDelegated, "unmarshal error"), nil, err + } + return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "success", protoCdc), nil, nil + } +} diff --git a/x/authz/simulation/operations_test.go b/x/authz/simulation/operations_test.go new file mode 100644 index 0000000000..83be182df7 --- /dev/null +++ b/x/authz/simulation/operations_test.go @@ -0,0 +1,197 @@ +package simulation_test + +import ( + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + abci "github.com/tendermint/tendermint/abci/types" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/simulation" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +type SimTestSuite struct { + suite.Suite + + ctx sdk.Context + app *simapp.SimApp + protoCdc *codec.ProtoCodec +} + +func (suite *SimTestSuite) SetupTest() { + checkTx := false + app := simapp.Setup(checkTx) + suite.app = app + suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{}) + suite.protoCdc = codec.NewProtoCodec(suite.app.InterfaceRegistry()) +} + +func (suite *SimTestSuite) TestWeightedOperations() { + cdc := suite.app.AppCodec() + appParams := make(simtypes.AppParams) + + weightesOps := simulation.WeightedOperations(appParams, cdc, suite.app.AccountKeeper, + suite.app.BankKeeper, suite.app.AuthzKeeper, cdc, suite.protoCdc, + ) + + // setup 3 accounts + s := rand.NewSource(1) + r := rand.New(s) + accs := suite.getTestingAccounts(r, 3) + + expected := []struct { + weight int + opMsgRoute string + opMsgName string + }{ + {simappparams.DefaultWeightMsgDelegate, types.ModuleName, simulation.TypeMsgGrantAuthorization}, + {simappparams.DefaultWeightMsgUndelegate, types.ModuleName, simulation.TypeMsgRevokeAuthorization}, + {simappparams.DefaultWeightMsgSend, types.ModuleName, simulation.TypeMsgExecDelegated}, + } + + for i, w := range weightesOps { + operationMsg, _, _ := w.Op()(r, suite.app.BaseApp, suite.ctx, accs, "") + // the following checks are very much dependent from the ordering of the output given + // by WeightedOperations. if the ordering in WeightedOperations changes some tests + // will fail + suite.Require().Equal(expected[i].weight, w.Weight(), "weight should be the same") + suite.Require().Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") + suite.Require().Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") + } +} + +func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { + accounts := simtypes.RandomAccounts(r, n) + + initAmt := sdk.TokensFromConsensusPower(200000) + initCoins := sdk.NewCoins(sdk.NewCoin("foo", initAmt)) + + // add coins to the accounts + for _, account := range accounts { + acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, account.Address) + suite.app.AccountKeeper.SetAccount(suite.ctx, acc) + err := suite.app.BankKeeper.SetBalances(suite.ctx, account.Address, initCoins) + suite.Require().NoError(err) + } + + return accounts +} + +func (suite *SimTestSuite) TestSimulateGrantAuthorization() { + // setup 3 accounts + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 2) + blockTime := time.Now().UTC() + ctx := suite.ctx.WithBlockTime(blockTime) + + // begin a new block + suite.app.BeginBlock(abci.RequestBeginBlock{ + Header: tmproto.Header{ + Height: suite.app.LastBlockHeight() + 1, + AppHash: suite.app.LastCommitID().Hash, + }, + }) + + granter := accounts[0] + grantee := accounts[1] + + // execute operation + op := simulation.SimulateMsgGrantAuthorization(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.AuthzKeeper, suite.protoCdc) + operationMsg, futureOperations, err := op(r, suite.app.BaseApp, ctx, accounts, "") + suite.Require().NoError(err) + + var msg types.MsgGrantAuthorizationRequest + suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + suite.Require().True(operationMsg.OK) + suite.Require().Equal(granter.Address.String(), msg.Granter) + suite.Require().Equal(grantee.Address.String(), msg.Grantee) + suite.Require().Len(futureOperations, 0) + +} + +func (suite *SimTestSuite) TestSimulateRevokeAuthorization() { + // setup 3 accounts + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 3) + + // begin a new block + suite.app.BeginBlock(abci.RequestBeginBlock{ + Header: tmproto.Header{ + Height: suite.app.LastBlockHeight() + 1, + AppHash: suite.app.LastCommitID().Hash, + }}) + + initAmt := sdk.TokensFromConsensusPower(200000) + initCoins := sdk.NewCoins(sdk.NewCoin("foo", initAmt)) + + granter := accounts[0] + grantee := accounts[1] + authorization := types.NewSendAuthorization(initCoins) + + err := suite.app.AuthzKeeper.Grant(suite.ctx, grantee.Address, granter.Address, authorization, time.Now().Add(30*time.Hour)) + suite.Require().NoError(err) + + // execute operation + op := simulation.SimulateMsgRevokeAuthorization(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.AuthzKeeper, suite.protoCdc) + operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") + suite.Require().NoError(err) + + var msg types.MsgRevokeAuthorizationRequest + suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + + suite.Require().True(operationMsg.OK) + suite.Require().Equal(granter.Address.String(), msg.Granter) + suite.Require().Equal(grantee.Address.String(), msg.Grantee) + suite.Require().Equal(types.SendAuthorization{}.MethodName(), msg.MethodName) + suite.Require().Len(futureOperations, 0) + +} + +func (suite *SimTestSuite) TestSimulateExecAuthorization() { + // setup 3 accounts + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 3) + + // begin a new block + suite.app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: suite.app.LastBlockHeight() + 1, AppHash: suite.app.LastCommitID().Hash}}) + + initAmt := sdk.TokensFromConsensusPower(200000) + initCoins := sdk.NewCoins(sdk.NewCoin("foo", initAmt)) + + granter := accounts[0] + grantee := accounts[1] + authorization := types.NewSendAuthorization(initCoins) + + err := suite.app.AuthzKeeper.Grant(suite.ctx, grantee.Address, granter.Address, authorization, time.Now().Add(30*time.Hour)) + suite.Require().NoError(err) + + // execute operation + op := simulation.SimulateMsgExecuteAuthorized(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.AuthzKeeper, suite.app.AppCodec(), suite.protoCdc) + operationMsg, futureOperations, err := op(r, suite.app.BaseApp, suite.ctx, accounts, "") + suite.Require().NoError(err) + + var msg types.MsgExecAuthorizedRequest + + suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + + suite.Require().True(operationMsg.OK) + suite.Require().Equal(grantee.Address.String(), msg.Grantee) + suite.Require().Len(futureOperations, 0) + +} + +func TestSimTestSuite(t *testing.T) { + suite.Run(t, new(SimTestSuite)) +} diff --git a/x/authz/types/authorizations.go b/x/authz/types/authorizations.go new file mode 100644 index 0000000000..18533fe072 --- /dev/null +++ b/x/authz/types/authorizations.go @@ -0,0 +1,63 @@ +package types + +import ( + "time" + + "github.com/gogo/protobuf/proto" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +type Authorization interface { + proto.Message + + // MethodName returns the fully-qualified Msg service method name as described in ADR 031. + MethodName() string + + // Accept determines whether this grant permits the provided sdk.ServiceMsg to be performed, and if + // so provides an upgraded authorization instance. + Accept(msg sdk.ServiceMsg, block tmproto.Header) (allow bool, updated Authorization, delete bool) +} + +// NewAuthorizationGrant returns new AuthrizationGrant +func NewAuthorizationGrant(authorization Authorization, expiration time.Time) (AuthorizationGrant, error) { + auth := AuthorizationGrant{ + Expiration: expiration, + } + msg, ok := authorization.(proto.Message) + if !ok { + return AuthorizationGrant{}, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", authorization) + } + + any, err := types.NewAnyWithValue(msg) + if err != nil { + return AuthorizationGrant{}, err + } + + auth.Authorization = any + + return auth, nil +} + +var ( + _ types.UnpackInterfacesMessage = &AuthorizationGrant{} +) + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (auth AuthorizationGrant) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var authorization Authorization + return unpacker.UnpackAny(auth.Authorization, &authorization) +} + +// GetAuthorizationGrant returns the cached value from the AuthorizationGrant.Authorization if present. +func (auth AuthorizationGrant) GetAuthorizationGrant() Authorization { + authorization, ok := auth.Authorization.GetCachedValue().(Authorization) + if !ok { + return nil + } + return authorization +} diff --git a/x/authz/types/authz.pb.go b/x/authz/types/authz.pb.go new file mode 100644 index 0000000000..3343083205 --- /dev/null +++ b/x/authz/types/authz.pb.go @@ -0,0 +1,759 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/authz/v1beta1/authz.proto + +package types + +import ( + fmt "fmt" + types1 "github.com/cosmos/cosmos-sdk/codec/types" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "github.com/golang/protobuf/ptypes/timestamp" + _ "github.com/regen-network/cosmos-proto" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// SendAuthorization allows the grantee to spend up to spend_limit coins from +// the granter's account. +type SendAuthorization struct { + SpendLimit github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=spend_limit,json=spendLimit,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"spend_limit"` +} + +func (m *SendAuthorization) Reset() { *m = SendAuthorization{} } +func (m *SendAuthorization) String() string { return proto.CompactTextString(m) } +func (*SendAuthorization) ProtoMessage() {} +func (*SendAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_544dc2e84b61c637, []int{0} +} +func (m *SendAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SendAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SendAuthorization.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 *SendAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_SendAuthorization.Merge(m, src) +} +func (m *SendAuthorization) XXX_Size() int { + return m.Size() +} +func (m *SendAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_SendAuthorization.DiscardUnknown(m) +} + +var xxx_messageInfo_SendAuthorization proto.InternalMessageInfo + +func (m *SendAuthorization) GetSpendLimit() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.SpendLimit + } + return nil +} + +// GenericAuthorization gives the grantee unrestricted permissions to execute +// the provided method on behalf of the granter's account. +type GenericAuthorization struct { + // method name to grant unrestricted permissions to execute + // Note: MethodName() is already a method on `GenericAuthorization` type, + // we need some custom naming here so using `MessageName` + MessageName string `protobuf:"bytes,1,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"` +} + +func (m *GenericAuthorization) Reset() { *m = GenericAuthorization{} } +func (m *GenericAuthorization) String() string { return proto.CompactTextString(m) } +func (*GenericAuthorization) ProtoMessage() {} +func (*GenericAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_544dc2e84b61c637, []int{1} +} +func (m *GenericAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenericAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenericAuthorization.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 *GenericAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenericAuthorization.Merge(m, src) +} +func (m *GenericAuthorization) XXX_Size() int { + return m.Size() +} +func (m *GenericAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_GenericAuthorization.DiscardUnknown(m) +} + +var xxx_messageInfo_GenericAuthorization proto.InternalMessageInfo + +func (m *GenericAuthorization) GetMessageName() string { + if m != nil { + return m.MessageName + } + return "" +} + +// AuthorizationGrant gives permissions to execute +// the provide method with expiration time. +type AuthorizationGrant struct { + Authorization *types1.Any `protobuf:"bytes,1,opt,name=authorization,proto3" json:"authorization,omitempty"` + Expiration time.Time `protobuf:"bytes,2,opt,name=expiration,proto3,stdtime" json:"expiration"` +} + +func (m *AuthorizationGrant) Reset() { *m = AuthorizationGrant{} } +func (m *AuthorizationGrant) String() string { return proto.CompactTextString(m) } +func (*AuthorizationGrant) ProtoMessage() {} +func (*AuthorizationGrant) Descriptor() ([]byte, []int) { + return fileDescriptor_544dc2e84b61c637, []int{2} +} +func (m *AuthorizationGrant) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AuthorizationGrant) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AuthorizationGrant.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 *AuthorizationGrant) XXX_Merge(src proto.Message) { + xxx_messageInfo_AuthorizationGrant.Merge(m, src) +} +func (m *AuthorizationGrant) XXX_Size() int { + return m.Size() +} +func (m *AuthorizationGrant) XXX_DiscardUnknown() { + xxx_messageInfo_AuthorizationGrant.DiscardUnknown(m) +} + +var xxx_messageInfo_AuthorizationGrant proto.InternalMessageInfo + +func (m *AuthorizationGrant) GetAuthorization() *types1.Any { + if m != nil { + return m.Authorization + } + return nil +} + +func (m *AuthorizationGrant) GetExpiration() time.Time { + if m != nil { + return m.Expiration + } + return time.Time{} +} + +func init() { + proto.RegisterType((*SendAuthorization)(nil), "cosmos.authz.v1beta1.SendAuthorization") + proto.RegisterType((*GenericAuthorization)(nil), "cosmos.authz.v1beta1.GenericAuthorization") + proto.RegisterType((*AuthorizationGrant)(nil), "cosmos.authz.v1beta1.AuthorizationGrant") +} + +func init() { proto.RegisterFile("cosmos/authz/v1beta1/authz.proto", fileDescriptor_544dc2e84b61c637) } + +var fileDescriptor_544dc2e84b61c637 = []byte{ + // 410 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xbf, 0x8e, 0xd3, 0x30, + 0x1c, 0xc7, 0x63, 0x90, 0x10, 0x38, 0x3a, 0xa1, 0x46, 0x19, 0xee, 0x3a, 0x24, 0xd5, 0x4d, 0x15, + 0xd2, 0x39, 0x77, 0xc7, 0xc6, 0x76, 0xe1, 0xa4, 0x5b, 0x38, 0x86, 0xc0, 0x04, 0x43, 0xe5, 0x24, + 0x26, 0xb1, 0xa8, 0xed, 0x28, 0x76, 0xd0, 0xf5, 0x9e, 0xa2, 0x03, 0x2f, 0x01, 0x33, 0x0f, 0x51, + 0x31, 0x55, 0x4c, 0x4c, 0x2d, 0x4a, 0x5f, 0x04, 0xc5, 0x76, 0x50, 0x53, 0x10, 0x53, 0xfc, 0xfb, + 0xf3, 0xfd, 0xe4, 0x9b, 0x6f, 0x0c, 0x27, 0x99, 0x90, 0x4c, 0xc8, 0x08, 0x37, 0xaa, 0xbc, 0x8f, + 0x3e, 0x5d, 0xa4, 0x44, 0xe1, 0x0b, 0x53, 0xa1, 0xaa, 0x16, 0x4a, 0x78, 0xbe, 0xd9, 0x40, 0xa6, + 0x67, 0x37, 0xc6, 0x81, 0xd5, 0xa5, 0x58, 0x92, 0x3f, 0xb2, 0x4c, 0x50, 0x6e, 0x54, 0xe3, 0x13, + 0x33, 0x9f, 0xe9, 0x2a, 0xb2, 0x08, 0x33, 0x0a, 0x0b, 0x21, 0x8a, 0x39, 0x89, 0x74, 0x95, 0x36, + 0x1f, 0x22, 0x45, 0x19, 0x91, 0x0a, 0xb3, 0xca, 0x2e, 0xf8, 0x85, 0x28, 0x84, 0x11, 0x76, 0xa7, + 0x9e, 0x78, 0x28, 0xc3, 0x7c, 0x61, 0x46, 0xa7, 0x9f, 0x01, 0x1c, 0xbd, 0x21, 0x3c, 0xbf, 0x6a, + 0x54, 0x29, 0x6a, 0x7a, 0x8f, 0x15, 0x15, 0xdc, 0x9b, 0x43, 0x57, 0x56, 0x84, 0xe7, 0xb3, 0x39, + 0x65, 0x54, 0x1d, 0x83, 0xc9, 0xc3, 0xa9, 0x7b, 0x79, 0x82, 0xac, 0x97, 0xce, 0x78, 0xff, 0x35, + 0xe8, 0xa5, 0xa0, 0x3c, 0x3e, 0x5f, 0x6d, 0x42, 0xe7, 0xeb, 0x36, 0x9c, 0x16, 0x54, 0x95, 0x4d, + 0x8a, 0x32, 0xc1, 0xac, 0x71, 0xfb, 0x38, 0x93, 0xf9, 0xc7, 0x48, 0x2d, 0x2a, 0x22, 0xb5, 0x40, + 0x26, 0x50, 0xf3, 0x5f, 0x75, 0xf8, 0x17, 0xa3, 0x1f, 0xdf, 0xce, 0x8e, 0x06, 0x06, 0x4e, 0xdf, + 0x43, 0xff, 0x86, 0x70, 0x52, 0xd3, 0x6c, 0x68, 0xec, 0x1c, 0xba, 0x8c, 0xa8, 0x52, 0xe4, 0x33, + 0x8e, 0x19, 0x39, 0x06, 0x13, 0x30, 0x7d, 0x12, 0x3f, 0x6d, 0x37, 0xa1, 0x7b, 0x4b, 0xa4, 0xc4, + 0x05, 0x79, 0x8d, 0x19, 0x49, 0xa0, 0xd9, 0xe9, 0xce, 0xff, 0x82, 0x7f, 0x01, 0xd0, 0x1b, 0x74, + 0x6e, 0x6a, 0xcc, 0x95, 0x77, 0x0b, 0x8f, 0xf0, 0x7e, 0x57, 0xd3, 0xdd, 0x4b, 0x1f, 0x99, 0xf4, + 0x50, 0x9f, 0x1e, 0xba, 0xe2, 0x8b, 0x78, 0xf4, 0xfd, 0x10, 0x9b, 0x0c, 0xd5, 0xde, 0x35, 0x84, + 0xe4, 0xae, 0xa2, 0xb5, 0x61, 0x3d, 0xd0, 0xac, 0xf1, 0x5f, 0xac, 0xb7, 0xfd, 0x0f, 0x8c, 0x1f, + 0x77, 0x19, 0x2e, 0xb7, 0x21, 0x48, 0xf6, 0x74, 0xf1, 0xf5, 0xaa, 0x0d, 0xc0, 0xba, 0x0d, 0xc0, + 0xaf, 0x36, 0x00, 0xcb, 0x5d, 0xe0, 0xac, 0x77, 0x81, 0xf3, 0x73, 0x17, 0x38, 0xef, 0x9e, 0xfd, + 0x37, 0xeb, 0x3b, 0x7b, 0x2d, 0x75, 0xe6, 0xe9, 0x23, 0xfd, 0xbe, 0xe7, 0xbf, 0x03, 0x00, 0x00, + 0xff, 0xff, 0x87, 0x61, 0xb9, 0xa8, 0xb3, 0x02, 0x00, 0x00, +} + +func (m *SendAuthorization) 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 *SendAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SendAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.SpendLimit) > 0 { + for iNdEx := len(m.SpendLimit) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SpendLimit[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthz(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *GenericAuthorization) 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 *GenericAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenericAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MessageName) > 0 { + i -= len(m.MessageName) + copy(dAtA[i:], m.MessageName) + i = encodeVarintAuthz(dAtA, i, uint64(len(m.MessageName))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *AuthorizationGrant) 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 *AuthorizationGrant) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AuthorizationGrant) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expiration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintAuthz(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x12 + if m.Authorization != nil { + { + size, err := m.Authorization.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthz(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintAuthz(dAtA []byte, offset int, v uint64) int { + offset -= sovAuthz(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *SendAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.SpendLimit) > 0 { + for _, e := range m.SpendLimit { + l = e.Size() + n += 1 + l + sovAuthz(uint64(l)) + } + } + return n +} + +func (m *GenericAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.MessageName) + if l > 0 { + n += 1 + l + sovAuthz(uint64(l)) + } + return n +} + +func (m *AuthorizationGrant) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Authorization != nil { + l = m.Authorization.Size() + n += 1 + l + sovAuthz(uint64(l)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration) + n += 1 + l + sovAuthz(uint64(l)) + return n +} + +func sovAuthz(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozAuthz(x uint64) (n int) { + return sovAuthz(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *SendAuthorization) 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 ErrIntOverflowAuthz + } + 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: SendAuthorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SendAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SpendLimit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SpendLimit = append(m.SpendLimit, types.Coin{}) + if err := m.SpendLimit[len(m.SpendLimit)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthz(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthz + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GenericAuthorization) 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 ErrIntOverflowAuthz + } + 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: GenericAuthorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenericAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MessageName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + 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 ErrInvalidLengthAuthz + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MessageName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthz(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthz + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *AuthorizationGrant) 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 ErrIntOverflowAuthz + } + 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: AuthorizationGrant: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AuthorizationGrant: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorization", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Authorization == nil { + m.Authorization = &types1.Any{} + } + if err := m.Authorization.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthz + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthz + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthz + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Expiration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipAuthz(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthAuthz + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipAuthz(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, ErrIntOverflowAuthz + } + 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, ErrIntOverflowAuthz + } + 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, ErrIntOverflowAuthz + } + 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, ErrInvalidLengthAuthz + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupAuthz + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthAuthz + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthAuthz = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowAuthz = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupAuthz = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/authz/types/codec.go b/x/authz/types/codec.go new file mode 100644 index 0000000000..88b30932df --- /dev/null +++ b/x/authz/types/codec.go @@ -0,0 +1,25 @@ +package types + +import ( + types "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +// RegisterInterfaces registers the interfaces types with the interface registry +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.MsgRequest)(nil), + &MsgGrantAuthorizationRequest{}, + &MsgRevokeAuthorizationRequest{}, + &MsgExecAuthorizedRequest{}, + ) + + registry.RegisterInterface( + "cosmos.authz.v1beta1.Authorization", + (*Authorization)(nil), + &SendAuthorization{}, + &GenericAuthorization{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} diff --git a/x/authz/types/errors.go b/x/authz/types/errors.go new file mode 100644 index 0000000000..dc4357b1f9 --- /dev/null +++ b/x/authz/types/errors.go @@ -0,0 +1,10 @@ +package types + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// x/authz module sentinel errors +var ( + ErrInvalidExpirationTime = sdkerrors.Register(ModuleName, 3, "expiration time of authorization should be more than current time") +) diff --git a/x/authz/types/events.go b/x/authz/types/events.go new file mode 100644 index 0000000000..9da0f68b14 --- /dev/null +++ b/x/authz/types/events.go @@ -0,0 +1,14 @@ +package types + +// authz module events +const ( + EventGrantAuthorization = "grant-authorization" + EventRevokeAuthorization = "revoke-authorization" + EventExecuteAuthorization = "execute-authorization" + + AttributeKeyGrantType = "grant-type" + AttributeKeyGranteeAddress = "grantee" + AttributeKeyGranterAddress = "granter" + + AttributeValueCategory = ModuleName +) diff --git a/x/authz/types/expected_keepers.go b/x/authz/types/expected_keepers.go new file mode 100644 index 0000000000..ef7869dd2c --- /dev/null +++ b/x/authz/types/expected_keepers.go @@ -0,0 +1,16 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +// AccountKeeper defines the expected account keeper (noalias) +type AccountKeeper interface { + GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI +} + +// BankKeeper defines the expected interface needed to retrieve account balances. +type BankKeeper interface { + SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins +} diff --git a/x/authz/types/generic_authorization.go b/x/authz/types/generic_authorization.go new file mode 100644 index 0000000000..242608c631 --- /dev/null +++ b/x/authz/types/generic_authorization.go @@ -0,0 +1,28 @@ +package types + +import ( + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + _ Authorization = &GenericAuthorization{} +) + +// NewGenericAuthorization creates a new GenericAuthorization object. +func NewGenericAuthorization(methodName string) *GenericAuthorization { + return &GenericAuthorization{ + MessageName: methodName, + } +} + +// MethodName implements Authorization.MethodName. +func (cap GenericAuthorization) MethodName() string { + return cap.MessageName +} + +// Accept implements Authorization.Accept. +func (cap GenericAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (allow bool, updated Authorization, delete bool) { + return true, &cap, false +} diff --git a/x/authz/types/genesis.go b/x/authz/types/genesis.go new file mode 100644 index 0000000000..6ae3529d2e --- /dev/null +++ b/x/authz/types/genesis.go @@ -0,0 +1,41 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec/types" +) + +// NewGenesisState creates new GenesisState object +func NewGenesisState(entries []GrantAuthorization) *GenesisState { + return &GenesisState{ + Authorization: entries, + } +} + +// ValidateGenesis check the given genesis state has no integrity issues +func ValidateGenesis(data GenesisState) error { + return nil +} + +// DefaultGenesisState - Return a default genesis state +func DefaultGenesisState() *GenesisState { + return &GenesisState{} +} + +var _ types.UnpackInterfacesMessage = GenesisState{} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (data GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error { + for _, authorization := range data.Authorization { + err := authorization.UnpackInterfaces(unpacker) + if err != nil { + return err + } + } + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (msg GrantAuthorization) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var authorization Authorization + return unpacker.UnpackAny(msg.Authorization, &authorization) +} diff --git a/x/authz/types/genesis.pb.go b/x/authz/types/genesis.pb.go new file mode 100644 index 0000000000..0cf5c85577 --- /dev/null +++ b/x/authz/types/genesis.pb.go @@ -0,0 +1,680 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/authz/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "github.com/golang/protobuf/ptypes/timestamp" + _ "github.com/regen-network/cosmos-proto" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the authz module's genesis state. +type GenesisState struct { + Authorization []GrantAuthorization `protobuf:"bytes,1,rep,name=authorization,proto3" json:"authorization"` +} + +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_4c2fbb971da7c892, []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) GetAuthorization() []GrantAuthorization { + if m != nil { + return m.Authorization + } + return nil +} + +// GrantAuthorization defines the GenesisState/GrantAuthorization type. +type GrantAuthorization struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + Authorization *types.Any `protobuf:"bytes,3,opt,name=authorization,proto3" json:"authorization,omitempty"` + Expiration time.Time `protobuf:"bytes,4,opt,name=expiration,proto3,stdtime" json:"expiration"` +} + +func (m *GrantAuthorization) Reset() { *m = GrantAuthorization{} } +func (m *GrantAuthorization) String() string { return proto.CompactTextString(m) } +func (*GrantAuthorization) ProtoMessage() {} +func (*GrantAuthorization) Descriptor() ([]byte, []int) { + return fileDescriptor_4c2fbb971da7c892, []int{1} +} +func (m *GrantAuthorization) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GrantAuthorization) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GrantAuthorization.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 *GrantAuthorization) XXX_Merge(src proto.Message) { + xxx_messageInfo_GrantAuthorization.Merge(m, src) +} +func (m *GrantAuthorization) XXX_Size() int { + return m.Size() +} +func (m *GrantAuthorization) XXX_DiscardUnknown() { + xxx_messageInfo_GrantAuthorization.DiscardUnknown(m) +} + +var xxx_messageInfo_GrantAuthorization proto.InternalMessageInfo + +func (m *GrantAuthorization) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *GrantAuthorization) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *GrantAuthorization) GetAuthorization() *types.Any { + if m != nil { + return m.Authorization + } + return nil +} + +func (m *GrantAuthorization) GetExpiration() time.Time { + if m != nil { + return m.Expiration + } + return time.Time{} +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "cosmos.authz.v1beta1.GenesisState") + proto.RegisterType((*GrantAuthorization)(nil), "cosmos.authz.v1beta1.GrantAuthorization") +} + +func init() { + proto.RegisterFile("cosmos/authz/v1beta1/genesis.proto", fileDescriptor_4c2fbb971da7c892) +} + +var fileDescriptor_4c2fbb971da7c892 = []byte{ + // 346 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xbb, 0x6e, 0xc2, 0x30, + 0x14, 0x86, 0xe3, 0x82, 0x7a, 0x31, 0x65, 0x68, 0xc4, 0x90, 0x22, 0x35, 0x20, 0xa6, 0xa8, 0x12, + 0xb6, 0xa0, 0x4f, 0x40, 0x84, 0xc4, 0xd4, 0x85, 0x32, 0x75, 0xa9, 0x1c, 0x70, 0x4d, 0xd4, 0x26, + 0x8e, 0xe2, 0x43, 0x05, 0x3c, 0x05, 0x0f, 0xd3, 0x87, 0x40, 0x9d, 0x18, 0xbb, 0xf4, 0x22, 0x78, + 0x91, 0x2a, 0x71, 0xa2, 0x72, 0x9b, 0xe2, 0xf8, 0xff, 0xce, 0xf9, 0x7f, 0x9f, 0x83, 0x1b, 0x43, + 0xa9, 0x02, 0xa9, 0x28, 0x9b, 0xc0, 0x78, 0x4e, 0xdf, 0x5a, 0x1e, 0x07, 0xd6, 0xa2, 0x82, 0x87, + 0x5c, 0xf9, 0x8a, 0x44, 0xb1, 0x04, 0x69, 0x56, 0x34, 0x43, 0x52, 0x86, 0x64, 0x4c, 0xb5, 0x26, + 0xa4, 0x14, 0xaf, 0x9c, 0xa6, 0x8c, 0x37, 0x79, 0xa6, 0xe0, 0x07, 0x5c, 0x01, 0x0b, 0x22, 0x5d, + 0x56, 0xbd, 0xde, 0x07, 0x58, 0x38, 0xcb, 0xa4, 0x8a, 0x90, 0x42, 0xa6, 0x47, 0x9a, 0x9c, 0xf2, + 0x02, 0xed, 0xf3, 0xa4, 0x85, 0xcc, 0x54, 0x4b, 0x37, 0x47, 0x63, 0xc2, 0x54, 0xcb, 0x8d, 0x11, + 0xbe, 0xec, 0xe9, 0xc8, 0x0f, 0xc0, 0x80, 0x9b, 0x03, 0x5c, 0x4e, 0x48, 0x19, 0xfb, 0x73, 0x06, + 0xbe, 0x0c, 0x2d, 0x54, 0x2f, 0x38, 0xa5, 0xb6, 0x43, 0x8e, 0xbd, 0x84, 0xf4, 0x62, 0x16, 0x42, + 0x67, 0x9b, 0x77, 0x8b, 0xcb, 0xef, 0x9a, 0xd1, 0xdf, 0x6d, 0xd2, 0xf8, 0x42, 0xd8, 0x3c, 0x64, + 0x4d, 0x0b, 0x9f, 0x89, 0xe4, 0x96, 0xc7, 0x16, 0xaa, 0x23, 0xe7, 0xa2, 0x9f, 0xff, 0xfe, 0x2b, + 0xdc, 0x3a, 0xd9, 0x56, 0xb8, 0x79, 0xbf, 0x1f, 0xb0, 0x50, 0x47, 0x4e, 0xa9, 0x5d, 0x21, 0x7a, + 0x66, 0x24, 0x9f, 0x19, 0xe9, 0x84, 0x33, 0xf7, 0xea, 0xe3, 0xbd, 0x59, 0xde, 0xf1, 0xdc, 0x4b, + 0x66, 0x76, 0x31, 0xe6, 0xd3, 0xc8, 0x8f, 0x75, 0xaf, 0x62, 0xda, 0xab, 0x7a, 0xd0, 0x6b, 0x90, + 0x2f, 0xc8, 0x3d, 0x4f, 0x9e, 0xb7, 0xf8, 0xa9, 0xa1, 0xfe, 0x56, 0x9d, 0xdb, 0x5d, 0xae, 0x6d, + 0xb4, 0x5a, 0xdb, 0xe8, 0x77, 0x6d, 0xa3, 0xc5, 0xc6, 0x36, 0x56, 0x1b, 0xdb, 0xf8, 0xdc, 0xd8, + 0xc6, 0xe3, 0xad, 0xf0, 0x61, 0x3c, 0xf1, 0xc8, 0x50, 0x06, 0xd9, 0x5e, 0xb2, 0x4f, 0x53, 0x8d, + 0x5e, 0xe8, 0x34, 0x5b, 0x0b, 0xcc, 0x22, 0xae, 0xbc, 0xd3, 0xd4, 0xef, 0xee, 0x2f, 0x00, 0x00, + 0xff, 0xff, 0x52, 0x9c, 0x43, 0x7a, 0x5a, 0x02, 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 + if len(m.Authorization) > 0 { + for iNdEx := len(m.Authorization) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Authorization[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *GrantAuthorization) 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 *GrantAuthorization) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GrantAuthorization) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expiration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintGenesis(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x22 + if m.Authorization != nil { + { + size, err := m.Authorization.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Granter))) + 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 + if len(m.Authorization) > 0 { + for _, e := range m.Authorization { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *GrantAuthorization) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if m.Authorization != nil { + l = m.Authorization.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration) + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *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 Authorization", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Authorization = append(m.Authorization, GrantAuthorization{}) + if err := m.Authorization[len(m.Authorization)-1].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 *GrantAuthorization) 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: GrantAuthorization: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GrantAuthorization: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", 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.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", 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.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorization", 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 m.Authorization == nil { + m.Authorization = &types.Any{} + } + if err := m.Authorization.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Expiration, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/authz/types/keys.go b/x/authz/types/keys.go new file mode 100644 index 0000000000..3be659c5ae --- /dev/null +++ b/x/authz/types/keys.go @@ -0,0 +1,41 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName is the module name constant used in many places + ModuleName = "authz" + + // StoreKey is the store key string for authz + StoreKey = ModuleName + + // RouterKey is the message route for authz + RouterKey = ModuleName + + // QuerierRoute is the querier route for authz + QuerierRoute = ModuleName +) + +// Keys for authz store +// Items are stored with the following key: values +// +// - 0x01: Grant + +var ( + // Keys for store prefixes + GrantKey = []byte{0x01} // prefix for each key +) + +// GetAuthorizationStoreKey - return authorization store key +func GetAuthorizationStoreKey(grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) []byte { + return append(append(append(GrantKey, granter.Bytes()...), grantee.Bytes()...), []byte(msgType)...) +} + +// ExtractAddressesFromGrantKey - split granter & grantee address from the authorization key +func ExtractAddressesFromGrantKey(key []byte) (granterAddr, granteeAddr sdk.AccAddress) { + granterAddr = sdk.AccAddress(key[1 : sdk.AddrLen+1]) + granteeAddr = sdk.AccAddress(key[sdk.AddrLen+1 : sdk.AddrLen*2+1]) + return granterAddr, granteeAddr +} diff --git a/x/authz/types/keys_test.go b/x/authz/types/keys_test.go new file mode 100644 index 0000000000..1d6d7cef66 --- /dev/null +++ b/x/authz/types/keys_test.go @@ -0,0 +1,20 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var granter = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) +var grantee = sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) +var msgType = SendAuthorization{}.MethodName() + +func TestGrantkey(t *testing.T) { + granter1, grantee1 := ExtractAddressesFromGrantKey(GetAuthorizationStoreKey(grantee, granter, msgType)) + require.Equal(t, granter, granter1) + require.Equal(t, grantee, grantee1) +} diff --git a/x/authz/types/msgs.go b/x/authz/types/msgs.go new file mode 100644 index 0000000000..59ae59c20a --- /dev/null +++ b/x/authz/types/msgs.go @@ -0,0 +1,215 @@ +package types + +import ( + "time" + + "github.com/gogo/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var ( + _ sdk.MsgRequest = &MsgGrantAuthorizationRequest{} + _ sdk.MsgRequest = &MsgRevokeAuthorizationRequest{} + _ sdk.MsgRequest = &MsgExecAuthorizedRequest{} + + _ types.UnpackInterfacesMessage = &MsgGrantAuthorizationRequest{} + _ types.UnpackInterfacesMessage = &MsgExecAuthorizedRequest{} +) + +// NewMsgGrantAuthorization creates a new MsgGrantAuthorization +//nolint:interfacer +func NewMsgGrantAuthorization(granter sdk.AccAddress, grantee sdk.AccAddress, authorization Authorization, expiration time.Time) (*MsgGrantAuthorizationRequest, error) { + m := &MsgGrantAuthorizationRequest{ + Granter: granter.String(), + Grantee: grantee.String(), + Expiration: expiration, + } + err := m.SetAuthorization(authorization) + if err != nil { + return nil, err + } + return m, nil +} + +// GetSigners implements Msg +func (msg MsgGrantAuthorizationRequest) GetSigners() []sdk.AccAddress { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{granter} +} + +// ValidateBasic implements Msg +func (msg MsgGrantAuthorizationRequest) ValidateBasic() error { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid granter address") + } + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid granter address") + } + + if granter.Equals(grantee) { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "granter and grantee cannot be same") + } + + if msg.Expiration.Unix() < time.Now().Unix() { + return sdkerrors.Wrap(ErrInvalidExpirationTime, "Time can't be in the past") + } + + return nil +} + +// GetGrantAuthorization returns the cache value from the MsgGrantAuthorization.Authorization if present. +func (msg *MsgGrantAuthorizationRequest) GetGrantAuthorization() Authorization { + authorization, ok := msg.Authorization.GetCachedValue().(Authorization) + if !ok { + return nil + } + return authorization +} + +// SetAuthorization converts Authorization to any and adds it to MsgGrantAuthorization.Authorization. +func (msg *MsgGrantAuthorizationRequest) SetAuthorization(authorization Authorization) error { + m, ok := authorization.(proto.Message) + if !ok { + return sdkerrors.Wrapf(sdkerrors.ErrPackAny, "can't proto marshal %T", m) + } + any, err := types.NewAnyWithValue(m) + if err != nil { + return err + } + msg.Authorization = any + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (msg MsgExecAuthorizedRequest) UnpackInterfaces(unpacker types.AnyUnpacker) error { + for _, x := range msg.Msgs { + var msgExecAuthorized sdk.MsgRequest + err := unpacker.UnpackAny(x, &msgExecAuthorized) + if err != nil { + return err + } + } + + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (msg MsgGrantAuthorizationRequest) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var authorization Authorization + return unpacker.UnpackAny(msg.Authorization, &authorization) +} + +// NewMsgRevokeAuthorization creates a new MsgRevokeAuthorization +//nolint:interfacer +func NewMsgRevokeAuthorization(granter sdk.AccAddress, grantee sdk.AccAddress, methodName string) MsgRevokeAuthorizationRequest { + return MsgRevokeAuthorizationRequest{ + Granter: granter.String(), + Grantee: grantee.String(), + MethodName: methodName, + } +} + +// GetSigners implements Msg +func (msg MsgRevokeAuthorizationRequest) GetSigners() []sdk.AccAddress { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{granter} +} + +// ValidateBasic implements MsgRequest.ValidateBasic +func (msg MsgRevokeAuthorizationRequest) ValidateBasic() error { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid granter address") + } + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid grantee address") + } + + if granter.Equals(grantee) { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "granter and grantee cannot be same") + } + + if msg.MethodName == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "missing method name") + } + + return nil +} + +// NewMsgExecAuthorized creates a new MsgExecAuthorized +//nolint:interfacer +func NewMsgExecAuthorized(grantee sdk.AccAddress, msgs []sdk.ServiceMsg) MsgExecAuthorizedRequest { + msgsAny := make([]*types.Any, len(msgs)) + for i, msg := range msgs { + bz, err := proto.Marshal(msg.Request) + if err != nil { + panic(err) + } + + anyMsg := &types.Any{ + TypeUrl: msg.MethodName, + Value: bz, + } + + msgsAny[i] = anyMsg + } + + return MsgExecAuthorizedRequest{ + Grantee: grantee.String(), + Msgs: msgsAny, + } +} + +// GetServiceMsgs returns the cache values from the MsgExecAuthorized.Msgs if present. +func (msg MsgExecAuthorizedRequest) GetServiceMsgs() ([]sdk.ServiceMsg, error) { + msgs := make([]sdk.ServiceMsg, len(msg.Msgs)) + for i, msgAny := range msg.Msgs { + msgReq, ok := msgAny.GetCachedValue().(sdk.MsgRequest) + if !ok { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "messages contains %T which is not a sdk.MsgRequest", msgAny) + } + srvMsg := sdk.ServiceMsg{ + MethodName: msgAny.TypeUrl, + Request: msgReq, + } + + msgs[i] = srvMsg + } + + return msgs, nil +} + +// GetSigners implements Msg +func (msg MsgExecAuthorizedRequest) GetSigners() []sdk.AccAddress { + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + panic(err) + } + return []sdk.AccAddress{grantee} +} + +// ValidateBasic implements Msg +func (msg MsgExecAuthorizedRequest) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "invalid grantee address") + } + + if len(msg.Msgs) == 0 { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "messages cannot be empty") + } + + return nil +} diff --git a/x/authz/types/msgs_test.go b/x/authz/types/msgs_test.go new file mode 100644 index 0000000000..3c6cea8905 --- /dev/null +++ b/x/authz/types/msgs_test.go @@ -0,0 +1,103 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/authz/types" +) + +var ( + coinsPos = sdk.NewCoins(sdk.NewInt64Coin("steak", 100)) + granter = sdk.AccAddress("_______granter______") + grantee = sdk.AccAddress("_______grantee______") +) + +func TestMsgExecAuthorized(t *testing.T) { + tests := []struct { + title string + grantee sdk.AccAddress + msgs []sdk.ServiceMsg + expectPass bool + }{ + {"nil grantee address", nil, []sdk.ServiceMsg{}, false}, + {"zero-messages test: should fail", grantee, []sdk.ServiceMsg{}, false}, + {"valid test: msg type", grantee, []sdk.ServiceMsg{ + { + MethodName: types.SendAuthorization{}.MethodName(), + Request: &banktypes.MsgSend{ + Amount: sdk.NewCoins(sdk.NewInt64Coin("steak", 2)), + FromAddress: granter.String(), + ToAddress: grantee.String(), + }, + }, + }, true}, + } + for i, tc := range tests { + msg := types.NewMsgExecAuthorized(tc.grantee, tc.msgs) + if tc.expectPass { + require.NoError(t, msg.ValidateBasic(), "test: %v", i) + } else { + require.Error(t, msg.ValidateBasic(), "test: %v", i) + } + } +} +func TestMsgRevokeAuthorization(t *testing.T) { + tests := []struct { + title string + granter, grantee sdk.AccAddress + msgType string + expectPass bool + }{ + {"nil Granter address", nil, grantee, "hello", false}, + {"nil Grantee address", granter, nil, "hello", false}, + {"nil Granter and Grantee address", nil, nil, "hello", false}, + {"valid test case", granter, grantee, "hello", true}, + } + for i, tc := range tests { + msg := types.NewMsgRevokeAuthorization(tc.granter, tc.grantee, tc.msgType) + if tc.expectPass { + require.NoError(t, msg.ValidateBasic(), "test: %v", i) + } else { + require.Error(t, msg.ValidateBasic(), "test: %v", i) + } + } +} + +func TestMsgGrantAuthorization(t *testing.T) { + tests := []struct { + title string + granter, grantee sdk.AccAddress + authorization types.Authorization + expiration time.Time + expectErr bool + expectPass bool + }{ + {"nil granter address", nil, grantee, &types.SendAuthorization{SpendLimit: coinsPos}, time.Now(), false, false}, + {"nil grantee address", granter, nil, &types.SendAuthorization{SpendLimit: coinsPos}, time.Now(), false, false}, + {"nil granter and grantee address", nil, nil, &types.SendAuthorization{SpendLimit: coinsPos}, time.Now(), false, false}, + {"nil authorization", granter, grantee, nil, time.Now(), true, false}, + {"valid test case", granter, grantee, &types.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 1, 0), false, true}, + {"past time", granter, grantee, &types.SendAuthorization{SpendLimit: coinsPos}, time.Now().AddDate(0, 0, -1), false, false}, + } + for i, tc := range tests { + msg, err := types.NewMsgGrantAuthorization( + tc.granter, tc.grantee, tc.authorization, tc.expiration, + ) + if !tc.expectErr { + require.NoError(t, err) + } else { + continue + } + if tc.expectPass { + require.NoError(t, msg.ValidateBasic(), "test: %v", i) + } else { + require.Error(t, msg.ValidateBasic(), "test: %v", i) + } + } +} diff --git a/x/authz/types/query.pb.go b/x/authz/types/query.pb.go new file mode 100644 index 0000000000..91accaa109 --- /dev/null +++ b/x/authz/types/query.pb.go @@ -0,0 +1,1278 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/authz/v1beta1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-sdk/codec/types" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "github.com/regen-network/cosmos-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 + +// QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. +type QueryAuthorizationRequest struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + MethodName string `protobuf:"bytes,3,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"` +} + +func (m *QueryAuthorizationRequest) Reset() { *m = QueryAuthorizationRequest{} } +func (m *QueryAuthorizationRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAuthorizationRequest) ProtoMessage() {} +func (*QueryAuthorizationRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_376d714ffdeb1545, []int{0} +} +func (m *QueryAuthorizationRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAuthorizationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAuthorizationRequest.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 *QueryAuthorizationRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAuthorizationRequest.Merge(m, src) +} +func (m *QueryAuthorizationRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAuthorizationRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAuthorizationRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAuthorizationRequest proto.InternalMessageInfo + +func (m *QueryAuthorizationRequest) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *QueryAuthorizationRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *QueryAuthorizationRequest) GetMethodName() string { + if m != nil { + return m.MethodName + } + return "" +} + +// QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. +type QueryAuthorizationResponse struct { + // authorization is a authorization granted for grantee by granter. + Authorization *AuthorizationGrant `protobuf:"bytes,1,opt,name=authorization,proto3" json:"authorization,omitempty"` +} + +func (m *QueryAuthorizationResponse) Reset() { *m = QueryAuthorizationResponse{} } +func (m *QueryAuthorizationResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAuthorizationResponse) ProtoMessage() {} +func (*QueryAuthorizationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_376d714ffdeb1545, []int{1} +} +func (m *QueryAuthorizationResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAuthorizationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAuthorizationResponse.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 *QueryAuthorizationResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAuthorizationResponse.Merge(m, src) +} +func (m *QueryAuthorizationResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAuthorizationResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAuthorizationResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAuthorizationResponse proto.InternalMessageInfo + +func (m *QueryAuthorizationResponse) GetAuthorization() *AuthorizationGrant { + if m != nil { + return m.Authorization + } + return nil +} + +// QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. +type QueryAuthorizationsRequest struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + // pagination defines an pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,3,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryAuthorizationsRequest) Reset() { *m = QueryAuthorizationsRequest{} } +func (m *QueryAuthorizationsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryAuthorizationsRequest) ProtoMessage() {} +func (*QueryAuthorizationsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_376d714ffdeb1545, []int{2} +} +func (m *QueryAuthorizationsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAuthorizationsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAuthorizationsRequest.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 *QueryAuthorizationsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAuthorizationsRequest.Merge(m, src) +} +func (m *QueryAuthorizationsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryAuthorizationsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAuthorizationsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAuthorizationsRequest proto.InternalMessageInfo + +func (m *QueryAuthorizationsRequest) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *QueryAuthorizationsRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *QueryAuthorizationsRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. +type QueryAuthorizationsResponse struct { + // authorizations is a list of grants granted for grantee by granter. + Authorizations []*AuthorizationGrant `protobuf:"bytes,1,rep,name=authorizations,proto3" json:"authorizations,omitempty"` + // pagination defines an pagination for the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryAuthorizationsResponse) Reset() { *m = QueryAuthorizationsResponse{} } +func (m *QueryAuthorizationsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryAuthorizationsResponse) ProtoMessage() {} +func (*QueryAuthorizationsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_376d714ffdeb1545, []int{3} +} +func (m *QueryAuthorizationsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryAuthorizationsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryAuthorizationsResponse.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 *QueryAuthorizationsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryAuthorizationsResponse.Merge(m, src) +} +func (m *QueryAuthorizationsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryAuthorizationsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryAuthorizationsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryAuthorizationsResponse proto.InternalMessageInfo + +func (m *QueryAuthorizationsResponse) GetAuthorizations() []*AuthorizationGrant { + if m != nil { + return m.Authorizations + } + return nil +} + +func (m *QueryAuthorizationsResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +func init() { + proto.RegisterType((*QueryAuthorizationRequest)(nil), "cosmos.authz.v1beta1.QueryAuthorizationRequest") + proto.RegisterType((*QueryAuthorizationResponse)(nil), "cosmos.authz.v1beta1.QueryAuthorizationResponse") + proto.RegisterType((*QueryAuthorizationsRequest)(nil), "cosmos.authz.v1beta1.QueryAuthorizationsRequest") + proto.RegisterType((*QueryAuthorizationsResponse)(nil), "cosmos.authz.v1beta1.QueryAuthorizationsResponse") +} + +func init() { proto.RegisterFile("cosmos/authz/v1beta1/query.proto", fileDescriptor_376d714ffdeb1545) } + +var fileDescriptor_376d714ffdeb1545 = []byte{ + // 489 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0xbf, 0x6f, 0xd4, 0x30, + 0x14, 0xc7, 0xcf, 0x77, 0x02, 0x84, 0x4f, 0xed, 0x60, 0x75, 0x48, 0x03, 0x0a, 0xa7, 0x0c, 0x50, + 0x55, 0x22, 0xe6, 0x8e, 0xbf, 0xa0, 0xa5, 0xa2, 0x82, 0xa1, 0x2a, 0x19, 0x59, 0x2a, 0xa7, 0x7d, + 0x38, 0x11, 0x8d, 0x9d, 0xc6, 0x0e, 0xa2, 0x45, 0x2c, 0xac, 0x2c, 0x48, 0x2c, 0xfc, 0x29, 0x2c, + 0x0c, 0x6c, 0x8c, 0x95, 0x58, 0x18, 0xd1, 0x1d, 0x7f, 0x08, 0x8a, 0xed, 0xb4, 0x09, 0x0a, 0x6a, + 0xab, 0x4e, 0xb1, 0xdf, 0xaf, 0xef, 0xe7, 0x3d, 0x3f, 0x05, 0x4f, 0xf6, 0xa5, 0xca, 0xa5, 0xa2, + 0xac, 0xd2, 0xe9, 0x09, 0x7d, 0x33, 0x4d, 0x40, 0xb3, 0x29, 0x3d, 0xaa, 0xa0, 0x3c, 0x8e, 0x8a, + 0x52, 0x6a, 0x49, 0x56, 0x6c, 0x44, 0x64, 0x22, 0x22, 0x17, 0xe1, 0xaf, 0x70, 0xc9, 0xa5, 0x09, + 0xa0, 0xf5, 0xc9, 0xc6, 0xfa, 0xab, 0x5c, 0x4a, 0x7e, 0x08, 0xd4, 0xdc, 0x92, 0xea, 0x15, 0x65, + 0xc2, 0x95, 0xf1, 0xef, 0x3a, 0x17, 0x2b, 0x32, 0xca, 0x84, 0x90, 0x9a, 0xe9, 0x4c, 0x0a, 0xd5, + 0x24, 0x5a, 0x91, 0x3d, 0x5b, 0xd1, 0x29, 0x5a, 0xd7, 0xba, 0x23, 0x4c, 0x98, 0x02, 0x0b, 0x76, + 0x86, 0x59, 0x30, 0x9e, 0x09, 0x53, 0xc7, 0xc5, 0xf6, 0x77, 0x63, 0xc9, 0x4d, 0x44, 0x58, 0xe0, + 0xd5, 0x17, 0x75, 0x8d, 0x8d, 0x4a, 0xa7, 0xb2, 0xcc, 0x4e, 0x4c, 0x76, 0x0c, 0x47, 0x15, 0x28, + 0x4d, 0x3c, 0x7c, 0x8b, 0x97, 0x4c, 0x68, 0x28, 0x3d, 0x34, 0x41, 0x6b, 0xb7, 0xe3, 0xe6, 0x7a, + 0xee, 0x01, 0x6f, 0xd8, 0xf6, 0x00, 0xb9, 0x87, 0xc7, 0x39, 0xe8, 0x54, 0x1e, 0xec, 0x09, 0x96, + 0x83, 0x37, 0x32, 0x5e, 0x6c, 0x4d, 0x3b, 0x2c, 0x87, 0xf0, 0x10, 0xfb, 0x7d, 0x8a, 0xaa, 0x90, + 0x42, 0x01, 0xd9, 0xc1, 0x4b, 0xac, 0xed, 0x30, 0xc2, 0xe3, 0xd9, 0x5a, 0xd4, 0x37, 0xf5, 0xa8, + 0x53, 0x63, 0xbb, 0x26, 0x88, 0xbb, 0xe9, 0xe1, 0x17, 0xd4, 0x27, 0xa7, 0xae, 0xd3, 0xe1, 0x53, + 0x8c, 0xcf, 0x07, 0x6d, 0x1a, 0x1c, 0xcf, 0xee, 0x37, 0x7c, 0xf5, 0xab, 0x44, 0x76, 0x5d, 0x1a, + 0xc8, 0x5d, 0xc6, 0xc1, 0xe9, 0xc5, 0xad, 0xcc, 0xf0, 0x2b, 0xc2, 0x77, 0x7a, 0xd1, 0xdc, 0x28, + 0x76, 0xf1, 0x72, 0xa7, 0x17, 0xe5, 0xa1, 0xc9, 0xe8, 0x4a, 0xb3, 0xf8, 0x27, 0x9f, 0x6c, 0x77, + 0xc8, 0x87, 0x86, 0xfc, 0xc1, 0x85, 0xe4, 0x16, 0xa7, 0x8d, 0x3e, 0xfb, 0x38, 0xc2, 0x37, 0x0c, + 0x3a, 0xf9, 0x86, 0xf0, 0x52, 0x47, 0x99, 0xd0, 0x7e, 0xbc, 0xff, 0x6e, 0x99, 0xff, 0xe8, 0xf2, + 0x09, 0x16, 0x25, 0x7c, 0xf6, 0xe1, 0xe7, 0x9f, 0xcf, 0xc3, 0x27, 0x64, 0x83, 0xf6, 0xee, 0xb7, + 0x7b, 0x42, 0x45, 0xdf, 0xb9, 0xd3, 0x7b, 0x67, 0x82, 0x33, 0x13, 0x38, 0x13, 0xf9, 0x8e, 0xf0, + 0x72, 0x77, 0xfe, 0xe4, 0xd2, 0x3c, 0xcd, 0x16, 0xf9, 0xd3, 0x2b, 0x64, 0xb8, 0x16, 0x9e, 0x9b, + 0x16, 0xb6, 0xc8, 0xe6, 0xb5, 0x5b, 0x50, 0x9b, 0x5b, 0x3f, 0xe6, 0x01, 0x3a, 0x9d, 0x07, 0xe8, + 0xf7, 0x3c, 0x40, 0x9f, 0x16, 0xc1, 0xe0, 0x74, 0x11, 0x0c, 0x7e, 0x2d, 0x82, 0xc1, 0xcb, 0x75, + 0x9e, 0xe9, 0xb4, 0x4a, 0xa2, 0x7d, 0x99, 0x37, 0x3a, 0xf6, 0xf3, 0x50, 0x1d, 0xbc, 0xa6, 0x6f, + 0x9d, 0xa8, 0x3e, 0x2e, 0x40, 0x25, 0x37, 0xcd, 0x0f, 0xe1, 0xf1, 0xdf, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x92, 0xc3, 0xa0, 0xea, 0x02, 0x05, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the + // provided msg type. + Authorization(ctx context.Context, in *QueryAuthorizationRequest, opts ...grpc.CallOption) (*QueryAuthorizationResponse, error) + // Returns list of `Authorization`, granted to the grantee by the granter. + Authorizations(ctx context.Context, in *QueryAuthorizationsRequest, opts ...grpc.CallOption) (*QueryAuthorizationsResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Authorization(ctx context.Context, in *QueryAuthorizationRequest, opts ...grpc.CallOption) (*QueryAuthorizationResponse, error) { + out := new(QueryAuthorizationResponse) + err := c.cc.Invoke(ctx, "/cosmos.authz.v1beta1.Query/Authorization", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Authorizations(ctx context.Context, in *QueryAuthorizationsRequest, opts ...grpc.CallOption) (*QueryAuthorizationsResponse, error) { + out := new(QueryAuthorizationsResponse) + err := c.cc.Invoke(ctx, "/cosmos.authz.v1beta1.Query/Authorizations", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the + // provided msg type. + Authorization(context.Context, *QueryAuthorizationRequest) (*QueryAuthorizationResponse, error) + // Returns list of `Authorization`, granted to the grantee by the granter. + Authorizations(context.Context, *QueryAuthorizationsRequest) (*QueryAuthorizationsResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Authorization(ctx context.Context, req *QueryAuthorizationRequest) (*QueryAuthorizationResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Authorization not implemented") +} +func (*UnimplementedQueryServer) Authorizations(ctx context.Context, req *QueryAuthorizationsRequest) (*QueryAuthorizationsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Authorizations not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Authorization_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAuthorizationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Authorization(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.authz.v1beta1.Query/Authorization", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Authorization(ctx, req.(*QueryAuthorizationRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Authorizations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAuthorizationsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Authorizations(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.authz.v1beta1.Query/Authorizations", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Authorizations(ctx, req.(*QueryAuthorizationsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cosmos.authz.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Authorization", + Handler: _Query_Authorization_Handler, + }, + { + MethodName: "Authorizations", + Handler: _Query_Authorizations_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cosmos/authz/v1beta1/query.proto", +} + +func (m *QueryAuthorizationRequest) 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 *QueryAuthorizationRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAuthorizationRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MethodName) > 0 { + i -= len(m.MethodName) + copy(dAtA[i:], m.MethodName) + i = encodeVarintQuery(dAtA, i, uint64(len(m.MethodName))) + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAuthorizationResponse) 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 *QueryAuthorizationResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAuthorizationResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Authorization != nil { + { + size, err := m.Authorization.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 (m *QueryAuthorizationsRequest) 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 *QueryAuthorizationsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAuthorizationsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryAuthorizationsResponse) 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 *QueryAuthorizationsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryAuthorizationsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Authorizations) > 0 { + for iNdEx := len(m.Authorizations) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Authorizations[iNdEx].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 *QueryAuthorizationRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.MethodName) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAuthorizationResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Authorization != nil { + l = m.Authorization.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAuthorizationsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryAuthorizationsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Authorizations) > 0 { + for _, e := range m.Authorizations { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.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 *QueryAuthorizationRequest) 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: QueryAuthorizationRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAuthorizationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", 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.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", 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.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MethodName", 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.MethodName = 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 *QueryAuthorizationResponse) 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: QueryAuthorizationResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAuthorizationResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorization", 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.Authorization == nil { + m.Authorization = &AuthorizationGrant{} + } + if err := m.Authorization.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAuthorizationsRequest) 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: QueryAuthorizationsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAuthorizationsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", 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.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", 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.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", 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.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryAuthorizationsResponse) 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: QueryAuthorizationsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryAuthorizationsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorizations", 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 + } + m.Authorizations = append(m.Authorizations, &AuthorizationGrant{}) + if err := m.Authorizations[len(m.Authorizations)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", 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.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.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/authz/types/query.pb.gw.go b/x/authz/types/query.pb.gw.go new file mode 100644 index 0000000000..d1cd24bc0b --- /dev/null +++ b/x/authz/types/query.pb.gw.go @@ -0,0 +1,362 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: cosmos/authz/v1beta1/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/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 ( + filter_Query_Authorization_0 = &utilities.DoubleArray{Encoding: map[string]int{"granter": 0, "grantee": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + +func request_Query_Authorization_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAuthorizationRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Authorization_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Authorization(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Authorization_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAuthorizationRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Authorization_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Authorization(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_Authorizations_0 = &utilities.DoubleArray{Encoding: map[string]int{"granter": 0, "grantee": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}} +) + +func request_Query_Authorizations_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAuthorizationsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Authorizations_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.Authorizations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Authorizations_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAuthorizationsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_Authorizations_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.Authorizations(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 (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Authorization_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Authorization_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Authorization_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Authorizations_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Authorizations_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Authorizations_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_Authorization_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_Authorization_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_Authorization_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Authorizations_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_Authorizations_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_Authorizations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Authorization_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6, 2, 7}, []string{"cosmos", "authz", "v1beta1", "granters", "granter", "grantees", "grantee", "grant"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_Authorizations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6, 2, 7}, []string{"cosmos", "authz", "v1beta1", "granters", "granter", "grantees", "grantee", "grants"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_Authorization_0 = runtime.ForwardResponseMessage + + forward_Query_Authorizations_0 = runtime.ForwardResponseMessage +) diff --git a/x/authz/types/send_authorization.go b/x/authz/types/send_authorization.go new file mode 100644 index 0000000000..2bb2a63a74 --- /dev/null +++ b/x/authz/types/send_authorization.go @@ -0,0 +1,45 @@ +package types + +import ( + "reflect" + + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + bank "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +var ( + _ Authorization = &SendAuthorization{} +) + +// NewSendAuthorization creates a new SendAuthorization object. +func NewSendAuthorization(spendLimit sdk.Coins) *SendAuthorization { + return &SendAuthorization{ + SpendLimit: spendLimit, + } +} + +// MethodName implements Authorization.MethodName. +func (authorization SendAuthorization) MethodName() string { + return "/cosmos.bank.v1beta1.Msg/Send" +} + +// Accept implements Authorization.Accept. +func (authorization SendAuthorization) Accept(msg sdk.ServiceMsg, block tmproto.Header) (allow bool, updated Authorization, delete bool) { + if reflect.TypeOf(msg.Request) == reflect.TypeOf(&bank.MsgSend{}) { + msg, ok := msg.Request.(*bank.MsgSend) + if ok { + limitLeft, isNegative := authorization.SpendLimit.SafeSub(msg.Amount) + if isNegative { + return false, nil, false + } + if limitLeft.IsZero() { + return true, nil, true + } + + return true, &SendAuthorization{SpendLimit: limitLeft}, false + } + } + return false, nil, false +} diff --git a/x/authz/types/tx.pb.go b/x/authz/types/tx.pb.go new file mode 100644 index 0000000000..7705f5d44a --- /dev/null +++ b/x/authz/types/tx.pb.go @@ -0,0 +1,1609 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/authz/v1beta1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/codec/types" + types1 "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "github.com/golang/protobuf/ptypes/timestamp" + _ "github.com/regen-network/cosmos-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" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +// account with the provided expiration time. +type MsgGrantAuthorizationRequest struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + Authorization *types.Any `protobuf:"bytes,3,opt,name=authorization,proto3" json:"authorization,omitempty"` + Expiration time.Time `protobuf:"bytes,4,opt,name=expiration,proto3,stdtime" json:"expiration"` +} + +func (m *MsgGrantAuthorizationRequest) Reset() { *m = MsgGrantAuthorizationRequest{} } +func (m *MsgGrantAuthorizationRequest) String() string { return proto.CompactTextString(m) } +func (*MsgGrantAuthorizationRequest) ProtoMessage() {} +func (*MsgGrantAuthorizationRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{0} +} +func (m *MsgGrantAuthorizationRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgGrantAuthorizationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgGrantAuthorizationRequest.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 *MsgGrantAuthorizationRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgGrantAuthorizationRequest.Merge(m, src) +} +func (m *MsgGrantAuthorizationRequest) XXX_Size() int { + return m.Size() +} +func (m *MsgGrantAuthorizationRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MsgGrantAuthorizationRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgGrantAuthorizationRequest proto.InternalMessageInfo + +func (m *MsgGrantAuthorizationRequest) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *MsgGrantAuthorizationRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *MsgGrantAuthorizationRequest) GetAuthorization() *types.Any { + if m != nil { + return m.Authorization + } + return nil +} + +func (m *MsgGrantAuthorizationRequest) GetExpiration() time.Time { + if m != nil { + return m.Expiration + } + return time.Time{} +} + +// MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. +type MsgExecAuthorizedResponse struct { + Result *types1.Result `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` +} + +func (m *MsgExecAuthorizedResponse) Reset() { *m = MsgExecAuthorizedResponse{} } +func (m *MsgExecAuthorizedResponse) String() string { return proto.CompactTextString(m) } +func (*MsgExecAuthorizedResponse) ProtoMessage() {} +func (*MsgExecAuthorizedResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{1} +} +func (m *MsgExecAuthorizedResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgExecAuthorizedResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgExecAuthorizedResponse.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 *MsgExecAuthorizedResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgExecAuthorizedResponse.Merge(m, src) +} +func (m *MsgExecAuthorizedResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgExecAuthorizedResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgExecAuthorizedResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgExecAuthorizedResponse proto.InternalMessageInfo + +func (m *MsgExecAuthorizedResponse) GetResult() *types1.Result { + if m != nil { + return m.Result + } + return nil +} + +// MsgExecAuthorizedRequest attempts to execute the provided messages using +// authorizations granted to the grantee. Each message should have only +// one signer corresponding to the granter of the authorization. +type MsgExecAuthorizedRequest struct { + Grantee string `protobuf:"bytes,1,opt,name=grantee,proto3" json:"grantee,omitempty"` + Msgs []*types.Any `protobuf:"bytes,2,rep,name=msgs,proto3" json:"msgs,omitempty"` +} + +func (m *MsgExecAuthorizedRequest) Reset() { *m = MsgExecAuthorizedRequest{} } +func (m *MsgExecAuthorizedRequest) String() string { return proto.CompactTextString(m) } +func (*MsgExecAuthorizedRequest) ProtoMessage() {} +func (*MsgExecAuthorizedRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{2} +} +func (m *MsgExecAuthorizedRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgExecAuthorizedRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgExecAuthorizedRequest.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 *MsgExecAuthorizedRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgExecAuthorizedRequest.Merge(m, src) +} +func (m *MsgExecAuthorizedRequest) XXX_Size() int { + return m.Size() +} +func (m *MsgExecAuthorizedRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MsgExecAuthorizedRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgExecAuthorizedRequest proto.InternalMessageInfo + +func (m *MsgExecAuthorizedRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *MsgExecAuthorizedRequest) GetMsgs() []*types.Any { + if m != nil { + return m.Msgs + } + return nil +} + +// MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. +type MsgGrantAuthorizationResponse struct { +} + +func (m *MsgGrantAuthorizationResponse) Reset() { *m = MsgGrantAuthorizationResponse{} } +func (m *MsgGrantAuthorizationResponse) String() string { return proto.CompactTextString(m) } +func (*MsgGrantAuthorizationResponse) ProtoMessage() {} +func (*MsgGrantAuthorizationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{3} +} +func (m *MsgGrantAuthorizationResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgGrantAuthorizationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgGrantAuthorizationResponse.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 *MsgGrantAuthorizationResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgGrantAuthorizationResponse.Merge(m, src) +} +func (m *MsgGrantAuthorizationResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgGrantAuthorizationResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgGrantAuthorizationResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgGrantAuthorizationResponse proto.InternalMessageInfo + +// MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the +// granter's account with that has been granted to the grantee. +type MsgRevokeAuthorizationRequest struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + MethodName string `protobuf:"bytes,3,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"` +} + +func (m *MsgRevokeAuthorizationRequest) Reset() { *m = MsgRevokeAuthorizationRequest{} } +func (m *MsgRevokeAuthorizationRequest) String() string { return proto.CompactTextString(m) } +func (*MsgRevokeAuthorizationRequest) ProtoMessage() {} +func (*MsgRevokeAuthorizationRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{4} +} +func (m *MsgRevokeAuthorizationRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRevokeAuthorizationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRevokeAuthorizationRequest.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 *MsgRevokeAuthorizationRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRevokeAuthorizationRequest.Merge(m, src) +} +func (m *MsgRevokeAuthorizationRequest) XXX_Size() int { + return m.Size() +} +func (m *MsgRevokeAuthorizationRequest) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRevokeAuthorizationRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRevokeAuthorizationRequest proto.InternalMessageInfo + +func (m *MsgRevokeAuthorizationRequest) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *MsgRevokeAuthorizationRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *MsgRevokeAuthorizationRequest) GetMethodName() string { + if m != nil { + return m.MethodName + } + return "" +} + +// MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. +type MsgRevokeAuthorizationResponse struct { +} + +func (m *MsgRevokeAuthorizationResponse) Reset() { *m = MsgRevokeAuthorizationResponse{} } +func (m *MsgRevokeAuthorizationResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRevokeAuthorizationResponse) ProtoMessage() {} +func (*MsgRevokeAuthorizationResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_3ceddab7d8589ad1, []int{5} +} +func (m *MsgRevokeAuthorizationResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRevokeAuthorizationResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRevokeAuthorizationResponse.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 *MsgRevokeAuthorizationResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRevokeAuthorizationResponse.Merge(m, src) +} +func (m *MsgRevokeAuthorizationResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRevokeAuthorizationResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRevokeAuthorizationResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRevokeAuthorizationResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgGrantAuthorizationRequest)(nil), "cosmos.authz.v1beta1.MsgGrantAuthorizationRequest") + proto.RegisterType((*MsgExecAuthorizedResponse)(nil), "cosmos.authz.v1beta1.MsgExecAuthorizedResponse") + proto.RegisterType((*MsgExecAuthorizedRequest)(nil), "cosmos.authz.v1beta1.MsgExecAuthorizedRequest") + proto.RegisterType((*MsgGrantAuthorizationResponse)(nil), "cosmos.authz.v1beta1.MsgGrantAuthorizationResponse") + proto.RegisterType((*MsgRevokeAuthorizationRequest)(nil), "cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest") + proto.RegisterType((*MsgRevokeAuthorizationResponse)(nil), "cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse") +} + +func init() { proto.RegisterFile("cosmos/authz/v1beta1/tx.proto", fileDescriptor_3ceddab7d8589ad1) } + +var fileDescriptor_3ceddab7d8589ad1 = []byte{ + // 521 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0x8d, 0x93, 0xaa, 0xd0, 0x8d, 0x8a, 0xc4, 0x92, 0x83, 0x63, 0x51, 0xdb, 0x32, 0x97, 0x08, + 0xa9, 0x6b, 0x35, 0xe5, 0xc0, 0xb5, 0x51, 0x11, 0xa7, 0x70, 0xb0, 0xe0, 0xc2, 0x81, 0x6a, 0x9d, + 0x0c, 0x1b, 0xab, 0xb5, 0xd7, 0xf5, 0xae, 0xab, 0xa4, 0x12, 0x12, 0x9f, 0xd0, 0x8f, 0xe1, 0x23, + 0x2a, 0x4e, 0x3d, 0x72, 0x02, 0x94, 0x1c, 0xf8, 0x07, 0x4e, 0x28, 0xbb, 0x1b, 0x48, 0xda, 0x18, + 0x11, 0x89, 0x93, 0x3d, 0x33, 0x6f, 0x66, 0x9e, 0xdf, 0x5b, 0x2f, 0xda, 0x1b, 0x70, 0x91, 0x72, + 0x11, 0xd2, 0x52, 0x8e, 0x2e, 0xc3, 0x8b, 0x83, 0x18, 0x24, 0x3d, 0x08, 0xe5, 0x98, 0xe4, 0x05, + 0x97, 0x1c, 0xb7, 0x74, 0x99, 0xa8, 0x32, 0x31, 0x65, 0xa7, 0xad, 0xb3, 0x27, 0x0a, 0x13, 0x1a, + 0x88, 0x0a, 0x9c, 0x16, 0xe3, 0x8c, 0xeb, 0xfc, 0xfc, 0xcd, 0x64, 0x3d, 0xc6, 0x39, 0x3b, 0x83, + 0x50, 0x45, 0x71, 0xf9, 0x3e, 0x94, 0x49, 0x0a, 0x42, 0xd2, 0x34, 0x37, 0x80, 0xf6, 0x6d, 0x00, + 0xcd, 0x26, 0xa6, 0xf4, 0xc4, 0x30, 0x8c, 0xa9, 0x80, 0x90, 0xc6, 0x83, 0xe4, 0x37, 0xcb, 0x79, + 0xa0, 0x41, 0xc1, 0x0f, 0x0b, 0x3d, 0xee, 0x0b, 0xf6, 0xb2, 0xa0, 0x99, 0x3c, 0x2a, 0xe5, 0x88, + 0x17, 0xc9, 0x25, 0x95, 0x09, 0xcf, 0x22, 0x38, 0x2f, 0x41, 0x48, 0x6c, 0xa3, 0x7b, 0x6c, 0x5e, + 0x84, 0xc2, 0xb6, 0x7c, 0xab, 0xb3, 0x13, 0x2d, 0xc2, 0x3f, 0x15, 0xb0, 0xeb, 0xcb, 0x15, 0xc0, + 0x7d, 0xb4, 0x4b, 0x97, 0x67, 0xd9, 0x0d, 0xdf, 0xea, 0x34, 0xbb, 0x2d, 0xa2, 0xc9, 0x92, 0x05, + 0x59, 0x72, 0x94, 0x4d, 0x7a, 0x0f, 0x3f, 0x7f, 0xda, 0xdf, 0x5d, 0x5d, 0xbd, 0xda, 0x8d, 0x8f, + 0x11, 0x82, 0x71, 0x9e, 0x14, 0x7a, 0xd6, 0x96, 0x9a, 0xe5, 0xdc, 0x99, 0xf5, 0x7a, 0xa1, 0x4c, + 0xef, 0xfe, 0xf5, 0x57, 0xaf, 0x76, 0xf5, 0xcd, 0xb3, 0xa2, 0xa5, 0xbe, 0xe0, 0x0d, 0x6a, 0xf7, + 0x05, 0x7b, 0x31, 0x86, 0xc1, 0x62, 0x19, 0x0c, 0x23, 0x10, 0x39, 0xcf, 0x04, 0xe0, 0xe7, 0x68, + 0xbb, 0x00, 0x51, 0x9e, 0x49, 0xf5, 0x91, 0xcd, 0xae, 0x4f, 0x8c, 0x39, 0x73, 0xf1, 0x88, 0xd2, + 0xcb, 0x88, 0x47, 0x22, 0x85, 0x8b, 0x0c, 0x3e, 0x78, 0x87, 0xec, 0x35, 0x63, 0x6f, 0x69, 0x07, + 0xab, 0xda, 0x01, 0xee, 0xa0, 0xad, 0x54, 0x30, 0x61, 0xd7, 0xfd, 0x46, 0x95, 0x30, 0x91, 0x42, + 0x04, 0x1e, 0xda, 0xab, 0xf0, 0x47, 0x53, 0x0f, 0xa4, 0x02, 0x44, 0x70, 0xc1, 0x4f, 0xe1, 0xbf, + 0x39, 0xe8, 0xa1, 0x66, 0x0a, 0x72, 0xc4, 0x87, 0x27, 0x19, 0x4d, 0x41, 0xf9, 0xb7, 0x13, 0x21, + 0x9d, 0x7a, 0x45, 0x53, 0x08, 0x7c, 0xe4, 0x56, 0x6d, 0xd5, 0xbc, 0xba, 0x3f, 0xeb, 0xa8, 0xd1, + 0x17, 0x0c, 0x7f, 0x40, 0xf8, 0x2e, 0x7b, 0xdc, 0x25, 0xeb, 0x7e, 0x10, 0xf2, 0xb7, 0xa3, 0xe8, + 0x1c, 0x6e, 0xd4, 0x63, 0x9c, 0x3d, 0x47, 0x0f, 0x56, 0xcd, 0xc1, 0xa4, 0x72, 0xcc, 0x5a, 0x17, + 0x9d, 0xf0, 0x9f, 0xf1, 0x66, 0xe5, 0x47, 0x0b, 0x3d, 0x5a, 0xa3, 0x0c, 0xae, 0xe6, 0x5f, 0xed, + 0x9e, 0xf3, 0x6c, 0xb3, 0x26, 0x4d, 0xa1, 0x77, 0x7c, 0x3d, 0x75, 0xad, 0x9b, 0xa9, 0x6b, 0x7d, + 0x9f, 0xba, 0xd6, 0xd5, 0xcc, 0xad, 0xdd, 0xcc, 0xdc, 0xda, 0x97, 0x99, 0x5b, 0x7b, 0xfb, 0x94, + 0x25, 0x72, 0x54, 0xc6, 0x64, 0xc0, 0x53, 0x73, 0x01, 0x99, 0xc7, 0xbe, 0x18, 0x9e, 0x86, 0x63, + 0x73, 0x9f, 0xc9, 0x49, 0x0e, 0x22, 0xde, 0x56, 0xe7, 0xf1, 0xf0, 0x57, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x9d, 0x19, 0xe1, 0xec, 0x04, 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 { + // GrantAuthorization grants the provided authorization to the grantee on the granter's + // account with the provided expiration time. + GrantAuthorization(ctx context.Context, in *MsgGrantAuthorizationRequest, opts ...grpc.CallOption) (*MsgGrantAuthorizationResponse, error) + // ExecAuthorized attempts to execute the provided messages using + // authorizations granted to the grantee. Each message should have only + // one signer corresponding to the granter of the authorization. + ExecAuthorized(ctx context.Context, in *MsgExecAuthorizedRequest, opts ...grpc.CallOption) (*MsgExecAuthorizedResponse, error) + // RevokeAuthorization revokes any authorization corresponding to the provided method name on the + // granter's account that has been granted to the grantee. + RevokeAuthorization(ctx context.Context, in *MsgRevokeAuthorizationRequest, opts ...grpc.CallOption) (*MsgRevokeAuthorizationResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) GrantAuthorization(ctx context.Context, in *MsgGrantAuthorizationRequest, opts ...grpc.CallOption) (*MsgGrantAuthorizationResponse, error) { + out := new(MsgGrantAuthorizationResponse) + err := c.cc.Invoke(ctx, "/cosmos.authz.v1beta1.Msg/GrantAuthorization", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) ExecAuthorized(ctx context.Context, in *MsgExecAuthorizedRequest, opts ...grpc.CallOption) (*MsgExecAuthorizedResponse, error) { + out := new(MsgExecAuthorizedResponse) + err := c.cc.Invoke(ctx, "/cosmos.authz.v1beta1.Msg/ExecAuthorized", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) RevokeAuthorization(ctx context.Context, in *MsgRevokeAuthorizationRequest, opts ...grpc.CallOption) (*MsgRevokeAuthorizationResponse, error) { + out := new(MsgRevokeAuthorizationResponse) + err := c.cc.Invoke(ctx, "/cosmos.authz.v1beta1.Msg/RevokeAuthorization", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // GrantAuthorization grants the provided authorization to the grantee on the granter's + // account with the provided expiration time. + GrantAuthorization(context.Context, *MsgGrantAuthorizationRequest) (*MsgGrantAuthorizationResponse, error) + // ExecAuthorized attempts to execute the provided messages using + // authorizations granted to the grantee. Each message should have only + // one signer corresponding to the granter of the authorization. + ExecAuthorized(context.Context, *MsgExecAuthorizedRequest) (*MsgExecAuthorizedResponse, error) + // RevokeAuthorization revokes any authorization corresponding to the provided method name on the + // granter's account that has been granted to the grantee. + RevokeAuthorization(context.Context, *MsgRevokeAuthorizationRequest) (*MsgRevokeAuthorizationResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) GrantAuthorization(ctx context.Context, req *MsgGrantAuthorizationRequest) (*MsgGrantAuthorizationResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GrantAuthorization not implemented") +} +func (*UnimplementedMsgServer) ExecAuthorized(ctx context.Context, req *MsgExecAuthorizedRequest) (*MsgExecAuthorizedResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ExecAuthorized not implemented") +} +func (*UnimplementedMsgServer) RevokeAuthorization(ctx context.Context, req *MsgRevokeAuthorizationRequest) (*MsgRevokeAuthorizationResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RevokeAuthorization not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_GrantAuthorization_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgGrantAuthorizationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).GrantAuthorization(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.authz.v1beta1.Msg/GrantAuthorization", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).GrantAuthorization(ctx, req.(*MsgGrantAuthorizationRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_ExecAuthorized_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgExecAuthorizedRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).ExecAuthorized(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.authz.v1beta1.Msg/ExecAuthorized", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).ExecAuthorized(ctx, req.(*MsgExecAuthorizedRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_RevokeAuthorization_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRevokeAuthorizationRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RevokeAuthorization(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.authz.v1beta1.Msg/RevokeAuthorization", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RevokeAuthorization(ctx, req.(*MsgRevokeAuthorizationRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cosmos.authz.v1beta1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GrantAuthorization", + Handler: _Msg_GrantAuthorization_Handler, + }, + { + MethodName: "ExecAuthorized", + Handler: _Msg_ExecAuthorized_Handler, + }, + { + MethodName: "RevokeAuthorization", + Handler: _Msg_RevokeAuthorization_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cosmos/authz/v1beta1/tx.proto", +} + +func (m *MsgGrantAuthorizationRequest) 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 *MsgGrantAuthorizationRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgGrantAuthorizationRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + n1, err1 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expiration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration):]) + if err1 != nil { + return 0, err1 + } + i -= n1 + i = encodeVarintTx(dAtA, i, uint64(n1)) + i-- + dAtA[i] = 0x22 + if m.Authorization != nil { + { + size, err := m.Authorization.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintTx(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgExecAuthorizedResponse) 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 *MsgExecAuthorizedResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgExecAuthorizedResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Result != nil { + { + size, err := m.Result.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgExecAuthorizedRequest) 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 *MsgExecAuthorizedRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgExecAuthorizedRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Msgs) > 0 { + for iNdEx := len(m.Msgs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Msgs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintTx(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgGrantAuthorizationResponse) 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 *MsgGrantAuthorizationResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgGrantAuthorizationResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgRevokeAuthorizationRequest) 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 *MsgRevokeAuthorizationRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRevokeAuthorizationRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MethodName) > 0 { + i -= len(m.MethodName) + copy(dAtA[i:], m.MethodName) + i = encodeVarintTx(dAtA, i, uint64(len(m.MethodName))) + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintTx(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRevokeAuthorizationResponse) 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 *MsgRevokeAuthorizationResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRevokeAuthorizationResponse) 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 *MsgGrantAuthorizationRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Authorization != nil { + l = m.Authorization.Size() + n += 1 + l + sovTx(uint64(l)) + } + l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Expiration) + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgExecAuthorizedResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Result != nil { + l = m.Result.Size() + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgExecAuthorizedRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Msgs) > 0 { + for _, e := range m.Msgs { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgGrantAuthorizationResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRevokeAuthorizationRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.MethodName) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRevokeAuthorizationResponse) 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 *MsgGrantAuthorizationRequest) 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: MsgGrantAuthorizationRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgGrantAuthorizationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", 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.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", 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.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Authorization", 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 m.Authorization == nil { + m.Authorization = &types.Any{} + } + if err := m.Authorization.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiration", 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 := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Expiration, 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 *MsgExecAuthorizedResponse) 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: MsgExecAuthorizedResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgExecAuthorizedResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", 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 m.Result == nil { + m.Result = &types1.Result{} + } + if err := m.Result.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 *MsgExecAuthorizedRequest) 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: MsgExecAuthorizedRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgExecAuthorizedRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", 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.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Msgs", 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 + } + m.Msgs = append(m.Msgs, &types.Any{}) + if err := m.Msgs[len(m.Msgs)-1].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 *MsgGrantAuthorizationResponse) 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: MsgGrantAuthorizationResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgGrantAuthorizationResponse: 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 (m *MsgRevokeAuthorizationRequest) 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: MsgRevokeAuthorizationRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRevokeAuthorizationRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", 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.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", 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.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MethodName", 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.MethodName = string(dAtA[iNdEx:postIndex]) + 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 *MsgRevokeAuthorizationResponse) 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: MsgRevokeAuthorizationResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRevokeAuthorizationResponse: 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") +) diff --git a/x/bank/client/testutil/cli_helpers.go b/x/bank/client/testutil/cli_helpers.go index 820c668c45..0f1b848cb7 100644 --- a/x/bank/client/testutil/cli_helpers.go +++ b/x/bank/client/testutil/cli_helpers.go @@ -4,10 +4,8 @@ import ( "context" "fmt" - gogogrpc "github.com/gogo/protobuf/grpc" "github.com/spf13/cobra" "github.com/tendermint/tendermint/libs/cli" - grpc "google.golang.org/grpc" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -15,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/testutil" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" bankcli "github.com/cosmos/cosmos-sdk/x/bank/client/cli" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -33,38 +32,6 @@ func QueryBalancesExec(clientCtx client.Context, address fmt.Stringer, extraArgs return clitestutil.ExecTestCLICmd(clientCtx, bankcli.GetBalancesCmd(), args) } -// serviceMsgClientConn is an instance of grpc.ClientConn that is used to test building -// transactions with MsgClient's. It is intended to be replaced by the work in -// https://github.com/cosmos/cosmos-sdk/issues/7541 when that is ready. -type serviceMsgClientConn struct { - msgs []sdk.Msg -} - -func (t *serviceMsgClientConn) Invoke(_ context.Context, method string, args, _ interface{}, _ ...grpc.CallOption) error { - req, ok := args.(sdk.MsgRequest) - if !ok { - return fmt.Errorf("%T should implement %T", args, (*sdk.MsgRequest)(nil)) - } - - err := req.ValidateBasic() - if err != nil { - return err - } - - t.msgs = append(t.msgs, sdk.ServiceMsg{ - MethodName: method, - Request: req, - }) - - return nil -} - -func (t *serviceMsgClientConn) NewStream(context.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { - return nil, fmt.Errorf("not supported") -} - -var _ gogogrpc.ClientConn = &serviceMsgClientConn{} - // newSendTxMsgServiceCmd is just for the purpose of testing ServiceMsg's in an end-to-end case. It is effectively // NewSendTxCmd but using MsgClient. func newSendTxMsgServiceCmd() *cobra.Command { @@ -90,14 +57,14 @@ ignored as it is implied from [from_key_or_address].`, } msg := types.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) - svcMsgClientConn := &serviceMsgClientConn{} + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} bankMsgClient := types.NewMsgClient(svcMsgClientConn) _, err = bankMsgClient.Send(context.Background(), msg) if err != nil { return err } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.msgs...) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) }, } diff --git a/x/bank/simulation/operations.go b/x/bank/simulation/operations.go index 9fcc80f0fe..40be2feeb4 100644 --- a/x/bank/simulation/operations.go +++ b/x/bank/simulation/operations.go @@ -76,7 +76,7 @@ func SimulateMsgSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Operatio return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -217,7 +217,7 @@ func SimulateMsgMultiSend(ak types.AccountKeeper, bk keeper.Keeper) simtypes.Ope return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "invalid transfers"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/distribution/simulation/operations.go b/x/distribution/simulation/operations.go index 09090d1f64..b83e6f8a4e 100644 --- a/x/distribution/simulation/operations.go +++ b/x/distribution/simulation/operations.go @@ -120,7 +120,7 @@ func SimulateMsgSetWithdrawAddress(ak types.AccountKeeper, bk types.BankKeeper, return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -172,7 +172,7 @@ func SimulateMsgWithdrawDelegatorReward(ak types.AccountKeeper, bk types.BankKee return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -227,7 +227,7 @@ func SimulateMsgWithdrawValidatorCommission(ak types.AccountKeeper, bk types.Ban return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -282,6 +282,6 @@ func SimulateMsgFundCommunityPool(ak types.AccountKeeper, bk types.BankKeeper, k return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/gov/simulation/operations.go b/x/gov/simulation/operations.go index 2ea89ca97b..d90ca07d5c 100644 --- a/x/gov/simulation/operations.go +++ b/x/gov/simulation/operations.go @@ -162,7 +162,7 @@ func SimulateMsgSubmitProposal( return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - opMsg := simtypes.NewOperationMsg(msg, true, "") + opMsg := simtypes.NewOperationMsg(msg, true, "", nil) // get the submitted proposal ID proposalID, err := k.GetProposalID(ctx) @@ -248,7 +248,7 @@ func SimulateMsgDeposit(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Ke return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -311,7 +311,7 @@ func operationSimulateMsgVote(ak types.AccountKeeper, bk types.BankKeeper, k kee return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/slashing/simulation/operations.go b/x/slashing/simulation/operations.go index 20acc9e91a..1c49775cc1 100644 --- a/x/slashing/simulation/operations.go +++ b/x/slashing/simulation/operations.go @@ -115,23 +115,23 @@ func SimulateMsgUnjail(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Kee validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { if res != nil && err == nil { if info.Tombstoned { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator should not have been unjailed if validator tombstoned") + return simtypes.NewOperationMsg(msg, true, "", nil), nil, errors.New("validator should not have been unjailed if validator tombstoned") } if ctx.BlockHeader().Time.Before(info.JailedUntil) { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator unjailed while validator still in jail period") + return simtypes.NewOperationMsg(msg, true, "", nil), nil, errors.New("validator unjailed while validator still in jail period") } if validator.TokensFromShares(selfDel.GetShares()).TruncateInt().LT(validator.GetMinSelfDelegation()) { - return simtypes.NewOperationMsg(msg, true, ""), nil, errors.New("validator unjailed even though self-delegation too low") + return simtypes.NewOperationMsg(msg, true, "", nil), nil, errors.New("validator unjailed even though self-delegation too low") } } // msg failed as expected - return simtypes.NewOperationMsg(msg, false, ""), nil, nil + return simtypes.NewOperationMsg(msg, false, "", nil), nil, nil } if err != nil { return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, errors.New(res.Log) } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/staking/simulation/operations.go b/x/staking/simulation/operations.go index 0bcb274ed7..d9621bc732 100644 --- a/x/staking/simulation/operations.go +++ b/x/staking/simulation/operations.go @@ -173,7 +173,7 @@ func SimulateMsgCreateValidator(ak types.AccountKeeper, bk types.BankKeeper, k k return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -244,7 +244,7 @@ func SimulateMsgEditValidator(ak types.AccountKeeper, bk types.BankKeeper, k kee return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -317,7 +317,7 @@ func SimulateMsgDelegate(ak types.AccountKeeper, bk types.BankKeeper, k keeper.K return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -407,7 +407,7 @@ func SimulateMsgUndelegate(ak types.AccountKeeper, bk types.BankKeeper, k keeper return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } @@ -520,6 +520,6 @@ func SimulateMsgBeginRedelegate(ak types.AccountKeeper, bk types.BankKeeper, k k return simtypes.NoOpMsg(types.ModuleName, msg.Type(), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + return simtypes.NewOperationMsg(msg, true, "", nil), nil, nil } } diff --git a/x/staking/types/tx.pb.go b/x/staking/types/tx.pb.go index fad3a8c75e..50e1765ff6 100644 --- a/x/staking/types/tx.pb.go +++ b/x/staking/types/tx.pb.go @@ -6,11 +6,6 @@ package types import ( context "context" fmt "fmt" - io "io" - math "math" - math_bits "math/bits" - time "time" - types "github.com/cosmos/cosmos-sdk/codec/types" github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" types1 "github.com/cosmos/cosmos-sdk/types" @@ -23,6 +18,10 @@ 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" + time "time" ) // Reference imports to suppress errors if they are not otherwise used. From 50b4be91108784197aa6b311257f0256cdd1e67f Mon Sep 17 00:00:00 2001 From: vincent Date: Tue, 26 Jan 2021 17:32:05 +0800 Subject: [PATCH 12/40] Fix query signing infos command (#8427) * fix query signing infos command * add changelog --- CHANGELOG.md | 1 + x/slashing/client/cli/query.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7bf603d78..fd4aa4a138 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (x/slashing) [\#8427](https://github.com/cosmos/cosmos-sdk/pull/8427) Fix query signing infos command * (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account * (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value diff --git a/x/slashing/client/cli/query.go b/x/slashing/client/cli/query.go index b6b71a344c..d55b33201b 100644 --- a/x/slashing/client/cli/query.go +++ b/x/slashing/client/cli/query.go @@ -81,7 +81,7 @@ func GetCmdQuerySigningInfos() *cobra.Command { $ query slashing signing-infos `), - Args: cobra.ExactArgs(1), + Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { From 09b8f7783ab3bf147335cc9c58459186a6cd84a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?colin=20axn=C3=A9r?= <25233464+colin-axner@users.noreply.github.com> Date: Tue, 26 Jan 2021 13:03:21 +0100 Subject: [PATCH 13/40] ibc: MsgTransfer amino JSON, commits from @fedekunze (#8437) --- CHANGELOG.md | 4 ++++ x/auth/client/rest/rest_test.go | 3 +-- x/ibc/applications/transfer/module.go | 4 +++- x/ibc/applications/transfer/types/codec.go | 18 +++++++++++++++++- x/ibc/applications/transfer/types/msgs.go | 5 ++--- x/ibc/applications/transfer/types/msgs_test.go | 10 ++++++++++ 6 files changed, 37 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd4aa4a138..75f7adb0b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### State Machine Breaking + +* (x/ibc) [\#8266](https://github.com/cosmos/cosmos-sdk/issues/8266) Add amino JSON for IBC messages in order to support Ledger text signing. + ### Improvements * (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. diff --git a/x/auth/client/rest/rest_test.go b/x/auth/client/rest/rest_test.go index d485467249..1196e52e4a 100644 --- a/x/auth/client/rest/rest_test.go +++ b/x/auth/client/rest/rest_test.go @@ -186,8 +186,7 @@ func (s *IntegrationTestSuite) TestBroadcastIBCTxRequest() { res, err := rest.PostRequest(fmt.Sprintf("%s/txs", val.APIAddress), "application/json", []byte(req)) s.Require().NoError(err) - // Make sure the error message is correct. - s.Require().Contains(string(res), "this transaction cannot be broadcasted via legacy REST endpoints") + s.Require().NotContains(string(res), "this transaction cannot be broadcasted via legacy REST endpoints", string(res)) } // Helper function to test querying txs. We will use it to query StdTx and service `Msg`s. diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index bf324e2c9b..039597afe5 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -46,7 +46,9 @@ func (AppModuleBasic) Name() string { } // RegisterLegacyAminoCodec implements AppModuleBasic interface -func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} // RegisterInterfaces registers module concrete types into protobuf Any. func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { diff --git a/x/ibc/applications/transfer/types/codec.go b/x/ibc/applications/transfer/types/codec.go index 18b594f8a7..24ad7e5a90 100644 --- a/x/ibc/applications/transfer/types/codec.go +++ b/x/ibc/applications/transfer/types/codec.go @@ -7,6 +7,12 @@ import ( "github.com/cosmos/cosmos-sdk/types/msgservice" ) +// RegisterLegacyAminoCodec registers the necessary x/ibc transfer interfaces and concrete types +// on the provided LegacyAmino codec. These types are used for Amino JSON serialization. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgTransfer{}, "cosmos-sdk/MsgTransfer", nil) +} + // RegisterInterfaces register the ibc transfer module interfaces to protobuf // Any. func RegisterInterfaces(registry codectypes.InterfaceRegistry) { @@ -16,10 +22,20 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { } var ( + amino = codec.NewLegacyAmino() + // ModuleCdc references the global x/ibc-transfer module codec. Note, the codec // should ONLY be used in certain instances of tests and for JSON encoding. // - // The actual codec used for serialization should be provided to x/ibc-transfer and + // The actual codec used for serialization should be provided to x/ibc transfer and // defined at the application level. ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + + // AminoCdc is a amino codec created to support amino json compatible msgs. + AminoCdc = codec.NewAminoCodec(amino) ) + +func init() { + RegisterLegacyAminoCodec(amino) + amino.Seal() +} diff --git a/x/ibc/applications/transfer/types/msgs.go b/x/ibc/applications/transfer/types/msgs.go index 0654826713..cf2293213a 100644 --- a/x/ibc/applications/transfer/types/msgs.go +++ b/x/ibc/applications/transfer/types/msgs.go @@ -70,10 +70,9 @@ func (msg MsgTransfer) ValidateBasic() error { return ValidateIBCDenom(msg.Token.Denom) } -// GetSignBytes implements sdk.Msg. The function will panic since it is used -// for amino transaction verification which IBC does not support. +// GetSignBytes implements sdk.Msg. func (msg MsgTransfer) GetSignBytes() []byte { - panic("IBC messages do not support amino") + return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg)) } // GetSigners implements sdk.Msg diff --git a/x/ibc/applications/transfer/types/msgs_test.go b/x/ibc/applications/transfer/types/msgs_test.go index 89bd39524a..1fc70c543b 100644 --- a/x/ibc/applications/transfer/types/msgs_test.go +++ b/x/ibc/applications/transfer/types/msgs_test.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "testing" "github.com/stretchr/testify/require" @@ -51,6 +52,15 @@ func TestMsgTransferType(t *testing.T) { require.Equal(t, "transfer", msg.Type()) } +func TestMsgTransferGetSignBytes(t *testing.T) { + msg := NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0) + expected := fmt.Sprintf(`{"type":"cosmos-sdk/MsgTransfer","value":{"receiver":"%s","sender":"%s","source_channel":"testchannel","source_port":"testportid","timeout_height":{"revision_height":"10"},"token":{"amount":"100","denom":"atom"}}}`, addr2, addr1) + require.NotPanics(t, func() { + res := msg.GetSignBytes() + require.Equal(t, expected, string(res)) + }) +} + // TestMsgTransferValidation tests ValidateBasic for MsgTransfer func TestMsgTransferValidation(t *testing.T) { testCases := []struct { From ce11c9043e9b483fcdb520ee31e3f3b5a68fbe17 Mon Sep 17 00:00:00 2001 From: Marko Date: Wed, 27 Jan 2021 10:08:18 +0000 Subject: [PATCH 14/40] avoid login when in PR (#8449) --- .github/workflows/docker.yml | 1 + .github/workflows/proto-docker.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 9456ebf302..6116e6d921 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -42,6 +42,7 @@ jobs: uses: docker/setup-buildx-action@v1 - name: Login to DockerHub + if: ${{ github.event_name != 'pull_request' }} uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_USERNAME }} diff --git a/.github/workflows/proto-docker.yml b/.github/workflows/proto-docker.yml index b127de0a58..7a9aecfb25 100644 --- a/.github/workflows/proto-docker.yml +++ b/.github/workflows/proto-docker.yml @@ -31,6 +31,7 @@ jobs: uses: docker/setup-buildx-action@v1 - name: Login to DockerHub + if: ${{ github.event_name != 'pull_request' }} uses: docker/login-action@v1 with: username: ${{ secrets.DOCKERHUBTM_USERNAME }} From fd04f41e234c9bbcef4f4fb4b7204c032d4eaddf Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Wed, 27 Jan 2021 19:19:04 +0900 Subject: [PATCH 15/40] ibc-transfer: fix non-deterministic attribute value (#8442) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- x/ibc/applications/transfer/module.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index 039597afe5..900526f583 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -379,7 +379,7 @@ func (am AppModule) OnAcknowledgementPacket( sdk.NewAttribute(types.AttributeKeyReceiver, data.Receiver), sdk.NewAttribute(types.AttributeKeyDenom, data.Denom), sdk.NewAttribute(types.AttributeKeyAmount, fmt.Sprintf("%d", data.Amount)), - sdk.NewAttribute(types.AttributeKeyAck, fmt.Sprintf("%v", ack)), + sdk.NewAttribute(types.AttributeKeyAck, ack.String()), ), ) From e2f510afcc3478edab4a7d8d786dccbec333dddd Mon Sep 17 00:00:00 2001 From: Riccardo Montagnin Date: Wed, 27 Jan 2021 12:07:45 +0100 Subject: [PATCH 16/40] Compatibility with the ARM architecture (#8396) Co-authored-by: Alessio Treglia Co-authored-by: Jonathan Gimeno --- .github/workflows/test.yml | 20 ++++++++++++++++++++ CHANGELOG.md | 1 + Makefile | 2 +- snapshots/store.go | 6 +++--- store/rootmulti/store.go | 4 ++-- x/ibc/applications/transfer/module.go | 4 ++-- x/ibc/core/02-client/types/client.go | 2 +- 7 files changed, 30 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d8f051e60c..dd09041862 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,6 +31,26 @@ jobs: path: ~/go/bin key: ${{ runner.os }}-go-tparse-binary + build: + runs-on: ubuntu-latest + strategy: + matrix: + go-arch: ["amd64", "arm", "arm64"] + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2.1.3 + with: + go-version: 1.15 + - uses: technote-space/get-diff-action@v4 + id: git_diff + with: + PATTERNS: | + **/**.go + go.mod + go.sum + - name: Build + run: GOARCH=${{ matrix.go-arch }} LEDGER_ENABLED=false make build + test-cosmovisor: runs-on: ubuntu-latest steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 75f7adb0b4..0ea84cb347 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. +* [\#8396](https://github.com/cosmos/cosmos-sdk/pull/8396) Add support for ARM platform ### Bug Fixes diff --git a/Makefile b/Makefile index 0f4cf9e80f..f49f95e734 100644 --- a/Makefile +++ b/Makefile @@ -479,4 +479,4 @@ rosetta-data: docker run --name data_dir_build -t rosetta-ci:latest sh /rosetta/data.sh docker cp data_dir_build:/tmp/data.tar.gz "$(CURDIR)/contrib/rosetta/node/data.tar.gz" docker container rm data_dir_build -.PHONY: rosetta-data \ No newline at end of file +.PHONY: rosetta-data diff --git a/snapshots/store.go b/snapshots/store.go index e0bcbe6bd5..77ff58e22f 100644 --- a/snapshots/store.go +++ b/snapshots/store.go @@ -91,7 +91,7 @@ func (s *Store) Get(height uint64, format uint32) (*types.Snapshot, error) { // Get fetches the latest snapshot from the database, if any. func (s *Store) GetLatest() (*types.Snapshot, error) { - iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(math.MaxUint64, math.MaxUint32)) + iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(uint64(math.MaxUint64), math.MaxUint32)) if err != nil { return nil, sdkerrors.Wrap(err, "failed to find latest snapshot") } @@ -111,7 +111,7 @@ func (s *Store) GetLatest() (*types.Snapshot, error) { // List lists snapshots, in reverse order (newest first). func (s *Store) List() ([]*types.Snapshot, error) { - iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(math.MaxUint64, math.MaxUint32)) + iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(uint64(math.MaxUint64), math.MaxUint32)) if err != nil { return nil, sdkerrors.Wrap(err, "failed to list snapshots") } @@ -181,7 +181,7 @@ func (s *Store) loadChunkFile(height uint64, format uint32, chunk uint32) (io.Re // Prune removes old snapshots. The given number of most recent heights (regardless of format) are retained. func (s *Store) Prune(retain uint32) (uint64, error) { - iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(math.MaxUint64, math.MaxUint32)) + iter, err := s.db.ReverseIterator(encodeKey(0, 0), encodeKey(uint64(math.MaxUint64), math.MaxUint32)) if err != nil { return 0, sdkerrors.Wrap(err, "failed to prune snapshots") } diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 03fa1b561f..0e8cba44ef 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -711,9 +711,9 @@ func (rs *Store) Restore( if height == 0 { return sdkerrors.Wrap(sdkerrors.ErrLogic, "cannot restore snapshot at height 0") } - if height > math.MaxInt64 { + if height > uint64(math.MaxUint64) { return sdkerrors.Wrapf(snapshottypes.ErrInvalidMetadata, - "snapshot height %v cannot exceed %v", height, math.MaxInt64) + "snapshot height %v cannot exceed %v", height, int64(math.MaxInt64)) } // Signal readiness. Must be done before the readers below are set up, since the zlib diff --git a/x/ibc/applications/transfer/module.go b/x/ibc/applications/transfer/module.go index 900526f583..67c736555b 100644 --- a/x/ibc/applications/transfer/module.go +++ b/x/ibc/applications/transfer/module.go @@ -202,8 +202,8 @@ func ValidateTransferChannelParams( if err != nil { return err } - if channelSequence > math.MaxUint32 { - return sdkerrors.Wrapf(types.ErrMaxTransferChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, math.MaxUint32) + if channelSequence > uint64(math.MaxUint32) { + return sdkerrors.Wrapf(types.ErrMaxTransferChannels, "channel sequence %d is greater than max allowed transfer channels %d", channelSequence, uint64(math.MaxUint32)) } if order != channeltypes.UNORDERED { return sdkerrors.Wrapf(channeltypes.ErrInvalidChannelOrdering, "expected %s channel, got %s ", channeltypes.UNORDERED, order) diff --git a/x/ibc/core/02-client/types/client.go b/x/ibc/core/02-client/types/client.go index 1c44d6e2b9..6d51828af0 100644 --- a/x/ibc/core/02-client/types/client.go +++ b/x/ibc/core/02-client/types/client.go @@ -93,7 +93,7 @@ func ValidateClientType(clientType string) error { } smallestPossibleClientID := FormatClientIdentifier(clientType, 0) - largestPossibleClientID := FormatClientIdentifier(clientType, math.MaxUint64) + largestPossibleClientID := FormatClientIdentifier(clientType, uint64(math.MaxUint64)) // IsValidClientID will check client type format and if the sequence is a uint64 if !IsValidClientID(smallestPossibleClientID) { From 580e9681a5eb41773cad73ea03647e7253704fed Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Wed, 27 Jan 2021 22:40:56 -0800 Subject: [PATCH 17/40] types: use proper lowercase syntax for coins in benchmarks (#8435) Instead of COINZ_%d use coinZ%d which is the syntax accepted by types.ParseCoin, to generate coins to use in benchmarking. Fixes #8433 --- types/coin_benchmark_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/coin_benchmark_test.go b/types/coin_benchmark_test.go index fc73afe87a..bfc2bfe99c 100644 --- a/types/coin_benchmark_test.go +++ b/types/coin_benchmark_test.go @@ -6,7 +6,7 @@ import ( ) func coinName(suffix int) string { - return fmt.Sprintf("COINZ_%d", suffix) + return fmt.Sprintf("coinz%d", suffix) } func BenchmarkCoinsAdditionIntersect(b *testing.B) { From 784a9a69a160d805fffd7fa945c281f8cdcf19d3 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Wed, 27 Jan 2021 23:52:08 -0800 Subject: [PATCH 18/40] all: ensure b.ReportAllocs() in all the benchmarks (#8460) With this change, we'll get details on the number of allocations performed by code. Later on when we have continuous benchmarking infrastructure, this change will prove useful to flag regressions. Fixes #8459 Co-authored-by: Alessio Treglia --- crypto/armor_test.go | 2 ++ crypto/keys/internal/benchmarking/bench.go | 1 + crypto/keys/secp256k1/bench_test.go | 3 +++ simapp/sim_bench_test.go | 2 ++ store/cache/benchmark_test.go | 1 + store/cachekv/store_bench_test.go | 1 + store/cachekv/store_test.go | 2 ++ store/iavl/store_test.go | 1 + store/rootmulti/store_test.go | 2 ++ types/address_bench_test.go | 2 ++ types/coin_benchmark_test.go | 2 ++ types/decimal_test.go | 1 + x/auth/keeper/keeper_bench_test.go | 1 + x/bank/bench_test.go | 1 + x/mint/types/minter_test.go | 3 +++ 15 files changed, 25 insertions(+) diff --git a/crypto/armor_test.go b/crypto/armor_test.go index abbc7870aa..70854f6dcb 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -158,6 +158,8 @@ func TestUnarmorInfoBytesErrors(t *testing.T) { } func BenchmarkBcryptGenerateFromPassword(b *testing.B) { + b.ReportAllocs() + passphrase := []byte("passphrase") for securityParam := 9; securityParam < 16; securityParam++ { param := securityParam diff --git a/crypto/keys/internal/benchmarking/bench.go b/crypto/keys/internal/benchmarking/bench.go index a789da91f9..a55936d5c3 100644 --- a/crypto/keys/internal/benchmarking/bench.go +++ b/crypto/keys/internal/benchmarking/bench.go @@ -25,6 +25,7 @@ func (zeroReader) Read(buf []byte) (int, error) { // BenchmarkKeyGeneration benchmarks the given key generation algorithm using // a dummy reader. func BenchmarkKeyGeneration(b *testing.B, generateKey func(reader io.Reader) types.PrivKey) { + b.ReportAllocs() var zero zeroReader for i := 0; i < b.N; i++ { generateKey(zero) diff --git a/crypto/keys/secp256k1/bench_test.go b/crypto/keys/secp256k1/bench_test.go index 423f7a5a52..a9f694de75 100644 --- a/crypto/keys/secp256k1/bench_test.go +++ b/crypto/keys/secp256k1/bench_test.go @@ -9,6 +9,7 @@ import ( ) func BenchmarkKeyGeneration(b *testing.B) { + b.ReportAllocs() benchmarkKeygenWrapper := func(reader io.Reader) types.PrivKey { priv := genPrivKey(reader) return &PrivKey{Key: priv} @@ -17,11 +18,13 @@ func BenchmarkKeyGeneration(b *testing.B) { } func BenchmarkSigning(b *testing.B) { + b.ReportAllocs() priv := GenPrivKey() benchmarking.BenchmarkSigning(b, priv) } func BenchmarkVerification(b *testing.B) { + b.ReportAllocs() priv := GenPrivKey() benchmarking.BenchmarkVerification(b, priv) } diff --git a/simapp/sim_bench_test.go b/simapp/sim_bench_test.go index 7c22dcfe8a..ba5c71c6f3 100644 --- a/simapp/sim_bench_test.go +++ b/simapp/sim_bench_test.go @@ -14,6 +14,7 @@ import ( // Profile with: // /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/simapp -bench ^BenchmarkFullAppSimulation$ -Commit=true -cpuprofile cpu.out func BenchmarkFullAppSimulation(b *testing.B) { + b.ReportAllocs() config, db, dir, logger, _, err := SetupSimulation("goleveldb-app-sim", "Simulation") if err != nil { b.Fatalf("simulation setup failed: %s", err.Error()) @@ -57,6 +58,7 @@ func BenchmarkFullAppSimulation(b *testing.B) { } func BenchmarkInvariants(b *testing.B) { + b.ReportAllocs() config, db, dir, logger, _, err := SetupSimulation("leveldb-app-invariant-bench", "Simulation") if err != nil { b.Fatalf("simulation setup failed: %s", err.Error()) diff --git a/store/cache/benchmark_test.go b/store/cache/benchmark_test.go index cf8206272c..10b5da2bfb 100644 --- a/store/cache/benchmark_test.go +++ b/store/cache/benchmark_test.go @@ -22,6 +22,7 @@ func populate(mgr *CommitKVStoreCacheManager) { } func BenchmarkReset(b *testing.B) { + b.ReportAllocs() mgr := freshMgr() b.ResetTimer() diff --git a/store/cachekv/store_bench_test.go b/store/cachekv/store_bench_test.go index 4902819834..2957fe6a65 100644 --- a/store/cachekv/store_bench_test.go +++ b/store/cachekv/store_bench_test.go @@ -12,6 +12,7 @@ import ( ) func benchmarkCacheKVStoreIterator(numKVs int, b *testing.B) { + b.ReportAllocs() mem := dbadapter.Store{DB: dbm.NewMemDB()} cstore := cachekv.NewStore(mem) keys := make([]string, numKVs) diff --git a/store/cachekv/store_test.go b/store/cachekv/store_test.go index e3b33341b8..0404f33f2a 100644 --- a/store/cachekv/store_test.go +++ b/store/cachekv/store_test.go @@ -516,6 +516,7 @@ func (krc *keyRangeCounter) key() int { func bz(s string) []byte { return []byte(s) } func BenchmarkCacheKVStoreGetNoKeyFound(b *testing.B) { + b.ReportAllocs() st := newCacheKVStore() b.ResetTimer() // assumes b.N < 2**24 @@ -525,6 +526,7 @@ func BenchmarkCacheKVStoreGetNoKeyFound(b *testing.B) { } func BenchmarkCacheKVStoreGetKeyFound(b *testing.B) { + b.ReportAllocs() st := newCacheKVStore() for i := 0; i < b.N; i++ { arr := []byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)} diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index 790830038b..cfda5efacf 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -556,6 +556,7 @@ func TestIAVLStoreQuery(t *testing.T) { } func BenchmarkIAVLIteratorNext(b *testing.B) { + b.ReportAllocs() db := dbm.NewMemDB() treeSize := 1000 tree, err := iavl.NewMutableTree(db, cacheSize) diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index e4654f410d..eafc0d6bb8 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -689,6 +689,7 @@ func BenchmarkMultistoreSnapshotRestore1M(b *testing.B) { } func benchmarkMultistoreSnapshot(b *testing.B, stores uint8, storeKeys uint64) { + b.ReportAllocs() b.StopTimer() source := newMultiStoreWithGeneratedData(dbm.NewMemDB(), stores, storeKeys) version := source.LastCommitID().Version @@ -716,6 +717,7 @@ func benchmarkMultistoreSnapshot(b *testing.B, stores uint8, storeKeys uint64) { } func benchmarkMultistoreSnapshotRestore(b *testing.B, stores uint8, storeKeys uint64) { + b.ReportAllocs() b.StopTimer() source := newMultiStoreWithGeneratedData(dbm.NewMemDB(), stores, storeKeys) version := uint64(source.LastCommitID().Version) diff --git a/types/address_bench_test.go b/types/address_bench_test.go index 59222dacf9..88a7e537a0 100644 --- a/types/address_bench_test.go +++ b/types/address_bench_test.go @@ -12,6 +12,7 @@ import ( ) func BenchmarkBech32ifyPubKey(b *testing.B) { + b.ReportAllocs() pkBz := make([]byte, ed25519.PubKeySize) pk := &ed25519.PubKey{Key: pkBz} rng := rand.New(rand.NewSource(time.Now().Unix())) @@ -29,6 +30,7 @@ func BenchmarkBech32ifyPubKey(b *testing.B) { } func BenchmarkGetPubKeyFromBech32(b *testing.B) { + b.ReportAllocs() pkBz := make([]byte, ed25519.PubKeySize) pk := &ed25519.PubKey{Key: pkBz} rng := rand.New(rand.NewSource(time.Now().Unix())) diff --git a/types/coin_benchmark_test.go b/types/coin_benchmark_test.go index bfc2bfe99c..c6e0401121 100644 --- a/types/coin_benchmark_test.go +++ b/types/coin_benchmark_test.go @@ -10,6 +10,7 @@ func coinName(suffix int) string { } func BenchmarkCoinsAdditionIntersect(b *testing.B) { + b.ReportAllocs() benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) { return func(b *testing.B) { coinsA := Coins(make([]Coin, numCoinsA)) @@ -39,6 +40,7 @@ func BenchmarkCoinsAdditionIntersect(b *testing.B) { } func BenchmarkCoinsAdditionNoIntersect(b *testing.B) { + b.ReportAllocs() benchmarkingFunc := func(numCoinsA int, numCoinsB int) func(b *testing.B) { return func(b *testing.B) { coinsA := Coins(make([]Coin, numCoinsA)) diff --git a/types/decimal_test.go b/types/decimal_test.go index ffd09afc27..8e62275a0e 100644 --- a/types/decimal_test.go +++ b/types/decimal_test.go @@ -487,6 +487,7 @@ func (s *decimalTestSuite) TestOperationOrders() { } func BenchmarkMarshalTo(b *testing.B) { + b.ReportAllocs() bis := []struct { in sdk.Dec want []byte diff --git a/x/auth/keeper/keeper_bench_test.go b/x/auth/keeper/keeper_bench_test.go index a217eddaca..1a18dff845 100644 --- a/x/auth/keeper/keeper_bench_test.go +++ b/x/auth/keeper/keeper_bench_test.go @@ -7,6 +7,7 @@ import ( ) func BenchmarkAccountMapperGetAccountFound(b *testing.B) { + b.ReportAllocs() app, ctx := createTestApp(false) // assumes b.N < 2**24 diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index f1affb9d99..0648b3b627 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -18,6 +18,7 @@ import ( var moduleAccAddr = authtypes.NewModuleAddress(stakingtypes.BondedPoolName) func BenchmarkOneBankSendTxPerBlock(b *testing.B) { + b.ReportAllocs() // Add an account at genesis acc := authtypes.BaseAccount{ Address: addr1.String(), diff --git a/x/mint/types/minter_test.go b/x/mint/types/minter_test.go index 8760a66f44..4abedb51cd 100644 --- a/x/mint/types/minter_test.go +++ b/x/mint/types/minter_test.go @@ -89,6 +89,7 @@ func TestBlockProvision(t *testing.T) { // using sdk.Dec operations: (current implementation) // BenchmarkBlockProvision-4 3000000 429 ns/op func BenchmarkBlockProvision(b *testing.B) { + b.ReportAllocs() minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) params := DefaultParams() @@ -105,6 +106,7 @@ func BenchmarkBlockProvision(b *testing.B) { // Next inflation benchmarking // BenchmarkNextInflation-4 1000000 1828 ns/op func BenchmarkNextInflation(b *testing.B) { + b.ReportAllocs() minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) params := DefaultParams() bondedRatio := sdk.NewDecWithPrec(1, 1) @@ -119,6 +121,7 @@ func BenchmarkNextInflation(b *testing.B) { // Next annual provisions benchmarking // BenchmarkNextAnnualProvisions-4 5000000 251 ns/op func BenchmarkNextAnnualProvisions(b *testing.B) { + b.ReportAllocs() minter := InitialMinter(sdk.NewDecWithPrec(1, 1)) params := DefaultParams() totalSupply := sdk.NewInt(100000000000000) From 034d14048856940877be4edb356ae729308f1ca9 Mon Sep 17 00:00:00 2001 From: Rikard Hjort Date: Thu, 28 Jan 2021 17:59:51 +0100 Subject: [PATCH 19/40] Misc documentation fixes (#8452) * EndBlock: "beginning" => "end" * misc fixes * beginning => end * fix error in run-node tutorial * Use correct keyring backend when interacting * multiply stakes by 1000 * query accounts with the bank submodule, not accounts * specify key backend for transactions Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/building-modules/beginblock-endblock.md | 2 +- docs/building-modules/module-manager.md | 5 +++-- docs/run-node/interact-node.md | 8 ++++---- docs/run-node/run-node.md | 4 ++-- docs/run-node/txs.md | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/building-modules/beginblock-endblock.md b/docs/building-modules/beginblock-endblock.md index 09a48df880..cb8dbba1dd 100644 --- a/docs/building-modules/beginblock-endblock.md +++ b/docs/building-modules/beginblock-endblock.md @@ -24,7 +24,7 @@ The actual implementation of `BeginBlocker` and `EndBlocker` in `./abci.go` are A specificity of the `EndBlocker` is that it can return validator updates to the underlying consensus engine in the form of an [`[]abci.ValidatorUpdates`](https://tendermint.com/docs/app-dev/abci-spec.html#validatorupdate). This is the preferred way to implement custom validator changes. -It is possible for developers to defined the order of execution between the `BeginBlocker`/`EndBlocker` functions of each of their application's modules via the module's manager `SetOrderBeginBlocker`/`SetOrderEndBlocker` methods. For more on the module manager, click [here](./module-manager.md#manager). +It is possible for developers to define the order of execution between the `BeginBlocker`/`EndBlocker` functions of each of their application's modules via the module's manager `SetOrderBeginBlocker`/`SetOrderEndBlocker` methods. For more on the module manager, click [here](./module-manager.md#manager). See an example implementation of `BeginBlocker` from the `distr` module: diff --git a/docs/building-modules/module-manager.md b/docs/building-modules/module-manager.md index cd8cc4b9ec..919ec1425c 100644 --- a/docs/building-modules/module-manager.md +++ b/docs/building-modules/module-manager.md @@ -74,7 +74,8 @@ Let us go through the methods of `AppModule`: - `LegacyQuerierHandler(*codec.LegacyAmino)` (deprecated): Returns a [`querier`](./query-services.md#legacy-queriers) given the query `path`, in order to process the `query`. - `RegisterServices(Configurator)`: Allows a module to register services. - `BeginBlock(sdk.Context, abci.RequestBeginBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the beginning of each block. Implement empty if no logic needs to be triggered at the beginning of each block for this module. -- `EndBlock(sdk.Context, abci.RequestEndBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the beginning of each block. This is also where the module can inform the underlying consensus engine of validator set changes (e.g. the `staking` module). Implement empty if no logic needs to be triggered at the beginning of each block for this module. +- `EndBlock(sdk.Context, abci.RequestEndBlock)`: This method gives module developers the option to implement logic that is automatically triggered at the end of each block. This is also where the module can inform the underlying consensus engine of validator set changes (e.g. the `staking` module). Implement empty if no logic needs to be triggered at the end of each block for this module. + ### Implementing the Application Module Interfaces @@ -132,7 +133,7 @@ The module manager is used throughout the application whenever an action on a co - `SetOrderInitGenesis(moduleNames ...string)`: Sets the order in which the [`InitGenesis`](./genesis.md#initgenesis) function of each module will be called when the application is first started. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). - `SetOrderExportGenesis(moduleNames ...string)`: Sets the order in which the [`ExportGenesis`](./genesis.md#exportgenesis) function of each module will be called in case of an export. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). - `SetOrderBeginBlockers(moduleNames ...string)`: Sets the order in which the `BeginBlock()` function of each module will be called at the beginning of each block. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). -- `SetOrderEndBlockers(moduleNames ...string)`: Sets the order in which the `EndBlock()` function of each module will be called at the beginning of each block. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). +- `SetOrderEndBlockers(moduleNames ...string)`: Sets the order in which the `EndBlock()` function of each module will be called at the end of each block. This function is generally called from the application's main [constructor function](../basics/app-anatomy.md#constructor-function). - `RegisterInvariants(ir sdk.InvariantRegistry)`: Registers the [invariants](./invariants.md) of each module. - `RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter, legacyQuerierCdc *codec.LegacyAmino)`: Registers legacy [`Msg`](./messages-and-queries.md#messages) and [`querier`](./query-services.md#legacy-queriers) routes. - `RegisterServices(cfg Configurator)`: Registers all module services. diff --git a/docs/run-node/interact-node.md b/docs/run-node/interact-node.md index a07981341f..bb208f7d8d 100644 --- a/docs/run-node/interact-node.md +++ b/docs/run-node/interact-node.md @@ -16,7 +16,7 @@ There are multiple ways to interact with a node: using the CLI, using gRPC or us Now that your chain is running, it is time to try sending tokens from the first account you created to a second account. In a new terminal window, start by running the following query command: ```bash -simd query account $MY_VALIDATOR_ADDRESS --chain-id my-test-chain +simd query bank balances $MY_VALIDATOR_ADDRESS --chain-id my-test-chain ``` You should see the current balance of the account you created, equal to the original balance of `stake` you granted it minus the amount you delegated via the `gentx`. Now, create a second account: @@ -31,16 +31,16 @@ RECIPIENT=$(simd keys show recipient -a --keyring-backend test) The command above creates a local key-pair that is not yet registered on the chain. An account is created the first time it receives tokens from another account. Now, run the following command to send tokens to the `recipient` account: ```bash -simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --chain-id my-test-chain +simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000000stake --chain-id my-test-chain --keyring-backend test # Check that the recipient account did receive the tokens. -simd query account $RECIPIENT --chain-id my-test-chain +simd query bank balances $RECIPIENT --chain-id my-test-chain ``` Finally, delegate some of the stake tokens sent to the `recipient` account to the validator: ```bash -simd tx staking delegate $(simd keys show my_validator --bech val -a --keyring-backend test) 500stake --from recipient --chain-id my-test-chain +simd tx staking delegate $(simd keys show my_validator --bech val -a --keyring-backend test) 500stake --from recipient --chain-id my-test-chain --keyring-backend test # Query the total delegations to `validator`. simd query staking delegations-to $(simd keys show my_validator --bech val -a --keyring-backend test) --chain-id my-test-chain diff --git a/docs/run-node/run-node.md b/docs/run-node/run-node.md index aee7d84e13..d7aaf8f582 100644 --- a/docs/run-node/run-node.md +++ b/docs/run-node/run-node.md @@ -44,7 +44,7 @@ Before starting the chain, you need to populate the state with at least one acco Now that you have created a local account, go ahead and grant it some `stake` tokens in your chain's genesis file. Doing so will also make sure your chain is aware of this account's existence: ```bash -simd add-genesis-account $MY_VALIDATOR_ADDRESS 100000000stake +simd add-genesis-account $MY_VALIDATOR_ADDRESS 100000000000stake ``` Recall that `$MY_VALIDATOR_ADDRESS` is a variable that holds the address of the `my_validator` key in the [keyring](./keyring.md#adding-keys-to-the-keyring). Also note that the tokens in the SDK have the `{amount}{denom}` format: `amount` is is a 18-digit-precision decimal number, and `denom` is the unique token identifier with its denomination key (e.g. `atom` or `uatom`). Here, we are granting `stake` tokens, as `stake` is the token identifier used for staking in [`simapp`](https://github.com/cosmos/cosmos-sdk/tree/v0.40.0-rc3/simapp). For your own chain with its own staking denom, that token identifier should be used instead. @@ -53,7 +53,7 @@ Now that your account has some tokens, you need to add a validator to your chain ```bash # Create a gentx. -simd gentx my_validator 100000stake --chain-id my-test-chain --keyring-backend test +simd gentx my_validator 100000000stake --chain-id my-test-chain --keyring-backend test # Add the gentx to the genesis file. simd collect-gentxs diff --git a/docs/run-node/txs.md b/docs/run-node/txs.md index 9fbc642efc..ce977212d2 100644 --- a/docs/run-node/txs.md +++ b/docs/run-node/txs.md @@ -11,7 +11,7 @@ This document describes how to generate an (unsigned) transaction, signing it (w The easiest way to send transactions is using the CLI, as we have seen in the previous page when [interacting with a node](./interact-node.md#using-the-cli). For example, running the following command ```bash -simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --chain-id my-test-chain +simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --chain-id my-test-chain --keyring-backend test ``` will run the following steps: From c252a60ff8781a01c716aba8fa661954d6e6c703 Mon Sep 17 00:00:00 2001 From: Artur Troian Date: Thu, 28 Jan 2021 20:58:44 -0500 Subject: [PATCH 20/40] fix: bind values from env variables to flags (#8337) allows clients access values in env variables Signed-off-by: Artur Troian --- docs/core/cli.md | 18 ++++++++++++++++++ server/util.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/docs/core/cli.md b/docs/core/cli.md index 8e11bf488d..10203e769e 100644 --- a/docs/core/cli.md +++ b/docs/core/cli.md @@ -108,6 +108,24 @@ Flags are added to commands directly (generally in the [module's CLI file](../bu +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/simapp/simd/cmd/root.go#L118 +## Environment variables + +Each flag is bound to it's respecteve named environment variable. Then name of the environment variable consist of two parts - capital case `basename` followed by flag name of the flag. `-` must be substituted with `_`. For example flag `--home` for application with basename `GAIA` is bound to `GAIA_HOME`. It allows to reduce amount of flags typed for routine operations. For example instead of: +```sh +gaia --home=./ --node= --chain-id="testchain-1" --keyring-backend=test tx ... --from= +``` +this will be more convinient: +```sh +# define env variables in .env, .envrc etc +GAIA_HOME= +GAIA_NODE= +GAIA_CHAIN_ID="testchain-1" +GAIA_KEYRING_BACKEND="test" + +# and later just use +gaia tx ... --from= +``` + ## Configurations It is vital that the root command of an application uses `PersistentPreRun()` cobra command property for executing the command, so all child commands have access to the server and client contexts. These contexts are set as their default values initially and maybe modified, scoped to the command, in their respective `PersistentPreRun()` functions. Note that the `client.Context` is typically pre-populated with "default" values that may be useful for all commands to inherit and override if necessary. diff --git a/server/util.go b/server/util.go index e461a12fb8..b431b715db 100644 --- a/server/util.go +++ b/server/util.go @@ -17,6 +17,7 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/spf13/viper" tmcfg "github.com/tendermint/tendermint/config" tmlog "github.com/tendermint/tendermint/libs/log" @@ -63,6 +64,37 @@ func NewContext(v *viper.Viper, config *tmcfg.Config, logger tmlog.Logger) *Cont return &Context{v, config, logger} } +func bindFlags(basename string, cmd *cobra.Command, v *viper.Viper) (err error) { + defer func() { + recover() + }() + + cmd.Flags().VisitAll(func(f *pflag.Flag) { + // Environment variables can't have dashes in them, so bind them to their equivalent + // keys with underscores, e.g. --favorite-color to STING_FAVORITE_COLOR + err = v.BindEnv(f.Name, fmt.Sprintf("%s_%s", basename, strings.ToUpper(strings.ReplaceAll(f.Name, "-", "_")))) + if err != nil { + panic(err) + } + + err = v.BindPFlag(f.Name, f) + if err != nil { + panic(err) + } + + // Apply the viper config value to the flag when the flag is not set and viper has a value + if !f.Changed && v.IsSet(f.Name) { + val := v.Get(f.Name) + err = cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val)) + if err != nil { + panic(err) + } + } + }) + + return +} + // InterceptConfigsPreRunHandler performs a pre-run function for the root daemon // application command. It will create a Viper literal and a default server // Context. The server Tendermint configuration will either be read and parsed @@ -98,6 +130,9 @@ func InterceptConfigsPreRunHandler(cmd *cobra.Command) error { // return value is a tendermint configuration object serverCtx.Config = config + if err = bindFlags(basename, cmd, serverCtx.Viper); err != nil { + return err + } var logWriter io.Writer if strings.ToLower(serverCtx.Viper.GetString(flags.FlagLogFormat)) == tmcfg.LogFormatPlain { From 3b8e0f9387386dc3cb375a662bc4bc0ad211f284 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 29 Jan 2021 18:46:23 +0000 Subject: [PATCH 21/40] store/multistore: revert a height limit increase from #8396 (#8466) See https://github.com/cosmos/cosmos-sdk/pull/8396#discussion_r565654207 Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- store/rootmulti/store.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 0e8cba44ef..1ca43eae9d 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -711,7 +711,7 @@ func (rs *Store) Restore( if height == 0 { return sdkerrors.Wrap(sdkerrors.ErrLogic, "cannot restore snapshot at height 0") } - if height > uint64(math.MaxUint64) { + if height > uint64(math.MaxInt64) { return sdkerrors.Wrapf(snapshottypes.ErrInvalidMetadata, "snapshot height %v cannot exceed %v", height, int64(math.MaxInt64)) } From d97e7907f176777ed8a464006d360bb3e1a223e4 Mon Sep 17 00:00:00 2001 From: atheeshp <59333759+atheeshp@users.noreply.github.com> Date: Sat, 30 Jan 2021 01:24:51 +0530 Subject: [PATCH 22/40] Add fee grant module (#8061) * Add docs * Add BasicFeeAllowance implementation * Add expiration structs and complete basic fee * Add delegation messages, add validation logic * Add keeper and helper structs * Add alias and handler to top level * Add delegation module * Add basic querier * Add types tests * Add types tests * More internal test coverage * Solid internal test coverage * Expose Querier to top level module * Add FeeAccount to auth/types, like StdTx, SignDoc * Fix all tests in x/auth * All tests pass * Appease the Golang Linter * Add fee-account command line flag * Start on DelegatedDeductFeeDecorator * Cleanup the Decorator * Wire up delegation module in simapp * add basic test for decorator (no delegation) * Table tests for deduct fees * Table tests over all conditions of delegated fee decorator * Build full ante handler stack and test it * Start genesis * Implement Genesis * Rename package delegation to subkeys * Clarify antes test cases, handle empty account w/o fees * Allow paying delegated fees with no account * Pull mempool into delegated ante, for control on StdFee * Use custom DelegatedTx, DelegatedFee for subkeys * Revert all changes to x/auth.StdTx * Appease scopelint * Register DelegatedTx with codec * Address PR comments * Remove unnecessary DelegatedMempoolFeeDecorator * Cleaned up errors in querier * Clean up message sign bytes * Minor PR comments * Replace GetAllFees... with Iterator variants * PrepareForExport adjusts grant expiration height * Panic on de/serialization error in keeper * Move custom ante handler chain to tests, update docs * More cleanup * More doc cleanup * Renamed subkeys module to fee_grant * Rename subkeys/delegation to fee grant in all strings * Modify Msg and Keeper methods to use Grant not Delegate * Add PeriodicFeeAllowance * Update aliases * Cover all accept cases for PeriodicFeeAllowance * Et tu scopelint? * Update docs as requested * Remove error return from GetFeeGrant * Code cleanup as requested by PR * Updated all errors to use new sdk/errors package * Use test suite for keeper tests * Clean up alias.go file * Define expected interfaces in exported, rather than importing from account * Remove dependency on auth/ante * Improve godoc, Logger * Cleaned up ExpiresAt * Improve error reporting with UseGrantedFee * Enforce period limit subset of basic limit * Add events * Rename fee_grant to feegrant * Ensure KeeperTestSuite actually runs * Move types/tx to types * Update alias file, include ante * I do need nolint in alias.go * Properly emit events in the handler. Use cosmos-sdk in amino types * Update godoc * Linting... * Update errors * Update pkg doc and fix ante-handler order * Merge PR #5782: Migrate x/feegrant to proto * fix errors * proto changes * proto changes * fix errors * fix errors * genesis state changed to proto * fix keeper tests * fix test * fixed tests * fix tests * updated expected keepers * updated ante tests * lint * deleted alias.go * tx updated to proto tx * remove explicit signmode * tests * Added `cli/query.go` * Added tx.go in cli * updated `module.go` * resolve errors in tx.go * Add fee payer gentx func * updated tx * fixed error * WIP: cli tests * fix query error * fix tests * Unused types and funcs * fix tests * rename helper func to create tx * remove unused * update tx cfg * fix cli tests * added simulations * Add `decoder.go` * fix build fail * added init genesis code * update tx.go * fixed LGTM alert * modified cli * remove gogoproto extensions * change acc address type to string * lint * fix simulations * Add gen simulations * remove legacy querier * remove legacy code * add grpc queries tests * fix simulations * update module.go * lint * register feegrant NewSimulationManager * fix sims * fix sims * add genesis test * add periodic grant * updated cmd * changed times * updated flags * removed days as period clock * added condition for period and exp * add periodic fee cli tests * udpated tests * fix lint * fix tests * fix sims * renaming to `fee_grant` * review changes * fix test * add condition for duplicate grants * fix tests * add `genTxWithFeeGranter` in tests * fix simulation * one of changes & test fixes * fix test * fix lint * changed package name `feegrant` to `fee_grant` * review comments * review changes * review change * review changes * added fee-account in flags * address review changes * read fee granter from cli * updated create account with mnemonic * Address review comments * move `simapp/ante` file to `feegrant/ante` * update keeper logic to create account * update docs * fix tests * update `serviceMsgClientConn` from `msgservice` * review changes * add test case for using more fees than allowed * eliminate panic checks from keeper * fix lint * change store keys string to bytes * fix tests * review changes * review changes * udpate docs * make spend limit optional * fix tests * fix tests * review changes * add norace tag * proto-docs * add docs Co-authored-by: Ethan Frey Co-authored-by: Alexander Bezobchuk Co-authored-by: Aleksandr Bezobchuk Co-authored-by: SaReN Co-authored-by: aleem1413 Co-authored-by: MD Aleem <72057206+aleem1314@users.noreply.github.com> Co-authored-by: Anil Kumar Kammari Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- client/cmd.go | 13 + client/context.go | 8 + client/flags/flags.go | 2 + client/query.go | 5 + client/tx/tx.go | 1 + client/tx_config.go | 1 + docs/core/proto-docs.md | 9266 +++++++++--------- proto/cosmos/feegrant/v1beta1/feegrant.proto | 81 + proto/cosmos/feegrant/v1beta1/genesis.proto | 12 + proto/cosmos/feegrant/v1beta1/query.proto | 52 + proto/cosmos/feegrant/v1beta1/tx.proto | 40 + simapp/app.go | 17 +- simapp/params/weights.go | 4 + x/auth/legacy/legacytx/stdtx_builder.go | 3 + x/feegrant/ante/ante.go | 35 + x/feegrant/ante/fee.go | 82 + x/feegrant/ante/fee_test.go | 287 + x/feegrant/client/cli/cli_test.go | 621 ++ x/feegrant/client/cli/query.go | 129 + x/feegrant/client/cli/tx.go | 211 + x/feegrant/client/rest/grpc_query_test.go | 209 + x/feegrant/doc.go | 29 + x/feegrant/genesis.go | 61 + x/feegrant/genesis_test.go | 56 + x/feegrant/keeper/grpc_query.go | 94 + x/feegrant/keeper/keeper.go | 190 + x/feegrant/keeper/keeper_test.go | 257 + x/feegrant/keeper/msg_server.go | 72 + x/feegrant/module.go | 210 + x/feegrant/simulation/decoder.go | 26 + x/feegrant/simulation/decoder_test.go | 62 + x/feegrant/simulation/genesis.go | 38 + x/feegrant/simulation/genesis_test.go | 39 + x/feegrant/simulation/operations.go | 200 + x/feegrant/simulation/operations_test.go | 173 + x/feegrant/types/basic_fee.go | 61 + x/feegrant/types/basic_fee_test.go | 140 + x/feegrant/types/codec.go | 24 + x/feegrant/types/errors.go | 21 + x/feegrant/types/events.go | 13 + x/feegrant/types/expected_keepers.go | 23 + x/feegrant/types/expiration.go | 138 + x/feegrant/types/expiration_test.go | 161 + x/feegrant/types/feegrant.pb.go | 1701 ++++ x/feegrant/types/fees.go | 32 + x/feegrant/types/genesis.go | 40 + x/feegrant/types/genesis.pb.go | 333 + x/feegrant/types/grant.go | 92 + x/feegrant/types/grant_test.go | 99 + x/feegrant/types/key.go | 35 + x/feegrant/types/msgs.go | 101 + x/feegrant/types/periodic_fee.go | 120 + x/feegrant/types/periodic_fee_test.go | 205 + x/feegrant/types/query.pb.go | 1172 +++ x/feegrant/types/query.pb.gw.go | 322 + x/feegrant/types/tx.pb.go | 1033 ++ x/mint/simulation/decoder.go | 2 +- 57 files changed, 13983 insertions(+), 4471 deletions(-) create mode 100644 proto/cosmos/feegrant/v1beta1/feegrant.proto create mode 100644 proto/cosmos/feegrant/v1beta1/genesis.proto create mode 100644 proto/cosmos/feegrant/v1beta1/query.proto create mode 100644 proto/cosmos/feegrant/v1beta1/tx.proto create mode 100644 x/feegrant/ante/ante.go create mode 100644 x/feegrant/ante/fee.go create mode 100644 x/feegrant/ante/fee_test.go create mode 100644 x/feegrant/client/cli/cli_test.go create mode 100644 x/feegrant/client/cli/query.go create mode 100644 x/feegrant/client/cli/tx.go create mode 100644 x/feegrant/client/rest/grpc_query_test.go create mode 100644 x/feegrant/doc.go create mode 100644 x/feegrant/genesis.go create mode 100644 x/feegrant/genesis_test.go create mode 100644 x/feegrant/keeper/grpc_query.go create mode 100644 x/feegrant/keeper/keeper.go create mode 100644 x/feegrant/keeper/keeper_test.go create mode 100644 x/feegrant/keeper/msg_server.go create mode 100644 x/feegrant/module.go create mode 100644 x/feegrant/simulation/decoder.go create mode 100644 x/feegrant/simulation/decoder_test.go create mode 100644 x/feegrant/simulation/genesis.go create mode 100644 x/feegrant/simulation/genesis_test.go create mode 100644 x/feegrant/simulation/operations.go create mode 100644 x/feegrant/simulation/operations_test.go create mode 100644 x/feegrant/types/basic_fee.go create mode 100644 x/feegrant/types/basic_fee_test.go create mode 100644 x/feegrant/types/codec.go create mode 100644 x/feegrant/types/errors.go create mode 100644 x/feegrant/types/events.go create mode 100644 x/feegrant/types/expected_keepers.go create mode 100644 x/feegrant/types/expiration.go create mode 100644 x/feegrant/types/expiration_test.go create mode 100644 x/feegrant/types/feegrant.pb.go create mode 100644 x/feegrant/types/fees.go create mode 100644 x/feegrant/types/genesis.go create mode 100644 x/feegrant/types/genesis.pb.go create mode 100644 x/feegrant/types/grant.go create mode 100644 x/feegrant/types/grant_test.go create mode 100644 x/feegrant/types/key.go create mode 100644 x/feegrant/types/msgs.go create mode 100644 x/feegrant/types/periodic_fee.go create mode 100644 x/feegrant/types/periodic_fee_test.go create mode 100644 x/feegrant/types/query.pb.go create mode 100644 x/feegrant/types/query.pb.gw.go create mode 100644 x/feegrant/types/tx.pb.go diff --git a/client/cmd.go b/client/cmd.go index eccf59c351..437022695d 100644 --- a/client/cmd.go +++ b/client/cmd.go @@ -221,6 +221,19 @@ func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, err clientCtx = clientCtx.WithSignModeStr(signModeStr) } + if clientCtx.FeeGranter == nil || flagSet.Changed(flags.FlagFeeAccount) { + granter, _ := flagSet.GetString(flags.FlagFeeAccount) + + if granter != "" { + granterAcc, err := sdk.AccAddressFromBech32(granter) + if err != nil { + return clientCtx, err + } + + clientCtx = clientCtx.WithFeeGranterAddress(granterAcc) + } + } + if clientCtx.From == "" || flagSet.Changed(flags.FlagFrom) { from, _ := flagSet.GetString(flags.FlagFrom) fromAddr, fromName, keyType, err := GetFromFields(clientCtx.Keyring, from, clientCtx.GenerateOnly) diff --git a/client/context.go b/client/context.go index 0e3d1181af..f7f555339c 100644 --- a/client/context.go +++ b/client/context.go @@ -44,6 +44,7 @@ type Context struct { TxConfig TxConfig AccountRetriever AccountRetriever NodeURI string + FeeGranter sdk.AccAddress // TODO: Deprecated (remove). LegacyAmino *codec.LegacyAmino @@ -166,6 +167,13 @@ func (ctx Context) WithFromAddress(addr sdk.AccAddress) Context { return ctx } +// WithFeeGranterAddress returns a copy of the context with an updated fee granter account +// address. +func (ctx Context) WithFeeGranterAddress(addr sdk.AccAddress) Context { + ctx.FeeGranter = addr + return ctx +} + // WithBroadcastMode returns a copy of the context with an updated broadcast // mode. func (ctx Context) WithBroadcastMode(mode string) Context { diff --git a/client/flags/flags.go b/client/flags/flags.go index 282a61c4c9..1afb55b467 100644 --- a/client/flags/flags.go +++ b/client/flags/flags.go @@ -70,6 +70,7 @@ const ( FlagCountTotal = "count-total" FlagTimeoutHeight = "timeout-height" FlagKeyAlgorithm = "algo" + FlagFeeAccount = "fee-account" // Tendermint logging flags FlagLogLevel = "log_level" @@ -112,6 +113,7 @@ func AddTxFlagsToCmd(cmd *cobra.Command) { cmd.Flags().String(FlagKeyringBackend, DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)") cmd.Flags().String(FlagSignMode, "", "Choose sign mode (direct|amino-json), this is an advanced feature") cmd.Flags().Uint64(FlagTimeoutHeight, 0, "Set a block timeout height to prevent the tx from being committed past a certain height") + cmd.Flags().String(FlagFeeAccount, "", "Fee account pays fees for the transaction instead of deducting from the signer") // --gas can accept integers and "auto" cmd.Flags().String(FlagGas, "", fmt.Sprintf("gas limit to set per-transaction; set to %q to calculate sufficient gas automatically (default %d)", GasFlagAuto, DefaultGasLimit)) diff --git a/client/query.go b/client/query.go index 18a5c3c2f4..bb65d9bf38 100644 --- a/client/query.go +++ b/client/query.go @@ -57,6 +57,11 @@ func (ctx Context) GetFromAddress() sdk.AccAddress { return ctx.FromAddress } +// GetFeeGranterAddress returns the fee granter address from the context +func (ctx Context) GetFeeGranterAddress() sdk.AccAddress { + return ctx.FeeGranter +} + // GetFromName returns the key name for the current context. func (ctx Context) GetFromName() string { return ctx.FromName diff --git a/client/tx/tx.go b/client/tx/tx.go index 594293732b..62e3e9098e 100644 --- a/client/tx/tx.go +++ b/client/tx/tx.go @@ -117,6 +117,7 @@ func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error { } } + tx.SetFeeGranter(clientCtx.GetFeeGranterAddress()) err = Sign(txf, clientCtx.GetFromName(), tx, true) if err != nil { return err diff --git a/client/tx_config.go b/client/tx_config.go index 6992a7a240..8220e917b2 100644 --- a/client/tx_config.go +++ b/client/tx_config.go @@ -42,5 +42,6 @@ type ( SetFeeAmount(amount sdk.Coins) SetGasLimit(limit uint64) SetTimeoutHeight(height uint64) + SetFeeGranter(feeGranter sdk.AccAddress) } ) diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index ec30ba730b..6b5909a3db 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -4,70 +4,116 @@ ## Table of Contents -- [cosmos/auth/v1beta1/auth.proto](#cosmos/auth/v1beta1/auth.proto) - - [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) - - [ModuleAccount](#cosmos.auth.v1beta1.ModuleAccount) - - [Params](#cosmos.auth.v1beta1.Params) +- [cosmos/tx/v1beta1/tx.proto](#cosmos/tx/v1beta1/tx.proto) + - [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) + - [Fee](#cosmos.tx.v1beta1.Fee) + - [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) + - [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) + - [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) + - [SignDoc](#cosmos.tx.v1beta1.SignDoc) + - [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) + - [Tx](#cosmos.tx.v1beta1.Tx) + - [TxBody](#cosmos.tx.v1beta1.TxBody) + - [TxRaw](#cosmos.tx.v1beta1.TxRaw) -- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) - - [GenesisState](#cosmos.auth.v1beta1.GenesisState) +- [cosmos/tx/v1beta1/service.proto](#cosmos/tx/v1beta1/service.proto) + - [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) + - [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) + - [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) + - [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) + - [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) + - [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) + - [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) + - [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) -- [cosmos/auth/v1beta1/query.proto](#cosmos/auth/v1beta1/query.proto) - - [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) - - [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) - - [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) + - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) - - [Query](#cosmos.auth.v1beta1.Query) + - [Service](#cosmos.tx.v1beta1.Service) -- [cosmos/base/v1beta1/coin.proto](#cosmos/base/v1beta1/coin.proto) - - [Coin](#cosmos.base.v1beta1.Coin) - - [DecCoin](#cosmos.base.v1beta1.DecCoin) - - [DecProto](#cosmos.base.v1beta1.DecProto) - - [IntProto](#cosmos.base.v1beta1.IntProto) +- [cosmos/tx/signing/v1beta1/signing.proto](#cosmos/tx/signing/v1beta1/signing.proto) + - [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) + - [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) + - [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) + - [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) + - [SignatureDescriptors](#cosmos.tx.signing.v1beta1.SignatureDescriptors) -- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) - - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) - - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) - - [SendAuthorization](#cosmos.authz.v1beta1.SendAuthorization) + - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) -- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) - - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) - - [Attribute](#cosmos.base.abci.v1beta1.Attribute) - - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) - - [MsgData](#cosmos.base.abci.v1beta1.MsgData) - - [Result](#cosmos.base.abci.v1beta1.Result) - - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) - - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) - - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) - - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) - - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) +- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) + - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) + - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) -- [cosmos/authz/v1beta1/tx.proto](#cosmos/authz/v1beta1/tx.proto) - - [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) - - [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) - - [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) - - [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) - - [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) - - [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) + - [Msg](#cosmos.crisis.v1beta1.Msg) - - [Msg](#cosmos.authz.v1beta1.Msg) +- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) + - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) -- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) - - [GenesisState](#cosmos.authz.v1beta1.GenesisState) - - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) +- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) + - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) -- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) - - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) - - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) +- [cosmos/crypto/multisig/v1beta1/multisig.proto](#cosmos/crypto/multisig/v1beta1/multisig.proto) + - [CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) + - [MultiSignature](#cosmos.crypto.multisig.v1beta1.MultiSignature) -- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto) - - [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) - - [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) - - [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) - - [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) +- [cosmos/crypto/secp256k1/keys.proto](#cosmos/crypto/secp256k1/keys.proto) + - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) + - [PubKey](#cosmos.crypto.secp256k1.PubKey) - - [Query](#cosmos.authz.v1beta1.Query) +- [cosmos/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) + - [PrivKey](#cosmos.crypto.ed25519.PrivKey) + - [PubKey](#cosmos.crypto.ed25519.PubKey) + +- [cosmos/mint/v1beta1/query.proto](#cosmos/mint/v1beta1/query.proto) + - [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) + - [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) + - [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) + - [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) + - [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) + + - [Query](#cosmos.mint.v1beta1.Query) + +- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) + - [GenesisState](#cosmos.mint.v1beta1.GenesisState) + +- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) + - [Minter](#cosmos.mint.v1beta1.Minter) + - [Params](#cosmos.mint.v1beta1.Params) + +- [cosmos/feegrant/v1beta1/feegrant.proto](#cosmos/feegrant/v1beta1/feegrant.proto) + - [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) + - [Duration](#cosmos.feegrant.v1beta1.Duration) + - [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) + - [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) + - [PeriodicFeeAllowance](#cosmos.feegrant.v1beta1.PeriodicFeeAllowance) + +- [cosmos/feegrant/v1beta1/query.proto](#cosmos/feegrant/v1beta1/query.proto) + - [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) + - [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) + - [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) + - [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) + + - [Query](#cosmos.feegrant.v1beta1.Query) + +- [cosmos/feegrant/v1beta1/tx.proto](#cosmos/feegrant/v1beta1/tx.proto) + - [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) + - [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) + - [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) + - [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) + + - [Msg](#cosmos.feegrant.v1beta1.Msg) + +- [cosmos/feegrant/v1beta1/genesis.proto](#cosmos/feegrant/v1beta1/genesis.proto) + - [GenesisState](#cosmos.feegrant.v1beta1.GenesisState) + +- [cosmos/capability/v1beta1/capability.proto](#cosmos/capability/v1beta1/capability.proto) + - [Capability](#cosmos.capability.v1beta1.Capability) + - [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) + - [Owner](#cosmos.capability.v1beta1.Owner) + +- [cosmos/capability/v1beta1/genesis.proto](#cosmos/capability/v1beta1/genesis.proto) + - [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) + - [GenesisState](#cosmos.capability.v1beta1.GenesisState) - [cosmos/bank/v1beta1/bank.proto](#cosmos/bank/v1beta1/bank.proto) - [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) @@ -78,10 +124,6 @@ - [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) - [Supply](#cosmos.bank.v1beta1.Supply) -- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) - - [Balance](#cosmos.bank.v1beta1.Balance) - - [GenesisState](#cosmos.bank.v1beta1.GenesisState) - - [cosmos/bank/v1beta1/query.proto](#cosmos/bank/v1beta1/query.proto) - [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) - [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) @@ -108,107 +150,85 @@ - [Msg](#cosmos.bank.v1beta1.Msg) -- [cosmos/base/kv/v1beta1/kv.proto](#cosmos/base/kv/v1beta1/kv.proto) - - [Pair](#cosmos.base.kv.v1beta1.Pair) - - [Pairs](#cosmos.base.kv.v1beta1.Pairs) +- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) + - [Balance](#cosmos.bank.v1beta1.Balance) + - [GenesisState](#cosmos.bank.v1beta1.GenesisState) -- [cosmos/base/reflection/v1beta1/reflection.proto](#cosmos/base/reflection/v1beta1/reflection.proto) - - [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) - - [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) - - [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) - - [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) +- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) + - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) + - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) + - [SendAuthorization](#cosmos.authz.v1beta1.SendAuthorization) - - [ReflectionService](#cosmos.base.reflection.v1beta1.ReflectionService) +- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto) + - [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) + - [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) + - [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) + - [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) -- [cosmos/base/snapshots/v1beta1/snapshot.proto](#cosmos/base/snapshots/v1beta1/snapshot.proto) - - [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) - - [Snapshot](#cosmos.base.snapshots.v1beta1.Snapshot) + - [Query](#cosmos.authz.v1beta1.Query) -- [cosmos/base/store/v1beta1/commit_info.proto](#cosmos/base/store/v1beta1/commit_info.proto) - - [CommitID](#cosmos.base.store.v1beta1.CommitID) - - [CommitInfo](#cosmos.base.store.v1beta1.CommitInfo) - - [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) +- [cosmos/authz/v1beta1/tx.proto](#cosmos/authz/v1beta1/tx.proto) + - [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) + - [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) + - [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) + - [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) + - [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) + - [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) -- [cosmos/base/store/v1beta1/snapshot.proto](#cosmos/base/store/v1beta1/snapshot.proto) - - [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) - - [SnapshotItem](#cosmos.base.store.v1beta1.SnapshotItem) - - [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) + - [Msg](#cosmos.authz.v1beta1.Msg) -- [cosmos/base/tendermint/v1beta1/query.proto](#cosmos/base/tendermint/v1beta1/query.proto) - - [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) - - [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) - - [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) - - [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) - - [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) - - [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) - - [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) - - [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) - - [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) - - [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) - - [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) - - [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) - - [Module](#cosmos.base.tendermint.v1beta1.Module) - - [Validator](#cosmos.base.tendermint.v1beta1.Validator) - - [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) +- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) + - [GenesisState](#cosmos.authz.v1beta1.GenesisState) + - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) - - [Service](#cosmos.base.tendermint.v1beta1.Service) +- [cosmos/gov/v1beta1/gov.proto](#cosmos/gov/v1beta1/gov.proto) + - [Deposit](#cosmos.gov.v1beta1.Deposit) + - [DepositParams](#cosmos.gov.v1beta1.DepositParams) + - [Proposal](#cosmos.gov.v1beta1.Proposal) + - [TallyParams](#cosmos.gov.v1beta1.TallyParams) + - [TallyResult](#cosmos.gov.v1beta1.TallyResult) + - [TextProposal](#cosmos.gov.v1beta1.TextProposal) + - [Vote](#cosmos.gov.v1beta1.Vote) + - [VotingParams](#cosmos.gov.v1beta1.VotingParams) -- [cosmos/capability/v1beta1/capability.proto](#cosmos/capability/v1beta1/capability.proto) - - [Capability](#cosmos.capability.v1beta1.Capability) - - [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) - - [Owner](#cosmos.capability.v1beta1.Owner) + - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) + - [VoteOption](#cosmos.gov.v1beta1.VoteOption) -- [cosmos/capability/v1beta1/genesis.proto](#cosmos/capability/v1beta1/genesis.proto) - - [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) - - [GenesisState](#cosmos.capability.v1beta1.GenesisState) +- [cosmos/gov/v1beta1/query.proto](#cosmos/gov/v1beta1/query.proto) + - [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) + - [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) + - [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) + - [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) + - [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) + - [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) + - [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) + - [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) + - [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) + - [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) + - [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) + - [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) + - [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) + - [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) + - [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) -- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) - - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) + - [Query](#cosmos.gov.v1beta1.Query) -- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) - - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) - - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) +- [cosmos/gov/v1beta1/tx.proto](#cosmos/gov/v1beta1/tx.proto) + - [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) + - [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) + - [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) + - [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) + - [MsgVote](#cosmos.gov.v1beta1.MsgVote) + - [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) - - [Msg](#cosmos.crisis.v1beta1.Msg) + - [Msg](#cosmos.gov.v1beta1.Msg) -- [cosmos/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) - - [PrivKey](#cosmos.crypto.ed25519.PrivKey) - - [PubKey](#cosmos.crypto.ed25519.PubKey) +- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) + - [GenesisState](#cosmos.gov.v1beta1.GenesisState) -- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) - - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) - -- [cosmos/crypto/multisig/v1beta1/multisig.proto](#cosmos/crypto/multisig/v1beta1/multisig.proto) - - [CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) - - [MultiSignature](#cosmos.crypto.multisig.v1beta1.MultiSignature) - -- [cosmos/crypto/secp256k1/keys.proto](#cosmos/crypto/secp256k1/keys.proto) - - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) - - [PubKey](#cosmos.crypto.secp256k1.PubKey) - -- [cosmos/distribution/v1beta1/distribution.proto](#cosmos/distribution/v1beta1/distribution.proto) - - [CommunityPoolSpendProposal](#cosmos.distribution.v1beta1.CommunityPoolSpendProposal) - - [CommunityPoolSpendProposalWithDeposit](#cosmos.distribution.v1beta1.CommunityPoolSpendProposalWithDeposit) - - [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) - - [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) - - [FeePool](#cosmos.distribution.v1beta1.FeePool) - - [Params](#cosmos.distribution.v1beta1.Params) - - [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) - - [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) - - [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) - - [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) - - [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) - - [ValidatorSlashEvents](#cosmos.distribution.v1beta1.ValidatorSlashEvents) - -- [cosmos/distribution/v1beta1/genesis.proto](#cosmos/distribution/v1beta1/genesis.proto) - - [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) - - [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) - - [GenesisState](#cosmos.distribution.v1beta1.GenesisState) - - [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) - - [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) - - [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) - - [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) - - [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) +- [cosmos/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) + - [GenesisState](#cosmos.genutil.v1beta1.GenesisState) - [cosmos/distribution/v1beta1/query.proto](#cosmos/distribution/v1beta1/query.proto) - [QueryCommunityPoolRequest](#cosmos.distribution.v1beta1.QueryCommunityPoolRequest) @@ -244,112 +264,116 @@ - [Msg](#cosmos.distribution.v1beta1.Msg) -- [cosmos/evidence/v1beta1/evidence.proto](#cosmos/evidence/v1beta1/evidence.proto) - - [Equivocation](#cosmos.evidence.v1beta1.Equivocation) +- [cosmos/distribution/v1beta1/genesis.proto](#cosmos/distribution/v1beta1/genesis.proto) + - [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) + - [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) + - [GenesisState](#cosmos.distribution.v1beta1.GenesisState) + - [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) + - [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) + - [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) + - [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) + - [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) -- [cosmos/evidence/v1beta1/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) - - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) +- [cosmos/distribution/v1beta1/distribution.proto](#cosmos/distribution/v1beta1/distribution.proto) + - [CommunityPoolSpendProposal](#cosmos.distribution.v1beta1.CommunityPoolSpendProposal) + - [CommunityPoolSpendProposalWithDeposit](#cosmos.distribution.v1beta1.CommunityPoolSpendProposalWithDeposit) + - [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) + - [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) + - [FeePool](#cosmos.distribution.v1beta1.FeePool) + - [Params](#cosmos.distribution.v1beta1.Params) + - [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) + - [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) + - [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) + - [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) + - [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) + - [ValidatorSlashEvents](#cosmos.distribution.v1beta1.ValidatorSlashEvents) -- [cosmos/evidence/v1beta1/query.proto](#cosmos/evidence/v1beta1/query.proto) - - [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) - - [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) - - [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) - - [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) +- [cosmos/upgrade/v1beta1/query.proto](#cosmos/upgrade/v1beta1/query.proto) + - [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) + - [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) + - [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) + - [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) + - [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) + - [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) - - [Query](#cosmos.evidence.v1beta1.Query) + - [Query](#cosmos.upgrade.v1beta1.Query) -- [cosmos/evidence/v1beta1/tx.proto](#cosmos/evidence/v1beta1/tx.proto) - - [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) - - [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) +- [cosmos/upgrade/v1beta1/upgrade.proto](#cosmos/upgrade/v1beta1/upgrade.proto) + - [CancelSoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal) + - [Plan](#cosmos.upgrade.v1beta1.Plan) + - [SoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.SoftwareUpgradeProposal) - - [Msg](#cosmos.evidence.v1beta1.Msg) +- [cosmos/base/kv/v1beta1/kv.proto](#cosmos/base/kv/v1beta1/kv.proto) + - [Pair](#cosmos.base.kv.v1beta1.Pair) + - [Pairs](#cosmos.base.kv.v1beta1.Pairs) -- [cosmos/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) - - [GenesisState](#cosmos.genutil.v1beta1.GenesisState) +- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) + - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) + - [Attribute](#cosmos.base.abci.v1beta1.Attribute) + - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) + - [MsgData](#cosmos.base.abci.v1beta1.MsgData) + - [Result](#cosmos.base.abci.v1beta1.Result) + - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) + - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) + - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) + - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) + - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) -- [cosmos/gov/v1beta1/gov.proto](#cosmos/gov/v1beta1/gov.proto) - - [Deposit](#cosmos.gov.v1beta1.Deposit) - - [DepositParams](#cosmos.gov.v1beta1.DepositParams) - - [Proposal](#cosmos.gov.v1beta1.Proposal) - - [TallyParams](#cosmos.gov.v1beta1.TallyParams) - - [TallyResult](#cosmos.gov.v1beta1.TallyResult) - - [TextProposal](#cosmos.gov.v1beta1.TextProposal) - - [Vote](#cosmos.gov.v1beta1.Vote) - - [VotingParams](#cosmos.gov.v1beta1.VotingParams) +- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) + - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) + - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) - - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) - - [VoteOption](#cosmos.gov.v1beta1.VoteOption) +- [cosmos/base/store/v1beta1/snapshot.proto](#cosmos/base/store/v1beta1/snapshot.proto) + - [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) + - [SnapshotItem](#cosmos.base.store.v1beta1.SnapshotItem) + - [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) -- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) - - [GenesisState](#cosmos.gov.v1beta1.GenesisState) +- [cosmos/base/store/v1beta1/commit_info.proto](#cosmos/base/store/v1beta1/commit_info.proto) + - [CommitID](#cosmos.base.store.v1beta1.CommitID) + - [CommitInfo](#cosmos.base.store.v1beta1.CommitInfo) + - [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) -- [cosmos/gov/v1beta1/query.proto](#cosmos/gov/v1beta1/query.proto) - - [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) - - [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) - - [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) - - [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) - - [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) - - [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) - - [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) - - [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) - - [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) - - [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) - - [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) - - [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) - - [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) - - [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) - - [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) +- [cosmos/base/v1beta1/coin.proto](#cosmos/base/v1beta1/coin.proto) + - [Coin](#cosmos.base.v1beta1.Coin) + - [DecCoin](#cosmos.base.v1beta1.DecCoin) + - [DecProto](#cosmos.base.v1beta1.DecProto) + - [IntProto](#cosmos.base.v1beta1.IntProto) - - [Query](#cosmos.gov.v1beta1.Query) +- [cosmos/base/tendermint/v1beta1/query.proto](#cosmos/base/tendermint/v1beta1/query.proto) + - [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) + - [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) + - [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) + - [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) + - [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) + - [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) + - [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) + - [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) + - [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) + - [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) + - [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) + - [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) + - [Module](#cosmos.base.tendermint.v1beta1.Module) + - [Validator](#cosmos.base.tendermint.v1beta1.Validator) + - [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) -- [cosmos/gov/v1beta1/tx.proto](#cosmos/gov/v1beta1/tx.proto) - - [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) - - [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) - - [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) - - [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) - - [MsgVote](#cosmos.gov.v1beta1.MsgVote) - - [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) + - [Service](#cosmos.base.tendermint.v1beta1.Service) - - [Msg](#cosmos.gov.v1beta1.Msg) +- [cosmos/base/snapshots/v1beta1/snapshot.proto](#cosmos/base/snapshots/v1beta1/snapshot.proto) + - [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) + - [Snapshot](#cosmos.base.snapshots.v1beta1.Snapshot) -- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) - - [Minter](#cosmos.mint.v1beta1.Minter) - - [Params](#cosmos.mint.v1beta1.Params) +- [cosmos/base/reflection/v1beta1/reflection.proto](#cosmos/base/reflection/v1beta1/reflection.proto) + - [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) + - [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) + - [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) + - [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) -- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) - - [GenesisState](#cosmos.mint.v1beta1.GenesisState) - -- [cosmos/mint/v1beta1/query.proto](#cosmos/mint/v1beta1/query.proto) - - [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) - - [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) - - [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) - - [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) - - [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) - - - [Query](#cosmos.mint.v1beta1.Query) - -- [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) - - [ParamChange](#cosmos.params.v1beta1.ParamChange) - - [ParameterChangeProposal](#cosmos.params.v1beta1.ParameterChangeProposal) - -- [cosmos/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto) - - [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) - - - [Query](#cosmos.params.v1beta1.Query) + - [ReflectionService](#cosmos.base.reflection.v1beta1.ReflectionService) - [cosmos/slashing/v1beta1/slashing.proto](#cosmos/slashing/v1beta1/slashing.proto) - [Params](#cosmos.slashing.v1beta1.Params) - [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) -- [cosmos/slashing/v1beta1/genesis.proto](#cosmos/slashing/v1beta1/genesis.proto) - - [GenesisState](#cosmos.slashing.v1beta1.GenesisState) - - [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) - - [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) - - [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) - - [cosmos/slashing/v1beta1/query.proto](#cosmos/slashing/v1beta1/query.proto) - [QueryParamsRequest](#cosmos.slashing.v1beta1.QueryParamsRequest) - [QueryParamsResponse](#cosmos.slashing.v1beta1.QueryParamsResponse) @@ -366,33 +390,47 @@ - [Msg](#cosmos.slashing.v1beta1.Msg) -- [cosmos/staking/v1beta1/staking.proto](#cosmos/staking/v1beta1/staking.proto) - - [Commission](#cosmos.staking.v1beta1.Commission) - - [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) - - [DVPair](#cosmos.staking.v1beta1.DVPair) - - [DVPairs](#cosmos.staking.v1beta1.DVPairs) - - [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) - - [DVVTriplets](#cosmos.staking.v1beta1.DVVTriplets) - - [Delegation](#cosmos.staking.v1beta1.Delegation) - - [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) - - [Description](#cosmos.staking.v1beta1.Description) - - [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) - - [Params](#cosmos.staking.v1beta1.Params) - - [Pool](#cosmos.staking.v1beta1.Pool) - - [Redelegation](#cosmos.staking.v1beta1.Redelegation) - - [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) - - [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) - - [RedelegationResponse](#cosmos.staking.v1beta1.RedelegationResponse) - - [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) - - [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) - - [ValAddresses](#cosmos.staking.v1beta1.ValAddresses) - - [Validator](#cosmos.staking.v1beta1.Validator) +- [cosmos/slashing/v1beta1/genesis.proto](#cosmos/slashing/v1beta1/genesis.proto) + - [GenesisState](#cosmos.slashing.v1beta1.GenesisState) + - [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) + - [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) + - [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) - - [BondStatus](#cosmos.staking.v1beta1.BondStatus) +- [cosmos/evidence/v1beta1/evidence.proto](#cosmos/evidence/v1beta1/evidence.proto) + - [Equivocation](#cosmos.evidence.v1beta1.Equivocation) -- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) - - [GenesisState](#cosmos.staking.v1beta1.GenesisState) - - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) +- [cosmos/evidence/v1beta1/query.proto](#cosmos/evidence/v1beta1/query.proto) + - [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) + - [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) + - [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) + - [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) + + - [Query](#cosmos.evidence.v1beta1.Query) + +- [cosmos/evidence/v1beta1/tx.proto](#cosmos/evidence/v1beta1/tx.proto) + - [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) + - [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) + + - [Msg](#cosmos.evidence.v1beta1.Msg) + +- [cosmos/evidence/v1beta1/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) + - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) + +- [cosmos/auth/v1beta1/auth.proto](#cosmos/auth/v1beta1/auth.proto) + - [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) + - [ModuleAccount](#cosmos.auth.v1beta1.ModuleAccount) + - [Params](#cosmos.auth.v1beta1.Params) + +- [cosmos/auth/v1beta1/query.proto](#cosmos/auth/v1beta1/query.proto) + - [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) + - [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) + - [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) + + - [Query](#cosmos.auth.v1beta1.Query) + +- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) + - [GenesisState](#cosmos.auth.v1beta1.GenesisState) - [cosmos/staking/v1beta1/query.proto](#cosmos/staking/v1beta1/query.proto) - [QueryDelegationRequest](#cosmos.staking.v1beta1.QueryDelegationRequest) @@ -440,55 +478,33 @@ - [Msg](#cosmos.staking.v1beta1.Msg) -- [cosmos/tx/signing/v1beta1/signing.proto](#cosmos/tx/signing/v1beta1/signing.proto) - - [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) - - [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) - - [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) - - [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) - - [SignatureDescriptors](#cosmos.tx.signing.v1beta1.SignatureDescriptors) +- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) + - [GenesisState](#cosmos.staking.v1beta1.GenesisState) + - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) - - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) +- [cosmos/staking/v1beta1/staking.proto](#cosmos/staking/v1beta1/staking.proto) + - [Commission](#cosmos.staking.v1beta1.Commission) + - [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) + - [DVPair](#cosmos.staking.v1beta1.DVPair) + - [DVPairs](#cosmos.staking.v1beta1.DVPairs) + - [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) + - [DVVTriplets](#cosmos.staking.v1beta1.DVVTriplets) + - [Delegation](#cosmos.staking.v1beta1.Delegation) + - [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) + - [Description](#cosmos.staking.v1beta1.Description) + - [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) + - [Params](#cosmos.staking.v1beta1.Params) + - [Pool](#cosmos.staking.v1beta1.Pool) + - [Redelegation](#cosmos.staking.v1beta1.Redelegation) + - [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) + - [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) + - [RedelegationResponse](#cosmos.staking.v1beta1.RedelegationResponse) + - [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) + - [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) + - [ValAddresses](#cosmos.staking.v1beta1.ValAddresses) + - [Validator](#cosmos.staking.v1beta1.Validator) -- [cosmos/tx/v1beta1/tx.proto](#cosmos/tx/v1beta1/tx.proto) - - [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) - - [Fee](#cosmos.tx.v1beta1.Fee) - - [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) - - [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) - - [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) - - [SignDoc](#cosmos.tx.v1beta1.SignDoc) - - [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) - - [Tx](#cosmos.tx.v1beta1.Tx) - - [TxBody](#cosmos.tx.v1beta1.TxBody) - - [TxRaw](#cosmos.tx.v1beta1.TxRaw) - -- [cosmos/tx/v1beta1/service.proto](#cosmos/tx/v1beta1/service.proto) - - [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) - - [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) - - [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) - - [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) - - [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) - - [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) - - [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) - - [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) - - - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) - - - [Service](#cosmos.tx.v1beta1.Service) - -- [cosmos/upgrade/v1beta1/upgrade.proto](#cosmos/upgrade/v1beta1/upgrade.proto) - - [CancelSoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal) - - [Plan](#cosmos.upgrade.v1beta1.Plan) - - [SoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.SoftwareUpgradeProposal) - -- [cosmos/upgrade/v1beta1/query.proto](#cosmos/upgrade/v1beta1/query.proto) - - [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) - - [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) - - [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) - - [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) - - [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) - - [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) - - - [Query](#cosmos.upgrade.v1beta1.Query) + - [BondStatus](#cosmos.staking.v1beta1.BondStatus) - [cosmos/vesting/v1beta1/tx.proto](#cosmos/vesting/v1beta1/tx.proto) - [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) @@ -503,13 +519,15 @@ - [Period](#cosmos.vesting.v1beta1.Period) - [PeriodicVestingAccount](#cosmos.vesting.v1beta1.PeriodicVestingAccount) -- [ibc/applications/transfer/v1/transfer.proto](#ibc/applications/transfer/v1/transfer.proto) - - [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) - - [FungibleTokenPacketData](#ibc.applications.transfer.v1.FungibleTokenPacketData) - - [Params](#ibc.applications.transfer.v1.Params) +- [cosmos/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto) + - [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) -- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) - - [GenesisState](#ibc.applications.transfer.v1.GenesisState) + - [Query](#cosmos.params.v1beta1.Query) + +- [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) + - [ParamChange](#cosmos.params.v1beta1.ParamChange) + - [ParameterChangeProposal](#cosmos.params.v1beta1.ParameterChangeProposal) - [ibc/applications/transfer/v1/query.proto](#ibc/applications/transfer/v1/query.proto) - [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) @@ -521,6 +539,20 @@ - [Query](#ibc.applications.transfer.v1.Query) +- [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) + - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) + - [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) + + - [Msg](#ibc.applications.transfer.v1.Msg) + +- [ibc/applications/transfer/v1/transfer.proto](#ibc/applications/transfer/v1/transfer.proto) + - [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) + - [FungibleTokenPacketData](#ibc.applications.transfer.v1.FungibleTokenPacketData) + - [Params](#ibc.applications.transfer.v1.Params) + +- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) + - [GenesisState](#ibc.applications.transfer.v1.GenesisState) + - [ibc/core/client/v1/client.proto](#ibc/core/client/v1/client.proto) - [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) - [ClientUpdateProposal](#ibc.core.client.v1.ClientUpdateProposal) @@ -529,11 +561,36 @@ - [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) - [Params](#ibc.core.client.v1.Params) -- [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) - - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) - - [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) +- [ibc/core/client/v1/query.proto](#ibc/core/client/v1/query.proto) + - [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) + - [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) + - [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) + - [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) + - [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) + - [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) + - [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) + - [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) + - [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) + - [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) - - [Msg](#ibc.applications.transfer.v1.Msg) + - [Query](#ibc.core.client.v1.Query) + +- [ibc/core/client/v1/tx.proto](#ibc/core/client/v1/tx.proto) + - [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) + - [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) + - [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) + - [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) + - [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) + - [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) + - [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) + - [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) + + - [Msg](#ibc.core.client.v1.Msg) + +- [ibc/core/client/v1/genesis.proto](#ibc/core/client/v1/genesis.proto) + - [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) + - [GenesisState](#ibc.core.client.v1.GenesisState) + - [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) - [ibc/core/channel/v1/channel.proto](#ibc/core/channel/v1/channel.proto) - [Acknowledgement](#ibc.core.channel.v1.Acknowledgement) @@ -546,10 +603,6 @@ - [Order](#ibc.core.channel.v1.Order) - [State](#ibc.core.channel.v1.State) -- [ibc/core/channel/v1/genesis.proto](#ibc/core/channel/v1/genesis.proto) - - [GenesisState](#ibc.core.channel.v1.GenesisState) - - [PacketSequence](#ibc.core.channel.v1.PacketSequence) - - [ibc/core/channel/v1/query.proto](#ibc/core/channel/v1/query.proto) - [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) - [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) @@ -604,36 +657,9 @@ - [Msg](#ibc.core.channel.v1.Msg) -- [ibc/core/client/v1/genesis.proto](#ibc/core/client/v1/genesis.proto) - - [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) - - [GenesisState](#ibc.core.client.v1.GenesisState) - - [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) - -- [ibc/core/client/v1/query.proto](#ibc/core/client/v1/query.proto) - - [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) - - [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) - - [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) - - [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) - - [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) - - [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) - - [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) - - [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) - - [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) - - [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) - - - [Query](#ibc.core.client.v1.Query) - -- [ibc/core/client/v1/tx.proto](#ibc/core/client/v1/tx.proto) - - [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) - - [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) - - [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) - - [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) - - [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) - - [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) - - [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) - - [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) - - - [Msg](#ibc.core.client.v1.Msg) +- [ibc/core/channel/v1/genesis.proto](#ibc/core/channel/v1/genesis.proto) + - [GenesisState](#ibc.core.channel.v1.GenesisState) + - [PacketSequence](#ibc.core.channel.v1.PacketSequence) - [ibc/core/commitment/v1/commitment.proto](#ibc/core/commitment/v1/commitment.proto) - [MerklePath](#ibc.core.commitment.v1.MerklePath) @@ -651,9 +677,6 @@ - [State](#ibc.core.connection.v1.State) -- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) - - [GenesisState](#ibc.core.connection.v1.GenesisState) - - [ibc/core/connection/v1/query.proto](#ibc/core/connection/v1/query.proto) - [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) - [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) @@ -680,12 +703,22 @@ - [Msg](#ibc.core.connection.v1.Msg) +- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) + - [GenesisState](#ibc.core.connection.v1.GenesisState) + - [ibc/core/types/v1/genesis.proto](#ibc/core/types/v1/genesis.proto) - [GenesisState](#ibc.core.types.v1.GenesisState) - [ibc/lightclients/localhost/v1/localhost.proto](#ibc/lightclients/localhost/v1/localhost.proto) - [ClientState](#ibc.lightclients.localhost.v1.ClientState) +- [ibc/lightclients/tendermint/v1/tendermint.proto](#ibc/lightclients/tendermint/v1/tendermint.proto) + - [ClientState](#ibc.lightclients.tendermint.v1.ClientState) + - [ConsensusState](#ibc.lightclients.tendermint.v1.ConsensusState) + - [Fraction](#ibc.lightclients.tendermint.v1.Fraction) + - [Header](#ibc.lightclients.tendermint.v1.Header) + - [Misbehaviour](#ibc.lightclients.tendermint.v1.Misbehaviour) + - [ibc/lightclients/solomachine/v1/solomachine.proto](#ibc/lightclients/solomachine/v1/solomachine.proto) - [ChannelStateData](#ibc.lightclients.solomachine.v1.ChannelStateData) - [ClientState](#ibc.lightclients.solomachine.v1.ClientState) @@ -706,74 +739,190 @@ - [DataType](#ibc.lightclients.solomachine.v1.DataType) -- [ibc/lightclients/tendermint/v1/tendermint.proto](#ibc/lightclients/tendermint/v1/tendermint.proto) - - [ClientState](#ibc.lightclients.tendermint.v1.ClientState) - - [ConsensusState](#ibc.lightclients.tendermint.v1.ConsensusState) - - [Fraction](#ibc.lightclients.tendermint.v1.Fraction) - - [Header](#ibc.lightclients.tendermint.v1.Header) - - [Misbehaviour](#ibc.lightclients.tendermint.v1.Misbehaviour) - - [Scalar Value Types](#scalar-value-types) - +

    Top

    -## cosmos/auth/v1beta1/auth.proto +## cosmos/tx/v1beta1/tx.proto - + -### BaseAccount -BaseAccount defines a base account type. It contains all the necessary fields -for basic account functionality. Any custom account type should extend this -type for additional functionality (e.g. vesting). +### AuthInfo +AuthInfo describes the fee and signer modes that are used to sign a +transaction. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `account_number` | [uint64](#uint64) | | | -| `sequence` | [uint64](#uint64) | | | +| `signer_infos` | [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) | repeated | signer_infos defines the signing modes for the required signers. The number and order of elements must match the required signers from TxBody's messages. The first element is the primary signer and the one which pays the fee. | +| `fee` | [Fee](#cosmos.tx.v1beta1.Fee) | | Fee is the fee and gas limit for the transaction. The first signer is the primary signer and the one which pays the fee. The fee can be calculated based on the cost of evaluating the body and doing signature verification of the signers. This can be estimated via simulation. | - + -### ModuleAccount -ModuleAccount defines an account for modules that holds coins on a pool. +### Fee +Fee includes the amount of coins paid in fees and the maximum +gas to be used by the transaction. The ratio yields an effective "gasprice", +which must be above some miminum to be accepted into the mempool. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | -| `name` | [string](#string) | | | -| `permissions` | [string](#string) | repeated | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | amount is the amount of coins to be paid as a fee | +| `gas_limit` | [uint64](#uint64) | | gas_limit is the maximum gas that can be used in transaction processing before an out of gas error occurs | +| `payer` | [string](#string) | | if unset, the first signer is responsible for paying the fees. If set, the specified account must pay the fees. the payer must be a tx signer (and thus have signed this field in AuthInfo). setting this field does *not* change the ordering of required signers for the transaction. | +| `granter` | [string](#string) | | if set, the fee payer (either the first signer or the value of the payer field) requests that a fee grant be used to pay fees instead of the fee payer's own balance. If an appropriate fee grant does not exist or the chain does not support fee grants, this will fail | - + -### Params -Params defines the parameters for the auth module. +### ModeInfo +ModeInfo describes the signing mode of a single or nested multisig signer. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `max_memo_characters` | [uint64](#uint64) | | | -| `tx_sig_limit` | [uint64](#uint64) | | | -| `tx_size_cost_per_byte` | [uint64](#uint64) | | | -| `sig_verify_cost_ed25519` | [uint64](#uint64) | | | -| `sig_verify_cost_secp256k1` | [uint64](#uint64) | | | +| `single` | [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) | | single represents a single signer | +| `multi` | [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) | | multi represents a nested multisig signer | + + + + + + + + +### ModeInfo.Multi +Multi is the mode info for a multisig public key + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | +| `mode_infos` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | repeated | mode_infos is the corresponding modes of the signers of the multisig which could include nested multisig public keys | + + + + + + + + +### ModeInfo.Single +Single is the mode info for a single signer. It is structured as a message +to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the +future + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | + + + + + + + + +### SignDoc +SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `body_bytes` | [bytes](#bytes) | | body_bytes is protobuf serialization of a TxBody that matches the representation in TxRaw. | +| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in TxRaw. | +| `chain_id` | [string](#string) | | chain_id is the unique identifier of the chain this transaction targets. It prevents signed transactions from being used on another chain by an attacker | +| `account_number` | [uint64](#uint64) | | account_number is the account number of the account in state | + + + + + + + + +### SignerInfo +SignerInfo describes the public key and signing mode of a single top-level +signer. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer. It is optional for accounts that already exist in state. If unset, the verifier can use the required \ signer address for this position and lookup the public key. | +| `mode_info` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | | mode_info describes the signing mode of the signer and is a nested structure to support nested multisig pubkey's | +| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | + + + + + + + + +### Tx +Tx is the standard type used for broadcasting transactions. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `body` | [TxBody](#cosmos.tx.v1beta1.TxBody) | | body is the processable content of the transaction | +| `auth_info` | [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) | | auth_info is the authorization related content of the transaction, specifically signers, signer modes and fee | +| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | + + + + + + + + +### TxBody +TxBody is the body of a transaction that all signers sign over. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `messages` | [google.protobuf.Any](#google.protobuf.Any) | repeated | messages is a list of messages to be executed. The required signers of those messages define the number and order of elements in AuthInfo's signer_infos and Tx's signatures. Each required signer address is added to the list only the first time it occurs. By convention, the first required signer (usually from the first message) is referred to as the primary signer and pays the fee for the whole transaction. | +| `memo` | [string](#string) | | memo is any arbitrary memo to be added to the transaction | +| `timeout_height` | [uint64](#uint64) | | timeout is the block height after which this transaction will not be processed by the chain | +| `extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, the transaction will be rejected | +| `non_critical_extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, they will be ignored | + + + + + + + + +### TxRaw +TxRaw is a variant of Tx that pins the signer's exact binary representation +of body and auth_info. This is used for signing, broadcasting and +verification. The binary `serialize(tx: TxRaw)` is stored in Tendermint and +the hash `sha256(serialize(tx: TxRaw))` becomes the "txhash", commonly used +as the transaction ID. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `body_bytes` | [bytes](#bytes) | | body_bytes is a protobuf serialization of a TxBody that matches the representation in SignDoc. | +| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in SignDoc. | +| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | @@ -789,23 +938,364 @@ Params defines the parameters for the auth module. - +

    Top

    -## cosmos/auth/v1beta1/genesis.proto +## cosmos/tx/v1beta1/service.proto - + + +### BroadcastTxRequest +BroadcastTxRequest is the request type for the Service.BroadcastTxRequest +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | +| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | + + + + + + + + +### BroadcastTxResponse +BroadcastTxResponse is the response type for the +Service.BroadcastTx method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | + + + + + + + + +### GetTxRequest +GetTxRequest is the request type for the Service.GetTx +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | + + + + + + + + +### GetTxResponse +GetTxResponse is the response type for the Service.GetTx method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the queried transaction. | +| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | + + + + + + + + +### GetTxsEventRequest +GetTxsEventRequest is the request type for the Service.TxsByEvents +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `events` | [string](#string) | repeated | events is the list of transaction event type. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | + + + + + + + + +### GetTxsEventResponse +GetTxsEventResponse is the response type for the Service.TxsByEvents +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `txs` | [Tx](#cosmos.tx.v1beta1.Tx) | repeated | txs is the list of queried transactions. | +| `tx_responses` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | tx_responses is the list of queried TxResponses. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | + + + + + + + + +### SimulateRequest +SimulateRequest is the request type for the Service.Simulate +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | + + + + + + + + +### SimulateResponse +SimulateResponse is the response type for the +Service.SimulateRPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `gas_info` | [cosmos.base.abci.v1beta1.GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | gas_info is the information about gas used in the simulation. | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | result is the result of the simulation. | + + + + + + + + + + +### BroadcastMode +BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| BROADCAST_MODE_UNSPECIFIED | 0 | zero-value for mode ordering | +| BROADCAST_MODE_BLOCK | 1 | BROADCAST_MODE_BLOCK defines a tx broadcasting mode where the client waits for the tx to be committed in a block. | +| BROADCAST_MODE_SYNC | 2 | BROADCAST_MODE_SYNC defines a tx broadcasting mode where the client waits for a CheckTx execution response only. | +| BROADCAST_MODE_ASYNC | 3 | BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns immediately. | + + + + + + + + + +### Service +Service defines a gRPC service for interacting with transactions. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Simulate` | [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) | [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) | Simulate simulates executing a transaction for estimating gas usage. | POST|/cosmos/tx/v1beta1/simulate| +| `GetTx` | [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) | [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) | GetTx fetches a tx by hash. | GET|/cosmos/tx/v1beta1/txs/{hash}| +| `BroadcastTx` | [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) | [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) | BroadcastTx broadcast transaction. | POST|/cosmos/tx/v1beta1/txs| +| `GetTxsEvent` | [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) | [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) | GetTxsEvent fetches txs by event. | GET|/cosmos/tx/v1beta1/txs| + + + + + + +

    Top

    + +## cosmos/tx/signing/v1beta1/signing.proto + + + + + +### SignatureDescriptor +SignatureDescriptor is a convenience type which represents the full data for +a signature including the public key of the signer, signing modes and the +signature itself. It is primarily used for coordinating signatures between +clients. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer | +| `data` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | | | +| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | + + + + + + + + +### SignatureDescriptor.Data +Data represents signature data + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `single` | [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) | | single represents a single signer | +| `multi` | [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) | | multi represents a multisig signer | + + + + + + + + +### SignatureDescriptor.Data.Multi +Multi is the signature data for a multisig public key + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | +| `signatures` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | repeated | signatures is the signatures of the multi-signature | + + + + + + + + +### SignatureDescriptor.Data.Single +Single is the signature data for a single signer + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `mode` | [SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | +| `signature` | [bytes](#bytes) | | signature is the raw signature bytes | + + + + + + + + +### SignatureDescriptors +SignatureDescriptors wraps multiple SignatureDescriptor's. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | + + + + + + + + + + +### SignMode +SignMode represents a signing mode with its own security guarantees. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| SIGN_MODE_UNSPECIFIED | 0 | SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected | +| SIGN_MODE_DIRECT | 1 | SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified with raw bytes from Tx | +| SIGN_MODE_TEXTUAL | 2 | SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable textual representation on top of the binary representation from SIGN_MODE_DIRECT | +| SIGN_MODE_LEGACY_AMINO_JSON | 127 | SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses Amino JSON and will be removed in the future | + + + + + + + + + + + +

    Top

    + +## cosmos/crisis/v1beta1/tx.proto + + + + + +### MsgVerifyInvariant +MsgVerifyInvariant represents a message to verify a particular invariance. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `sender` | [string](#string) | | | +| `invariant_module_name` | [string](#string) | | | +| `invariant_route` | [string](#string) | | | + + + + + + + + +### MsgVerifyInvariantResponse +MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. + + + + + + + + + + + + + + +### Msg +Msg defines the bank Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `VerifyInvariant` | [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) | [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) | VerifyInvariant defines a method to verify a particular invariance. | | + + + + + + +

    Top

    + +## cosmos/crisis/v1beta1/genesis.proto + + + + ### GenesisState -GenesisState defines the auth module's genesis state. +GenesisState defines the crisis module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines all the paramaters of the module. | -| `accounts` | [google.protobuf.Any](#google.protobuf.Any) | repeated | accounts are the accounts present at genesis. | +| `constant_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | constant_fee is the fee used to verify the invariant in the crisis module. | @@ -821,44 +1311,253 @@ GenesisState defines the auth module's genesis state. - +

    Top

    -## cosmos/auth/v1beta1/query.proto +## cosmos/crypto/multisig/keys.proto - + -### QueryAccountRequest -QueryAccountRequest is the request type for the Query/Account RPC method. +### LegacyAminoPubKey +LegacyAminoPubKey specifies a public key type +which nests multiple public keys and a threshold, +it uses legacy amino address rules. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address defines the address to query for. | +| `threshold` | [uint32](#uint32) | | | +| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | + - + -### QueryAccountResponse -QueryAccountResponse is the response type for the Query/Account RPC method. + + + + + + + +

    Top

    + +## cosmos/crypto/multisig/v1beta1/multisig.proto + + + + + +### CompactBitArray +CompactBitArray is an implementation of a space efficient bit array. +This is used to ensure that the encoded data takes up a minimal amount of +space after proto encoding. +This is not thread safe, and is not intended for concurrent usage. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | +| `extra_bits_stored` | [uint32](#uint32) | | | +| `elems` | [bytes](#bytes) | | | - + + +### MultiSignature +MultiSignature wraps the signatures from a multisig.LegacyAminoPubKey. +See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers +signed and with which modes. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `signatures` | [bytes](#bytes) | repeated | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/crypto/secp256k1/keys.proto + + + + + +### PrivKey +PrivKey defines a secp256k1 private key. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | + + + + + + + + +### PubKey +PubKey defines a secp256k1 public key +Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte +if the y-coordinate is the lexicographically largest of the two associated with +the x-coordinate. Otherwise the first byte is a 0x03. +This prefix is followed with the x-coordinate. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/crypto/ed25519/keys.proto + + + + + +### PrivKey +PrivKey defines a ed25519 private key. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | + + + + + + + + +### PubKey +PubKey defines a ed25519 public key +Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte +if the y-coordinate is the lexicographically largest of the two associated with +the x-coordinate. Otherwise the first byte is a 0x03. +This prefix is followed with the x-coordinate. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/mint/v1beta1/query.proto + + + + + +### QueryAnnualProvisionsRequest +QueryAnnualProvisionsRequest is the request type for the +Query/AnnualProvisions RPC method. + + + + + + + + +### QueryAnnualProvisionsResponse +QueryAnnualProvisionsResponse is the response type for the +Query/AnnualProvisions RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | + + + + + + + + +### QueryInflationRequest +QueryInflationRequest is the request type for the Query/Inflation RPC method. + + + + + + + + +### QueryInflationResponse +QueryInflationResponse is the response type for the Query/Inflation RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | + + + + + + + ### QueryParamsRequest QueryParamsRequest is the request type for the Query/Params RPC method. @@ -868,7 +1567,7 @@ QueryParamsRequest is the request type for the Query/Params RPC method. - + ### QueryParamsResponse QueryParamsResponse is the response type for the Query/Params RPC method. @@ -876,7 +1575,7 @@ QueryParamsResponse is the response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines the parameters of the module. | +| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | @@ -889,89 +1588,38 @@ QueryParamsResponse is the response type for the Query/Params RPC method. - + ### Query -Query defines the gRPC querier service. +Query provides defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Account` | [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) | [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) | Account returns account details based on address. | GET|/cosmos/auth/v1beta1/accounts/{address}| -| `Params` | [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) | Params queries all parameters. | GET|/cosmos/auth/v1beta1/params| +| `Params` | [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) | Params returns the total set of minting parameters. | GET|/cosmos/mint/v1beta1/params| +| `Inflation` | [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) | [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) | Inflation returns the current minting inflation value. | GET|/cosmos/mint/v1beta1/inflation| +| `AnnualProvisions` | [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) | [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) | AnnualProvisions current minting annual provisions value. | GET|/cosmos/mint/v1beta1/annual_provisions| - +

    Top

    -## cosmos/base/v1beta1/coin.proto +## cosmos/mint/v1beta1/genesis.proto - + -### Coin -Coin defines a token with a denomination and an amount. - -NOTE: The amount field is an Int which implements the custom method -signatures required by gogoproto. +### GenesisState +GenesisState defines the mint module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | - - - - - - - - -### DecCoin -DecCoin defines a token with a denomination and a decimal amount. - -NOTE: The amount field is an Dec which implements the custom method -signatures required by gogoproto. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | - - - - - - - - -### DecProto -DecProto defines a Protobuf wrapper around a Dec object. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `dec` | [string](#string) | | | - - - - - - - - -### IntProto -IntProto defines a Protobuf wrapper around an Int object. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `int` | [string](#string) | | | +| `minter` | [Minter](#cosmos.mint.v1beta1.Minter) | | minter is a space for holding current inflation information. | +| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines all the paramaters of the module. | @@ -987,56 +1635,147 @@ IntProto defines a Protobuf wrapper around an Int object. - +

    Top

    -## cosmos/authz/v1beta1/authz.proto +## cosmos/mint/v1beta1/mint.proto - + -### AuthorizationGrant -AuthorizationGrant gives permissions to execute -the provide method with expiration time. +### Minter +Minter represents the minting state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `inflation` | [string](#string) | | current annual inflation rate | +| `annual_provisions` | [string](#string) | | current annual expected provisions | - + -### GenericAuthorization -GenericAuthorization gives the grantee unrestricted permissions to execute -the provided method on behalf of the granter's account. +### Params +Params holds parameters for the mint module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `method_name` | [string](#string) | | method name to grant unrestricted permissions to execute Note: MethodName() is already a method on `GenericAuthorization` type, we need some custom naming here so using `MessageName` | +| `mint_denom` | [string](#string) | | type of coin to mint | +| `inflation_rate_change` | [string](#string) | | maximum annual change in inflation rate | +| `inflation_max` | [string](#string) | | maximum inflation rate | +| `inflation_min` | [string](#string) | | minimum inflation rate | +| `goal_bonded` | [string](#string) | | goal of percent bonded atoms | +| `blocks_per_year` | [uint64](#uint64) | | expected blocks per year | + - + -### SendAuthorization -SendAuthorization allows the grantee to spend up to spend_limit coins from -the granter's account. + + + + + + + +

    Top

    + +## cosmos/feegrant/v1beta1/feegrant.proto + + + + + +### BasicFeeAllowance +BasicFeeAllowance implements FeeAllowance with a one-time grant of tokens +that optionally expires. The delegatee can use up to SpendLimit to cover fees. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `expiration` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | | + + + + + + + + +### Duration +Duration is a span of a clock time or number of blocks. +This is designed to be added to an ExpiresAt struct. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | +| `blocks` | [uint64](#uint64) | | | + + + + + + + + +### ExpiresAt +ExpiresAt is a point in time where something expires. +It may be *either* block time or block height + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `height` | [int64](#int64) | | | + + + + + + + + +### FeeAllowanceGrant +FeeAllowanceGrant is stored in the KVStore to record a grant with full context + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | + + + + + + + + +### PeriodicFeeAllowance +PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, +as well as a limit per time period. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `basic` | [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) | | | +| `period` | [Duration](#cosmos.feegrant.v1beta1.Duration) | | | +| `period_spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `period_can_spend` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `period_reset` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | | @@ -1052,480 +1791,52 @@ the granter's account. - +

    Top

    -## cosmos/base/abci/v1beta1/abci.proto +## cosmos/feegrant/v1beta1/query.proto - + -### ABCIMessageLog -ABCIMessageLog defines a structure containing an indexed tx ABCI message log. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `msg_index` | [uint32](#uint32) | | | -| `log` | [string](#string) | | | -| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | - - - - - - - - -### Attribute -Attribute defines an attribute wrapper where the key and value are -strings instead of raw bytes. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | - - - - - - - - -### GasInfo -GasInfo defines tx execution gas context. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | -| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | - - - - - - - - -### MsgData -MsgData defines the data returned in a Result object during message -execution. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `msg_type` | [string](#string) | | | -| `data` | [bytes](#bytes) | | | - - - - - - - - -### Result -Result is the union of ResponseFormat and ResponseCheckTx. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | -| `log` | [string](#string) | | Log contains the log information from message or handler execution. | -| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | - - - - - - - - -### SearchTxsResult -SearchTxsResult defines a structure for querying txs pageable - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `total_count` | [uint64](#uint64) | | Count of all txs | -| `count` | [uint64](#uint64) | | Count of txs in current page | -| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | -| `page_total` | [uint64](#uint64) | | Count of total pages | -| `limit` | [uint64](#uint64) | | Max count txs per page | -| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | - - - - - - - - -### SimulationResponse -SimulationResponse defines the response generated when a transaction is -successfully simulated. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | -| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | - - - - - - - - -### StringEvent -StringEvent defines en Event object wrapper where all the attributes -contain key/value pairs that are strings instead of raw bytes. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `type` | [string](#string) | | | -| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | - - - - - - - - -### TxMsgData -TxMsgData defines a list of MsgData. A transaction will have a MsgData object -for each message. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | - - - - - - - - -### TxResponse -TxResponse defines a structure containing relevant tx data and metadata. The -tags are stringified and the log is JSON decoded. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | The block height | -| `txhash` | [string](#string) | | The transaction hash. | -| `codespace` | [string](#string) | | Namespace for the Code | -| `code` | [uint32](#uint32) | | Response code. | -| `data` | [string](#string) | | Result bytes, if any. | -| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | -| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | -| `info` | [string](#string) | | Additional information. May be non-deterministic. | -| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | -| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | -| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | -| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/authz/v1beta1/tx.proto - - - - - -### MsgExecAuthorizedRequest -MsgExecAuthorizedRequest attempts to execute the provided messages using -authorizations granted to the grantee. Each message should have only -one signer corresponding to the granter of the authorization. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `grantee` | [string](#string) | | | -| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | - - - - - - - - -### MsgExecAuthorizedResponse -MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | - - - - - - - - -### MsgGrantAuthorizationRequest -MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's -account with the provided expiration time. +### QueryFeeAllowanceRequest +QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `granter` | [string](#string) | | | | `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### MsgGrantAuthorizationResponse -MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. - - - - - - - - -### MsgRevokeAuthorizationRequest -MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the -granter's account with that has been granted to the grantee. +### QueryFeeAllowanceResponse +QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | +| `fee_allowance` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | | fee_allowance is a fee_allowance granted for grantee by granter. | - + -### MsgRevokeAuthorizationResponse -MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. - - - - - - - - - - - - - - -### Msg -Msg defines the authz Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `GrantAuthorization` | [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) | [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) | GrantAuthorization grants the provided authorization to the grantee on the granter's account with the provided expiration time. | | -| `ExecAuthorized` | [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) | [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) | ExecAuthorized attempts to execute the provided messages using authorizations granted to the grantee. Each message should have only one signer corresponding to the granter of the authorization. | | -| `RevokeAuthorization` | [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) | [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) | RevokeAuthorization revokes any authorization corresponding to the provided method name on the granter's account that has been granted to the grantee. | | - - - - - - -

    Top

    - -## cosmos/authz/v1beta1/genesis.proto - - - - - -### GenesisState -GenesisState defines the authz module's genesis state. +### QueryFeeAllowancesRequest +QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | - - - - - - - - -### GrantAuthorization -GrantAuthorization defines the GenesisState/GrantAuthorization type. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/base/query/v1beta1/pagination.proto - - - - - -### PageRequest -PageRequest is to be embedded in gRPC request messages for efficient -pagination. Ex: - - message SomeRequest { - Foo some_parameter = 1; - PageRequest pagination = 2; - } - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | -| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | -| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | -| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | - - - - - - - - -### PageResponse -PageResponse is to be embedded in gRPC response messages where the -corresponding request message has used PageRequest. - - message SomeResponse { - repeated Bar results = 1; - PageResponse page = 2; - } - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | -| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/authz/v1beta1/query.proto - - - - - -### QueryAuthorizationRequest -QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | - - - - - - - - -### QueryAuthorizationResponse -QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | - - - - - - - - -### QueryAuthorizationsRequest -QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | | `grantee` | [string](#string) | | | | `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | @@ -1534,15 +1845,15 @@ QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC - + -### QueryAuthorizationsResponse -QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. +### QueryFeeAllowancesResponse +QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorizations` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | repeated | authorizations is a list of grants granted for grantee by granter. | +| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | fee_allowances are fee_allowance's granted for grantee by granter. | | `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | @@ -1556,15 +1867,240 @@ QueryAuthorizationsResponse is the response type for the Query/Authorizations RP - + ### Query Query defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Authorization` | [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) | [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) | Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the provided msg type. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant| -| `Authorizations` | [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) | [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants| +| `FeeAllowance` | [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) | [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) | FeeAllowance returns fee granted to the grantee by the granter. | GET|/cosmos/feegrant/v1beta1/fee_allowance/{granter}/{grantee}| +| `FeeAllowances` | [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) | [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) | FeeAllowances returns all the grants for address. | GET|/cosmos/feegrant/v1beta1/fee_allowances/{grantee}| + + + + + + +

    Top

    + +## cosmos/feegrant/v1beta1/tx.proto + + + + + +### MsgGrantFeeAllowance +MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance +of fees from the account of Granter. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | + + + + + + + + +### MsgGrantFeeAllowanceResponse +MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. + + + + + + + + +### MsgRevokeFeeAllowance +MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | + + + + + + + + +### MsgRevokeFeeAllowanceResponse +MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. + + + + + + + + + + + + + + +### Msg +Msg defines the feegrant msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `GrantFeeAllowance` | [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) | [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) | GrantFeeAllowance grants fee allowance to the grantee on the granter's account with the provided expiration time. | | +| `RevokeFeeAllowance` | [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) | [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) | RevokeFeeAllowance revokes any fee allowance of granter's account that has been granted to the grantee. | | + + + + + + +

    Top

    + +## cosmos/feegrant/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState contains a set of fee allowances, persisted from the store + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/capability/v1beta1/capability.proto + + + + + +### Capability +Capability defines an implementation of an object capability. The index +provided to a Capability must be globally unique. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `index` | [uint64](#uint64) | | | + + + + + + + + +### CapabilityOwners +CapabilityOwners defines a set of owners of a single Capability. The set of +owners must be unique. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | + + + + + + + + +### Owner +Owner defines a single capability owner. An owner is defined by the name of +capability and the module name. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `module` | [string](#string) | | | +| `name` | [string](#string) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/capability/v1beta1/genesis.proto + + + + + +### GenesisOwners +GenesisOwners defines the capability owners with their corresponding index. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `index` | [uint64](#uint64) | | index is the index of the capability owner. | +| `index_owners` | [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) | | index_owners are the owners at the given index. | + + + + + + + + +### GenesisState +GenesisState defines the capability module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `index` | [uint64](#uint64) | | index is the capability global index. | +| `owners` | [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) | repeated | owners represents a map from index to owners of the capability index index key is string to allow amino marshalling. | + + + + + + + + + + @@ -1694,57 +2230,6 @@ amounts in the network. - - - - - - - - - - - -

    Top

    - -## cosmos/bank/v1beta1/genesis.proto - - - - - -### Balance -Balance defines an account address and balance pair used in the bank module's -genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address of the balance holder. | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | coins defines the different coins this balance holds. | - - - - - - - - -### GenesisState -GenesisState defines the bank module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. | -| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. | -| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. | -| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. | - - - - - @@ -2076,38 +2561,42 @@ Msg defines the bank Msg service. - +

    Top

    -## cosmos/base/kv/v1beta1/kv.proto +## cosmos/bank/v1beta1/genesis.proto - + -### Pair -Pair defines a key/value bytes tuple. +### Balance +Balance defines an account address and balance pair used in the bank module's +genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | +| `address` | [string](#string) | | address is the address of the balance holder. | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | coins defines the different coins this balance holds. | - + -### Pairs -Pairs defines a repeated slice of Pair objects. +### GenesisState +GenesisState defines the bank module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | +| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. | +| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. | +| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. | +| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. | @@ -2123,125 +2612,56 @@ Pairs defines a repeated slice of Pair objects. - +

    Top

    -## cosmos/base/reflection/v1beta1/reflection.proto +## cosmos/authz/v1beta1/authz.proto - + -### ListAllInterfacesRequest -ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. - - - - - - - - -### ListAllInterfacesResponse -ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. +### AuthorizationGrant +AuthorizationGrant gives permissions to execute +the provide method with expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### ListImplementationsRequest -ListImplementationsRequest is the request type of the ListImplementations -RPC. +### GenericAuthorization +GenericAuthorization gives the grantee unrestricted permissions to execute +the provided method on behalf of the granter's account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | +| `method_name` | [string](#string) | | method name to grant unrestricted permissions to execute Note: MethodName() is already a method on `GenericAuthorization` type, we need some custom naming here so using `MessageName` | - + -### ListImplementationsResponse -ListImplementationsResponse is the response type of the ListImplementations -RPC. +### SendAuthorization +SendAuthorization allows the grantee to spend up to spend_limit coins from +the granter's account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `implementation_message_names` | [string](#string) | repeated | | - - - - - - - - - - - - - - -### ReflectionService -ReflectionService defines a service for interface reflection. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ListAllInterfaces` | [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) | [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) | ListAllInterfaces lists all the interfaces registered in the interface registry. | GET|/cosmos/base/reflection/v1beta1/interfaces| -| `ListImplementations` | [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) | [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) | ListImplementations list all the concrete types that implement a given interface. | GET|/cosmos/base/reflection/v1beta1/interfaces/{interface_name}/implementations| - - - - - - -

    Top

    - -## cosmos/base/snapshots/v1beta1/snapshot.proto - - - - - -### Metadata -Metadata contains SDK-specific snapshot metadata. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | - - - - - - - - -### Snapshot -Snapshot contains Tendermint state sync snapshot info. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [uint64](#uint64) | | | -| `format` | [uint32](#uint32) | | | -| `chunks` | [uint32](#uint32) | | | -| `hash` | [bytes](#bytes) | | | -| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | @@ -2257,210 +2677,55 @@ Snapshot contains Tendermint state sync snapshot info. - +

    Top

    -## cosmos/base/store/v1beta1/commit_info.proto +## cosmos/authz/v1beta1/query.proto - + -### CommitID -CommitID defines the committment information when a specific store is -committed. +### QueryAuthorizationRequest +QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `hash` | [bytes](#bytes) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - + -### CommitInfo -CommitInfo defines commit information used by the multi-store when committing -a version/height. +### QueryAuthorizationResponse +QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | +| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | - + -### StoreInfo -StoreInfo defines store-specific commit information. It contains a reference -between a store name and the commit ID. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/base/store/v1beta1/snapshot.proto - - - - - -### SnapshotIAVLItem -SnapshotIAVLItem is an exported IAVL node. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | -| `version` | [int64](#int64) | | | -| `height` | [int32](#int32) | | | - - - - - - - - -### SnapshotItem -SnapshotItem is an item contained in a rootmulti.Store snapshot. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | -| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | - - - - - - - - -### SnapshotStoreItem -SnapshotStoreItem contains metadata about a snapshotted store. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/base/tendermint/v1beta1/query.proto - - - - - -### GetBlockByHeightRequest -GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | - - - - - - - - -### GetBlockByHeightResponse -GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - - - - - - - - -### GetLatestBlockRequest -GetLatestBlockRequest is the request type for the Query/GetLatestBlock RPC method. - - - - - - - - -### GetLatestBlockResponse -GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - - - - - - - - -### GetLatestValidatorSetRequest -GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetByHeight RPC method. +### QueryAuthorizationsRequest +QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | | `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | @@ -2468,162 +2733,21 @@ GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetBy - + -### GetLatestValidatorSetResponse -GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. +### QueryAuthorizationsResponse +QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `block_height` | [int64](#int64) | | | -| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | +| `authorizations` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | repeated | authorizations is a list of grants granted for grantee by granter. | | `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - - - -### GetNodeInfoRequest -GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. - - - - - - - - -### GetNodeInfoResponse -GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | -| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | - - - - - - - - -### GetSyncingRequest -GetSyncingRequest is the request type for the Query/GetSyncing RPC method. - - - - - - - - -### GetSyncingResponse -GetSyncingResponse is the response type for the Query/GetSyncing RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `syncing` | [bool](#bool) | | | - - - - - - - - -### GetValidatorSetByHeightRequest -GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - - - - - - - - -### GetValidatorSetByHeightResponse -GetValidatorSetByHeightResponse is the response type for the Query/GetValidatorSetByHeight RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `block_height` | [int64](#int64) | | | -| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - - - - - - - - -### Module -Module is the type for VersionInfo - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [string](#string) | | module path | -| `version` | [string](#string) | | module version | -| `sum` | [string](#string) | | checksum | - - - - - - - - -### Validator -Validator is the type for the validator-set. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `voting_power` | [int64](#int64) | | | -| `proposer_priority` | [int64](#int64) | | | - - - - - - - - -### VersionInfo -VersionInfo is the type for the GetNodeInfoResponse message. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `app_name` | [string](#string) | | | -| `version` | [string](#string) | | | -| `git_commit` | [string](#string) | | | -| `build_tags` | [string](#string) | | | -| `go_version` | [string](#string) | | | -| `build_deps` | [Module](#cosmos.base.tendermint.v1beta1.Module) | repeated | | - - - - - @@ -2631,196 +2755,111 @@ VersionInfo is the type for the GetNodeInfoResponse message. - + -### Service -Service defines the gRPC querier service for tendermint queries. +### Query +Query defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `GetNodeInfo` | [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) | [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) | GetNodeInfo queries the current node info. | GET|/cosmos/base/tendermint/v1beta1/node_info| -| `GetSyncing` | [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) | [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) | GetSyncing queries node syncing. | GET|/cosmos/base/tendermint/v1beta1/syncing| -| `GetLatestBlock` | [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) | [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) | GetLatestBlock returns the latest block. | GET|/cosmos/base/tendermint/v1beta1/blocks/latest| -| `GetBlockByHeight` | [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) | [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) | GetBlockByHeight queries block for given height. | GET|/cosmos/base/tendermint/v1beta1/blocks/{height}| -| `GetLatestValidatorSet` | [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) | [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) | GetLatestValidatorSet queries latest validator-set. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/latest| -| `GetValidatorSetByHeight` | [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) | [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) | GetValidatorSetByHeight queries validator-set at a given height. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/{height}| +| `Authorization` | [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) | [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) | Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the provided msg type. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant| +| `Authorizations` | [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) | [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants| - +

    Top

    -## cosmos/capability/v1beta1/capability.proto +## cosmos/authz/v1beta1/tx.proto - + -### Capability -Capability defines an implementation of an object capability. The index -provided to a Capability must be globally unique. +### MsgExecAuthorizedRequest +MsgExecAuthorizedRequest attempts to execute the provided messages using +authorizations granted to the grantee. Each message should have only +one signer corresponding to the granter of the authorization. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | | +| `grantee` | [string](#string) | | | +| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | - + -### CapabilityOwners -CapabilityOwners defines a set of owners of a single Capability. The set of -owners must be unique. +### MsgExecAuthorizedResponse +MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | - + -### Owner -Owner defines a single capability owner. An owner is defined by the name of -capability and the module name. +### MsgGrantAuthorizationRequest +MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +account with the provided expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `module` | [string](#string) | | | -| `name` | [string](#string) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - + - - - +### MsgGrantAuthorizationResponse +MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. - -

    Top

    - -## cosmos/capability/v1beta1/genesis.proto - + -### GenesisOwners -GenesisOwners defines the capability owners with their corresponding index. +### MsgRevokeAuthorizationRequest +MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the +granter's account with that has been granted to the grantee. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | index is the index of the capability owner. | -| `index_owners` | [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) | | index_owners are the owners at the given index. | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - + -### GenesisState -GenesisState defines the capability module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | index is the capability global index. | -| `owners` | [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) | repeated | owners represents a map from index to owners of the capability index index key is string to allow amino marshalling. | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/crisis/v1beta1/genesis.proto - - - - - -### GenesisState -GenesisState defines the crisis module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `constant_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | constant_fee is the fee used to verify the invariant in the crisis module. | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/crisis/v1beta1/tx.proto - - - - - -### MsgVerifyInvariant -MsgVerifyInvariant represents a message to verify a particular invariance. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `sender` | [string](#string) | | | -| `invariant_module_name` | [string](#string) | | | -| `invariant_route` | [string](#string) | | | - - - - - - - - -### MsgVerifyInvariantResponse -MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. +### MsgRevokeAuthorizationResponse +MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. @@ -2833,54 +2872,55 @@ MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. - + ### Msg -Msg defines the bank Msg service. +Msg defines the authz Msg service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `VerifyInvariant` | [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) | [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) | VerifyInvariant defines a method to verify a particular invariance. | | +| `GrantAuthorization` | [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) | [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) | GrantAuthorization grants the provided authorization to the grantee on the granter's account with the provided expiration time. | | +| `ExecAuthorized` | [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) | [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) | ExecAuthorized attempts to execute the provided messages using authorizations granted to the grantee. Each message should have only one signer corresponding to the granter of the authorization. | | +| `RevokeAuthorization` | [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) | [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) | RevokeAuthorization revokes any authorization corresponding to the provided method name on the granter's account that has been granted to the grantee. | | - +

    Top

    -## cosmos/crypto/ed25519/keys.proto +## cosmos/authz/v1beta1/genesis.proto - + -### PrivKey -PrivKey defines a ed25519 private key. +### GenesisState +GenesisState defines the authz module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | - + -### PubKey -PubKey defines a ed25519 public key -Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -if the y-coordinate is the lexicographically largest of the two associated with -the x-coordinate. Otherwise the first byte is a 0x03. -This prefix is followed with the x-coordinate. +### GrantAuthorization +GrantAuthorization defines the GenesisState/GrantAuthorization type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | @@ -2896,162 +2936,24 @@ This prefix is followed with the x-coordinate. - +

    Top

    -## cosmos/crypto/multisig/keys.proto +## cosmos/gov/v1beta1/gov.proto - + -### LegacyAminoPubKey -LegacyAminoPubKey specifies a public key type -which nests multiple public keys and a threshold, -it uses legacy amino address rules. +### Deposit +Deposit defines an amount deposited by an account address to an active +proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `threshold` | [uint32](#uint32) | | | -| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/crypto/multisig/v1beta1/multisig.proto - - - - - -### CompactBitArray -CompactBitArray is an implementation of a space efficient bit array. -This is used to ensure that the encoded data takes up a minimal amount of -space after proto encoding. -This is not thread safe, and is not intended for concurrent usage. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `extra_bits_stored` | [uint32](#uint32) | | | -| `elems` | [bytes](#bytes) | | | - - - - - - - - -### MultiSignature -MultiSignature wraps the signatures from a multisig.LegacyAminoPubKey. -See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers -signed and with which modes. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signatures` | [bytes](#bytes) | repeated | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/crypto/secp256k1/keys.proto - - - - - -### PrivKey -PrivKey defines a secp256k1 private key. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | - - - - - - - - -### PubKey -PubKey defines a secp256k1 public key -Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -if the y-coordinate is the lexicographically largest of the two associated with -the x-coordinate. Otherwise the first byte is a 0x03. -This prefix is followed with the x-coordinate. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/distribution/v1beta1/distribution.proto - - - - - -### CommunityPoolSpendProposal -CommunityPoolSpendProposal details a proposal for use of community funds, -together with how many coins are proposed to be spent, and to which -recipient account. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | | `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | @@ -3059,203 +2961,593 @@ recipient account. - + -### CommunityPoolSpendProposalWithDeposit -CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal -with a deposit +### DepositParams +DepositParams defines the params for deposits on governance proposals. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `min_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Minimum deposit for a proposal to enter voting period. | +| `max_deposit_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months. | + + + + + + + + +### Proposal +Proposal defines the core field members of a governance proposal. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | +| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | | +| `final_tally_result` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | | +| `submit_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `deposit_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `total_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `voting_start_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `voting_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + + + + + + + + +### TallyParams +TallyParams defines the params for tallying votes on governance proposals. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `quorum` | [bytes](#bytes) | | Minimum percentage of total stake needed to vote for a result to be considered valid. | +| `threshold` | [bytes](#bytes) | | Minimum proportion of Yes votes for proposal to pass. Default value: 0.5. | +| `veto_threshold` | [bytes](#bytes) | | Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Default value: 1/3. | + + + + + + + + +### TallyResult +TallyResult defines a standard tally for a governance proposal. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `yes` | [string](#string) | | | +| `abstain` | [string](#string) | | | +| `no` | [string](#string) | | | +| `no_with_veto` | [string](#string) | | | + + + + + + + + +### TextProposal +TextProposal defines a standard text proposal whose changes need to be +manually updated in case of approval. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `title` | [string](#string) | | | | `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | -| `amount` | [string](#string) | | | -| `deposit` | [string](#string) | | | - + -### DelegationDelegatorReward -DelegationDelegatorReward represents the properties -of a delegator's delegation reward. +### Vote +Vote defines a vote on a governance proposal. +A Vote consists of a proposal ID, the voter, and the vote option. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | | -| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - + -### DelegatorStartingInfo -DelegatorStartingInfo represents the starting info for a delegator reward -period. It tracks the previous validator period, the delegation's amount of -staking token, and the creation height (to check later on if any slashes have -occurred). NOTE: Even though validators are slashed to whole staking tokens, -the delegators within the validator may be left with less than a full token, -thus sdk.Dec is used. +### VotingParams +VotingParams defines the params for voting on governance proposals. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `previous_period` | [uint64](#uint64) | | | -| `stake` | [string](#string) | | | -| `height` | [uint64](#uint64) | | | +| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. | + - -### FeePool -FeePool is the global fee pool for distribution. + + +### ProposalStatus +ProposalStatus enumerates the valid statuses of a proposal. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| PROPOSAL_STATUS_UNSPECIFIED | 0 | PROPOSAL_STATUS_UNSPECIFIED defines the default propopsal status. | +| PROPOSAL_STATUS_DEPOSIT_PERIOD | 1 | PROPOSAL_STATUS_DEPOSIT_PERIOD defines a proposal status during the deposit period. | +| PROPOSAL_STATUS_VOTING_PERIOD | 2 | PROPOSAL_STATUS_VOTING_PERIOD defines a proposal status during the voting period. | +| PROPOSAL_STATUS_PASSED | 3 | PROPOSAL_STATUS_PASSED defines a proposal status of a proposal that has passed. | +| PROPOSAL_STATUS_REJECTED | 4 | PROPOSAL_STATUS_REJECTED defines a proposal status of a proposal that has been rejected. | +| PROPOSAL_STATUS_FAILED | 5 | PROPOSAL_STATUS_FAILED defines a proposal status of a proposal that has failed. | + + + + + +### VoteOption +VoteOption enumerates the valid vote options for a given governance proposal. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| VOTE_OPTION_UNSPECIFIED | 0 | VOTE_OPTION_UNSPECIFIED defines a no-op vote option. | +| VOTE_OPTION_YES | 1 | VOTE_OPTION_YES defines a yes vote option. | +| VOTE_OPTION_ABSTAIN | 2 | VOTE_OPTION_ABSTAIN defines an abstain vote option. | +| VOTE_OPTION_NO | 3 | VOTE_OPTION_NO defines a no vote option. | +| VOTE_OPTION_NO_WITH_VETO | 4 | VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. | + + + + + + + + + + + +

    Top

    + +## cosmos/gov/v1beta1/query.proto + + + + + +### QueryDepositRequest +QueryDepositRequest is the request type for the Query/Deposit RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | - + -### Params -Params defines the set of params for the distribution module. +### QueryDepositResponse +QueryDepositResponse is the response type for the Query/Deposit RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `community_tax` | [string](#string) | | | -| `base_proposer_reward` | [string](#string) | | | -| `bonus_proposer_reward` | [string](#string) | | | -| `withdraw_addr_enabled` | [bool](#bool) | | | +| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | - + -### ValidatorAccumulatedCommission -ValidatorAccumulatedCommission represents accumulated commission -for a validator kept as a running counter, can be withdrawn at any time. +### QueryDepositsRequest +QueryDepositsRequest is the request type for the Query/Deposits RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - + -### ValidatorCurrentRewards -ValidatorCurrentRewards represents current rewards and current -period for a validator kept as a running counter and incremented -each block as long as the validator's tokens remain constant. +### QueryDepositsResponse +QueryDepositsResponse is the response type for the Query/Deposits RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `period` | [uint64](#uint64) | | | +| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - + -### ValidatorHistoricalRewards -ValidatorHistoricalRewards represents historical rewards for a validator. -Height is implicit within the store key. -Cumulative reward ratio is the sum from the zeroeth period -until this period of rewards / tokens, per the spec. -The reference count indicates the number of objects -which might need to reference this historical entry at any point. -ReferenceCount = - number of outstanding delegations which ended the associated period (and - might need to read that record) - + number of slashes which ended the associated period (and might need to - read that record) - + one per validator for the zeroeth period, set on initialization +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `reference_count` | [uint32](#uint32) | | | +| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | - + -### ValidatorOutstandingRewards -ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards -for a validator inexpensive to track, allows simple sanity checks. +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | voting_params defines the parameters related to voting. | +| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | deposit_params defines the parameters related to deposit. | +| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | tally_params defines the parameters related to tally. | - + -### ValidatorSlashEvent -ValidatorSlashEvent represents a validator slash event. -Height is implicit within the store key. -This is needed to calculate appropriate amount of staking tokens -for delegations which are withdrawn after a slash has occurred. +### QueryProposalRequest +QueryProposalRequest is the request type for the Query/Proposal RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_period` | [uint64](#uint64) | | | -| `fraction` | [string](#string) | | | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - + -### ValidatorSlashEvents -ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. +### QueryProposalResponse +QueryProposalResponse is the response type for the Query/Proposal RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | +| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | + + + + + + + + +### QueryProposalsRequest +QueryProposalsRequest is the request type for the Query/Proposals RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | proposal_status defines the status of the proposals. | +| `voter` | [string](#string) | | voter defines the voter address for the proposals. | +| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryProposalsResponse +QueryProposalsResponse is the response type for the Query/Proposals RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + + + +### QueryTallyResultRequest +QueryTallyResultRequest is the request type for the Query/Tally RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | + + + + + + + + +### QueryTallyResultResponse +QueryTallyResultResponse is the response type for the Query/Tally RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | + + + + + + + + +### QueryVoteRequest +QueryVoteRequest is the request type for the Query/Vote RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `voter` | [string](#string) | | voter defines the oter address for the proposals. | + + + + + + + + +### QueryVoteResponse +QueryVoteResponse is the response type for the Query/Vote RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | + + + + + + + + +### QueryVotesRequest +QueryVotesRequest is the request type for the Query/Votes RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryVotesResponse +QueryVotesResponse is the response type for the Query/Votes RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defined the queried votes. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service for gov module + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Proposal` | [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) | [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) | Proposal queries proposal details based on ProposalID. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}| +| `Proposals` | [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) | [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) | Proposals queries all proposals based on given status. | GET|/cosmos/gov/v1beta1/proposals| +| `Vote` | [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) | [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) | Vote queries voted information based on proposalID, voterAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}| +| `Votes` | [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) | [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) | Votes queries votes of a given proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes| +| `Params` | [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) | Params queries all parameters of the gov module. | GET|/cosmos/gov/v1beta1/params/{params_type}| +| `Deposit` | [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) | [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) | Deposit queries single deposit information based proposalID, depositAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}| +| `Deposits` | [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) | [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) | Deposits queries all deposits of a single proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits| +| `TallyResult` | [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) | [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) | TallyResult queries the tally of a proposal vote. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/tally| + + + + + + +

    Top

    + +## cosmos/gov/v1beta1/tx.proto + + + + + +### MsgDeposit +MsgDeposit defines a message to submit a deposit to an existing proposal. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + + + + + + +### MsgDepositResponse +MsgDepositResponse defines the Msg/Deposit response type. + + + + + + + + +### MsgSubmitProposal +MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary +proposal Content. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `initial_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `proposer` | [string](#string) | | | + + + + + + + + +### MsgSubmitProposalResponse +MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | + + + + + + + + +### MsgVote +MsgVote defines a message to cast a vote. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | + + + + + + + + +### MsgVoteResponse +MsgVoteResponse defines the Msg/Vote response type. + + + + + + + + + + + + + + +### Msg +Msg defines the bank Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `SubmitProposal` | [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) | [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) | SubmitProposal defines a method to create new proposal given a content. | | +| `Vote` | [MsgVote](#cosmos.gov.v1beta1.MsgVote) | [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) | Vote defines a method to add a vote on a specific proposal. | | +| `Deposit` | [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) | [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) | Deposit defines a method to add deposit on a specific proposal. | | + + + + + + +

    Top

    + +## cosmos/gov/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the gov module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `starting_proposal_id` | [uint64](#uint64) | | starting_proposal_id is the ID of the starting proposal. | +| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | deposits defines all the deposits present at genesis. | +| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defines all the votes present at genesis. | +| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | proposals defines all the proposals present at genesis. | +| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | params defines all the paramaters of related to deposit. | +| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | params defines all the paramaters of related to voting. | +| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | params defines all the paramaters of related to tally. | @@ -3271,151 +3563,22 @@ ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. - +

    Top

    -## cosmos/distribution/v1beta1/genesis.proto +## cosmos/genutil/v1beta1/genesis.proto - - -### DelegatorStartingInfoRecord -DelegatorStartingInfoRecord used for import / export via genesis json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `starting_info` | [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) | | starting_info defines the starting info of a delegator. | - - - - - - - - -### DelegatorWithdrawInfo -DelegatorWithdrawInfo is the address for where distributions rewards are -withdrawn to by default this struct is only used at genesis to feed in -default withdraw addresses. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | -| `withdraw_address` | [string](#string) | | withdraw_address is the address to withdraw the delegation rewards to. | - - - - - - - + ### GenesisState -GenesisState defines the distribution module's genesis state. +GenesisState defines the raw genesis transaction in JSON. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines all the paramaters of the module. | -| `fee_pool` | [FeePool](#cosmos.distribution.v1beta1.FeePool) | | fee_pool defines the fee pool at genesis. | -| `delegator_withdraw_infos` | [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) | repeated | fee_pool defines the delegator withdraw infos at genesis. | -| `previous_proposer` | [string](#string) | | fee_pool defines the previous proposer at genesis. | -| `outstanding_rewards` | [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) | repeated | fee_pool defines the outstanding rewards of all validators at genesis. | -| `validator_accumulated_commissions` | [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) | repeated | fee_pool defines the accumulated commisions of all validators at genesis. | -| `validator_historical_rewards` | [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) | repeated | fee_pool defines the historical rewards of all validators at genesis. | -| `validator_current_rewards` | [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) | repeated | fee_pool defines the current rewards of all validators at genesis. | -| `delegator_starting_infos` | [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) | repeated | fee_pool defines the delegator starting infos at genesis. | -| `validator_slash_events` | [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) | repeated | fee_pool defines the validator slash events at genesis. | - - - - - - - - -### ValidatorAccumulatedCommissionRecord -ValidatorAccumulatedCommissionRecord is used for import / export via genesis -json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `accumulated` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | accumulated is the accumulated commission of a validator. | - - - - - - - - -### ValidatorCurrentRewardsRecord -ValidatorCurrentRewardsRecord is used for import / export via genesis json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `rewards` | [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) | | rewards defines the current rewards of a validator. | - - - - - - - - -### ValidatorHistoricalRewardsRecord -ValidatorHistoricalRewardsRecord is used for import / export via genesis -json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `period` | [uint64](#uint64) | | period defines the period the historical rewards apply to. | -| `rewards` | [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) | | rewards defines the historical rewards of a validator. | - - - - - - - - -### ValidatorOutstandingRewardsRecord -ValidatorOutstandingRewardsRecord is used for import/export via genesis json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `outstanding_rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | outstanding_rewards represents the oustanding rewards of a validator. | - - - - - - - - -### ValidatorSlashEventRecord -ValidatorSlashEventRecord is used for import / export via genesis json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `height` | [uint64](#uint64) | | height defines the block height at which the slash event occured. | -| `period` | [uint64](#uint64) | | period is the period of the slash event. | -| `validator_slash_event` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | | validator_slash_event describes the slash event. | +| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | @@ -3883,57 +4046,151 @@ Msg defines the distribution Msg service. - +

    Top

    -## cosmos/evidence/v1beta1/evidence.proto +## cosmos/distribution/v1beta1/genesis.proto - + -### Equivocation -Equivocation implements the Evidence interface and defines evidence of double -signing misbehavior. +### DelegatorStartingInfoRecord +DelegatorStartingInfoRecord used for import / export via genesis json. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `power` | [int64](#int64) | | | -| `consensus_address` | [string](#string) | | | +| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `starting_info` | [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) | | starting_info defines the starting info of a delegator. | - - + - +### DelegatorWithdrawInfo +DelegatorWithdrawInfo is the address for where distributions rewards are +withdrawn to by default this struct is only used at genesis to feed in +default withdraw addresses. - + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | +| `withdraw_address` | [string](#string) | | withdraw_address is the address to withdraw the delegation rewards to. | - -

    Top

    - -## cosmos/evidence/v1beta1/genesis.proto - + ### GenesisState -GenesisState defines the evidence module's genesis state. +GenesisState defines the distribution module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | +| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines all the paramaters of the module. | +| `fee_pool` | [FeePool](#cosmos.distribution.v1beta1.FeePool) | | fee_pool defines the fee pool at genesis. | +| `delegator_withdraw_infos` | [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) | repeated | fee_pool defines the delegator withdraw infos at genesis. | +| `previous_proposer` | [string](#string) | | fee_pool defines the previous proposer at genesis. | +| `outstanding_rewards` | [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) | repeated | fee_pool defines the outstanding rewards of all validators at genesis. | +| `validator_accumulated_commissions` | [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) | repeated | fee_pool defines the accumulated commisions of all validators at genesis. | +| `validator_historical_rewards` | [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) | repeated | fee_pool defines the historical rewards of all validators at genesis. | +| `validator_current_rewards` | [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) | repeated | fee_pool defines the current rewards of all validators at genesis. | +| `delegator_starting_infos` | [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) | repeated | fee_pool defines the delegator starting infos at genesis. | +| `validator_slash_events` | [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) | repeated | fee_pool defines the validator slash events at genesis. | + + + + + + + + +### ValidatorAccumulatedCommissionRecord +ValidatorAccumulatedCommissionRecord is used for import / export via genesis +json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `accumulated` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | accumulated is the accumulated commission of a validator. | + + + + + + + + +### ValidatorCurrentRewardsRecord +ValidatorCurrentRewardsRecord is used for import / export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `rewards` | [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) | | rewards defines the current rewards of a validator. | + + + + + + + + +### ValidatorHistoricalRewardsRecord +ValidatorHistoricalRewardsRecord is used for import / export via genesis +json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `period` | [uint64](#uint64) | | period defines the period the historical rewards apply to. | +| `rewards` | [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) | | rewards defines the historical rewards of a validator. | + + + + + + + + +### ValidatorOutstandingRewardsRecord +ValidatorOutstandingRewardsRecord is used for import/export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `outstanding_rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | outstanding_rewards represents the oustanding rewards of a validator. | + + + + + + + + +### ValidatorSlashEventRecord +ValidatorSlashEventRecord is used for import / export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `height` | [uint64](#uint64) | | height defines the block height at which the slash event occured. | +| `period` | [uint64](#uint64) | | period is the period of the slash event. | +| `validator_slash_event` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | | validator_slash_event describes the slash event. | @@ -3949,203 +4206,26 @@ GenesisState defines the evidence module's genesis state. - +

    Top

    -## cosmos/evidence/v1beta1/query.proto +## cosmos/distribution/v1beta1/distribution.proto - + -### QueryAllEvidenceRequest -QueryEvidenceRequest is the request type for the Query/AllEvidence RPC -method. +### CommunityPoolSpendProposal +CommunityPoolSpendProposal details a proposal for use of community funds, +together with how many coins are proposed to be spent, and to which +recipient account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - - - - - - - -### QueryAllEvidenceResponse -QueryAllEvidenceResponse is the response type for the Query/AllEvidence RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence returns all evidences. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - - - - - - - - -### QueryEvidenceRequest -QueryEvidenceRequest is the request type for the Query/Evidence RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | - - - - - - - - -### QueryEvidenceResponse -QueryEvidenceResponse is the response type for the Query/Evidence RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | evidence returns the requested evidence. | - - - - - - - - - - - - - - -### Query -Query defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Evidence` | [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) | [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) | Evidence queries evidence based on evidence hash. | GET|/cosmos/evidence/v1beta1/evidence/{evidence_hash}| -| `AllEvidence` | [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) | [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) | AllEvidence queries all evidence. | GET|/cosmos/evidence/v1beta1/evidence| - - - - - - -

    Top

    - -## cosmos/evidence/v1beta1/tx.proto - - - - - -### MsgSubmitEvidence -MsgSubmitEvidence represents a message that supports submitting arbitrary -Evidence of misbehavior such as equivocation or counterfactual signing. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `submitter` | [string](#string) | | | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | - - - - - - - - -### MsgSubmitEvidenceResponse -MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | - - - - - - - - - - - - - - -### Msg -Msg defines the evidence Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SubmitEvidence` | [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) | [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) | SubmitEvidence submits an arbitrary Evidence of misbehavior such as equivocation or counterfactual signing. | | - - - - - - -

    Top

    - -## cosmos/genutil/v1beta1/genesis.proto - - - - - -### GenesisState -GenesisState defines the raw genesis transaction in JSON. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/gov/v1beta1/gov.proto - - - - - -### Deposit -Deposit defines an amount deposited by an account address to an active -proposal. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | | `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | @@ -4153,85 +4233,349 @@ proposal. - + -### DepositParams -DepositParams defines the params for deposits on governance proposals. +### CommunityPoolSpendProposalWithDeposit +CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal +with a deposit | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `min_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Minimum deposit for a proposal to enter voting period. | -| `max_deposit_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months. | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [string](#string) | | | +| `deposit` | [string](#string) | | | - + -### Proposal -Proposal defines the core field members of a governance proposal. +### DelegationDelegatorReward +DelegationDelegatorReward represents the properties +of a delegator's delegation reward. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | | -| `final_tally_result` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | | -| `submit_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `deposit_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `total_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `voting_start_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `voting_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `validator_address` | [string](#string) | | | +| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - + -### TallyParams -TallyParams defines the params for tallying votes on governance proposals. +### DelegatorStartingInfo +DelegatorStartingInfo represents the starting info for a delegator reward +period. It tracks the previous validator period, the delegation's amount of +staking token, and the creation height (to check later on if any slashes have +occurred). NOTE: Even though validators are slashed to whole staking tokens, +the delegators within the validator may be left with less than a full token, +thus sdk.Dec is used. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `quorum` | [bytes](#bytes) | | Minimum percentage of total stake needed to vote for a result to be considered valid. | -| `threshold` | [bytes](#bytes) | | Minimum proportion of Yes votes for proposal to pass. Default value: 0.5. | -| `veto_threshold` | [bytes](#bytes) | | Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Default value: 1/3. | +| `previous_period` | [uint64](#uint64) | | | +| `stake` | [string](#string) | | | +| `height` | [uint64](#uint64) | | | - + -### TallyResult -TallyResult defines a standard tally for a governance proposal. +### FeePool +FeePool is the global fee pool for distribution. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `yes` | [string](#string) | | | -| `abstain` | [string](#string) | | | -| `no` | [string](#string) | | | -| `no_with_veto` | [string](#string) | | | +| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - + -### TextProposal -TextProposal defines a standard text proposal whose changes need to be -manually updated in case of approval. +### Params +Params defines the set of params for the distribution module. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `community_tax` | [string](#string) | | | +| `base_proposer_reward` | [string](#string) | | | +| `bonus_proposer_reward` | [string](#string) | | | +| `withdraw_addr_enabled` | [bool](#bool) | | | + + + + + + + + +### ValidatorAccumulatedCommission +ValidatorAccumulatedCommission represents accumulated commission +for a validator kept as a running counter, can be withdrawn at any time. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | + + + + + + + + +### ValidatorCurrentRewards +ValidatorCurrentRewards represents current rewards and current +period for a validator kept as a running counter and incremented +each block as long as the validator's tokens remain constant. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `period` | [uint64](#uint64) | | | + + + + + + + + +### ValidatorHistoricalRewards +ValidatorHistoricalRewards represents historical rewards for a validator. +Height is implicit within the store key. +Cumulative reward ratio is the sum from the zeroeth period +until this period of rewards / tokens, per the spec. +The reference count indicates the number of objects +which might need to reference this historical entry at any point. +ReferenceCount = + number of outstanding delegations which ended the associated period (and + might need to read that record) + + number of slashes which ended the associated period (and might need to + read that record) + + one per validator for the zeroeth period, set on initialization + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `reference_count` | [uint32](#uint32) | | | + + + + + + + + +### ValidatorOutstandingRewards +ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards +for a validator inexpensive to track, allows simple sanity checks. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | + + + + + + + + +### ValidatorSlashEvent +ValidatorSlashEvent represents a validator slash event. +Height is implicit within the store key. +This is needed to calculate appropriate amount of staking tokens +for delegations which are withdrawn after a slash has occurred. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_period` | [uint64](#uint64) | | | +| `fraction` | [string](#string) | | | + + + + + + + + +### ValidatorSlashEvents +ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/upgrade/v1beta1/query.proto + + + + + +### QueryAppliedPlanRequest +QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `name` | [string](#string) | | name is the name of the applied plan to query for. | + + + + + + + + +### QueryAppliedPlanResponse +QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | + + + + + + + + +### QueryCurrentPlanRequest +QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC +method. + + + + + + + + +### QueryCurrentPlanResponse +QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | + + + + + + + + +### QueryUpgradedConsensusStateRequest +QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `last_height` | [int64](#int64) | | last height of the current chain must be sent in request as this is the height under which next consensus state is stored | + + + + + + + + +### QueryUpgradedConsensusStateResponse +QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | + + + + + + + + + + + + + + +### Query +Query defines the gRPC upgrade querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CurrentPlan` | [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) | [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) | CurrentPlan queries the current upgrade plan. | GET|/cosmos/upgrade/v1beta1/current_plan| +| `AppliedPlan` | [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) | [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) | AppliedPlan queries a previously applied upgrade plan by its name. | GET|/cosmos/upgrade/v1beta1/applied_plan/{name}| +| `UpgradedConsensusState` | [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) | [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) | UpgradedConsensusState queries the consensus state that will serve as a trusted kernel for the next version of this chain. It will only be stored at the last height of this chain. UpgradedConsensusState RPC not supported with legacy querier | GET|/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}| + + + + + + +

    Top

    + +## cosmos/upgrade/v1beta1/upgrade.proto + + + + + +### CancelSoftwareUpgradeProposal +CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software +upgrade. | Field | Type | Label | Description | @@ -4244,101 +4588,37 @@ manually updated in case of approval. - + -### Vote -Vote defines a vote on a governance proposal. -A Vote consists of a proposal ID, the voter, and the vote option. +### Plan +Plan specifies information about a planned upgrade and when it should occur. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | +| `name` | [string](#string) | | Sets the name for the upgrade. This name will be used by the upgraded version of the software to apply any special "on-upgrade" commands during the first BeginBlock method after the upgrade is applied. It is also used to detect whether a software version can handle a given upgrade. If no upgrade handler with this name has been set in the software, it will be assumed that the software is out-of-date when the upgrade Time or Height is reached and the software will exit. | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | The time after which the upgrade must be performed. Leave set to its zero value to use a pre-defined Height instead. | +| `height` | [int64](#int64) | | The height at which the upgrade must be performed. Only used if Time is not set. | +| `info` | [string](#string) | | Any application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to | +| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | IBC-enabled chains can opt-in to including the upgraded client state in its upgrade plan This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connecting chains can verify that the new upgraded client is valid by verifying a proof on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades | - + -### VotingParams -VotingParams defines the params for voting on governance proposals. +### SoftwareUpgradeProposal +SoftwareUpgradeProposal is a gov Content type for initiating a software +upgrade. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. | - - - - - - - - - - -### ProposalStatus -ProposalStatus enumerates the valid statuses of a proposal. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| PROPOSAL_STATUS_UNSPECIFIED | 0 | PROPOSAL_STATUS_UNSPECIFIED defines the default propopsal status. | -| PROPOSAL_STATUS_DEPOSIT_PERIOD | 1 | PROPOSAL_STATUS_DEPOSIT_PERIOD defines a proposal status during the deposit period. | -| PROPOSAL_STATUS_VOTING_PERIOD | 2 | PROPOSAL_STATUS_VOTING_PERIOD defines a proposal status during the voting period. | -| PROPOSAL_STATUS_PASSED | 3 | PROPOSAL_STATUS_PASSED defines a proposal status of a proposal that has passed. | -| PROPOSAL_STATUS_REJECTED | 4 | PROPOSAL_STATUS_REJECTED defines a proposal status of a proposal that has been rejected. | -| PROPOSAL_STATUS_FAILED | 5 | PROPOSAL_STATUS_FAILED defines a proposal status of a proposal that has failed. | - - - - - -### VoteOption -VoteOption enumerates the valid vote options for a given governance proposal. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| VOTE_OPTION_UNSPECIFIED | 0 | VOTE_OPTION_UNSPECIFIED defines a no-op vote option. | -| VOTE_OPTION_YES | 1 | VOTE_OPTION_YES defines a yes vote option. | -| VOTE_OPTION_ABSTAIN | 2 | VOTE_OPTION_ABSTAIN defines an abstain vote option. | -| VOTE_OPTION_NO | 3 | VOTE_OPTION_NO defines a no vote option. | -| VOTE_OPTION_NO_WITH_VETO | 4 | VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. | - - - - - - - - - - - -

    Top

    - -## cosmos/gov/v1beta1/genesis.proto - - - - - -### GenesisState -GenesisState defines the gov module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `starting_proposal_id` | [uint64](#uint64) | | starting_proposal_id is the ID of the starting proposal. | -| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | deposits defines all the deposits present at genesis. | -| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defines all the votes present at genesis. | -| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | proposals defines all the proposals present at genesis. | -| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | params defines all the paramaters of related to deposit. | -| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | params defines all the paramaters of related to voting. | -| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | params defines all the paramaters of related to tally. | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | @@ -4354,444 +4634,38 @@ GenesisState defines the gov module's genesis state. - +

    Top

    -## cosmos/gov/v1beta1/query.proto +## cosmos/base/kv/v1beta1/kv.proto - + -### QueryDepositRequest -QueryDepositRequest is the request type for the Query/Deposit RPC method. +### Pair +Pair defines a key/value bytes tuple. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | - + -### QueryDepositResponse -QueryDepositResponse is the response type for the Query/Deposit RPC method. +### Pairs +Pairs defines a repeated slice of Pair objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | - - - - - - - - -### QueryDepositsRequest -QueryDepositsRequest is the request type for the Query/Deposits RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - - - - - - - -### QueryDepositsResponse -QueryDepositsResponse is the response type for the Query/Deposits RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - - - - - - - - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | - - - - - - - - -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | voting_params defines the parameters related to voting. | -| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | deposit_params defines the parameters related to deposit. | -| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | tally_params defines the parameters related to tally. | - - - - - - - - -### QueryProposalRequest -QueryProposalRequest is the request type for the Query/Proposal RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - - - - - - - - -### QueryProposalResponse -QueryProposalResponse is the response type for the Query/Proposal RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | - - - - - - - - -### QueryProposalsRequest -QueryProposalsRequest is the request type for the Query/Proposals RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | proposal_status defines the status of the proposals. | -| `voter` | [string](#string) | | voter defines the voter address for the proposals. | -| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - - - - - - - -### QueryProposalsResponse -QueryProposalsResponse is the response type for the Query/Proposals RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - - - - - - - - -### QueryTallyResultRequest -QueryTallyResultRequest is the request type for the Query/Tally RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - - - - - - - - -### QueryTallyResultResponse -QueryTallyResultResponse is the response type for the Query/Tally RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | - - - - - - - - -### QueryVoteRequest -QueryVoteRequest is the request type for the Query/Vote RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `voter` | [string](#string) | | voter defines the oter address for the proposals. | - - - - - - - - -### QueryVoteResponse -QueryVoteResponse is the response type for the Query/Vote RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | - - - - - - - - -### QueryVotesRequest -QueryVotesRequest is the request type for the Query/Votes RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - - - - - - - -### QueryVotesResponse -QueryVotesResponse is the response type for the Query/Votes RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defined the queried votes. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - - - - - - - - - - - - - - -### Query -Query defines the gRPC querier service for gov module - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Proposal` | [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) | [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) | Proposal queries proposal details based on ProposalID. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}| -| `Proposals` | [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) | [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) | Proposals queries all proposals based on given status. | GET|/cosmos/gov/v1beta1/proposals| -| `Vote` | [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) | [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) | Vote queries voted information based on proposalID, voterAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}| -| `Votes` | [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) | [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) | Votes queries votes of a given proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes| -| `Params` | [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) | Params queries all parameters of the gov module. | GET|/cosmos/gov/v1beta1/params/{params_type}| -| `Deposit` | [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) | [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) | Deposit queries single deposit information based proposalID, depositAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}| -| `Deposits` | [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) | [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) | Deposits queries all deposits of a single proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits| -| `TallyResult` | [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) | [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) | TallyResult queries the tally of a proposal vote. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/tally| - - - - - - -

    Top

    - -## cosmos/gov/v1beta1/tx.proto - - - - - -### MsgDeposit -MsgDeposit defines a message to submit a deposit to an existing proposal. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - - - - - - - -### MsgDepositResponse -MsgDepositResponse defines the Msg/Deposit response type. - - - - - - - - -### MsgSubmitProposal -MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary -proposal Content. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `initial_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `proposer` | [string](#string) | | | - - - - - - - - -### MsgSubmitProposalResponse -MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | - - - - - - - - -### MsgVote -MsgVote defines a message to cast a vote. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - - - - - - - - -### MsgVoteResponse -MsgVoteResponse defines the Msg/Vote response type. - - - - - - - - - - - - - - -### Msg -Msg defines the bank Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SubmitProposal` | [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) | [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) | SubmitProposal defines a method to create new proposal given a content. | | -| `Vote` | [MsgVote](#cosmos.gov.v1beta1.MsgVote) | [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) | Vote defines a method to add a vote on a specific proposal. | | -| `Deposit` | [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) | [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) | Deposit defines a method to add deposit on a specific proposal. | | - - - - - - -

    Top

    - -## cosmos/mint/v1beta1/mint.proto - - - - - -### Minter -Minter represents the minting state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `inflation` | [string](#string) | | current annual inflation rate | -| `annual_provisions` | [string](#string) | | current annual expected provisions | - - - - - - - - -### Params -Params holds parameters for the mint module. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `mint_denom` | [string](#string) | | type of coin to mint | -| `inflation_rate_change` | [string](#string) | | maximum annual change in inflation rate | -| `inflation_max` | [string](#string) | | maximum inflation rate | -| `inflation_min` | [string](#string) | | minimum inflation rate | -| `goal_bonded` | [string](#string) | | goal of percent bonded atoms | -| `blocks_per_year` | [uint64](#uint64) | | expected blocks per year | +| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | @@ -4807,161 +4681,39 @@ Params holds parameters for the mint module. - +

    Top

    -## cosmos/mint/v1beta1/genesis.proto +## cosmos/base/abci/v1beta1/abci.proto - + -### GenesisState -GenesisState defines the mint module's genesis state. +### ABCIMessageLog +ABCIMessageLog defines a structure containing an indexed tx ABCI message log. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `minter` | [Minter](#cosmos.mint.v1beta1.Minter) | | minter is a space for holding current inflation information. | -| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines all the paramaters of the module. | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/mint/v1beta1/query.proto - - - - - -### QueryAnnualProvisionsRequest -QueryAnnualProvisionsRequest is the request type for the -Query/AnnualProvisions RPC method. +| `msg_index` | [uint32](#uint32) | | | +| `log` | [string](#string) | | | +| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | - + -### QueryAnnualProvisionsResponse -QueryAnnualProvisionsResponse is the response type for the -Query/AnnualProvisions RPC method. +### Attribute +Attribute defines an attribute wrapper where the key and value are +strings instead of raw bytes. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | - - - - - - - - -### QueryInflationRequest -QueryInflationRequest is the request type for the Query/Inflation RPC method. - - - - - - - - -### QueryInflationResponse -QueryInflationResponse is the response type for the Query/Inflation RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | - - - - - - - - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. - - - - - - - - -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | - - - - - - - - - - - - - - -### Query -Query provides defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Params` | [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) | Params returns the total set of minting parameters. | GET|/cosmos/mint/v1beta1/params| -| `Inflation` | [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) | [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) | Inflation returns the current minting inflation value. | GET|/cosmos/mint/v1beta1/inflation| -| `AnnualProvisions` | [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) | [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) | AnnualProvisions current minting annual provisions value. | GET|/cosmos/mint/v1beta1/annual_provisions| - - - - - - -

    Top

    - -## cosmos/params/v1beta1/params.proto - - - - - -### ParamChange -ParamChange defines an individual parameter change, for use in -ParameterChangeProposal. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `subspace` | [string](#string) | | | | `key` | [string](#string) | | | | `value` | [string](#string) | | | @@ -4970,17 +4722,147 @@ ParameterChangeProposal. - + -### ParameterChangeProposal -ParameterChangeProposal defines a proposal to change one or more parameters. +### GasInfo +GasInfo defines tx execution gas context. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | repeated | | +| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | +| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | + + + + + + + + +### MsgData +MsgData defines the data returned in a Result object during message +execution. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `msg_type` | [string](#string) | | | +| `data` | [bytes](#bytes) | | | + + + + + + + + +### Result +Result is the union of ResponseFormat and ResponseCheckTx. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | +| `log` | [string](#string) | | Log contains the log information from message or handler execution. | +| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | + + + + + + + + +### SearchTxsResult +SearchTxsResult defines a structure for querying txs pageable + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `total_count` | [uint64](#uint64) | | Count of all txs | +| `count` | [uint64](#uint64) | | Count of txs in current page | +| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | +| `page_total` | [uint64](#uint64) | | Count of total pages | +| `limit` | [uint64](#uint64) | | Max count txs per page | +| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | + + + + + + + + +### SimulationResponse +SimulationResponse defines the response generated when a transaction is +successfully simulated. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | +| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | + + + + + + + + +### StringEvent +StringEvent defines en Event object wrapper where all the attributes +contain key/value pairs that are strings instead of raw bytes. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `type` | [string](#string) | | | +| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | + + + + + + + + +### TxMsgData +TxMsgData defines a list of MsgData. A transaction will have a MsgData object +for each message. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | + + + + + + + + +### TxResponse +TxResponse defines a structure containing relevant tx data and metadata. The +tags are stringified and the log is JSON decoded. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | The block height | +| `txhash` | [string](#string) | | The transaction hash. | +| `codespace` | [string](#string) | | Namespace for the Code | +| `code` | [uint32](#uint32) | | Response code. | +| `data` | [string](#string) | | Result bytes, if any. | +| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | +| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | +| `info` | [string](#string) | | Additional information. May be non-deterministic. | +| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | +| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | +| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | +| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | @@ -4996,38 +4878,514 @@ ParameterChangeProposal defines a proposal to change one or more parameters. - +

    Top

    -## cosmos/params/v1beta1/query.proto +## cosmos/base/query/v1beta1/pagination.proto - + -### QueryParamsRequest -QueryParamsRequest is request type for the Query/Params RPC method. +### PageRequest +PageRequest is to be embedded in gRPC request messages for efficient +pagination. Ex: + + message SomeRequest { + Foo some_parameter = 1; + PageRequest pagination = 2; + } | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `subspace` | [string](#string) | | subspace defines the module to query the parameter for. | -| `key` | [string](#string) | | key defines the key of the parameter in the subspace. | +| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | +| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | +| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | +| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | - + -### QueryParamsResponse -QueryParamsResponse is response type for the Query/Params RPC method. +### PageResponse +PageResponse is to be embedded in gRPC response messages where the +corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | +| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | +| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/base/store/v1beta1/snapshot.proto + + + + + +### SnapshotIAVLItem +SnapshotIAVLItem is an exported IAVL node. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | +| `version` | [int64](#int64) | | | +| `height` | [int32](#int32) | | | + + + + + + + + +### SnapshotItem +SnapshotItem is an item contained in a rootmulti.Store snapshot. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | +| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | + + + + + + + + +### SnapshotStoreItem +SnapshotStoreItem contains metadata about a snapshotted store. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `name` | [string](#string) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/base/store/v1beta1/commit_info.proto + + + + + +### CommitID +CommitID defines the committment information when a specific store is +committed. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `version` | [int64](#int64) | | | +| `hash` | [bytes](#bytes) | | | + + + + + + + + +### CommitInfo +CommitInfo defines commit information used by the multi-store when committing +a version/height. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `version` | [int64](#int64) | | | +| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | + + + + + + + + +### StoreInfo +StoreInfo defines store-specific commit information. It contains a reference +between a store name and the commit ID. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `name` | [string](#string) | | | +| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/base/v1beta1/coin.proto + + + + + +### Coin +Coin defines a token with a denomination and an amount. + +NOTE: The amount field is an Int which implements the custom method +signatures required by gogoproto. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | + + + + + + + + +### DecCoin +DecCoin defines a token with a denomination and a decimal amount. + +NOTE: The amount field is an Dec which implements the custom method +signatures required by gogoproto. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | + + + + + + + + +### DecProto +DecProto defines a Protobuf wrapper around a Dec object. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `dec` | [string](#string) | | | + + + + + + + + +### IntProto +IntProto defines a Protobuf wrapper around an Int object. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `int` | [string](#string) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/base/tendermint/v1beta1/query.proto + + + + + +### GetBlockByHeightRequest +GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | | + + + + + + + + +### GetBlockByHeightResponse +GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | +| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | + + + + + + + + +### GetLatestBlockRequest +GetLatestBlockRequest is the request type for the Query/GetLatestBlock RPC method. + + + + + + + + +### GetLatestBlockResponse +GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | +| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | + + + + + + + + +### GetLatestValidatorSetRequest +GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetByHeight RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | + + + + + + + + +### GetLatestValidatorSetResponse +GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_height` | [int64](#int64) | | | +| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | + + + + + + + + +### GetNodeInfoRequest +GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. + + + + + + + + +### GetNodeInfoResponse +GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | +| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | + + + + + + + + +### GetSyncingRequest +GetSyncingRequest is the request type for the Query/GetSyncing RPC method. + + + + + + + + +### GetSyncingResponse +GetSyncingResponse is the response type for the Query/GetSyncing RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `syncing` | [bool](#bool) | | | + + + + + + + + +### GetValidatorSetByHeightRequest +GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | + + + + + + + + +### GetValidatorSetByHeightResponse +GetValidatorSetByHeightResponse is the response type for the Query/GetValidatorSetByHeight RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_height` | [int64](#int64) | | | +| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | + + + + + + + + +### Module +Module is the type for VersionInfo + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `path` | [string](#string) | | module path | +| `version` | [string](#string) | | module version | +| `sum` | [string](#string) | | checksum | + + + + + + + + +### Validator +Validator is the type for the validator-set. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `voting_power` | [int64](#int64) | | | +| `proposer_priority` | [int64](#int64) | | | + + + + + + + + +### VersionInfo +VersionInfo is the type for the GetNodeInfoResponse message. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `name` | [string](#string) | | | +| `app_name` | [string](#string) | | | +| `version` | [string](#string) | | | +| `git_commit` | [string](#string) | | | +| `build_tags` | [string](#string) | | | +| `go_version` | [string](#string) | | | +| `build_deps` | [Module](#cosmos.base.tendermint.v1beta1.Module) | repeated | | @@ -5040,14 +5398,153 @@ QueryParamsResponse is response type for the Query/Params RPC method. - + -### Query -Query defines the gRPC querier service. +### Service +Service defines the gRPC querier service for tendermint queries. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Params` | [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) | Params queries a specific parameter of a module, given its subspace and key. | GET|/cosmos/params/v1beta1/params| +| `GetNodeInfo` | [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) | [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) | GetNodeInfo queries the current node info. | GET|/cosmos/base/tendermint/v1beta1/node_info| +| `GetSyncing` | [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) | [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) | GetSyncing queries node syncing. | GET|/cosmos/base/tendermint/v1beta1/syncing| +| `GetLatestBlock` | [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) | [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) | GetLatestBlock returns the latest block. | GET|/cosmos/base/tendermint/v1beta1/blocks/latest| +| `GetBlockByHeight` | [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) | [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) | GetBlockByHeight queries block for given height. | GET|/cosmos/base/tendermint/v1beta1/blocks/{height}| +| `GetLatestValidatorSet` | [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) | [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) | GetLatestValidatorSet queries latest validator-set. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/latest| +| `GetValidatorSetByHeight` | [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) | [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) | GetValidatorSetByHeight queries validator-set at a given height. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/{height}| + + + + + + +

    Top

    + +## cosmos/base/snapshots/v1beta1/snapshot.proto + + + + + +### Metadata +Metadata contains SDK-specific snapshot metadata. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | + + + + + + + + +### Snapshot +Snapshot contains Tendermint state sync snapshot info. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [uint64](#uint64) | | | +| `format` | [uint32](#uint32) | | | +| `chunks` | [uint32](#uint32) | | | +| `hash` | [bytes](#bytes) | | | +| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/base/reflection/v1beta1/reflection.proto + + + + + +### ListAllInterfacesRequest +ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. + + + + + + + + +### ListAllInterfacesResponse +ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | + + + + + + + + +### ListImplementationsRequest +ListImplementationsRequest is the request type of the ListImplementations +RPC. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | + + + + + + + + +### ListImplementationsResponse +ListImplementationsResponse is the response type of the ListImplementations +RPC. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `implementation_message_names` | [string](#string) | repeated | | + + + + + + + + + + + + + + +### ReflectionService +ReflectionService defines a service for interface reflection. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ListAllInterfaces` | [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) | [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) | ListAllInterfaces lists all the interfaces registered in the interface registry. | GET|/cosmos/base/reflection/v1beta1/interfaces| +| `ListImplementations` | [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) | [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) | ListImplementations list all the concrete types that implement a given interface. | GET|/cosmos/base/reflection/v1beta1/interfaces/{interface_name}/implementations| @@ -5099,88 +5596,6 @@ liveness activity. - - - - - - - - - - - -

    Top

    - -## cosmos/slashing/v1beta1/genesis.proto - - - - - -### GenesisState -GenesisState defines the slashing module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | params defines all the paramaters of related to deposit. | -| `signing_infos` | [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) | repeated | signing_infos represents a map between validator addresses and their signing infos. | -| `missed_blocks` | [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) | repeated | signing_infos represents a map between validator addresses and their missed blocks. | - - - - - - - - -### MissedBlock -MissedBlock contains height and missed status as boolean. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `index` | [int64](#int64) | | index is the height at which the block was missed. | -| `missed` | [bool](#bool) | | missed is the missed status. | - - - - - - - - -### SigningInfo -SigningInfo stores validator signing info of corresponding address. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the validator address. | -| `validator_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | validator_signing_info represents the signing info of this validator. | - - - - - - - - -### ValidatorMissedBlocks -ValidatorMissedBlocks contains array of missed blocks of corresponding -address. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the validator address. | -| `missed_blocks` | [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) | repeated | missed_blocks is an array of missed blocks by the validator. | - - - - - @@ -5360,375 +5775,73 @@ Msg defines the slashing Msg service. - +

    Top

    -## cosmos/staking/v1beta1/staking.proto +## cosmos/slashing/v1beta1/genesis.proto - + -### Commission -Commission defines commission parameters for a given validator. +### GenesisState +GenesisState defines the slashing module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commission_rates` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | | -| `update_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | params defines all the paramaters of related to deposit. | +| `signing_infos` | [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) | repeated | signing_infos represents a map between validator addresses and their signing infos. | +| `missed_blocks` | [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) | repeated | signing_infos represents a map between validator addresses and their missed blocks. | - + -### CommissionRates -CommissionRates defines the initial commission rates to be used for creating -a validator. +### MissedBlock +MissedBlock contains height and missed status as boolean. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rate` | [string](#string) | | | -| `max_rate` | [string](#string) | | | -| `max_change_rate` | [string](#string) | | | +| `index` | [int64](#int64) | | index is the height at which the block was missed. | +| `missed` | [bool](#bool) | | missed is the missed status. | - + -### DVPair -DVPair is struct that just has a delegator-validator pair with no other data. -It is intended to be used as a marshalable pointer. For example, a DVPair can -be used to construct the key to getting an UnbondingDelegation from state. +### SigningInfo +SigningInfo stores validator signing info of corresponding address. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | +| `address` | [string](#string) | | address is the validator address. | +| `validator_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | validator_signing_info represents the signing info of this validator. | - + -### DVPairs -DVPairs defines an array of DVPair objects. +### ValidatorMissedBlocks +ValidatorMissedBlocks contains array of missed blocks of corresponding +address. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | - - - - - - - - -### DVVTriplet -DVVTriplet is struct that just has a delegator-validator-validator triplet -with no other data. It is intended to be used as a marshalable pointer. For -example, a DVVTriplet can be used to construct the key to getting a -Redelegation from state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | - - - - - - - - -### DVVTriplets -DVVTriplets defines an array of DVVTriplet objects. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | - - - - - - - - -### Delegation -Delegation represents the bond with tokens held by an account. It is -owned by one delegator, and is associated with the voting power of one -validator. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `shares` | [string](#string) | | | - - - - - - - - -### DelegationResponse -DelegationResponse is equivalent to Delegation except that it contains a -balance in addition to shares which is more suitable for client responses. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | -| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - - - - - - - - -### Description -Description defines a validator description. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `moniker` | [string](#string) | | | -| `identity` | [string](#string) | | | -| `website` | [string](#string) | | | -| `security_contact` | [string](#string) | | | -| `details` | [string](#string) | | | - - - - - - - - -### HistoricalInfo -HistoricalInfo contains header and validator information for a given block. -It is stored as part of staking module's state, which persists the `n` most -recent HistoricalInfo -(`n` is set by the staking module's `historical_entries` parameter). - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | -| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | - - - - - - - - -### Params -Params defines the parameters for the staking module. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `unbonding_time` | [google.protobuf.Duration](#google.protobuf.Duration) | | | -| `max_validators` | [uint32](#uint32) | | | -| `max_entries` | [uint32](#uint32) | | | -| `historical_entries` | [uint32](#uint32) | | | -| `bond_denom` | [string](#string) | | | - - - - - - - - -### Pool -Pool is used for tracking bonded and not-bonded token supply of the bond -denomination. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `not_bonded_tokens` | [string](#string) | | | -| `bonded_tokens` | [string](#string) | | | - - - - - - - - -### Redelegation -Redelegation contains the list of a particular delegator's redelegating bonds -from a particular source validator to a particular destination validator. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | -| `entries` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | repeated | redelegation entries | - - - - - - - - -### RedelegationEntry -RedelegationEntry defines a redelegation object with relevant metadata. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `creation_height` | [int64](#int64) | | | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `initial_balance` | [string](#string) | | | -| `shares_dst` | [string](#string) | | | - - - - - - - - -### RedelegationEntryResponse -RedelegationEntryResponse is equivalent to a RedelegationEntry except that it -contains a balance in addition to shares which is more suitable for client -responses. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | -| `balance` | [string](#string) | | | - - - - - - - - -### RedelegationResponse -RedelegationResponse is equivalent to a Redelegation except that its entries -contain a balance in addition to shares which is more suitable for client -responses. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | -| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | - - - - - - - - -### UnbondingDelegation -UnbondingDelegation stores all of a single delegator's unbonding bonds -for a single validator in an time-ordered list. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `entries` | [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) | repeated | unbonding delegation entries | - - - - - - - - -### UnbondingDelegationEntry -UnbondingDelegationEntry defines an unbonding object with relevant metadata. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `creation_height` | [int64](#int64) | | | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `initial_balance` | [string](#string) | | | -| `balance` | [string](#string) | | | - - - - - - - - -### ValAddresses -ValAddresses defines a repeated set of validator addresses. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `addresses` | [string](#string) | repeated | | - - - - - - - - -### Validator -Validator defines a validator, together with the total amount of the -Validator's bond shares and their exchange rate to coins. Slashing results in -a decrease in the exchange rate, allowing correct calculation of future -undelegations without iterating over delegators. When coins are delegated to -this validator, the validator is credited with a delegation whose number of -bond shares is based on the amount of coins delegated divided by the current -exchange rate. Voting power can be calculated as total bonded shares -multiplied by exchange rate. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `operator_address` | [string](#string) | | | -| `consensus_pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `jailed` | [bool](#bool) | | | -| `status` | [BondStatus](#cosmos.staking.v1beta1.BondStatus) | | | -| `tokens` | [string](#string) | | | -| `delegator_shares` | [string](#string) | | | -| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | -| `unbonding_height` | [int64](#int64) | | | -| `unbonding_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `commission` | [Commission](#cosmos.staking.v1beta1.Commission) | | | -| `min_self_delegation` | [string](#string) | | | +| `address` | [string](#string) | | address is the validator address. | +| `missed_blocks` | [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) | repeated | missed_blocks is an array of missed blocks by the validator. | @@ -5736,20 +5849,6 @@ multiplied by exchange rate. - - - -### BondStatus -BondStatus is the status of a validator. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| BOND_STATUS_UNSPECIFIED | 0 | UNSPECIFIED defines an invalid validator status. | -| BOND_STATUS_UNBONDED | 1 | UNBONDED defines a validator that is not bonded. | -| BOND_STATUS_UNBONDING | 2 | UNBONDING defines a validator that is unbonding. | -| BOND_STATUS_BONDED | 3 | BONDED defines a validator that is bonded. | - - @@ -5758,45 +5857,391 @@ BondStatus is the status of a validator. - +

    Top

    -## cosmos/staking/v1beta1/genesis.proto +## cosmos/evidence/v1beta1/evidence.proto - + + +### Equivocation +Equivocation implements the Evidence interface and defines evidence of double +signing misbehavior. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `power` | [int64](#int64) | | | +| `consensus_address` | [string](#string) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/evidence/v1beta1/query.proto + + + + + +### QueryAllEvidenceRequest +QueryEvidenceRequest is the request type for the Query/AllEvidence RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryAllEvidenceResponse +QueryAllEvidenceResponse is the response type for the Query/AllEvidence RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence returns all evidences. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + + + +### QueryEvidenceRequest +QueryEvidenceRequest is the request type for the Query/Evidence RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | + + + + + + + + +### QueryEvidenceResponse +QueryEvidenceResponse is the response type for the Query/Evidence RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | evidence returns the requested evidence. | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Evidence` | [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) | [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) | Evidence queries evidence based on evidence hash. | GET|/cosmos/evidence/v1beta1/evidence/{evidence_hash}| +| `AllEvidence` | [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) | [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) | AllEvidence queries all evidence. | GET|/cosmos/evidence/v1beta1/evidence| + + + + + + +

    Top

    + +## cosmos/evidence/v1beta1/tx.proto + + + + + +### MsgSubmitEvidence +MsgSubmitEvidence represents a message that supports submitting arbitrary +Evidence of misbehavior such as equivocation or counterfactual signing. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `submitter` | [string](#string) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | + + + + + + + + +### MsgSubmitEvidenceResponse +MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | + + + + + + + + + + + + + + +### Msg +Msg defines the evidence Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `SubmitEvidence` | [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) | [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) | SubmitEvidence submits an arbitrary Evidence of misbehavior such as equivocation or counterfactual signing. | | + + + + + + +

    Top

    + +## cosmos/evidence/v1beta1/genesis.proto + + + + ### GenesisState -GenesisState defines the staking module's genesis state. +GenesisState defines the evidence module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params defines all the paramaters of related to deposit. | -| `last_total_power` | [bytes](#bytes) | | last_total_power tracks the total amounts of bonded tokens recorded during the previous end block. | -| `last_validator_powers` | [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) | repeated | last_validator_powers is a special index that provides a historical list of the last-block's bonded validators. | -| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | delegations defines the validator set at genesis. | -| `delegations` | [Delegation](#cosmos.staking.v1beta1.Delegation) | repeated | delegations defines the delegations active at genesis. | -| `unbonding_delegations` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | unbonding_delegations defines the unbonding delegations active at genesis. | -| `redelegations` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | repeated | redelegations defines the redelegations active at genesis. | -| `exported` | [bool](#bool) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | + - + -### LastValidatorPower -LastValidatorPower required for validator set update logic. + + + + + + + +

    Top

    + +## cosmos/auth/v1beta1/auth.proto + + + + + +### BaseAccount +BaseAccount defines a base account type. It contains all the necessary fields +for basic account functionality. Any custom account type should extend this +type for additional functionality (e.g. vesting). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address of the validator. | -| `power` | [int64](#int64) | | power defines the power of the validator. | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `account_number` | [uint64](#uint64) | | | +| `sequence` | [uint64](#uint64) | | | + + + + + + + + +### ModuleAccount +ModuleAccount defines an account for modules that holds coins on a pool. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | +| `name` | [string](#string) | | | +| `permissions` | [string](#string) | repeated | | + + + + + + + + +### Params +Params defines the parameters for the auth module. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `max_memo_characters` | [uint64](#uint64) | | | +| `tx_sig_limit` | [uint64](#uint64) | | | +| `tx_size_cost_per_byte` | [uint64](#uint64) | | | +| `sig_verify_cost_ed25519` | [uint64](#uint64) | | | +| `sig_verify_cost_secp256k1` | [uint64](#uint64) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/auth/v1beta1/query.proto + + + + + +### QueryAccountRequest +QueryAccountRequest is the request type for the Query/Account RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address defines the address to query for. | + + + + + + + + +### QueryAccountResponse +QueryAccountResponse is the response type for the Query/Account RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | + + + + + + + + +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. + + + + + + + + +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines the parameters of the module. | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Account` | [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) | [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) | Account returns account details based on address. | GET|/cosmos/auth/v1beta1/accounts/{address}| +| `Params` | [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) | Params queries all parameters. | GET|/cosmos/auth/v1beta1/params| + + + + + + +

    Top

    + +## cosmos/auth/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the auth module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines all the paramaters of the module. | +| `accounts` | [google.protobuf.Any](#google.protobuf.Any) | repeated | accounts are the accounts present at genesis. | @@ -6482,90 +6927,429 @@ Msg defines the staking Msg service. - +

    Top

    -## cosmos/tx/signing/v1beta1/signing.proto +## cosmos/staking/v1beta1/genesis.proto - + -### SignatureDescriptor -SignatureDescriptor is a convenience type which represents the full data for -a signature including the public key of the signer, signing modes and the -signature itself. It is primarily used for coordinating signatures between -clients. +### GenesisState +GenesisState defines the staking module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer | -| `data` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | | | -| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | +| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params defines all the paramaters of related to deposit. | +| `last_total_power` | [bytes](#bytes) | | last_total_power tracks the total amounts of bonded tokens recorded during the previous end block. | +| `last_validator_powers` | [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) | repeated | last_validator_powers is a special index that provides a historical list of the last-block's bonded validators. | +| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | delegations defines the validator set at genesis. | +| `delegations` | [Delegation](#cosmos.staking.v1beta1.Delegation) | repeated | delegations defines the delegations active at genesis. | +| `unbonding_delegations` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | unbonding_delegations defines the unbonding delegations active at genesis. | +| `redelegations` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | repeated | redelegations defines the redelegations active at genesis. | +| `exported` | [bool](#bool) | | | - + -### SignatureDescriptor.Data -Data represents signature data +### LastValidatorPower +LastValidatorPower required for validator set update logic. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `single` | [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) | | single represents a single signer | -| `multi` | [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) | | multi represents a multisig signer | +| `address` | [string](#string) | | address is the address of the validator. | +| `power` | [int64](#int64) | | power defines the power of the validator. | + - + -### SignatureDescriptor.Data.Multi -Multi is the signature data for a multisig public key + + + + + + + +

    Top

    + +## cosmos/staking/v1beta1/staking.proto + + + + + +### Commission +Commission defines commission parameters for a given validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | -| `signatures` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | repeated | signatures is the signatures of the multi-signature | +| `commission_rates` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | | +| `update_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### SignatureDescriptor.Data.Single -Single is the signature data for a single signer +### CommissionRates +CommissionRates defines the initial commission rates to be used for creating +a validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `mode` | [SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | -| `signature` | [bytes](#bytes) | | signature is the raw signature bytes | +| `rate` | [string](#string) | | | +| `max_rate` | [string](#string) | | | +| `max_change_rate` | [string](#string) | | | - + -### SignatureDescriptors -SignatureDescriptors wraps multiple SignatureDescriptor's. +### DVPair +DVPair is struct that just has a delegator-validator pair with no other data. +It is intended to be used as a marshalable pointer. For example, a DVPair can +be used to construct the key to getting an UnbondingDelegation from state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | + + + + + + + + +### DVPairs +DVPairs defines an array of DVPair objects. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | + + + + + + + + +### DVVTriplet +DVVTriplet is struct that just has a delegator-validator-validator triplet +with no other data. It is intended to be used as a marshalable pointer. For +example, a DVVTriplet can be used to construct the key to getting a +Redelegation from state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | + + + + + + + + +### DVVTriplets +DVVTriplets defines an array of DVVTriplet objects. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | + + + + + + + + +### Delegation +Delegation represents the bond with tokens held by an account. It is +owned by one delegator, and is associated with the voting power of one +validator. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `shares` | [string](#string) | | | + + + + + + + + +### DelegationResponse +DelegationResponse is equivalent to Delegation except that it contains a +balance in addition to shares which is more suitable for client responses. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | + + + + + + + + +### Description +Description defines a validator description. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `moniker` | [string](#string) | | | +| `identity` | [string](#string) | | | +| `website` | [string](#string) | | | +| `security_contact` | [string](#string) | | | +| `details` | [string](#string) | | | + + + + + + + + +### HistoricalInfo +HistoricalInfo contains header and validator information for a given block. +It is stored as part of staking module's state, which persists the `n` most +recent HistoricalInfo +(`n` is set by the staking module's `historical_entries` parameter). + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | +| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | + + + + + + + + +### Params +Params defines the parameters for the staking module. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `unbonding_time` | [google.protobuf.Duration](#google.protobuf.Duration) | | | +| `max_validators` | [uint32](#uint32) | | | +| `max_entries` | [uint32](#uint32) | | | +| `historical_entries` | [uint32](#uint32) | | | +| `bond_denom` | [string](#string) | | | + + + + + + + + +### Pool +Pool is used for tracking bonded and not-bonded token supply of the bond +denomination. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `not_bonded_tokens` | [string](#string) | | | +| `bonded_tokens` | [string](#string) | | | + + + + + + + + +### Redelegation +Redelegation contains the list of a particular delegator's redelegating bonds +from a particular source validator to a particular destination validator. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | +| `entries` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | repeated | redelegation entries | + + + + + + + + +### RedelegationEntry +RedelegationEntry defines a redelegation object with relevant metadata. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `creation_height` | [int64](#int64) | | | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `initial_balance` | [string](#string) | | | +| `shares_dst` | [string](#string) | | | + + + + + + + + +### RedelegationEntryResponse +RedelegationEntryResponse is equivalent to a RedelegationEntry except that it +contains a balance in addition to shares which is more suitable for client +responses. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | +| `balance` | [string](#string) | | | + + + + + + + + +### RedelegationResponse +RedelegationResponse is equivalent to a Redelegation except that its entries +contain a balance in addition to shares which is more suitable for client +responses. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | +| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | + + + + + + + + +### UnbondingDelegation +UnbondingDelegation stores all of a single delegator's unbonding bonds +for a single validator in an time-ordered list. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | +| `entries` | [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) | repeated | unbonding delegation entries | + + + + + + + + +### UnbondingDelegationEntry +UnbondingDelegationEntry defines an unbonding object with relevant metadata. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `creation_height` | [int64](#int64) | | | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `initial_balance` | [string](#string) | | | +| `balance` | [string](#string) | | | + + + + + + + + +### ValAddresses +ValAddresses defines a repeated set of validator addresses. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `addresses` | [string](#string) | repeated | | + + + + + + + + +### Validator +Validator defines a validator, together with the total amount of the +Validator's bond shares and their exchange rate to coins. Slashing results in +a decrease in the exchange rate, allowing correct calculation of future +undelegations without iterating over delegators. When coins are delegated to +this validator, the validator is credited with a delegation whose number of +bond shares is based on the amount of coins delegated divided by the current +exchange rate. Voting power can be calculated as total bonded shares +multiplied by exchange rate. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `operator_address` | [string](#string) | | | +| `consensus_pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `jailed` | [bool](#bool) | | | +| `status` | [BondStatus](#cosmos.staking.v1beta1.BondStatus) | | | +| `tokens` | [string](#string) | | | +| `delegator_shares` | [string](#string) | | | +| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | +| `unbonding_height` | [int64](#int64) | | | +| `unbonding_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `commission` | [Commission](#cosmos.staking.v1beta1.Commission) | | | +| `min_self_delegation` | [string](#string) | | | @@ -6574,17 +7358,17 @@ SignatureDescriptors wraps multiple SignatureDescriptor's. - + -### SignMode -SignMode represents a signing mode with its own security guarantees. +### BondStatus +BondStatus is the status of a validator. | Name | Number | Description | | ---- | ------ | ----------- | -| SIGN_MODE_UNSPECIFIED | 0 | SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected | -| SIGN_MODE_DIRECT | 1 | SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified with raw bytes from Tx | -| SIGN_MODE_TEXTUAL | 2 | SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable textual representation on top of the binary representation from SIGN_MODE_DIRECT | -| SIGN_MODE_LEGACY_AMINO_JSON | 127 | SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses Amino JSON and will be removed in the future | +| BOND_STATUS_UNSPECIFIED | 0 | UNSPECIFIED defines an invalid validator status. | +| BOND_STATUS_UNBONDED | 1 | UNBONDED defines a validator that is not bonded. | +| BOND_STATUS_UNBONDING | 2 | UNBONDING defines a validator that is unbonding. | +| BOND_STATUS_BONDED | 3 | BONDED defines a validator that is bonded. | @@ -6595,566 +7379,6 @@ SignMode represents a signing mode with its own security guarantees. - -

    Top

    - -## cosmos/tx/v1beta1/tx.proto - - - - - -### AuthInfo -AuthInfo describes the fee and signer modes that are used to sign a -transaction. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signer_infos` | [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) | repeated | signer_infos defines the signing modes for the required signers. The number and order of elements must match the required signers from TxBody's messages. The first element is the primary signer and the one which pays the fee. | -| `fee` | [Fee](#cosmos.tx.v1beta1.Fee) | | Fee is the fee and gas limit for the transaction. The first signer is the primary signer and the one which pays the fee. The fee can be calculated based on the cost of evaluating the body and doing signature verification of the signers. This can be estimated via simulation. | - - - - - - - - -### Fee -Fee includes the amount of coins paid in fees and the maximum -gas to be used by the transaction. The ratio yields an effective "gasprice", -which must be above some miminum to be accepted into the mempool. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | amount is the amount of coins to be paid as a fee | -| `gas_limit` | [uint64](#uint64) | | gas_limit is the maximum gas that can be used in transaction processing before an out of gas error occurs | -| `payer` | [string](#string) | | if unset, the first signer is responsible for paying the fees. If set, the specified account must pay the fees. the payer must be a tx signer (and thus have signed this field in AuthInfo). setting this field does *not* change the ordering of required signers for the transaction. | -| `granter` | [string](#string) | | if set, the fee payer (either the first signer or the value of the payer field) requests that a fee grant be used to pay fees instead of the fee payer's own balance. If an appropriate fee grant does not exist or the chain does not support fee grants, this will fail | - - - - - - - - -### ModeInfo -ModeInfo describes the signing mode of a single or nested multisig signer. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `single` | [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) | | single represents a single signer | -| `multi` | [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) | | multi represents a nested multisig signer | - - - - - - - - -### ModeInfo.Multi -Multi is the mode info for a multisig public key - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | -| `mode_infos` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | repeated | mode_infos is the corresponding modes of the signers of the multisig which could include nested multisig public keys | - - - - - - - - -### ModeInfo.Single -Single is the mode info for a single signer. It is structured as a message -to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the -future - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | - - - - - - - - -### SignDoc -SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `body_bytes` | [bytes](#bytes) | | body_bytes is protobuf serialization of a TxBody that matches the representation in TxRaw. | -| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in TxRaw. | -| `chain_id` | [string](#string) | | chain_id is the unique identifier of the chain this transaction targets. It prevents signed transactions from being used on another chain by an attacker | -| `account_number` | [uint64](#uint64) | | account_number is the account number of the account in state | - - - - - - - - -### SignerInfo -SignerInfo describes the public key and signing mode of a single top-level -signer. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer. It is optional for accounts that already exist in state. If unset, the verifier can use the required \ signer address for this position and lookup the public key. | -| `mode_info` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | | mode_info describes the signing mode of the signer and is a nested structure to support nested multisig pubkey's | -| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | - - - - - - - - -### Tx -Tx is the standard type used for broadcasting transactions. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `body` | [TxBody](#cosmos.tx.v1beta1.TxBody) | | body is the processable content of the transaction | -| `auth_info` | [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) | | auth_info is the authorization related content of the transaction, specifically signers, signer modes and fee | -| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | - - - - - - - - -### TxBody -TxBody is the body of a transaction that all signers sign over. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `messages` | [google.protobuf.Any](#google.protobuf.Any) | repeated | messages is a list of messages to be executed. The required signers of those messages define the number and order of elements in AuthInfo's signer_infos and Tx's signatures. Each required signer address is added to the list only the first time it occurs. By convention, the first required signer (usually from the first message) is referred to as the primary signer and pays the fee for the whole transaction. | -| `memo` | [string](#string) | | memo is any arbitrary memo to be added to the transaction | -| `timeout_height` | [uint64](#uint64) | | timeout is the block height after which this transaction will not be processed by the chain | -| `extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, the transaction will be rejected | -| `non_critical_extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, they will be ignored | - - - - - - - - -### TxRaw -TxRaw is a variant of Tx that pins the signer's exact binary representation -of body and auth_info. This is used for signing, broadcasting and -verification. The binary `serialize(tx: TxRaw)` is stored in Tendermint and -the hash `sha256(serialize(tx: TxRaw))` becomes the "txhash", commonly used -as the transaction ID. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `body_bytes` | [bytes](#bytes) | | body_bytes is a protobuf serialization of a TxBody that matches the representation in SignDoc. | -| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in SignDoc. | -| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/tx/v1beta1/service.proto - - - - - -### BroadcastTxRequest -BroadcastTxRequest is the request type for the Service.BroadcastTxRequest -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | -| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | - - - - - - - - -### BroadcastTxResponse -BroadcastTxResponse is the response type for the -Service.BroadcastTx method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - - - - - - - - -### GetTxRequest -GetTxRequest is the request type for the Service.GetTx -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | - - - - - - - - -### GetTxResponse -GetTxResponse is the response type for the Service.GetTx method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the queried transaction. | -| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - - - - - - - - -### GetTxsEventRequest -GetTxsEventRequest is the request type for the Service.TxsByEvents -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `events` | [string](#string) | repeated | events is the list of transaction event type. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - - - - - - - - -### GetTxsEventResponse -GetTxsEventResponse is the response type for the Service.TxsByEvents -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `txs` | [Tx](#cosmos.tx.v1beta1.Tx) | repeated | txs is the list of queried transactions. | -| `tx_responses` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | tx_responses is the list of queried TxResponses. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - - - - - - - - -### SimulateRequest -SimulateRequest is the request type for the Service.Simulate -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | - - - - - - - - -### SimulateResponse -SimulateResponse is the response type for the -Service.SimulateRPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `gas_info` | [cosmos.base.abci.v1beta1.GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | gas_info is the information about gas used in the simulation. | -| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | result is the result of the simulation. | - - - - - - - - - - -### BroadcastMode -BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| BROADCAST_MODE_UNSPECIFIED | 0 | zero-value for mode ordering | -| BROADCAST_MODE_BLOCK | 1 | BROADCAST_MODE_BLOCK defines a tx broadcasting mode where the client waits for the tx to be committed in a block. | -| BROADCAST_MODE_SYNC | 2 | BROADCAST_MODE_SYNC defines a tx broadcasting mode where the client waits for a CheckTx execution response only. | -| BROADCAST_MODE_ASYNC | 3 | BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns immediately. | - - - - - - - - - -### Service -Service defines a gRPC service for interacting with transactions. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Simulate` | [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) | [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) | Simulate simulates executing a transaction for estimating gas usage. | POST|/cosmos/tx/v1beta1/simulate| -| `GetTx` | [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) | [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) | GetTx fetches a tx by hash. | GET|/cosmos/tx/v1beta1/txs/{hash}| -| `BroadcastTx` | [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) | [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) | BroadcastTx broadcast transaction. | POST|/cosmos/tx/v1beta1/txs| -| `GetTxsEvent` | [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) | [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) | GetTxsEvent fetches txs by event. | GET|/cosmos/tx/v1beta1/txs| - - - - - - -

    Top

    - -## cosmos/upgrade/v1beta1/upgrade.proto - - - - - -### CancelSoftwareUpgradeProposal -CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software -upgrade. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | - - - - - - - - -### Plan -Plan specifies information about a planned upgrade and when it should occur. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | Sets the name for the upgrade. This name will be used by the upgraded version of the software to apply any special "on-upgrade" commands during the first BeginBlock method after the upgrade is applied. It is also used to detect whether a software version can handle a given upgrade. If no upgrade handler with this name has been set in the software, it will be assumed that the software is out-of-date when the upgrade Time or Height is reached and the software will exit. | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | The time after which the upgrade must be performed. Leave set to its zero value to use a pre-defined Height instead. | -| `height` | [int64](#int64) | | The height at which the upgrade must be performed. Only used if Time is not set. | -| `info` | [string](#string) | | Any application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to | -| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | IBC-enabled chains can opt-in to including the upgraded client state in its upgrade plan This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connecting chains can verify that the new upgraded client is valid by verifying a proof on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades | - - - - - - - - -### SoftwareUpgradeProposal -SoftwareUpgradeProposal is a gov Content type for initiating a software -upgrade. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/upgrade/v1beta1/query.proto - - - - - -### QueryAppliedPlanRequest -QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | name is the name of the applied plan to query for. | - - - - - - - - -### QueryAppliedPlanResponse -QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | - - - - - - - - -### QueryCurrentPlanRequest -QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC -method. - - - - - - - - -### QueryCurrentPlanResponse -QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | - - - - - - - - -### QueryUpgradedConsensusStateRequest -QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `last_height` | [int64](#int64) | | last height of the current chain must be sent in request as this is the height under which next consensus state is stored | - - - - - - - - -### QueryUpgradedConsensusStateResponse -QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | - - - - - - - - - - - - - - -### Query -Query defines the gRPC upgrade querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CurrentPlan` | [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) | [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) | CurrentPlan queries the current upgrade plan. | GET|/cosmos/upgrade/v1beta1/current_plan| -| `AppliedPlan` | [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) | [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) | AppliedPlan queries a previously applied upgrade plan by its name. | GET|/cosmos/upgrade/v1beta1/applied_plan/{name}| -| `UpgradedConsensusState` | [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) | [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) | UpgradedConsensusState queries the consensus state that will serve as a trusted kernel for the next version of this chain. It will only be stored at the last height of this chain. UpgradedConsensusState RPC not supported with legacy querier | GET|/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}| - - - - -

    Top

    @@ -7315,63 +7539,38 @@ periodically vests by unlocking coins during each specified period. - +

    Top

    -## ibc/applications/transfer/v1/transfer.proto +## cosmos/params/v1beta1/query.proto - + -### DenomTrace -DenomTrace contains the base denomination for ICS20 fungible tokens and the -source tracing information path. +### QueryParamsRequest +QueryParamsRequest is request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `path` | [string](#string) | | path defines the chain of port/channel identifiers used for tracing the source of the fungible token. | -| `base_denom` | [string](#string) | | base denomination of the relayed fungible token. | +| `subspace` | [string](#string) | | subspace defines the module to query the parameter for. | +| `key` | [string](#string) | | key defines the key of the parameter in the subspace. | - + -### FungibleTokenPacketData -FungibleTokenPacketData defines a struct for the packet payload -See FungibleTokenPacketData spec: -https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures +### QueryParamsResponse +QueryParamsResponse is response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | the token denomination to be transferred | -| `amount` | [uint64](#uint64) | | the token amount to be transferred | -| `sender` | [string](#string) | | the sender address | -| `receiver` | [string](#string) | | the recipient address on the destination chain | - - - - - - - - -### Params -Params defines the set of IBC transfer parameters. -NOTE: To prevent a single token from being transferred, set the -TransfersEnabled parameter to true and then set the bank module's SendEnabled -parameter for the denomination to false. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `send_enabled` | [bool](#bool) | | send_enabled enables or disables all cross-chain token transfers from this chain. | -| `receive_enabled` | [bool](#bool) | | receive_enabled enables or disables all cross-chain token transfers to this chain. | +| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | @@ -7383,28 +7582,56 @@ parameter for the denomination to false. + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Params` | [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) | Params queries a specific parameter of a module, given its subspace and key. | GET|/cosmos/params/v1beta1/params| + - +

    Top

    -## ibc/applications/transfer/v1/genesis.proto +## cosmos/params/v1beta1/params.proto - + -### GenesisState -GenesisState defines the ibc-transfer genesis state +### ParamChange +ParamChange defines an individual parameter change, for use in +ParameterChangeProposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | -| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | +| `subspace` | [string](#string) | | | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | + + + + + + + + +### ParameterChangeProposal +ParameterChangeProposal defines a proposal to change one or more parameters. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | repeated | | @@ -7538,6 +7765,170 @@ Query provides defines the gRPC querier service. + +

    Top

    + +## ibc/applications/transfer/v1/tx.proto + + + + + +### MsgTransfer +MsgTransfer defines a msg to transfer fungible tokens (i.e Coins) between +ICS20 enabled chains. See ICS Spec here: +https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `source_port` | [string](#string) | | the port on which the packet will be sent | +| `source_channel` | [string](#string) | | the channel by which the packet will be sent | +| `token` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | the tokens to be transferred | +| `sender` | [string](#string) | | the sender address | +| `receiver` | [string](#string) | | the recipient address on the destination chain | +| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Timeout height relative to the current block height. The timeout is disabled when set to 0. | +| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp (in nanoseconds) relative to the current block timestamp. The timeout is disabled when set to 0. | + + + + + + + + +### MsgTransferResponse +MsgTransferResponse defines the Msg/Transfer response type. + + + + + + + + + + + + + + +### Msg +Msg defines the ibc/transfer Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Transfer` | [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) | [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) | Transfer defines a rpc handler method for MsgTransfer. | | + + + + + + +

    Top

    + +## ibc/applications/transfer/v1/transfer.proto + + + + + +### DenomTrace +DenomTrace contains the base denomination for ICS20 fungible tokens and the +source tracing information path. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `path` | [string](#string) | | path defines the chain of port/channel identifiers used for tracing the source of the fungible token. | +| `base_denom` | [string](#string) | | base denomination of the relayed fungible token. | + + + + + + + + +### FungibleTokenPacketData +FungibleTokenPacketData defines a struct for the packet payload +See FungibleTokenPacketData spec: +https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | the token denomination to be transferred | +| `amount` | [uint64](#uint64) | | the token amount to be transferred | +| `sender` | [string](#string) | | the sender address | +| `receiver` | [string](#string) | | the recipient address on the destination chain | + + + + + + + + +### Params +Params defines the set of IBC transfer parameters. +NOTE: To prevent a single token from being transferred, set the +TransfersEnabled parameter to true and then set the bank module's SendEnabled +parameter for the denomination to false. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `send_enabled` | [bool](#bool) | | send_enabled enables or disables all cross-chain token transfers from this chain. | +| `receive_enabled` | [bool](#bool) | | receive_enabled enables or disables all cross-chain token transfers to this chain. | + + + + + + + + + + + + + + + + +

    Top

    + +## ibc/applications/transfer/v1/genesis.proto + + + + + +### GenesisState +GenesisState defines the ibc-transfer genesis state + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | | +| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | +| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | + + + + + + + + + + + + + + +

    Top

    @@ -7663,40 +8054,172 @@ Params defines the set of IBC light client parameters. - +

    Top

    -## ibc/applications/transfer/v1/tx.proto +## ibc/core/client/v1/query.proto - + -### MsgTransfer -MsgTransfer defines a msg to transfer fungible tokens (i.e Coins) between -ICS20 enabled chains. See ICS Spec here: -https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures +### QueryClientParamsRequest +QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. + + + + + + + + +### QueryClientParamsResponse +QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `source_port` | [string](#string) | | the port on which the packet will be sent | -| `source_channel` | [string](#string) | | the channel by which the packet will be sent | -| `token` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | the tokens to be transferred | -| `sender` | [string](#string) | | the sender address | -| `receiver` | [string](#string) | | the recipient address on the destination chain | -| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Timeout height relative to the current block height. The timeout is disabled when set to 0. | -| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp (in nanoseconds) relative to the current block timestamp. The timeout is disabled when set to 0. | +| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | - + -### MsgTransferResponse -MsgTransferResponse defines the Msg/Transfer response type. +### QueryClientStateRequest +QueryClientStateRequest is the request type for the Query/ClientState RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client state unique identifier | + + + + + + + + +### QueryClientStateResponse +QueryClientStateResponse is the response type for the Query/ClientState RPC +method. Besides the client state, it includes a proof and the height from +which the proof was retrieved. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state associated with the request identifier | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | + + + + + + + + +### QueryClientStatesRequest +QueryClientStatesRequest is the request type for the Query/ClientStates RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | + + + + + + + + +### QueryClientStatesResponse +QueryClientStatesResponse is the response type for the Query/ClientStates RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_states` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | list of stored ClientStates of the chain. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | + + + + + + + + +### QueryConsensusStateRequest +QueryConsensusStateRequest is the request type for the Query/ConsensusState +RPC method. Besides the consensus state, it includes a proof and the height +from which the proof was retrieved. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client identifier | +| `revision_number` | [uint64](#uint64) | | consensus state revision number | +| `revision_height` | [uint64](#uint64) | | consensus state revision height | +| `latest_height` | [bool](#bool) | | latest_height overrrides the height field and queries the latest stored ConsensusState | + + + + + + + + +### QueryConsensusStateResponse +QueryConsensusStateResponse is the response type for the Query/ConsensusState +RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client identifier at the given height | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | + + + + + + + + +### QueryConsensusStatesRequest +QueryConsensusStatesRequest is the request type for the Query/ConsensusStates +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | + + + + + + + + +### QueryConsensusStatesResponse +QueryConsensusStatesResponse is the response type for the +Query/ConsensusStates RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states associated with the identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | @@ -7709,14 +8232,229 @@ MsgTransferResponse defines the Msg/Transfer response type. - + -### Msg -Msg defines the ibc/transfer Msg service. +### Query +Query provides defines the gRPC querier service | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Transfer` | [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) | [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) | Transfer defines a rpc handler method for MsgTransfer. | | +| `ClientState` | [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) | [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) | ClientState queries an IBC light client. | GET|/ibc/core/client/v1beta1/client_states/{client_id}| +| `ClientStates` | [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) | [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) | ClientStates queries all the IBC light clients of a chain. | GET|/ibc/core/client/v1beta1/client_states| +| `ConsensusState` | [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) | [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) | ConsensusState queries a consensus state associated with a client state at a given height. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}/revision/{revision_number}/height/{revision_height}| +| `ConsensusStates` | [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) | [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) | ConsensusStates queries all the consensus state associated with a given client. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}| +| `ClientParams` | [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) | [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) | ClientParams queries all parameters of the ibc client. | GET|/ibc/client/v1beta1/params| + + + + + + +

    Top

    + +## ibc/core/client/v1/tx.proto + + + + + +### MsgCreateClient +MsgCreateClient defines a message to create an IBC client + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | light client state | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client that corresponds to a given height. | +| `signer` | [string](#string) | | signer address | + + + + + + + + +### MsgCreateClientResponse +MsgCreateClientResponse defines the Msg/CreateClient response type. + + + + + + + + +### MsgSubmitMisbehaviour +MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for +light client misbehaviour. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client unique identifier | +| `misbehaviour` | [google.protobuf.Any](#google.protobuf.Any) | | misbehaviour used for freezing the light client | +| `signer` | [string](#string) | | signer address | + + + + + + + + +### MsgSubmitMisbehaviourResponse +MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. + + + + + + + + +### MsgUpdateClient +MsgUpdateClient defines an sdk.Msg to update a IBC client state using +the given header. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client unique identifier | +| `header` | [google.protobuf.Any](#google.protobuf.Any) | | header to update the light client | +| `signer` | [string](#string) | | signer address | + + + + + + + + +### MsgUpdateClientResponse +MsgUpdateClientResponse defines the Msg/UpdateClient response type. + + + + + + + + +### MsgUpgradeClient +MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client unique identifier | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded client state | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded consensus state, only contains enough information to serve as a basis of trust in update logic | +| `proof_upgrade_client` | [bytes](#bytes) | | proof that old chain committed to new client | +| `proof_upgrade_consensus_state` | [bytes](#bytes) | | proof that old chain committed to new consensus state | +| `signer` | [string](#string) | | signer address | + + + + + + + + +### MsgUpgradeClientResponse +MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. + + + + + + + + + + + + + + +### Msg +Msg defines the ibc/client Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CreateClient` | [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) | [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) | CreateClient defines a rpc handler method for MsgCreateClient. | | +| `UpdateClient` | [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) | [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) | UpdateClient defines a rpc handler method for MsgUpdateClient. | | +| `UpgradeClient` | [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) | [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) | UpgradeClient defines a rpc handler method for MsgUpgradeClient. | | +| `SubmitMisbehaviour` | [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) | [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) | SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. | | + + + + + + +

    Top

    + +## ibc/core/client/v1/genesis.proto + + + + + +### GenesisMetadata +GenesisMetadata defines the genesis type for metadata that clients may return +with ExportMetadata + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | +| `value` | [bytes](#bytes) | | metadata value | + + + + + + + + +### GenesisState +GenesisState defines the ibc client submodule's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `clients` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | client states with their corresponding identifiers | +| `clients_consensus` | [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) | repeated | consensus states from each client | +| `clients_metadata` | [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) | repeated | metadata from each client | +| `params` | [Params](#ibc.core.client.v1.Params) | | | +| `create_localhost` | [bool](#bool) | | create localhost on initialization | +| `next_client_sequence` | [uint64](#uint64) | | the sequence for the next generated client identifier | + + + + + + + + +### IdentifiedGenesisMetadata +IdentifiedGenesisMetadata has the client metadata with the corresponding client id. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | | +| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | + + + + + + + + + + @@ -7891,62 +8629,6 @@ CLOSED, INIT, TRYOPEN, OPEN or UNINITIALIZED. - -

    Top

    - -## ibc/core/channel/v1/genesis.proto - - - - - -### GenesisState -GenesisState defines the ibc channel submodule's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | | -| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `receipts` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `send_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `recv_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `ack_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `next_channel_sequence` | [uint64](#uint64) | | the sequence for the next generated channel identifier | - - - - - - - - -### PacketSequence -PacketSequence defines the genesis type necessary to retrieve and store -next send and receive sequences. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `sequence` | [uint64](#uint64) | | | - - - - - - - - - - - - - - -

    Top

    @@ -8779,60 +9461,47 @@ Msg defines the ibc/channel Msg service. - +

    Top

    -## ibc/core/client/v1/genesis.proto +## ibc/core/channel/v1/genesis.proto - - -### GenesisMetadata -GenesisMetadata defines the genesis type for metadata that clients may return -with ExportMetadata - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | -| `value` | [bytes](#bytes) | | metadata value | - - - - - - - + ### GenesisState -GenesisState defines the ibc client submodule's genesis state. +GenesisState defines the ibc channel submodule's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `clients` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | client states with their corresponding identifiers | -| `clients_consensus` | [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) | repeated | consensus states from each client | -| `clients_metadata` | [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) | repeated | metadata from each client | -| `params` | [Params](#ibc.core.client.v1.Params) | | | -| `create_localhost` | [bool](#bool) | | create localhost on initialization | -| `next_client_sequence` | [uint64](#uint64) | | the sequence for the next generated client identifier | +| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | | +| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `receipts` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `send_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `recv_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `ack_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `next_channel_sequence` | [uint64](#uint64) | | the sequence for the next generated channel identifier | - + -### IdentifiedGenesisMetadata -IdentifiedGenesisMetadata has the client metadata with the corresponding client id. +### PacketSequence +PacketSequence defines the genesis type necessary to retrieve and store +next send and receive sequences. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `sequence` | [uint64](#uint64) | | | @@ -8848,343 +9517,6 @@ IdentifiedGenesisMetadata has the client metadata with the corresponding client - -

    Top

    - -## ibc/core/client/v1/query.proto - - - - - -### QueryClientParamsRequest -QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. - - - - - - - - -### QueryClientParamsResponse -QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | - - - - - - - - -### QueryClientStateRequest -QueryClientStateRequest is the request type for the Query/ClientState RPC -method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | - - - - - - - - -### QueryClientStateResponse -QueryClientStateResponse is the response type for the Query/ClientState RPC -method. Besides the client state, it includes a proof and the height from -which the proof was retrieved. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state associated with the request identifier | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - - - - - - - - -### QueryClientStatesRequest -QueryClientStatesRequest is the request type for the Query/ClientStates RPC -method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - - - - - - - -### QueryClientStatesResponse -QueryClientStatesResponse is the response type for the Query/ClientStates RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_states` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | list of stored ClientStates of the chain. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | - - - - - - - - -### QueryConsensusStateRequest -QueryConsensusStateRequest is the request type for the Query/ConsensusState -RPC method. Besides the consensus state, it includes a proof and the height -from which the proof was retrieved. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `revision_number` | [uint64](#uint64) | | consensus state revision number | -| `revision_height` | [uint64](#uint64) | | consensus state revision height | -| `latest_height` | [bool](#bool) | | latest_height overrrides the height field and queries the latest stored ConsensusState | - - - - - - - - -### QueryConsensusStateResponse -QueryConsensusStateResponse is the response type for the Query/ConsensusState -RPC method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client identifier at the given height | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - - - - - - - - -### QueryConsensusStatesRequest -QueryConsensusStatesRequest is the request type for the Query/ConsensusStates -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - - - - - - - -### QueryConsensusStatesResponse -QueryConsensusStatesResponse is the response type for the -Query/ConsensusStates RPC method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states associated with the identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | - - - - - - - - - - - - - - -### Query -Query provides defines the gRPC querier service - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ClientState` | [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) | [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) | ClientState queries an IBC light client. | GET|/ibc/core/client/v1beta1/client_states/{client_id}| -| `ClientStates` | [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) | [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) | ClientStates queries all the IBC light clients of a chain. | GET|/ibc/core/client/v1beta1/client_states| -| `ConsensusState` | [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) | [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) | ConsensusState queries a consensus state associated with a client state at a given height. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}/revision/{revision_number}/height/{revision_height}| -| `ConsensusStates` | [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) | [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) | ConsensusStates queries all the consensus state associated with a given client. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}| -| `ClientParams` | [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) | [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) | ClientParams queries all parameters of the ibc client. | GET|/ibc/client/v1beta1/params| - - - - - - -

    Top

    - -## ibc/core/client/v1/tx.proto - - - - - -### MsgCreateClient -MsgCreateClient defines a message to create an IBC client - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | light client state | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client that corresponds to a given height. | -| `signer` | [string](#string) | | signer address | - - - - - - - - -### MsgCreateClientResponse -MsgCreateClientResponse defines the Msg/CreateClient response type. - - - - - - - - -### MsgSubmitMisbehaviour -MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for -light client misbehaviour. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `misbehaviour` | [google.protobuf.Any](#google.protobuf.Any) | | misbehaviour used for freezing the light client | -| `signer` | [string](#string) | | signer address | - - - - - - - - -### MsgSubmitMisbehaviourResponse -MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. - - - - - - - - -### MsgUpdateClient -MsgUpdateClient defines an sdk.Msg to update a IBC client state using -the given header. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `header` | [google.protobuf.Any](#google.protobuf.Any) | | header to update the light client | -| `signer` | [string](#string) | | signer address | - - - - - - - - -### MsgUpdateClientResponse -MsgUpdateClientResponse defines the Msg/UpdateClient response type. - - - - - - - - -### MsgUpgradeClient -MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded client state | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded consensus state, only contains enough information to serve as a basis of trust in update logic | -| `proof_upgrade_client` | [bytes](#bytes) | | proof that old chain committed to new client | -| `proof_upgrade_consensus_state` | [bytes](#bytes) | | proof that old chain committed to new consensus state | -| `signer` | [string](#string) | | signer address | - - - - - - - - -### MsgUpgradeClientResponse -MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. - - - - - - - - - - - - - - -### Msg -Msg defines the ibc/client Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CreateClient` | [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) | [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) | CreateClient defines a rpc handler method for MsgCreateClient. | | -| `UpdateClient` | [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) | [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) | UpdateClient defines a rpc handler method for MsgUpdateClient. | | -| `UpgradeClient` | [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) | [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) | UpgradeClient defines a rpc handler method for MsgUpgradeClient. | | -| `SubmitMisbehaviour` | [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) | [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) | SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. | | - - - - -

    Top

    @@ -9409,39 +9741,6 @@ INIT, TRYOPEN, OPEN or UNINITIALIZED. - -

    Top

    - -## ibc/core/connection/v1/genesis.proto - - - - - -### GenesisState -GenesisState defines the ibc connection submodule's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | | -| `client_connection_paths` | [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) | repeated | | -| `next_connection_sequence` | [uint64](#uint64) | | the sequence for the next generated connection identifier | - - - - - - - - - - - - - - -

    Top

    @@ -9806,6 +10105,39 @@ Msg defines the ibc/connection Msg service. + +

    Top

    + +## ibc/core/connection/v1/genesis.proto + + + + + +### GenesisState +GenesisState defines the ibc connection submodule's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | | +| `client_connection_paths` | [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) | repeated | | +| `next_connection_sequence` | [uint64](#uint64) | | the sequence for the next generated connection identifier | + + + + + + + + + + + + + + +

    Top

    @@ -9862,6 +10194,128 @@ access to keys outside the client prefix. + + + + + + + + + + + +

    Top

    + +## ibc/lightclients/tendermint/v1/tendermint.proto + + + + + +### ClientState +ClientState from Tendermint tracks the current validator set, latest height, +and a possible frozen height. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `chain_id` | [string](#string) | | | +| `trust_level` | [Fraction](#ibc.lightclients.tendermint.v1.Fraction) | | | +| `trusting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the period since the LastestTimestamp during which the submitted headers are valid for upgrade | +| `unbonding_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the staking unbonding period | +| `max_clock_drift` | [google.protobuf.Duration](#google.protobuf.Duration) | | defines how much new (untrusted) header's Time can drift into the future. | +| `frozen_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Block height when the client was frozen due to a misbehaviour | +| `latest_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Latest height the client was updated to | +| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | Proof specifications used in verifying counterparty state | +| `upgrade_path` | [string](#string) | repeated | Path at which next upgraded client will be committed. Each element corresponds to the key for a single CommitmentProof in the chained proof. NOTE: ClientState must stored under `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using the default upgrade module, upgrade_path should be []string{"upgrade", "upgradedIBCState"}` | +| `allow_update_after_expiry` | [bool](#bool) | | This flag, when set to true, will allow governance to recover a client which has expired | +| `allow_update_after_misbehaviour` | [bool](#bool) | | This flag, when set to true, will allow governance to unfreeze a client whose chain has experienced a misbehaviour event | + + + + + + + + +### ConsensusState +ConsensusState defines the consensus state from Tendermint. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `timestamp` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | timestamp that corresponds to the block height in which the ConsensusState was stored. | +| `root` | [ibc.core.commitment.v1.MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) | | commitment root (i.e app hash) | +| `next_validators_hash` | [bytes](#bytes) | | | + + + + + + + + +### Fraction +Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `numerator` | [uint64](#uint64) | | | +| `denominator` | [uint64](#uint64) | | | + + + + + + + + +### Header +Header defines the Tendermint client consensus Header. +It encapsulates all the information necessary to update from a trusted +Tendermint ConsensusState. The inclusion of TrustedHeight and +TrustedValidators allows this update to process correctly, so long as the +ConsensusState for the TrustedHeight exists, this removes race conditions +among relayers The SignedHeader and ValidatorSet are the new untrusted update +fields for the client. The TrustedHeight is the height of a stored +ConsensusState on the client that will be used to verify the new untrusted +header. The Trusted ConsensusState must be within the unbonding period of +current time in order to correctly verify, and the TrustedValidators must +hash to TrustedConsensusState.NextValidatorsHash since that is the last +trusted validator set at the TrustedHeight. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `signed_header` | [tendermint.types.SignedHeader](#tendermint.types.SignedHeader) | | | +| `validator_set` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | +| `trusted_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `trusted_validators` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | + + + + + + + + +### Misbehaviour +Misbehaviour is a wrapper over two conflicting Headers +that implements Misbehaviour interface expected by ICS-02 + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | | +| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | +| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | + + + + + @@ -10189,128 +10643,6 @@ data sign byte encodings. - -

    Top

    - -## ibc/lightclients/tendermint/v1/tendermint.proto - - - - - -### ClientState -ClientState from Tendermint tracks the current validator set, latest height, -and a possible frozen height. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `chain_id` | [string](#string) | | | -| `trust_level` | [Fraction](#ibc.lightclients.tendermint.v1.Fraction) | | | -| `trusting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the period since the LastestTimestamp during which the submitted headers are valid for upgrade | -| `unbonding_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the staking unbonding period | -| `max_clock_drift` | [google.protobuf.Duration](#google.protobuf.Duration) | | defines how much new (untrusted) header's Time can drift into the future. | -| `frozen_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Block height when the client was frozen due to a misbehaviour | -| `latest_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Latest height the client was updated to | -| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | Proof specifications used in verifying counterparty state | -| `upgrade_path` | [string](#string) | repeated | Path at which next upgraded client will be committed. Each element corresponds to the key for a single CommitmentProof in the chained proof. NOTE: ClientState must stored under `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using the default upgrade module, upgrade_path should be []string{"upgrade", "upgradedIBCState"}` | -| `allow_update_after_expiry` | [bool](#bool) | | This flag, when set to true, will allow governance to recover a client which has expired | -| `allow_update_after_misbehaviour` | [bool](#bool) | | This flag, when set to true, will allow governance to unfreeze a client whose chain has experienced a misbehaviour event | - - - - - - - - -### ConsensusState -ConsensusState defines the consensus state from Tendermint. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `timestamp` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | timestamp that corresponds to the block height in which the ConsensusState was stored. | -| `root` | [ibc.core.commitment.v1.MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) | | commitment root (i.e app hash) | -| `next_validators_hash` | [bytes](#bytes) | | | - - - - - - - - -### Fraction -Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `numerator` | [uint64](#uint64) | | | -| `denominator` | [uint64](#uint64) | | | - - - - - - - - -### Header -Header defines the Tendermint client consensus Header. -It encapsulates all the information necessary to update from a trusted -Tendermint ConsensusState. The inclusion of TrustedHeight and -TrustedValidators allows this update to process correctly, so long as the -ConsensusState for the TrustedHeight exists, this removes race conditions -among relayers The SignedHeader and ValidatorSet are the new untrusted update -fields for the client. The TrustedHeight is the height of a stored -ConsensusState on the client that will be used to verify the new untrusted -header. The Trusted ConsensusState must be within the unbonding period of -current time in order to correctly verify, and the TrustedValidators must -hash to TrustedConsensusState.NextValidatorsHash since that is the last -trusted validator set at the TrustedHeight. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signed_header` | [tendermint.types.SignedHeader](#tendermint.types.SignedHeader) | | | -| `validator_set` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | -| `trusted_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `trusted_validators` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | - - - - - - - - -### Misbehaviour -Misbehaviour is a wrapper over two conflicting Headers -that implements Misbehaviour interface expected by ICS-02 - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | -| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | - - - - - - - - - - - - - - - ## Scalar Value Types | .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby | diff --git a/proto/cosmos/feegrant/v1beta1/feegrant.proto b/proto/cosmos/feegrant/v1beta1/feegrant.proto new file mode 100644 index 0000000000..534de582d9 --- /dev/null +++ b/proto/cosmos/feegrant/v1beta1/feegrant.proto @@ -0,0 +1,81 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant/types"; + +// BasicFeeAllowance implements FeeAllowance with a one-time grant of tokens +// that optionally expires. The delegatee can use up to SpendLimit to cover fees. +message BasicFeeAllowance { + option (cosmos_proto.implements_interface) = "FeeAllowanceI"; + + // spend_limit specifies the maximum amount of tokens that can be spent + // by this allowance and will be updated as tokens are spent. If it is + // empty, there is no spend limit and any amount of coins can be spent. + repeated cosmos.base.v1beta1.Coin spend_limit = 1 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // expiration specifies an optional time when this allowance expires + ExpiresAt expiration = 2 [(gogoproto.nullable) = false]; +} + +// PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, +// as well as a limit per time period. +message PeriodicFeeAllowance { + option (cosmos_proto.implements_interface) = "FeeAllowanceI"; + + // basic specifies a struct of `BasicFeeAllowance` + BasicFeeAllowance basic = 1 [(gogoproto.nullable) = false]; + + // period specifies the time duration in which period_spend_limit coins can + // be spent before that allowance is reset + Duration period = 2 [(gogoproto.nullable) = false]; + + // period_spend_limit specifies the maximum number of coins that can be spent + // in the period + repeated cosmos.base.v1beta1.Coin period_spend_limit = 3 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // period_can_spend is the number of coins left to be spent before the period_reset time + repeated cosmos.base.v1beta1.Coin period_can_spend = 4 + [(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"]; + + // period_reset is the time at which this period resets and a new one begins, + // it is calculated from the start time of the first transaction after the + // last period ended + ExpiresAt period_reset = 5 [(gogoproto.nullable) = false]; +} + +// Duration is a span of a clock time or number of blocks. +// This is designed to be added to an ExpiresAt struct. +message Duration { + // sum is the oneof that represents either duration or block + oneof sum { + google.protobuf.Duration duration = 1 [(gogoproto.stdduration) = true]; + uint64 blocks = 2; + } +} + +// ExpiresAt is a point in time where something expires. +// It may be *either* block time or block height +message ExpiresAt { + // sum is the oneof that represents either time or height + oneof sum { + google.protobuf.Timestamp time = 1 [(gogoproto.stdtime) = true]; + int64 height = 2; + } +} + +// FeeAllowanceGrant is stored in the KVStore to record a grant with full context +message FeeAllowanceGrant { + + string granter = 1; + string grantee = 2; + google.protobuf.Any allowance = 3 [(cosmos_proto.accepts_interface) = "FeeAllowanceI"]; +} diff --git a/proto/cosmos/feegrant/v1beta1/genesis.proto b/proto/cosmos/feegrant/v1beta1/genesis.proto new file mode 100644 index 0000000000..a021ea61df --- /dev/null +++ b/proto/cosmos/feegrant/v1beta1/genesis.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos/feegrant/v1beta1/feegrant.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant/types"; + +// GenesisState contains a set of fee allowances, persisted from the store +message GenesisState { + repeated FeeAllowanceGrant fee_allowances = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/cosmos/feegrant/v1beta1/query.proto b/proto/cosmos/feegrant/v1beta1/query.proto new file mode 100644 index 0000000000..42d5f30200 --- /dev/null +++ b/proto/cosmos/feegrant/v1beta1/query.proto @@ -0,0 +1,52 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "cosmos/feegrant/v1beta1/feegrant.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "google/api/annotations.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant/types"; + +// Query defines the gRPC querier service. +service Query { + + // FeeAllowance returns fee granted to the grantee by the granter. + rpc FeeAllowance(QueryFeeAllowanceRequest) returns (QueryFeeAllowanceResponse) { + option (google.api.http).get = "/cosmos/feegrant/v1beta1/fee_allowance/{granter}/{grantee}"; + } + + // FeeAllowances returns all the grants for address. + rpc FeeAllowances(QueryFeeAllowancesRequest) returns (QueryFeeAllowancesResponse) { + option (google.api.http).get = "/cosmos/feegrant/v1beta1/fee_allowances/{grantee}"; + } +} + +// QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. +message QueryFeeAllowanceRequest { + string granter = 1; + string grantee = 2; +} + +// QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. +message QueryFeeAllowanceResponse { + // fee_allowance is a fee_allowance granted for grantee by granter. + cosmos.feegrant.v1beta1.FeeAllowanceGrant fee_allowance = 1; +} + +// QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. +message QueryFeeAllowancesRequest { + string grantee = 1; + + // pagination defines an pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. +message QueryFeeAllowancesResponse { + // fee_allowances are fee_allowance's granted for grantee by granter. + repeated cosmos.feegrant.v1beta1.FeeAllowanceGrant fee_allowances = 1; + + // pagination defines an pagination for the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/proto/cosmos/feegrant/v1beta1/tx.proto b/proto/cosmos/feegrant/v1beta1/tx.proto new file mode 100644 index 0000000000..a36f358f25 --- /dev/null +++ b/proto/cosmos/feegrant/v1beta1/tx.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package cosmos.feegrant.v1beta1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/any.proto"; +import "cosmos_proto/cosmos.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/feegrant/types"; + +// Msg defines the feegrant msg service. +service Msg { + + // GrantFeeAllowance grants fee allowance to the grantee on the granter's + // account with the provided expiration time. + rpc GrantFeeAllowance(MsgGrantFeeAllowance) returns (MsgGrantFeeAllowanceResponse); + + // RevokeFeeAllowance revokes any fee allowance of granter's account that + // has been granted to the grantee. + rpc RevokeFeeAllowance(MsgRevokeFeeAllowance) returns (MsgRevokeFeeAllowanceResponse); +} + +// MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance +// of fees from the account of Granter. +message MsgGrantFeeAllowance { + string granter = 1; + string grantee = 2; + google.protobuf.Any allowance = 3 [(cosmos_proto.accepts_interface) = "FeeAllowanceI"]; +} + +// MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. +message MsgGrantFeeAllowanceResponse {} + +// MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. +message MsgRevokeFeeAllowance { + string granter = 1; + string grantee = 2; +} + +// MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. +message MsgRevokeFeeAllowanceResponse {} diff --git a/simapp/app.go b/simapp/app.go index 5e9c3e29e1..23ced043d0 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -55,6 +55,10 @@ import ( "github.com/cosmos/cosmos-sdk/x/evidence" evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + feegrant "github.com/cosmos/cosmos-sdk/x/feegrant" + feegrantante "github.com/cosmos/cosmos-sdk/x/feegrant/ante" + feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + feegranttypes "github.com/cosmos/cosmos-sdk/x/feegrant/types" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/cosmos/cosmos-sdk/x/gov" @@ -120,6 +124,7 @@ var ( crisis.AppModuleBasic{}, slashing.AppModuleBasic{}, ibc.AppModuleBasic{}, + feegrant.AppModuleBasic{}, upgrade.AppModuleBasic{}, evidence.AppModuleBasic{}, transfer.AppModuleBasic{}, @@ -181,6 +186,7 @@ type SimApp struct { IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly EvidenceKeeper evidencekeeper.Keeper TransferKeeper ibctransferkeeper.Keeper + FeeGrantKeeper feegrantkeeper.Keeper // make scoped keepers public for test purposes ScopedIBCKeeper capabilitykeeper.ScopedKeeper @@ -222,7 +228,7 @@ func NewSimApp( keys := sdk.NewKVStoreKeys( authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, + govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, feegranttypes.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, authztypes.StoreKey, ) @@ -277,6 +283,8 @@ func NewSimApp( app.CrisisKeeper = crisiskeeper.NewKeeper( app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName, ) + + app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegranttypes.StoreKey], app.AccountKeeper) app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath) // register the staking hooks @@ -347,6 +355,7 @@ func NewSimApp( bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper), crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), + feegrant.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), @@ -379,6 +388,7 @@ func NewSimApp( capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, ibchost.ModuleName, genutiltypes.ModuleName, evidencetypes.ModuleName, authztypes.ModuleName, ibctransfertypes.ModuleName, + feegranttypes.ModuleName, ) app.mm.RegisterInvariants(&app.CrisisKeeper) @@ -396,6 +406,7 @@ func NewSimApp( auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper), + feegrant.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), @@ -419,8 +430,8 @@ func NewSimApp( app.SetInitChainer(app.InitChainer) app.SetBeginBlocker(app.BeginBlocker) app.SetAnteHandler( - ante.NewAnteHandler( - app.AccountKeeper, app.BankKeeper, ante.DefaultSigVerificationGasConsumer, + feegrantante.NewAnteHandler( + app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, ante.DefaultSigVerificationGasConsumer, encodingConfig.TxConfig.SignModeHandler(), ), ) diff --git a/simapp/params/weights.go b/simapp/params/weights.go index 0ba377b009..a7ea85ef7c 100644 --- a/simapp/params/weights.go +++ b/simapp/params/weights.go @@ -20,4 +20,8 @@ const ( DefaultWeightCommunitySpendProposal int = 5 DefaultWeightTextProposal int = 5 DefaultWeightParamChangeProposal int = 5 + + // feegrant + DefaultWeightGrantFeeAllowance int = 100 + DefaultWeightRevokeFeeAllowance int = 100 ) diff --git a/x/auth/legacy/legacytx/stdtx_builder.go b/x/auth/legacy/legacytx/stdtx_builder.go index 153c4b2bbb..ae0e97a3f3 100644 --- a/x/auth/legacy/legacytx/stdtx_builder.go +++ b/x/auth/legacy/legacytx/stdtx_builder.go @@ -84,6 +84,9 @@ func (s *StdTxBuilder) SetTimeoutHeight(height uint64) { s.TimeoutHeight = height } +// SetFeeGranter does nothing for stdtx +func (s *StdTxBuilder) SetFeeGranter(_ sdk.AccAddress) {} + // StdTxConfig is a context.TxConfig for StdTx type StdTxConfig struct { Cdc *codec.LegacyAmino diff --git a/x/feegrant/ante/ante.go b/x/feegrant/ante/ante.go new file mode 100644 index 0000000000..483868c23e --- /dev/null +++ b/x/feegrant/ante/ante.go @@ -0,0 +1,35 @@ +package ante + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authante "github.com/cosmos/cosmos-sdk/x/auth/ante" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + "github.com/cosmos/cosmos-sdk/x/auth/signing" + feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + feegranttypes "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// NewAnteHandler returns an AnteHandler that checks and increments sequence +// numbers, checks signatures & account numbers, and deducts fees from the +// fee_payer or from fee_granter (if valid grant exist). +func NewAnteHandler( + ak authkeeper.AccountKeeper, bankKeeper feegranttypes.BankKeeper, feeGrantKeeper feegrantkeeper.Keeper, + sigGasConsumer authante.SignatureVerificationGasConsumer, signModeHandler signing.SignModeHandler, +) sdk.AnteHandler { + + return sdk.ChainAnteDecorators( + authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first + authante.NewRejectExtensionOptionsDecorator(), + authante.NewMempoolFeeDecorator(), + authante.NewValidateBasicDecorator(), + authante.TxTimeoutHeightDecorator{}, + authante.NewValidateMemoDecorator(ak), + authante.NewConsumeGasForTxSizeDecorator(ak), + NewDeductGrantedFeeDecorator(ak, bankKeeper, feeGrantKeeper), + authante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators + authante.NewValidateSigCountDecorator(ak), + authante.NewSigGasConsumeDecorator(ak, sigGasConsumer), + authante.NewSigVerificationDecorator(ak, signModeHandler), + authante.NewIncrementSequenceDecorator(ak), // innermost AnteDecorator + ) +} diff --git a/x/feegrant/ante/fee.go b/x/feegrant/ante/fee.go new file mode 100644 index 0000000000..52cbda7210 --- /dev/null +++ b/x/feegrant/ante/fee.go @@ -0,0 +1,82 @@ +package ante + +import ( + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authante "github.com/cosmos/cosmos-sdk/x/auth/ante" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// DeductGrantedFeeDecorator deducts fees from fee_payer or fee_granter (if exists a valid fee allowance) of the tx +// If the fee_payer or fee_granter does not have the funds to pay for the fees, return with InsufficientFunds error +// Call next AnteHandler if fees successfully deducted +// CONTRACT: Tx must implement GrantedFeeTx interface to use DeductGrantedFeeDecorator +type DeductGrantedFeeDecorator struct { + ak types.AccountKeeper + k keeper.Keeper + bk types.BankKeeper +} + +func NewDeductGrantedFeeDecorator(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper) DeductGrantedFeeDecorator { + return DeductGrantedFeeDecorator{ + ak: ak, + k: k, + bk: bk, + } +} + +// AnteHandle performs a decorated ante-handler responsible for deducting transaction +// fees. Fees will be deducted from the account designated by the FeePayer on a +// transaction by default. However, if the fee payer differs from the transaction +// signer, the handler will check if a fee grant has been authorized. If the +// transaction's signer does not exist, it will be created. +func (d DeductGrantedFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { + feeTx, ok := tx.(sdk.FeeTx) + if !ok { + return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a GrantedFeeTx") + } + + // sanity check from DeductFeeDecorator + if addr := d.ak.GetModuleAddress(authtypes.FeeCollectorName); addr == nil { + panic(fmt.Sprintf("%s module account has not been set", authtypes.FeeCollectorName)) + } + + fee := feeTx.GetFee() + feePayer := feeTx.FeePayer() + feeGranter := feeTx.FeeGranter() + + deductFeesFrom := feePayer + + // ensure the grant is allowed, if we request a different fee payer + if feeGranter != nil && !feeGranter.Equals(feePayer) { + err := d.k.UseGrantedFees(ctx, feeGranter, feePayer, fee) + if err != nil { + return ctx, sdkerrors.Wrapf(err, "%s not allowed to pay fees from %s", feeGranter, feePayer) + } + + deductFeesFrom = feeGranter + } + + // now, either way, we know that we are authorized to deduct the fees from the deductFeesFrom account + deductFeesFromAcc := d.ak.GetAccount(ctx, deductFeesFrom) + if deductFeesFromAcc == nil { + return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "fee payer address: %s does not exist", deductFeesFrom) + } + + // move on if there is no fee to deduct + if fee.IsZero() { + return next(ctx, tx, simulate) + } + + // deduct fee if non-zero + err = authante.DeductFees(d.bk, ctx, deductFeesFromAcc, fee) + if err != nil { + return ctx, err + } + + return next(ctx, tx, simulate) +} diff --git a/x/feegrant/ante/fee_test.go b/x/feegrant/ante/fee_test.go new file mode 100644 index 0000000000..293f448d73 --- /dev/null +++ b/x/feegrant/ante/fee_test.go @@ -0,0 +1,287 @@ +package ante_test + +import ( + "math/rand" + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/stretchr/testify/suite" + "github.com/tendermint/tendermint/crypto" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/simapp/helpers" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authante "github.com/cosmos/cosmos-sdk/x/auth/ante" + authsign "github.com/cosmos/cosmos-sdk/x/auth/signing" + "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/ante" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// AnteTestSuite is a test suite to be used with ante handler tests. +type AnteTestSuite struct { + suite.Suite + + app *simapp.SimApp + anteHandler sdk.AnteHandler + ctx sdk.Context + clientCtx client.Context + txBuilder client.TxBuilder +} + +// SetupTest setups a new test, with new app, context, and anteHandler. +func (suite *AnteTestSuite) SetupTest(isCheckTx bool) { + suite.app, suite.ctx = createTestApp(isCheckTx) + suite.ctx = suite.ctx.WithBlockHeight(1) + + // Set up TxConfig. + encodingConfig := simapp.MakeTestEncodingConfig() + // We're using TestMsg encoding in some tests, so register it here. + encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil) + testdata.RegisterInterfaces(encodingConfig.InterfaceRegistry) + + suite.clientCtx = client.Context{}. + WithTxConfig(encodingConfig.TxConfig) + + suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, suite.app.FeeGrantKeeper, authante.DefaultSigVerificationGasConsumer, encodingConfig.TxConfig.SignModeHandler()) +} + +func (suite *AnteTestSuite) TestDeductFeesNoDelegation() { + suite.SetupTest(true) + // setup + app, ctx := suite.app, suite.ctx + + protoTxCfg := tx.NewTxConfig(codec.NewProtoCodec(app.InterfaceRegistry()), tx.DefaultSignModes) + + // this just tests our handler + dfd := ante.NewDeductGrantedFeeDecorator(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper) + ourAnteHandler := sdk.ChainAnteDecorators(dfd) + + // this tests the whole stack + anteHandlerStack := suite.anteHandler + + // keys and addresses + priv1, _, addr1 := testdata.KeyTestPubAddr() + priv2, _, addr2 := testdata.KeyTestPubAddr() + priv3, _, addr3 := testdata.KeyTestPubAddr() + priv4, _, addr4 := testdata.KeyTestPubAddr() + priv5, _, addr5 := testdata.KeyTestPubAddr() + + // Set addr1 with insufficient funds + acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1) + app.AccountKeeper.SetAccount(ctx, acc1) + app.BankKeeper.SetBalances(ctx, addr1, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(10))}) + + // Set addr2 with more funds + acc2 := app.AccountKeeper.NewAccountWithAddress(ctx, addr2) + app.AccountKeeper.SetAccount(ctx, acc2) + app.BankKeeper.SetBalances(ctx, addr2, []sdk.Coin{sdk.NewCoin("atom", sdk.NewInt(99999))}) + + // grant fee allowance from `addr2` to `addr3` (plenty to pay) + err := app.FeeGrantKeeper.GrantFeeAllowance(ctx, addr2, addr3, &types.BasicFeeAllowance{ + SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 500)), + }) + suite.Require().NoError(err) + + // grant low fee allowance (20atom), to check the tx requesting more than allowed. + err = app.FeeGrantKeeper.GrantFeeAllowance(ctx, addr2, addr4, &types.BasicFeeAllowance{ + SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 20)), + }) + suite.Require().NoError(err) + + cases := map[string]struct { + signerKey cryptotypes.PrivKey + signer sdk.AccAddress + feeAccount sdk.AccAddress + feeAccountKey cryptotypes.PrivKey + handler sdk.AnteHandler + fee int64 + valid bool + }{ + "paying with low funds (only ours)": { + signerKey: priv1, + signer: addr1, + fee: 50, + handler: ourAnteHandler, + valid: false, + }, + "paying with good funds (only ours)": { + signerKey: priv2, + signer: addr2, + fee: 50, + handler: ourAnteHandler, + valid: true, + }, + "paying with no account (only ours)": { + signerKey: priv3, + signer: addr3, + fee: 1, + handler: ourAnteHandler, + valid: false, + }, + "no fee with real account (only ours)": { + signerKey: priv1, + signer: addr1, + fee: 0, + handler: ourAnteHandler, + valid: true, + }, + "no fee with no account (only ours)": { + signerKey: priv5, + signer: addr5, + fee: 0, + handler: ourAnteHandler, + valid: false, + }, + "valid fee grant without account (only ours)": { + signerKey: priv3, + signer: addr3, + feeAccount: addr2, + fee: 50, + handler: ourAnteHandler, + valid: true, + }, + "no fee grant (only ours)": { + signerKey: priv3, + signer: addr3, + feeAccount: addr1, + fee: 2, + handler: ourAnteHandler, + valid: false, + }, + "allowance smaller than requested fee (only ours)": { + signerKey: priv4, + signer: addr4, + feeAccount: addr2, + fee: 50, + handler: ourAnteHandler, + valid: false, + }, + "granter cannot cover allowed fee grant (only ours)": { + signerKey: priv4, + signer: addr4, + feeAccount: addr1, + fee: 50, + handler: ourAnteHandler, + valid: false, + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + suite.T().Run(name, func(t *testing.T) { + fee := sdk.NewCoins(sdk.NewInt64Coin("atom", tc.fee)) + msgs := []sdk.Msg{testdata.NewTestMsg(tc.signer)} + + acc := app.AccountKeeper.GetAccount(ctx, tc.signer) + privs, accNums, seqs := []cryptotypes.PrivKey{tc.signerKey}, []uint64{0}, []uint64{0} + if acc != nil { + accNums, seqs = []uint64{acc.GetAccountNumber()}, []uint64{acc.GetSequence()} + } + + tx, err := genTxWithFeeGranter(protoTxCfg, msgs, fee, helpers.DefaultGenTxGas, ctx.ChainID(), accNums, seqs, tc.feeAccount, privs...) + suite.Require().NoError(err) + _, err = ourAnteHandler(ctx, tx, false) + if tc.valid { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + + _, err = anteHandlerStack(ctx, tx, false) + if tc.valid { + suite.Require().NoError(err) + } else { + suite.Require().Error(err) + } + }) + } +} + +// returns context and app with params set on account keeper +func createTestApp(isCheckTx bool) (*simapp.SimApp, sdk.Context) { + app := simapp.Setup(isCheckTx) + ctx := app.BaseApp.NewContext(isCheckTx, tmproto.Header{}) + app.AccountKeeper.SetParams(ctx, authtypes.DefaultParams()) + + return app, ctx +} + +// don't consume any gas +func SigGasNoConsumer(meter sdk.GasMeter, sig []byte, pubkey crypto.PubKey, params authtypes.Params) error { + return nil +} + +func genTxWithFeeGranter(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accNums, + accSeqs []uint64, feeGranter sdk.AccAddress, priv ...cryptotypes.PrivKey) (sdk.Tx, error) { + sigs := make([]signing.SignatureV2, len(priv)) + + // create a random length memo + r := rand.New(rand.NewSource(time.Now().UnixNano())) + + memo := simulation.RandStringOfLength(r, simulation.RandIntBetween(r, 0, 100)) + + signMode := gen.SignModeHandler().DefaultMode() + + // 1st round: set SignatureV2 with empty signatures, to set correct + // signer infos. + for i, p := range priv { + sigs[i] = signing.SignatureV2{ + PubKey: p.PubKey(), + Data: &signing.SingleSignatureData{ + SignMode: signMode, + }, + Sequence: accSeqs[i], + } + } + + tx := gen.NewTxBuilder() + err := tx.SetMsgs(msgs...) + if err != nil { + return nil, err + } + err = tx.SetSignatures(sigs...) + if err != nil { + return nil, err + } + tx.SetMemo(memo) + tx.SetFeeAmount(feeAmt) + tx.SetGasLimit(gas) + tx.SetFeeGranter(feeGranter) + + // 2nd round: once all signer infos are set, every signer can sign. + for i, p := range priv { + signerData := authsign.SignerData{ + ChainID: chainID, + AccountNumber: accNums[i], + Sequence: accSeqs[i], + } + signBytes, err := gen.SignModeHandler().GetSignBytes(signMode, signerData, tx.GetTx()) + if err != nil { + panic(err) + } + sig, err := p.Sign(signBytes) + if err != nil { + panic(err) + } + sigs[i].Data.(*signing.SingleSignatureData).Signature = sig + err = tx.SetSignatures(sigs...) + if err != nil { + panic(err) + } + } + + return tx.GetTx(), nil +} + +func TestAnteTestSuite(t *testing.T) { + suite.Run(t, new(AnteTestSuite)) +} diff --git a/x/feegrant/client/cli/cli_test.go b/x/feegrant/client/cli/cli_test.go new file mode 100644 index 0000000000..224e7282a8 --- /dev/null +++ b/x/feegrant/client/cli/cli_test.go @@ -0,0 +1,621 @@ +// +build norace + +package cli_test + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/client/cli" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + govtestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/suite" + tmcli "github.com/tendermint/tendermint/libs/cli" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network + addedGranter sdk.AccAddress + addedGrantee sdk.AccAddress + addedGrant types.FeeAllowanceGrant +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + if testing.Short() { + s.T().Skip("skipping test in unit-tests mode.") + } + + cfg := network.DefaultConfig() + cfg.NumValidators = 2 + + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + _, err := s.network.WaitForHeight(1) + s.Require().NoError(err) + + val := s.network.Validators[0] + granter := val.Address + grantee := s.network.Validators[1].Address + + clientCtx := val.ClientCtx + commonFlags := []string{ + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + fee := sdk.NewCoin("stake", sdk.NewInt(100)) + duration := 365 * 24 * 60 * 60 + + args := append( + []string{ + granter.String(), + grantee.String(), + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, fee.String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%v", cli.FlagExpiration, duration), + }, + commonFlags..., + ) + + cmd := cli.NewCmdFeeGrant() + + _, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args) + s.Require().NoError(err) + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) + + s.addedGranter = granter + s.addedGrantee = grantee + + grant, err := types.NewFeeAllowanceGrant(granter, grantee, &types.BasicFeeAllowance{ + SpendLimit: sdk.NewCoins(fee), + }) + s.Require().NoError(err) + + s.addedGrant = grant +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestCmdGetFeeGrant() { + val := s.network.Validators[0] + granter := val.Address + grantee := s.addedGrantee + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErrMsg string + expectErr bool + respType *types.FeeAllowanceGrant + resp *types.FeeAllowanceGrant + }{ + { + "wrong granter", + []string{ + "wrong_granter", + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "decoding bech32 failed", + true, nil, nil, + }, + { + "wrong grantee", + []string{ + granter.String(), + "wrong_grantee", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "decoding bech32 failed", + true, nil, nil, + }, + { + "non existed grant", + []string{ + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "no fee allowance found", + true, nil, nil, + }, + { + "valid req", + []string{ + granter.String(), + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + "", + false, + &types.FeeAllowanceGrant{}, + &s.addedGrant, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryFeeGrant() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.expectErrMsg) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + s.Require().Equal(tc.respType.Grantee, tc.respType.Grantee) + s.Require().Equal(tc.respType.Granter, tc.respType.Granter) + s.Require().Equal( + tc.respType.GetFeeGrant().(*types.BasicFeeAllowance).SpendLimit, + tc.resp.GetFeeGrant().(*types.BasicFeeAllowance).SpendLimit, + ) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCmdGetFeeGrants() { + val := s.network.Validators[0] + grantee := s.addedGrantee + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + resp *types.QueryFeeAllowancesResponse + expectLength int + }{ + { + "wrong grantee", + []string{ + "wrong_grantee", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + true, nil, 0, + }, + { + "non existed grantee", + []string{ + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + false, &types.QueryFeeAllowancesResponse{}, 0, + }, + { + "valid req", + []string{ + grantee.String(), + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + }, + false, &types.QueryFeeAllowancesResponse{}, 1, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.GetCmdQueryFeeGrants() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.resp), out.String()) + s.Require().Len(tc.resp.FeeAllowances, tc.expectLength) + } + }) + } +} + +func (s *IntegrationTestSuite) TestNewCmdFeeGrant() { + val := s.network.Validators[0] + granter := val.Address + alreadyExistedGrantee := s.addedGrantee + clientCtx := val.ClientCtx + + commonFlags := []string{ + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + args []string + expectErr bool + respType proto.Message + expectedCode uint32 + }{ + { + "wrong granter address", + append( + []string{ + "wrong_granter", + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + true, nil, 0, + }, + { + "wrong grantee address", + append( + []string{ + granter.String(), + "wrong_grantee", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + true, nil, 0, + }, + { + "valid basic fee grant", + append( + []string{ + granter.String(), + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid basic fee grant without spend limit", + append( + []string{ + granter.String(), + "cosmos17h5lzptx3ghvsuhk7wx4c4hnl7rsswxjer97em", + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid basic fee grant without expiration", + append( + []string{ + granter.String(), + "cosmos16dlc38dcqt0uralyd8hksxyrny6kaeqfjvjwp5", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid basic fee grant without spend-limit and expiration", + append( + []string{ + granter.String(), + "cosmos1ku40qup9vwag4wtf8cls9mkszxfthaklxkp3c8", + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "try to add existed grant", + append( + []string{ + granter.String(), + alreadyExistedGrantee.String(), + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 18, + }, + { + "invalid number of args(periodic fee grant)", + append( + []string{ + granter.String(), + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, 10*60*60), + }, + commonFlags..., + ), + true, nil, 0, + }, + { + "period mentioned and period limit omitted, invalid periodic grant", + append( + []string{ + granter.String(), + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 10*60*60), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, 60*60), + }, + commonFlags..., + ), + true, nil, 0, + }, + { + "period cannot be greater than the actual expiration(periodic fee grant)", + append( + []string{ + granter.String(), + "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 10*60*60), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, 60*60), + }, + commonFlags..., + ), + true, nil, 0, + }, + { + "valid periodic fee grant", + append( + []string{ + granter.String(), + "cosmos1w55kgcf3ltaqdy4ww49nge3klxmrdavrr6frmp", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 60*60), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, 10*60*60), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid periodic fee grant without spend-limit", + append( + []string{ + granter.String(), + "cosmos1vevyks8pthkscvgazc97qyfjt40m6g9xe85ry8", + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 60*60), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%d", cli.FlagExpiration, 10*60*60), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid periodic fee grant without expiration", + append( + []string{ + granter.String(), + "cosmos14cm33pvnrv2497tyt8sp9yavhmw83nwej3m0e8", + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, "100stake"), + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 60*60), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + { + "valid periodic fee grant without spend-limit and expiration", + append( + []string{ + granter.String(), + "cosmos12nyk4pcf4arshznkpz882e4l4ts0lt0ap8ce54", + fmt.Sprintf("--%s=%d", cli.FlagPeriod, 60*60), + fmt.Sprintf("--%s=%s", cli.FlagPeriodLimit, "10stake"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, &sdk.TxResponse{}, 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.NewCmdFeeGrant() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestNewCmdRevokeFeegrant() { + val := s.network.Validators[0] + granter := s.addedGranter + grantee := s.addedGrantee + clientCtx := val.ClientCtx + + commonFlags := []string{ + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + args []string + expectErr bool + respType proto.Message + expectedCode uint32 + }{ + { + "invalid grantee", + append( + []string{ + "wrong_granter", + grantee.String(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + true, + nil, + 0, + }, + { + "invalid grantee", + append( + []string{ + granter.String(), + "wrong_grantee", + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + true, + nil, + 0, + }, + { + "Non existed grant", + append( + []string{ + granter.String(), + "cosmos1aeuqja06474dfrj7uqsvukm6rael982kk89mqr", + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, + &sdk.TxResponse{}, + 4, + }, + { + "Valid revoke", + append( + []string{ + granter.String(), + grantee.String(), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + }, + commonFlags..., + ), + false, + &sdk.TxResponse{}, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := cli.NewCmdRevokeFeegrant() + out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) + + if tc.expectErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxWithFeeGrant() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + granter := val.Address + + // creating an account manually (This account won't be exist in state) + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + grantee := sdk.AccAddress(info.GetPubKey().Address()) + + commonFlags := []string{ + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + fee := sdk.NewCoin("stake", sdk.NewInt(100)) + duration := 365 * 24 * 60 * 60 + + args := append( + []string{ + granter.String(), + grantee.String(), + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, fee.String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, granter), + fmt.Sprintf("--%s=%v", cli.FlagExpiration, duration), + }, + commonFlags..., + ) + + cmd := cli.NewCmdFeeGrant() + + _, err = clitestutil.ExecTestCLICmd(clientCtx, cmd, args) + s.Require().NoError(err) + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) + + // granted fee allowance for an account which is not in state and creating + // any tx with it by using --fee-account shouldn't fail + out, err := govtestutil.MsgSubmitProposal(val.ClientCtx, grantee.String(), + "Text Proposal", "No desc", govtypes.ProposalTypeText, + fmt.Sprintf("--%s=%s", flags.FlagFeeAccount, granter.String()), + ) + + s.Require().NoError(err) + var resp sdk.TxResponse + s.Require().NoError(clientCtx.JSONMarshaler.UnmarshalJSON(out.Bytes(), &resp), out.String()) + s.Require().Equal(uint32(0), resp.Code) +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/feegrant/client/cli/query.go b/x/feegrant/client/cli/query.go new file mode 100644 index 0000000000..c3a488ab55 --- /dev/null +++ b/x/feegrant/client/cli/query.go @@ -0,0 +1,129 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/spf13/cobra" +) + +// GetQueryCmd returns the cli query commands for this module +func GetQueryCmd() *cobra.Command { + feegrantQueryCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Querying commands for the feegrant module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + feegrantQueryCmd.AddCommand( + GetCmdQueryFeeGrant(), + GetCmdQueryFeeGrants(), + ) + + return feegrantQueryCmd +} + +// GetCmdQueryFeeGrant returns cmd to query for a grant between granter and grantee. +func GetCmdQueryFeeGrant() *cobra.Command { + cmd := &cobra.Command{ + Use: "grant [granter] [grantee]", + Args: cobra.ExactArgs(2), + Short: "Query details of a single grant", + Long: strings.TrimSpace( + fmt.Sprintf(`Query details for a grant. +You can find the fee-grant of a granter and grantee. + +Example: +$ %s query feegrant grant [granter] [grantee] +`, version.AppName), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + queryClient := types.NewQueryClient(clientCtx) + + granterAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + granteeAddr, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + res, err := queryClient.FeeAllowance( + cmd.Context(), + &types.QueryFeeAllowanceRequest{ + Granter: granterAddr.String(), + Grantee: granteeAddr.String(), + }, + ) + + if err != nil { + return err + } + + return clientCtx.PrintProto(res.FeeAllowance) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// GetCmdQueryFeeGrants returns cmd to query for all grants for a grantee. +func GetCmdQueryFeeGrants() *cobra.Command { + cmd := &cobra.Command{ + Use: "grants [grantee]", + Args: cobra.ExactArgs(1), + Short: "Query all grants of a grantee", + Long: strings.TrimSpace( + fmt.Sprintf(`Queries all the grants for a grantee address. + +Example: +$ %s query feegrant grants [grantee] +`, version.AppName), + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + queryClient := types.NewQueryClient(clientCtx) + + granteeAddr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + res, err := queryClient.FeeAllowances( + cmd.Context(), + &types.QueryFeeAllowancesRequest{ + Grantee: granteeAddr.String(), + Pagination: pageReq, + }, + ) + + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "grants") + + return cmd +} diff --git a/x/feegrant/client/cli/tx.go b/x/feegrant/client/cli/tx.go new file mode 100644 index 0000000000..a28ddb976c --- /dev/null +++ b/x/feegrant/client/cli/tx.go @@ -0,0 +1,211 @@ +package cli + +import ( + "fmt" + "strings" + "time" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// flag for feegrant module +const ( + FlagExpiration = "expiration" + FlagPeriod = "period" + FlagPeriodLimit = "period-limit" + FlagSpendLimit = "spend-limit" +) + +// GetTxCmd returns the transaction commands for this module +func GetTxCmd() *cobra.Command { + feegrantTxCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Feegrant transactions subcommands", + Long: "Grant and revoke fee allowance for a grantee by a granter", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + feegrantTxCmd.AddCommand( + NewCmdFeeGrant(), + NewCmdRevokeFeegrant(), + ) + + return feegrantTxCmd +} + +// NewCmdFeeGrant returns a CLI command handler for creating a MsgGrantFeeAllowance transaction. +func NewCmdFeeGrant() *cobra.Command { + cmd := &cobra.Command{ + Use: "grant [granter] [grantee]", + Short: "Grant Fee allowance to an address", + Long: strings.TrimSpace( + fmt.Sprintf( + `Grant authorization to pay fees from your address. Note, the'--from' flag is + ignored as it is implied from [granter]. + +Examples: +%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --expiration 36000 or +%s tx %s grant cosmos1skjw... cosmos1skjw... --spend-limit 100stake --period 3600 --period-limit 10stake --expiration 36000 + `, version.AppName, types.ModuleName, version.AppName, types.ModuleName, + ), + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + _, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + cmd.Flags().Set(flags.FlagFrom, args[0]) + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + grantee, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + granter := clientCtx.GetFromAddress() + sl, err := cmd.Flags().GetString(FlagSpendLimit) + if err != nil { + return err + } + + // if `FlagSpendLimit` isn't set, limit will be nil + limit, err := sdk.ParseCoinsNormalized(sl) + if err != nil { + return err + } + + exp, err := cmd.Flags().GetInt64(FlagExpiration) + if err != nil { + return err + } + + basic := types.BasicFeeAllowance{ + SpendLimit: limit, + } + + if exp != 0 { + expDuration := time.Duration(exp) * time.Second + basic.Expiration = types.ExpiresAtTime(time.Now().Add(expDuration)) + } + + var grant types.FeeAllowanceI + grant = &basic + + periodClock, err := cmd.Flags().GetInt64(FlagPeriod) + if err != nil { + return err + } + + periodLimitVal, err := cmd.Flags().GetString(FlagPeriodLimit) + if err != nil { + return err + } + + // Check any of period or periodLimit flags set, If set consider it as periodic fee allowance. + if periodClock > 0 || periodLimitVal != "" { + periodLimit, err := sdk.ParseCoinsNormalized(periodLimitVal) + if err != nil { + return err + } + + if periodClock > 0 && periodLimit != nil { + if exp > 0 && periodClock > exp { + return fmt.Errorf("period(%d) cannot be greater than the expiration(%d)", periodClock, exp) + } + + periodic := types.PeriodicFeeAllowance{ + Basic: basic, + Period: types.ClockDuration(time.Duration(periodClock) * time.Second), + PeriodReset: types.ExpiresAtTime(time.Now().Add(time.Duration(periodClock) * time.Second)), + PeriodSpendLimit: periodLimit, + PeriodCanSpend: periodLimit, + } + + grant = &periodic + + } else { + return fmt.Errorf("invalid number of args %d", len(args)) + } + } + + msg, err := types.NewMsgGrantFeeAllowance(grant, granter, grantee) + if err != nil { + return err + } + + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + feeGrantMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = feeGrantMsgClient.GrantFeeAllowance(cmd.Context(), msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) + }, + } + + flags.AddTxFlagsToCmd(cmd) + cmd.Flags().Int64(FlagExpiration, 0, "The second unit of time duration which the grant is active for the user") + cmd.Flags().String(FlagSpendLimit, "", "Spend limit specifies the max limit can be used, if not mentioned there is no limit") + cmd.Flags().Int64(FlagPeriod, 0, "period specifies the time duration in which period_spend_limit coins can be spent before that allowance is reset") + cmd.Flags().String(FlagPeriodLimit, "", "// period limit specifies the maximum number of coins that can be spent in the period") + + return cmd +} + +// NewCmdRevokeFeegrant returns a CLI command handler for creating a MsgRevokeFeeAllowance transaction. +func NewCmdRevokeFeegrant() *cobra.Command { + cmd := &cobra.Command{ + Use: "revoke [granter_address] [grantee_address]", + Short: "revoke fee-grant", + Long: strings.TrimSpace( + fmt.Sprintf(`revoke fee grant from a granter to a grantee. Note, the'--from' flag is + ignored as it is implied from [granter_address]. + +Example: + $ %s tx %s revoke cosmos1skj.. cosmos1skj.. + `, version.AppName, types.ModuleName), + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.Flags().Set(flags.FlagFrom, args[0]) + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + grantee, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + msg := types.NewMsgRevokeFeeAllowance(clientCtx.GetFromAddress(), grantee) + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + feeGrantMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = feeGrantMsgClient.RevokeFeeAllowance(cmd.Context(), &msg) + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), svcMsgClientConn.GetMsgs()...) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} diff --git a/x/feegrant/client/rest/grpc_query_test.go b/x/feegrant/client/rest/grpc_query_test.go new file mode 100644 index 0000000000..10d77a1e4c --- /dev/null +++ b/x/feegrant/client/rest/grpc_query_test.go @@ -0,0 +1,209 @@ +package rest_test + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/cosmos/cosmos-sdk/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/rest" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" + "github.com/cosmos/cosmos-sdk/x/feegrant/client/cli" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/suite" +) + +type IntegrationTestSuite struct { + suite.Suite + cfg network.Config + network *network.Network + grantee sdk.AccAddress +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := network.DefaultConfig() + + cfg.NumValidators = 1 + s.cfg = cfg + s.network = network.New(s.T(), cfg) + + val := s.network.Validators[0] + // Create new account in the keyring. + info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) + s.Require().NoError(err) + newAddr := sdk.AccAddress(info.GetPubKey().Address()) + + // Send some funds to the new account. + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + val.Address, + newAddr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + + s.grantee = newAddr + _, err = s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestQueryFeeAllowance() { + val := s.network.Validators[0] + baseURL := val.APIAddress + testCases := []struct { + name string + url string + expectErr bool + errorMsg string + preRun func() + postRun func(_ types.QueryFeeAllowanceResponse) + }{ + { + "fail: invalid granter", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowance/%s/%s", baseURL, "invalid_granter", s.grantee.String()), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + func() {}, + func(types.QueryFeeAllowanceResponse) {}, + }, + { + "fail: invalid grantee", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowance/%s/%s", baseURL, val.Address.String(), "invalid_grantee"), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + func() {}, + func(types.QueryFeeAllowanceResponse) {}, + }, + { + "fail: no grants", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowance/%s/%s", baseURL, val.Address.String(), s.grantee.String()), + true, + "no fee allowance found", + func() {}, + func(types.QueryFeeAllowanceResponse) {}, + }, + { + "valid query: expect single grant", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowance/%s/%s", baseURL, val.Address.String(), s.grantee.String()), + false, + "", + func() { + execFeeAllowance(val, s) + }, + func(allowance types.QueryFeeAllowanceResponse) { + s.Require().Equal(allowance.FeeAllowance.Granter, val.Address.String()) + s.Require().Equal(allowance.FeeAllowance.Grantee, s.grantee.String()) + }, + }, + } + for _, tc := range testCases { + s.Run(tc.name, func() { + tc.preRun() + resp, _ := rest.GetRequest(tc.url) + if tc.expectErr { + s.Require().Contains(string(resp), tc.errorMsg) + } else { + var allowance types.QueryFeeAllowanceResponse + err := val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, &allowance) + s.Require().NoError(err) + tc.postRun(allowance) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryGranteeAllowances() { + val := s.network.Validators[0] + baseURL := val.APIAddress + testCases := []struct { + name string + url string + expectErr bool + errorMsg string + preRun func() + postRun func(_ types.QueryFeeAllowancesResponse) + }{ + { + "fail: invalid grantee", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowances/%s", baseURL, "invalid_grantee"), + true, + "decoding bech32 failed: invalid index of 1: invalid request", + func() {}, + func(types.QueryFeeAllowancesResponse) {}, + }, + { + "success: no grants", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowances/%s?pagination.offset=1", baseURL, s.grantee.String()), + false, + "", + func() {}, + func(allowances types.QueryFeeAllowancesResponse) { + s.Require().Equal(len(allowances.FeeAllowances), 0) + }, + }, + { + "valid query: expect single grant", + fmt.Sprintf("%s/cosmos/feegrant/v1beta1/fee_allowances/%s", baseURL, s.grantee.String()), + false, + "", + func() { + execFeeAllowance(val, s) + }, + func(allowances types.QueryFeeAllowancesResponse) { + s.Require().Equal(len(allowances.FeeAllowances), 1) + s.Require().Equal(allowances.FeeAllowances[0].Granter, val.Address.String()) + s.Require().Equal(allowances.FeeAllowances[0].Grantee, s.grantee.String()) + }, + }, + } + for _, tc := range testCases { + s.Run(tc.name, func() { + tc.preRun() + resp, _ := rest.GetRequest(tc.url) + if tc.expectErr { + s.Require().Contains(string(resp), tc.errorMsg) + } else { + var allowance types.QueryFeeAllowancesResponse + err := val.ClientCtx.JSONMarshaler.UnmarshalJSON(resp, &allowance) + s.Require().NoError(err) + tc.postRun(allowance) + } + }) + } +} + +func execFeeAllowance(val *network.Validator, s *IntegrationTestSuite) { + fee := sdk.NewCoin("steak", sdk.NewInt(100)) + duration := 365 * 24 * 60 * 60 + args := []string{ + val.Address.String(), + s.grantee.String(), + fmt.Sprintf("--%s=%s", cli.FlagSpendLimit, fee.String()), + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%v", cli.FlagExpiration, duration), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + cmd := cli.NewCmdFeeGrant() + _, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, args) + s.Require().NoError(err) +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/feegrant/doc.go b/x/feegrant/doc.go new file mode 100644 index 0000000000..4f190e3140 --- /dev/null +++ b/x/feegrant/doc.go @@ -0,0 +1,29 @@ +/* +Package feegrant provides functionality for authorizing the payment of transaction +fees from one account (key) to another account (key). + +Effectively, this allows for a user to pay fees using the balance of an account +different from their own. Example use cases would be allowing a key on a device to +pay for fees using a master wallet, or a third party service allowing users to +pay for transactions without ever really holding their own tokens. This package +provides ways for specifying fee allowances such that authorizing fee payment to +another account can be done with clear and safe restrictions. + +A user would authorize granting fee payment to another user using +MsgDelegateFeeAllowance and revoke that delegation using MsgRevokeFeeAllowance. +In both cases, Granter is the one who is authorizing fee payment and Grantee is +the one who is receiving the fee payment authorization. So grantee would correspond +to the one who is signing a transaction and the granter would be the address that +pays the fees. + +The fee allowance that a grantee receives is specified by an implementation of +the FeeAllowance interface. Two FeeAllowance implementations are provided in +this package: BasicFeeAllowance and PeriodicFeeAllowance. + +In order to integrate this into an application, we must use the DeductGrantedFeeDecorator +ante handler from this package instead of the default DeductFeeDecorator from x/auth. + +To allow handling txs from empty accounts (with fees paid from an existing account), +we have to re-order the decorators as well. +*/ +package feegrant diff --git a/x/feegrant/genesis.go b/x/feegrant/genesis.go new file mode 100644 index 0000000000..f65cfdb578 --- /dev/null +++ b/x/feegrant/genesis.go @@ -0,0 +1,61 @@ +package feegrant + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// GenesisState contains a set of fee allowances, persisted from the store +type GenesisState []types.FeeAllowanceGrant + +// ValidateBasic ensures all grants in the genesis state are valid +func (g GenesisState) ValidateBasic() error { + for _, f := range g { + err := f.GetFeeGrant().ValidateBasic() + if err != nil { + return err + } + } + return nil +} + +// InitGenesis will initialize the keeper from a *previously validated* GenesisState +func InitGenesis(ctx sdk.Context, k keeper.Keeper, data *types.GenesisState) { + for _, f := range data.FeeAllowances { + granter, err := sdk.AccAddressFromBech32(f.Granter) + if err != nil { + panic(err) + } + grantee, err := sdk.AccAddressFromBech32(f.Grantee) + if err != nil { + panic(err) + } + + err = k.GrantFeeAllowance(ctx, granter, grantee, f.GetFeeGrant()) + if err != nil { + panic(err) + } + } +} + +// ExportGenesis will dump the contents of the keeper into a serializable GenesisState +// +// All expiration heights will be thrown off if we dump state and start at a new +// chain at height 0. Thus, we allow the Allowances to "prepare themselves" +// for export, like if they have expiry at 5000 and current is 4000, they export with +// expiry of 1000. Every FeeAllowance has a method `PrepareForExport` that allows +// them to perform any changes needed prior to export. +func ExportGenesis(ctx sdk.Context, k keeper.Keeper) (*types.GenesisState, error) { + time, height := ctx.BlockTime(), ctx.BlockHeight() + var grants []types.FeeAllowanceGrant + + err := k.IterateAllFeeAllowances(ctx, func(grant types.FeeAllowanceGrant) bool { + grants = append(grants, grant.PrepareForExport(time, height)) + return false + }) + + return &types.GenesisState{ + FeeAllowances: grants, + }, err +} diff --git a/x/feegrant/genesis_test.go b/x/feegrant/genesis_test.go new file mode 100644 index 0000000000..d086daac07 --- /dev/null +++ b/x/feegrant/genesis_test.go @@ -0,0 +1,56 @@ +package feegrant_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + feegrant "github.com/cosmos/cosmos-sdk/x/feegrant" + "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" +) + +type GenesisTestSuite struct { + suite.Suite + ctx sdk.Context + keeper keeper.Keeper +} + +func (suite *GenesisTestSuite) SetupTest() { + checkTx := false + app := simapp.Setup(checkTx) + suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1}) + suite.keeper = app.FeeGrantKeeper +} + +var ( + granteePub = secp256k1.GenPrivKey().PubKey() + granterPub = secp256k1.GenPrivKey().PubKey() + granteeAddr = sdk.AccAddress(granteePub.Address()) + granterAddr = sdk.AccAddress(granterPub.Address()) +) + +func (suite *GenesisTestSuite) TestImportExportGenesis() { + coins := sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1_000))) + now := suite.ctx.BlockHeader().Time + + allowance := &types.BasicFeeAllowance{SpendLimit: coins, Expiration: types.ExpiresAtTime(now.AddDate(1, 0, 0))} + err := suite.keeper.GrantFeeAllowance(suite.ctx, granterAddr, granteeAddr, allowance) + suite.Require().NoError(err) + + genesis, err := feegrant.ExportGenesis(suite.ctx, suite.keeper) + suite.Require().NoError(err) + // Clear keeper + suite.keeper.RevokeFeeAllowance(suite.ctx, granterAddr, granteeAddr) + feegrant.InitGenesis(suite.ctx, suite.keeper, genesis) + newGenesis, err := feegrant.ExportGenesis(suite.ctx, suite.keeper) + suite.Require().NoError(err) + suite.Require().Equal(genesis, newGenesis) +} + +func TestGenesisTestSuite(t *testing.T) { + suite.Run(t, new(GenesisTestSuite)) +} diff --git a/x/feegrant/keeper/grpc_query.go b/x/feegrant/keeper/grpc_query.go new file mode 100644 index 0000000000..0fce084f90 --- /dev/null +++ b/x/feegrant/keeper/grpc_query.go @@ -0,0 +1,94 @@ +package keeper + +import ( + "context" + + "github.com/gogo/protobuf/proto" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +var _ types.QueryServer = Keeper{} + +// FeeAllowance returns fee granted to the grantee by the granter. +func (q Keeper) FeeAllowance(c context.Context, req *types.QueryFeeAllowanceRequest) (*types.QueryFeeAllowanceResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + granterAddr, err := sdk.AccAddressFromBech32(req.Granter) + if err != nil { + return nil, err + } + + granteeAddr, err := sdk.AccAddressFromBech32(req.Grantee) + if err != nil { + return nil, err + } + + ctx := sdk.UnwrapSDKContext(c) + + feeAllowance := q.GetFeeAllowance(ctx, granterAddr, granteeAddr) + if feeAllowance == nil { + return nil, status.Errorf(codes.NotFound, "no fee allowance found") + } + + msg, ok := feeAllowance.(proto.Message) + if !ok { + return nil, status.Errorf(codes.Internal, "can't proto marshal %T", msg) + } + + feeAllowanceAny, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return nil, status.Errorf(codes.Internal, err.Error()) + } + + return &types.QueryFeeAllowanceResponse{ + FeeAllowance: &types.FeeAllowanceGrant{ + Granter: granterAddr.String(), + Grantee: granteeAddr.String(), + Allowance: feeAllowanceAny, + }, + }, nil +} + +func (q Keeper) FeeAllowances(c context.Context, req *types.QueryFeeAllowancesRequest) (*types.QueryFeeAllowancesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + granteeAddr, err := sdk.AccAddressFromBech32(req.Grantee) + if err != nil { + return nil, err + } + + ctx := sdk.UnwrapSDKContext(c) + + var grants []*types.FeeAllowanceGrant + + store := ctx.KVStore(q.storeKey) + grantsStore := prefix.NewStore(store, types.FeeAllowancePrefixByGrantee(granteeAddr)) + + pageRes, err := query.Paginate(grantsStore, req.Pagination, func(key []byte, value []byte) error { + var grant types.FeeAllowanceGrant + + if err := q.cdc.UnmarshalBinaryBare(value, &grant); err != nil { + return err + } + + grants = append(grants, &grant) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryFeeAllowancesResponse{FeeAllowances: grants, Pagination: pageRes}, nil +} diff --git a/x/feegrant/keeper/keeper.go b/x/feegrant/keeper/keeper.go new file mode 100644 index 0000000000..e6606bf0ca --- /dev/null +++ b/x/feegrant/keeper/keeper.go @@ -0,0 +1,190 @@ +package keeper + +import ( + "fmt" + + "github.com/tendermint/tendermint/libs/log" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// Keeper manages state of all fee grants, as well as calculating approval. +// It must have a codec with all available allowances registered. +type Keeper struct { + cdc codec.BinaryMarshaler + storeKey sdk.StoreKey + authKeeper types.AccountKeeper +} + +// NewKeeper creates a fee grant Keeper +func NewKeeper(cdc codec.BinaryMarshaler, storeKey sdk.StoreKey, ak types.AccountKeeper) Keeper { + return Keeper{ + cdc: cdc, + storeKey: storeKey, + authKeeper: ak, + } +} + +// Logger returns a module-specific logger. +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +// GrantFeeAllowance creates a new grant +func (k Keeper) GrantFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress, feeAllowance types.FeeAllowanceI) error { + + // create the account if it is not in account state + granteeAcc := k.authKeeper.GetAccount(ctx, grantee) + if granteeAcc == nil { + granteeAcc = k.authKeeper.NewAccountWithAddress(ctx, grantee) + k.authKeeper.SetAccount(ctx, granteeAcc) + } + + store := ctx.KVStore(k.storeKey) + key := types.FeeAllowanceKey(granter, grantee) + grant, err := types.NewFeeAllowanceGrant(granter, grantee, feeAllowance) + if err != nil { + return err + } + + bz, err := k.cdc.MarshalBinaryBare(&grant) + if err != nil { + return err + } + + store.Set(key, bz) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeSetFeeGrant, + sdk.NewAttribute(types.AttributeKeyGranter, grant.Granter), + sdk.NewAttribute(types.AttributeKeyGrantee, grant.Grantee), + ), + ) + + return nil +} + +// RevokeFeeAllowance removes an existing grant +func (k Keeper) RevokeFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress) error { + store := ctx.KVStore(k.storeKey) + key := types.FeeAllowanceKey(granter, grantee) + _, found := k.GetFeeGrant(ctx, granter, grantee) + if !found { + return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "fee-grant not found") + } + + store.Delete(key) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeRevokeFeeGrant, + sdk.NewAttribute(types.AttributeKeyGranter, granter.String()), + sdk.NewAttribute(types.AttributeKeyGrantee, grantee.String()), + ), + ) + return nil +} + +// GetFeeAllowance returns the allowance between the granter and grantee. +// If there is none, it returns nil, nil. +// Returns an error on parsing issues +func (k Keeper) GetFeeAllowance(ctx sdk.Context, granter, grantee sdk.AccAddress) types.FeeAllowanceI { + grant, found := k.GetFeeGrant(ctx, granter, grantee) + if !found { + return nil + } + + return grant.GetFeeGrant() +} + +// GetFeeGrant returns entire grant between both accounts +func (k Keeper) GetFeeGrant(ctx sdk.Context, granter sdk.AccAddress, grantee sdk.AccAddress) (types.FeeAllowanceGrant, bool) { + store := ctx.KVStore(k.storeKey) + key := types.FeeAllowanceKey(granter, grantee) + bz := store.Get(key) + if len(bz) == 0 { + return types.FeeAllowanceGrant{}, false + } + + var feegrant types.FeeAllowanceGrant + k.cdc.MustUnmarshalBinaryBare(bz, &feegrant) + + return feegrant, true +} + +// IterateAllGranteeFeeAllowances iterates over all the grants from anyone to the given grantee. +// Callback to get all data, returns true to stop, false to keep reading +func (k Keeper) IterateAllGranteeFeeAllowances(ctx sdk.Context, grantee sdk.AccAddress, cb func(types.FeeAllowanceGrant) bool) error { + store := ctx.KVStore(k.storeKey) + prefix := types.FeeAllowancePrefixByGrantee(grantee) + iter := sdk.KVStorePrefixIterator(store, prefix) + defer iter.Close() + + stop := false + for ; iter.Valid() && !stop; iter.Next() { + bz := iter.Value() + + var feeGrant types.FeeAllowanceGrant + k.cdc.MustUnmarshalBinaryBare(bz, &feeGrant) + + stop = cb(feeGrant) + } + + return nil +} + +// IterateAllFeeAllowances iterates over all the grants in the store. +// Callback to get all data, returns true to stop, false to keep reading +// Calling this without pagination is very expensive and only designed for export genesis +func (k Keeper) IterateAllFeeAllowances(ctx sdk.Context, cb func(types.FeeAllowanceGrant) bool) error { + store := ctx.KVStore(k.storeKey) + iter := sdk.KVStorePrefixIterator(store, types.FeeAllowanceKeyPrefix) + defer iter.Close() + + stop := false + for ; iter.Valid() && !stop; iter.Next() { + bz := iter.Value() + var feeGrant types.FeeAllowanceGrant + k.cdc.MustUnmarshalBinaryBare(bz, &feeGrant) + + stop = cb(feeGrant) + } + + return nil +} + +// UseGrantedFees will try to pay the given fee from the granter's account as requested by the grantee +func (k Keeper) UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins) error { + grant, found := k.GetFeeGrant(ctx, granter, grantee) + if !found || grant.GetFeeGrant() == nil { + return sdkerrors.Wrapf(types.ErrNoAllowance, "grant missing") + } + + remove, err := grant.GetFeeGrant().Accept(fee, ctx.BlockTime(), ctx.BlockHeight()) + if err == nil { + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeUseFeeGrant, + sdk.NewAttribute(types.AttributeKeyGranter, granter.String()), + sdk.NewAttribute(types.AttributeKeyGrantee, grantee.String()), + ), + ) + } + + if remove { + k.RevokeFeeAllowance(ctx, granter, grantee) + // note this returns nil if err == nil + return sdkerrors.Wrap(err, "removed grant") + } + + if err != nil { + return sdkerrors.Wrap(err, "invalid grant") + } + + // if we accepted, store the updated state of the allowance + return k.GrantFeeAllowance(ctx, granter, grantee, grant.GetFeeGrant()) +} diff --git a/x/feegrant/keeper/keeper_test.go b/x/feegrant/keeper/keeper_test.go new file mode 100644 index 0000000000..c14e141d31 --- /dev/null +++ b/x/feegrant/keeper/keeper_test.go @@ -0,0 +1,257 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +type KeeperTestSuite struct { + suite.Suite + + app *simapp.SimApp + ctx sdk.Context + addrs []sdk.AccAddress +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} + +func (suite *KeeperTestSuite) SetupTest() { + app := simapp.Setup(false) + ctx := app.BaseApp.NewContext(false, tmproto.Header{}) + + suite.app = app + suite.ctx = ctx + suite.addrs = simapp.AddTestAddrsIncremental(app, ctx, 4, sdk.NewInt(30000000)) +} + +func (suite *KeeperTestSuite) TestKeeperCrud() { + ctx := suite.ctx + k := suite.app.FeeGrantKeeper + + // some helpers + atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555)) + eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 123)) + basic := &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(334455), + } + + basic2 := &types.BasicFeeAllowance{ + SpendLimit: eth, + Expiration: types.ExpiresAtHeight(172436), + } + + // let's set up some initial state here + err := k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[1], basic) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[2], basic2) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[1], suite.addrs[2], basic) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[1], suite.addrs[3], basic) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[3], suite.addrs[0], basic2) + suite.Require().NoError(err) + + // remove some, overwrite other + k.RevokeFeeAllowance(ctx, suite.addrs[0], suite.addrs[1]) + k.RevokeFeeAllowance(ctx, suite.addrs[0], suite.addrs[2]) + + err = k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[2], basic) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[1], suite.addrs[2], basic2) + suite.Require().NoError(err) + + // end state: + // addr -> addr3 (basic) + // addr2 -> addr3 (basic2), addr4(basic) + // addr4 -> addr (basic2) + + // then lots of queries + cases := map[string]struct { + grantee sdk.AccAddress + granter sdk.AccAddress + allowance types.FeeAllowanceI + }{ + "addr revoked": { + granter: suite.addrs[0], + grantee: suite.addrs[1], + }, + "addr revoked and added": { + granter: suite.addrs[0], + grantee: suite.addrs[2], + allowance: basic, + }, + "addr never there": { + granter: suite.addrs[0], + grantee: suite.addrs[3], + }, + "addr modified": { + granter: suite.addrs[1], + grantee: suite.addrs[2], + allowance: basic2, + }, + } + + for name, tc := range cases { + tc := tc + suite.Run(name, func() { + allow := k.GetFeeAllowance(ctx, tc.granter, tc.grantee) + if tc.allowance == nil { + suite.Nil(allow) + return + } + suite.NotNil(allow) + suite.Equal(tc.allowance, allow) + }) + } + + grant1, err := types.NewFeeAllowanceGrant(suite.addrs[3], suite.addrs[0], basic2) + suite.NoError(err) + + grant2, err := types.NewFeeAllowanceGrant(suite.addrs[1], suite.addrs[2], basic2) + suite.NoError(err) + + grant3, err := types.NewFeeAllowanceGrant(suite.addrs[0], suite.addrs[2], basic) + suite.NoError(err) + + allCases := map[string]struct { + grantee sdk.AccAddress + grants []types.FeeAllowanceGrant + }{ + "addr2 has none": { + grantee: suite.addrs[1], + }, + "addr has one": { + grantee: suite.addrs[0], + grants: []types.FeeAllowanceGrant{ + grant1, + }, + }, + "addr3 has two": { + grantee: suite.addrs[2], + grants: []types.FeeAllowanceGrant{ + grant3, + grant2, + }, + }, + } + + for name, tc := range allCases { + tc := tc + suite.Run(name, func() { + var grants []types.FeeAllowanceGrant + err := k.IterateAllGranteeFeeAllowances(ctx, tc.grantee, func(grant types.FeeAllowanceGrant) bool { + grants = append(grants, grant) + return false + }) + suite.NoError(err) + suite.Equal(tc.grants, grants) + }) + } +} + +func (suite *KeeperTestSuite) TestUseGrantedFee() { + ctx := suite.ctx + k := suite.app.FeeGrantKeeper + + // some helpers + atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555)) + eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 123)) + future := &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(5678), + } + + expired := &types.BasicFeeAllowance{ + SpendLimit: eth, + Expiration: types.ExpiresAtHeight(55), + } + + // for testing limits of the contract + hugeAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 9999)) + _ = hugeAtom + smallAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 1)) + _ = smallAtom + futureAfterSmall := &types.BasicFeeAllowance{ + SpendLimit: sdk.NewCoins(sdk.NewInt64Coin("atom", 554)), + Expiration: types.ExpiresAtHeight(5678), + } + + // then lots of queries + cases := map[string]struct { + grantee sdk.AccAddress + granter sdk.AccAddress + fee sdk.Coins + allowed bool + final types.FeeAllowanceI + }{ + "use entire pot": { + granter: suite.addrs[0], + grantee: suite.addrs[1], + fee: atom, + allowed: true, + final: nil, + }, + "expired and removed": { + granter: suite.addrs[0], + grantee: suite.addrs[2], + fee: eth, + allowed: false, + final: nil, + }, + "too high": { + granter: suite.addrs[0], + grantee: suite.addrs[1], + fee: hugeAtom, + allowed: false, + final: future, + }, + "use a little": { + granter: suite.addrs[0], + grantee: suite.addrs[1], + fee: smallAtom, + allowed: true, + final: futureAfterSmall, + }, + } + + for name, tc := range cases { + tc := tc + suite.Run(name, func() { + // let's set up some initial state here + // addr -> addr2 (future) + // addr -> addr3 (expired) + + err := k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[1], future) + suite.Require().NoError(err) + + err = k.GrantFeeAllowance(ctx, suite.addrs[0], suite.addrs[3], expired) + suite.Require().NoError(err) + + err = k.UseGrantedFees(ctx, tc.granter, tc.grantee, tc.fee) + if tc.allowed { + suite.NoError(err) + } else { + suite.Error(err) + } + + loaded := k.GetFeeAllowance(ctx, tc.granter, tc.grantee) + + suite.Equal(tc.final, loaded) + }) + } +} diff --git a/x/feegrant/keeper/msg_server.go b/x/feegrant/keeper/msg_server.go new file mode 100644 index 0000000000..3cd96e79ba --- /dev/null +++ b/x/feegrant/keeper/msg_server.go @@ -0,0 +1,72 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the feegrant MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(k Keeper) types.MsgServer { + return &msgServer{ + Keeper: k, + } +} + +var _ types.MsgServer = msgServer{} + +func (k msgServer) GrantFeeAllowance(goCtx context.Context, msg *types.MsgGrantFeeAllowance) (*types.MsgGrantFeeAllowanceResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return nil, err + } + + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return nil, err + } + + // Checking for duplicate entry + f := k.Keeper.GetFeeAllowance(ctx, granter, grantee) + if f != nil { + return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "fee allowance already exists") + } + + err = k.Keeper.GrantFeeAllowance(ctx, granter, grantee, msg.GetFeeAllowanceI()) + if err != nil { + return nil, err + } + + return &types.MsgGrantFeeAllowanceResponse{}, nil +} + +func (k msgServer) RevokeFeeAllowance(goCtx context.Context, msg *types.MsgRevokeFeeAllowance) (*types.MsgRevokeFeeAllowanceResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + grantee, err := sdk.AccAddressFromBech32(msg.Grantee) + if err != nil { + return nil, err + } + + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + return nil, err + } + + err = k.Keeper.RevokeFeeAllowance(ctx, granter, grantee) + if err != nil { + return nil, err + } + + return &types.MsgRevokeFeeAllowanceResponse{}, nil +} diff --git a/x/feegrant/module.go b/x/feegrant/module.go new file mode 100644 index 0000000000..5f4ba807d8 --- /dev/null +++ b/x/feegrant/module.go @@ -0,0 +1,210 @@ +package feegrant + +import ( + "context" + "encoding/json" + "math/rand" + + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + abci "github.com/tendermint/tendermint/abci/types" + + sdkclient "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/client/cli" + "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} + _ module.AppModuleSimulation = AppModule{} +) + +// ---------------------------------------------------------------------------- +// AppModuleBasic +// ---------------------------------------------------------------------------- + +// AppModuleBasic defines the basic application module used by the feegrant module. +type AppModuleBasic struct { + cdc codec.Marshaler +} + +// Name returns the feegrant module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterServices registers a gRPC query service to respond to the +// module-specific gRPC queries. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) +} + +// RegisterLegacyAminoCodec registers the feegrant module's types for the given codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { +} + +// RegisterInterfaces registers the feegrant module's interface types +func (AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// LegacyQuerierHandler returns the feegrant module sdk.Querier. +func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sdk.Querier { + return nil +} + +// DefaultGenesis returns default genesis state as raw bytes for the feegrant +// module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONMarshaler) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesisState()) +} + +// ValidateGenesis performs genesis state validation for the feegrant module. +func (a AppModuleBasic) ValidateGenesis(cdc codec.JSONMarshaler, config sdkclient.TxEncodingConfig, bz json.RawMessage) error { + var data types.GenesisState + if err := cdc.UnmarshalJSON(bz, &data); err != nil { + sdkerrors.Wrapf(err, "failed to unmarshal %s genesis state", types.ModuleName) + } + + return types.ValidateGenesis(data) +} + +// RegisterRESTRoutes registers the REST routes for the feegrant module. +func (AppModuleBasic) RegisterRESTRoutes(ctx sdkclient.Context, rtr *mux.Router) {} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the feegrant module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx sdkclient.Context, mux *runtime.ServeMux) { + types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)) +} + +// GetTxCmd returns the root tx command for the feegrant module. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd() +} + +// GetQueryCmd returns no root query command for the feegrant module. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +// ---------------------------------------------------------------------------- +// AppModule +// ---------------------------------------------------------------------------- + +// AppModule implements an application module for the feegrant module. +type AppModule struct { + AppModuleBasic + keeper keeper.Keeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + registry cdctypes.InterfaceRegistry +} + +// NewAppModule creates a new AppModule object +func NewAppModule(cdc codec.Marshaler, ak types.AccountKeeper, bk types.BankKeeper, keeper keeper.Keeper, registry cdctypes.InterfaceRegistry) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{cdc: cdc}, + keeper: keeper, + accountKeeper: ak, + bankKeeper: bk, + registry: registry, + } +} + +// Name returns the feegrant module's name. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterInvariants registers the feegrant module invariants. +func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {} + +// Route returns the message routing key for the feegrant module. +func (am AppModule) Route() sdk.Route { + return sdk.NewRoute(types.RouterKey, nil) +} + +// NewHandler returns an sdk.Handler for the feegrant module. +func (am AppModule) NewHandler() sdk.Handler { + return nil +} + +// QuerierRoute returns the feegrant module's querier route name. +func (AppModule) QuerierRoute() string { + return "" +} + +// InitGenesis performs genesis initialization for the feegrant module. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONMarshaler, bz json.RawMessage) []abci.ValidatorUpdate { + var gs types.GenesisState + cdc.MustUnmarshalJSON(bz, &gs) + + InitGenesis(ctx, am.keeper, &gs) + return []abci.ValidatorUpdate{} +} + +// ExportGenesis returns the exported genesis state as raw bytes for the feegrant +// module. +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONMarshaler) json.RawMessage { + gs, err := ExportGenesis(ctx, am.keeper) + if err != nil { + panic(err) + } + + return cdc.MustMarshalJSON(gs) +} + +// BeginBlock returns the begin blocker for the feegrant module. +func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} + +// EndBlock returns the end blocker for the feegrant module. It returns no validator +// updates. +func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +//____________________________________________________________________________ + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the feegrant module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalContents returns all the feegrant content functions used to +// simulate governance proposals. +func (AppModule) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams creates randomized feegrant param changes for the simulator. +func (AppModule) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { + return nil +} + +// RegisterStoreDecoder registers a decoder for feegrant module's types +func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { + sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) +} + +// WeightedOperations returns all the feegrant module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + protoCdc := codec.NewProtoCodec(am.registry) + return simulation.WeightedOperations( + simState.AppParams, simState.Cdc, am.accountKeeper, am.bankKeeper, am.keeper, protoCdc, + ) +} diff --git a/x/feegrant/simulation/decoder.go b/x/feegrant/simulation/decoder.go new file mode 100644 index 0000000000..46e35594fd --- /dev/null +++ b/x/feegrant/simulation/decoder.go @@ -0,0 +1,26 @@ +package simulation + +import ( + "bytes" + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's +// Value to the corresponding feegrant type. +func NewDecodeStore(cdc codec.Marshaler) func(kvA, kvB kv.Pair) string { + return func(kvA, kvB kv.Pair) string { + switch { + case bytes.Equal(kvA.Key[:1], types.FeeAllowanceKeyPrefix): + var grantA, grantB types.FeeAllowanceGrant + cdc.MustUnmarshalBinaryBare(kvA.Value, &grantA) + cdc.MustUnmarshalBinaryBare(kvB.Value, &grantB) + return fmt.Sprintf("%v\n%v", grantA, grantB) + default: + panic(fmt.Sprintf("invalid feegrant key %X", kvA.Key)) + } + } +} diff --git a/x/feegrant/simulation/decoder_test.go b/x/feegrant/simulation/decoder_test.go new file mode 100644 index 0000000000..0087e5eba1 --- /dev/null +++ b/x/feegrant/simulation/decoder_test.go @@ -0,0 +1,62 @@ +package simulation_test + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/kv" + "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/require" +) + +var ( + granterPk = ed25519.GenPrivKey().PubKey() + granterAddr = sdk.AccAddress(granterPk.Address()) + granteePk = ed25519.GenPrivKey().PubKey() + granteeAddr = sdk.AccAddress(granterPk.Address()) +) + +func TestDecodeStore(t *testing.T) { + cdc := simapp.MakeTestEncodingConfig().Marshaler + dec := simulation.NewDecodeStore(cdc) + + grant, err := types.NewFeeAllowanceGrant(granterAddr, granteeAddr, &types.BasicFeeAllowance{ + SpendLimit: sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(100))), + }) + + require.NoError(t, err) + + grantBz, err := cdc.MarshalBinaryBare(&grant) + require.NoError(t, err) + + kvPairs := kv.Pairs{ + Pairs: []kv.Pair{ + {Key: []byte(types.FeeAllowanceKeyPrefix), Value: grantBz}, + {Key: []byte{0x99}, Value: []byte{0x99}}, + }, + } + + tests := []struct { + name string + expectedLog string + }{ + {"Grant", fmt.Sprintf("%v\n%v", grant, grant)}, + {"other", ""}, + } + + for i, tt := range tests { + i, tt := i, tt + t.Run(tt.name, func(t *testing.T) { + switch i { + case len(tests) - 1: + require.Panics(t, func() { dec(kvPairs.Pairs[i], kvPairs.Pairs[i]) }, tt.name) + default: + require.Equal(t, tt.expectedLog, dec(kvPairs.Pairs[i], kvPairs.Pairs[i]), tt.name) + } + }) + } +} diff --git a/x/feegrant/simulation/genesis.go b/x/feegrant/simulation/genesis.go new file mode 100644 index 0000000000..f9f4c7e127 --- /dev/null +++ b/x/feegrant/simulation/genesis.go @@ -0,0 +1,38 @@ +package simulation + +import ( + "encoding/json" + "fmt" + "math/rand" + + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +// Simulation parameter constants +const feegrant = "feegrant" + +// GenFeeGrants returns an empty slice of evidences. +func GenFeeGrants(_ *rand.Rand, _ []simtypes.Account) []types.FeeAllowanceGrant { + return []types.FeeAllowanceGrant{} +} + +// RandomizedGenState generates a random GenesisState for feegrant +func RandomizedGenState(simState *module.SimulationState) { + var feegrants []types.FeeAllowanceGrant + + simState.AppParams.GetOrGenerate( + simState.Cdc, feegrant, &feegrants, simState.Rand, + func(r *rand.Rand) { feegrants = GenFeeGrants(r, simState.Accounts) }, + ) + feegrantGenesis := types.NewGenesisState(feegrants) + + bz, err := json.MarshalIndent(&feegrantGenesis, "", " ") + if err != nil { + panic(err) + } + + fmt.Printf("Selected randomly generated %s parameters:\n%s\n", types.ModuleName, bz) + simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(feegrantGenesis) +} diff --git a/x/feegrant/simulation/genesis_test.go b/x/feegrant/simulation/genesis_test.go new file mode 100644 index 0000000000..4f3ae74b56 --- /dev/null +++ b/x/feegrant/simulation/genesis_test.go @@ -0,0 +1,39 @@ +package simulation_test + +import ( + "encoding/json" + "math/rand" + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/require" +) + +func TestRandomizedGenState(t *testing.T) { + interfaceRegistry := codectypes.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + s := rand.NewSource(1) + r := rand.New(s) + + simState := module.SimulationState{ + AppParams: make(simtypes.AppParams), + Cdc: cdc, + Rand: r, + NumBonded: 3, + Accounts: simtypes.RandomAccounts(r, 3), + InitialStake: 1000, + GenState: make(map[string]json.RawMessage), + } + + simulation.RandomizedGenState(&simState) + var feegrantGenesis types.GenesisState + simState.Cdc.MustUnmarshalJSON(simState.GenState[types.ModuleName], &feegrantGenesis) + + require.Len(t, feegrantGenesis.FeeAllowances, 0) +} diff --git a/x/feegrant/simulation/operations.go b/x/feegrant/simulation/operations.go new file mode 100644 index 0000000000..54821873b6 --- /dev/null +++ b/x/feegrant/simulation/operations.go @@ -0,0 +1,200 @@ +package simulation + +import ( + "context" + "math/rand" + "time" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp/helpers" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/cosmos/cosmos-sdk/x/simulation" +) + +// Simulation operation weights constants +const ( + OpWeightMsgGrantFeeAllowance = "op_weight_msg_grant_fee_allowance" + OpWeightMsgRevokeFeeAllowance = "op_weight_msg_grant_revoke_allowance" + TypeMsgGrantFeeAllowance = "/cosmos.feegrant.v1beta1.Msg/GrantFeeAllowance" + TypeMsgRevokeFeeAllowance = "/cosmos.feegrant.v1beta1.Msg/RevokeFeeAllowance" +) + +func WeightedOperations( + appParams simtypes.AppParams, cdc codec.JSONMarshaler, + ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, + protoCdc *codec.ProtoCodec, +) simulation.WeightedOperations { + + var ( + weightMsgGrantFeeAllowance int + weightMsgRevokeFeeAllowance int + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgGrantFeeAllowance, &weightMsgGrantFeeAllowance, nil, + func(_ *rand.Rand) { + weightMsgGrantFeeAllowance = simappparams.DefaultWeightGrantFeeAllowance + }, + ) + + appParams.GetOrGenerate(cdc, OpWeightMsgRevokeFeeAllowance, &weightMsgRevokeFeeAllowance, nil, + func(_ *rand.Rand) { + weightMsgRevokeFeeAllowance = simappparams.DefaultWeightRevokeFeeAllowance + }, + ) + + return simulation.WeightedOperations{ + simulation.NewWeightedOperation( + weightMsgGrantFeeAllowance, + SimulateMsgGrantFeeAllowance(ak, bk, k, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgRevokeFeeAllowance, + SimulateMsgRevokeFeeAllowance(ak, bk, k, protoCdc), + ), + } +} + +// SimulateMsgGrantFeeAllowance generates MsgGrantFeeAllowance with random values. +func SimulateMsgGrantFeeAllowance(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + granter, _ := simtypes.RandomAcc(r, accs) + grantee, _ := simtypes.RandomAcc(r, accs) + if grantee.Address.String() == granter.Address.String() { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, "grantee and granter cannot be same"), nil, nil + } + + f := k.GetFeeAllowance(ctx, granter.Address, grantee.Address) + if f != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, "fee allowance exists"), nil, nil + } + + account := ak.GetAccount(ctx, granter.Address) + + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, err.Error()), nil, err + } + + spendableCoins = spendableCoins.Sub(fees) + if spendableCoins.Empty() { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, "unable to grant empty coins as SpendLimit"), nil, nil + } + + msg, err := types.NewMsgGrantFeeAllowance(&types.BasicFeeAllowance{ + SpendLimit: spendableCoins, + Expiration: types.ExpiresAtTime(ctx.BlockTime().Add(30 * time.Hour)), + }, granter.Address, grantee.Address) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, err.Error()), nil, err + } + txGen := simappparams.MakeTestEncodingConfig().TxConfig + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + feegrantMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = feegrantMsgClient.GrantFeeAllowance(context.Background(), msg) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, err.Error()), nil, err + } + tx, err := helpers.GenTx( + txGen, + svcMsgClientConn.GetMsgs(), + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + granter.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgGrantFeeAllowance, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, svcMsgClientConn.GetMsgs()[0].Type(), "unable to deliver tx"), nil, err + } + return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "", protoCdc), nil, err + } +} + +// SimulateMsgRevokeFeeAllowance generates a MsgRevokeFeeAllowance with random values. +func SimulateMsgRevokeFeeAllowance(ak types.AccountKeeper, bk types.BankKeeper, k keeper.Keeper, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + + hasGrant := false + var granterAddr sdk.AccAddress + var granteeAddr sdk.AccAddress + k.IterateAllFeeAllowances(ctx, func(grant types.FeeAllowanceGrant) bool { + + granter, err := sdk.AccAddressFromBech32(grant.Granter) + if err != nil { + panic(err) + } + grantee, err := sdk.AccAddressFromBech32(grant.Grantee) + if err != nil { + panic(err) + } + granterAddr = granter + granteeAddr = grantee + hasGrant = true + return true + }) + + if !hasGrant { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeFeeAllowance, "no grants"), nil, nil + } + granter, ok := simtypes.FindAccount(accs, granterAddr) + + if !ok { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeFeeAllowance, "Account not found"), nil, nil + } + + account := ak.GetAccount(ctx, granter.Address) + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeFeeAllowance, err.Error()), nil, err + } + + msg := types.NewMsgRevokeFeeAllowance(granterAddr, granteeAddr) + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + svcMsgClientConn := &msgservice.ServiceMsgClientConn{} + feegrantMsgClient := types.NewMsgClient(svcMsgClientConn) + _, err = feegrantMsgClient.RevokeFeeAllowance(context.Background(), &msg) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, types.TypeMsgGrantFeeAllowance, err.Error()), nil, err + } + + tx, err := helpers.GenTx( + txGen, + svcMsgClientConn.GetMsgs(), + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + granter.PrivKey, + ) + + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, TypeMsgRevokeFeeAllowance, err.Error()), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + return simtypes.NewOperationMsg(svcMsgClientConn.GetMsgs()[0], true, "", protoCdc), nil, err + } +} diff --git a/x/feegrant/simulation/operations_test.go b/x/feegrant/simulation/operations_test.go new file mode 100644 index 0000000000..7c2593a530 --- /dev/null +++ b/x/feegrant/simulation/operations_test.go @@ -0,0 +1,173 @@ +package simulation_test + +import ( + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/suite" + + abci "github.com/tendermint/tendermint/abci/types" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" +) + +type SimTestSuite struct { + suite.Suite + + ctx sdk.Context + app *simapp.SimApp + protoCdc *codec.ProtoCodec +} + +func (suite *SimTestSuite) SetupTest() { + checkTx := false + app := simapp.Setup(checkTx) + suite.app = app + suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{}) + suite.protoCdc = codec.NewProtoCodec(suite.app.InterfaceRegistry()) + +} + +func (suite *SimTestSuite) getTestingAccounts(r *rand.Rand, n int) []simtypes.Account { + app, ctx := suite.app, suite.ctx + accounts := simtypes.RandomAccounts(r, n) + require := suite.Require() + + initAmt := sdk.TokensFromConsensusPower(200) + initCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initAmt)) + + // add coins to the accounts + for _, account := range accounts { + acc := app.AccountKeeper.NewAccountWithAddress(ctx, account.Address) + app.AccountKeeper.SetAccount(ctx, acc) + err := app.BankKeeper.SetBalances(ctx, account.Address, initCoins) + require.NoError(err) + } + + return accounts +} + +func (suite *SimTestSuite) TestWeightedOperations() { + app, ctx := suite.app, suite.ctx + require := suite.Require() + + ctx.WithChainID("test-chain") + + cdc := app.AppCodec() + appParams := make(simtypes.AppParams) + + weightesOps := simulation.WeightedOperations( + appParams, cdc, app.AccountKeeper, + app.BankKeeper, app.FeeGrantKeeper, + suite.protoCdc, + ) + + s := rand.NewSource(1) + r := rand.New(s) + accs := suite.getTestingAccounts(r, 3) + + expected := []struct { + weight int + opMsgRoute string + opMsgName string + }{ + { + simappparams.DefaultWeightGrantFeeAllowance, + types.ModuleName, + simulation.TypeMsgGrantFeeAllowance, + }, + { + simappparams.DefaultWeightRevokeFeeAllowance, + types.ModuleName, + simulation.TypeMsgRevokeFeeAllowance, + }, + } + + for i, w := range weightesOps { + operationMsg, _, _ := w.Op()(r, app.BaseApp, ctx, accs, ctx.ChainID()) + // the following checks are very much dependent from the ordering of the output given + // by WeightedOperations. if the ordering in WeightedOperations changes some tests + // will fail + require.Equal(expected[i].weight, w.Weight(), "weight should be the same") + require.Equal(expected[i].opMsgRoute, operationMsg.Route, "route should be the same") + require.Equal(expected[i].opMsgName, operationMsg.Name, "operation Msg name should be the same") + } +} + +func (suite *SimTestSuite) TestSimulateMsgGrantFeeAllowance() { + app, ctx := suite.app, suite.ctx + require := suite.Require() + + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 3) + + // begin a new block + app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: app.LastBlockHeight() + 1, AppHash: app.LastCommitID().Hash}}) + + // execute operation + op := simulation.SimulateMsgGrantFeeAllowance(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, suite.protoCdc) + operationMsg, futureOperations, err := op(r, app.BaseApp, ctx, accounts, "") + require.NoError(err) + + var msg types.MsgGrantFeeAllowance + suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + + require.True(operationMsg.OK) + require.Equal("cosmos1ghekyjucln7y67ntx7cf27m9dpuxxemn4c8g4r", msg.Granter) + require.Equal("cosmos1p8wcgrjr4pjju90xg6u9cgq55dxwq8j7u4x9a0", msg.Grantee) + require.Len(futureOperations, 0) +} + +func (suite *SimTestSuite) TestSimulateMsgRevokeFeeAllowance() { + app, ctx := suite.app, suite.ctx + require := suite.Require() + + s := rand.NewSource(1) + r := rand.New(s) + accounts := suite.getTestingAccounts(r, 3) + + // begin a new block + app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: suite.app.LastBlockHeight() + 1, AppHash: suite.app.LastCommitID().Hash}}) + + feeAmt := sdk.TokensFromConsensusPower(200000) + feeCoins := sdk.NewCoins(sdk.NewCoin("foo", feeAmt)) + + granter, grantee := accounts[0], accounts[1] + + err := app.FeeGrantKeeper.GrantFeeAllowance( + ctx, + granter.Address, + grantee.Address, + &types.BasicFeeAllowance{ + SpendLimit: feeCoins, + Expiration: types.ExpiresAtTime(ctx.BlockTime().Add(30 * time.Hour)), + }, + ) + require.NoError(err) + + // execute operation + op := simulation.SimulateMsgRevokeFeeAllowance(app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, suite.protoCdc) + operationMsg, futureOperations, err := op(r, app.BaseApp, ctx, accounts, "") + require.NoError(err) + + var msg types.MsgRevokeFeeAllowance + suite.app.AppCodec().UnmarshalJSON(operationMsg.Msg, &msg) + + require.True(operationMsg.OK) + require.Equal(granter.Address.String(), msg.Granter) + require.Equal(grantee.Address.String(), msg.Grantee) + require.Len(futureOperations, 0) +} + +func TestSimTestSuite(t *testing.T) { + suite.Run(t, new(SimTestSuite)) +} diff --git a/x/feegrant/types/basic_fee.go b/x/feegrant/types/basic_fee.go new file mode 100644 index 0000000000..6d97068051 --- /dev/null +++ b/x/feegrant/types/basic_fee.go @@ -0,0 +1,61 @@ +package types + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var _ FeeAllowanceI = (*BasicFeeAllowance)(nil) + +// Accept can use fee payment requested as well as timestamp/height of the current block +// to determine whether or not to process this. This is checked in +// Keeper.UseGrantedFees and the return values should match how it is handled there. +// +// If it returns an error, the fee payment is rejected, otherwise it is accepted. +// The FeeAllowance implementation is expected to update it's internal state +// and will be saved again after an acceptance. +// +// If remove is true (regardless of the error), the FeeAllowance will be deleted from storage +// (eg. when it is used up). (See call to RevokeFeeAllowance in Keeper.UseGrantedFees) +func (a *BasicFeeAllowance) Accept(fee sdk.Coins, blockTime time.Time, blockHeight int64) (bool, error) { + if a.Expiration.IsExpired(&blockTime, blockHeight) { + return true, sdkerrors.Wrap(ErrFeeLimitExpired, "basic allowance") + } + + if a.SpendLimit != nil { + left, invalid := a.SpendLimit.SafeSub(fee) + if invalid { + return false, sdkerrors.Wrap(ErrFeeLimitExceeded, "basic allowance") + } + + a.SpendLimit = left + return left.IsZero(), nil + } + + return false, nil +} + +// PrepareForExport will adjust the expiration based on export time. In particular, +// it will subtract the dumpHeight from any height-based expiration to ensure that +// the elapsed number of blocks this allowance is valid for is fixed. +func (a *BasicFeeAllowance) PrepareForExport(dumpTime time.Time, dumpHeight int64) FeeAllowanceI { + return &BasicFeeAllowance{ + SpendLimit: a.SpendLimit, + Expiration: a.Expiration.PrepareForExport(dumpTime, dumpHeight), + } +} + +// ValidateBasic implements FeeAllowance and enforces basic sanity checks +func (a BasicFeeAllowance) ValidateBasic() error { + if a.SpendLimit != nil { + if !a.SpendLimit.IsValid() { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "send amount is invalid: %s", a.SpendLimit) + } + if !a.SpendLimit.IsAllPositive() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "spend limit must be positive") + } + } + return a.Expiration.ValidateBasic() +} diff --git a/x/feegrant/types/basic_fee_test.go b/x/feegrant/types/basic_fee_test.go new file mode 100644 index 0000000000..a5669e99ad --- /dev/null +++ b/x/feegrant/types/basic_fee_test.go @@ -0,0 +1,140 @@ +package types_test + +import ( + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBasicFeeValidAllow(t *testing.T) { + eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 10)) + atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555)) + smallAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 43)) + bigAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 1000)) + leftAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 512)) + + cases := map[string]struct { + allow *types.BasicFeeAllowance + // all other checks are ignored if valid=false + fee sdk.Coins + blockTime time.Time + blockHeight int64 + valid bool + accept bool + remove bool + remains sdk.Coins + }{ + "empty": { + allow: &types.BasicFeeAllowance{}, + valid: true, + accept: true, + }, + "small fee without expire": { + allow: &types.BasicFeeAllowance{ + SpendLimit: atom, + }, + valid: true, + fee: smallAtom, + accept: true, + remove: false, + remains: leftAtom, + }, + "all fee without expire": { + allow: &types.BasicFeeAllowance{ + SpendLimit: smallAtom, + }, + valid: true, + fee: smallAtom, + accept: true, + remove: true, + }, + "wrong fee": { + allow: &types.BasicFeeAllowance{ + SpendLimit: smallAtom, + }, + valid: true, + fee: eth, + accept: false, + }, + "non-expired": { + allow: &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + valid: true, + fee: smallAtom, + blockHeight: 85, + accept: true, + remove: false, + remains: leftAtom, + }, + "expired": { + allow: &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + valid: true, + fee: smallAtom, + blockHeight: 121, + accept: false, + remove: true, + }, + "fee more than allowed": { + allow: &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + valid: true, + fee: bigAtom, + blockHeight: 85, + accept: false, + }, + "with out spend limit": { + allow: &types.BasicFeeAllowance{ + Expiration: types.ExpiresAtHeight(100), + }, + valid: true, + fee: bigAtom, + blockHeight: 85, + accept: true, + }, + "expired no spend limit": { + allow: &types.BasicFeeAllowance{ + Expiration: types.ExpiresAtHeight(100), + }, + valid: true, + fee: bigAtom, + blockHeight: 120, + accept: false, + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + t.Run(name, func(t *testing.T) { + err := tc.allow.ValidateBasic() + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + + // now try to deduct + remove, err := tc.allow.Accept(tc.fee, tc.blockTime, tc.blockHeight) + if !tc.accept { + require.Error(t, err) + return + } + require.NoError(t, err) + + require.Equal(t, tc.remove, remove) + if !remove { + assert.Equal(t, tc.allow.SpendLimit, tc.remains) + } + }) + } +} diff --git a/x/feegrant/types/codec.go b/x/feegrant/types/codec.go new file mode 100644 index 0000000000..686187cd75 --- /dev/null +++ b/x/feegrant/types/codec.go @@ -0,0 +1,24 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +// RegisterInterfaces registers the interfaces types with the interface registry +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.MsgRequest)(nil), + &MsgGrantFeeAllowance{}, + &MsgRevokeFeeAllowance{}, + ) + + registry.RegisterInterface( + "cosmos.feegrant.v1beta1.FeeAllowanceI", + (*FeeAllowanceI)(nil), + &BasicFeeAllowance{}, + &PeriodicFeeAllowance{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} diff --git a/x/feegrant/types/errors.go b/x/feegrant/types/errors.go new file mode 100644 index 0000000000..183f681ca5 --- /dev/null +++ b/x/feegrant/types/errors.go @@ -0,0 +1,21 @@ +package types + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// Codes for governance errors +const ( + DefaultCodespace = ModuleName +) + +var ( + // ErrFeeLimitExceeded error if there are not enough allowance to cover the fees + ErrFeeLimitExceeded = sdkerrors.Register(DefaultCodespace, 2, "fee limit exceeded") + // ErrFeeLimitExpired error if the allowance has expired + ErrFeeLimitExpired = sdkerrors.Register(DefaultCodespace, 3, "fee allowance expired") + // ErrInvalidDuration error if the Duration is invalid or doesn't match the expiration + ErrInvalidDuration = sdkerrors.Register(DefaultCodespace, 4, "invalid duration") + // ErrNoAllowance error if there is no allowance for that pair + ErrNoAllowance = sdkerrors.Register(DefaultCodespace, 5, "no allowance") +) diff --git a/x/feegrant/types/events.go b/x/feegrant/types/events.go new file mode 100644 index 0000000000..b82ccb7b1c --- /dev/null +++ b/x/feegrant/types/events.go @@ -0,0 +1,13 @@ +package types + +// evidence module events +const ( + EventTypeUseFeeGrant = "use_feegrant" + EventTypeRevokeFeeGrant = "revoke_feegrant" + EventTypeSetFeeGrant = "set_feegrant" + + AttributeKeyGranter = "granter" + AttributeKeyGrantee = "grantee" + + AttributeValueCategory = ModuleName +) diff --git a/x/feegrant/types/expected_keepers.go b/x/feegrant/types/expected_keepers.go new file mode 100644 index 0000000000..40966b06d4 --- /dev/null +++ b/x/feegrant/types/expected_keepers.go @@ -0,0 +1,23 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + auth "github.com/cosmos/cosmos-sdk/x/auth/types" + // supply "github.com/cosmos/cosmos-sdk/x/supply/exported" +) + +// AccountKeeper defines the expected auth Account Keeper (noalias) +type AccountKeeper interface { + GetModuleAddress(moduleName string) sdk.AccAddress + GetModuleAccount(ctx sdk.Context, moduleName string) auth.ModuleAccountI + + NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) auth.AccountI + GetAccount(ctx sdk.Context, addr sdk.AccAddress) auth.AccountI + SetAccount(ctx sdk.Context, acc auth.AccountI) +} + +// BankKeeper defines the expected supply Keeper (noalias) +type BankKeeper interface { + SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error +} diff --git a/x/feegrant/types/expiration.go b/x/feegrant/types/expiration.go new file mode 100644 index 0000000000..4922b6d481 --- /dev/null +++ b/x/feegrant/types/expiration.go @@ -0,0 +1,138 @@ +package types + +import ( + "time" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// ExpiresAtTime creates an expiration at the given time +func ExpiresAtTime(t time.Time) ExpiresAt { + return ExpiresAt{ + Sum: &ExpiresAt_Time{ + Time: &t, + }, + } +} + +// ExpiresAtHeight creates an expiration at the given height +func ExpiresAtHeight(h int64) ExpiresAt { + return ExpiresAt{ + &ExpiresAt_Height{ + Height: h, + }, + } +} + +// ValidateBasic performs basic sanity checks. +// Note that empty expiration is allowed +func (e ExpiresAt) ValidateBasic() error { + if e.HasDefinedTime() && e.GetHeight() != 0 { + return sdkerrors.Wrap(ErrInvalidDuration, "both time and height are set") + } + if e.GetHeight() < 0 { + return sdkerrors.Wrap(ErrInvalidDuration, "negative height") + } + return nil +} + +// Undefined returns true for an uninitialized struct +func (e ExpiresAt) Undefined() bool { + return (e.GetTime() == nil || e.GetTime().Unix() <= 0) && e.GetHeight() == 0 +} + +// HasDefinedTime returns true if `ExpiresAt` has valid time +func (e ExpiresAt) HasDefinedTime() bool { + t := e.GetTime() + return t != nil && t.Unix() > 0 +} + +// FastForward produces a new Expiration with the time or height set to the +// new value, depending on what was set on the original expiration +func (e ExpiresAt) FastForward(t time.Time, h int64) ExpiresAt { + if e.HasDefinedTime() { + return ExpiresAtTime(t) + } + return ExpiresAtHeight(h) +} + +// IsExpired returns if the time or height is *equal to* or greater +// than the defined expiration point. Note that it is expired upon +// an exact match. +// +// Note a "zero" ExpiresAt is never expired +func (e ExpiresAt) IsExpired(t *time.Time, h int64) bool { + if e.HasDefinedTime() && t.After(*e.GetTime()) { + return true + } + + return e.GetHeight() != 0 && h >= e.GetHeight() +} + +// IsCompatible returns true iff the two use the same units. +// If false, they cannot be added. +func (e ExpiresAt) IsCompatible(d Duration) bool { + if e.HasDefinedTime() { + return d.GetDuration() != nil && d.GetDuration().Seconds() > float64(0) + } + return d.GetBlocks() > 0 +} + +// Step will increase the expiration point by one Duration +// It returns an error if the Duration is incompatible +func (e ExpiresAt) Step(d Duration) (ExpiresAt, error) { + if !e.IsCompatible(d) { + return ExpiresAt{}, sdkerrors.Wrap(ErrInvalidDuration, "expiration time and provided duration have different units") + } + if e.HasDefinedTime() { + return ExpiresAtTime(e.GetTime().Add(*d.GetDuration())), nil + } + return ExpiresAtHeight(e.GetHeight() + int64(d.GetBlocks())), nil +} + +// MustStep is like Step, but panics on error +func (e ExpiresAt) MustStep(d Duration) ExpiresAt { + res, err := e.Step(d) + if err != nil { + panic(err) + } + return res +} + +// PrepareForExport will deduct the dumpHeight from the expiration, so when this is +// reloaded after a hard fork, the actual number of allowed blocks is constant +func (e ExpiresAt) PrepareForExport(dumpTime time.Time, dumpHeight int64) ExpiresAt { + if e.GetHeight() != 0 { + return ExpiresAtHeight(e.GetHeight() - dumpHeight) + } + return ExpiresAt{} +} + +// ClockDuration creates an Duration by clock time +func ClockDuration(d time.Duration) Duration { + return Duration{Sum: &Duration_Duration{ + Duration: &d, + }} +} + +// BlockDuration creates an Duration by block height +func BlockDuration(h uint64) Duration { + return Duration{Sum: &Duration_Blocks{ + Blocks: h, + }} +} + +// ValidateBasic performs basic sanity checks +// Note that exactly one must be set and it must be positive +func (d Duration) ValidateBasic() error { + if d.GetBlocks() == 0 && d.GetDuration() == nil { + return sdkerrors.Wrap(ErrInvalidDuration, "neither time and height are set") + } + if d.GetBlocks() != 0 && d.GetDuration() != nil && d.GetDuration().Seconds() != float64(0) { + return sdkerrors.Wrap(ErrInvalidDuration, "both time and height are set") + } + if d.GetDuration() != nil && d.GetDuration().Seconds() < 0 { + return sdkerrors.Wrap(ErrInvalidDuration, "negative clock step") + } + return nil +} diff --git a/x/feegrant/types/expiration_test.go b/x/feegrant/types/expiration_test.go new file mode 100644 index 0000000000..60b1753bcb --- /dev/null +++ b/x/feegrant/types/expiration_test.go @@ -0,0 +1,161 @@ +package types_test + +import ( + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestExpiresAt(t *testing.T) { + now := time.Now() + + cases := map[string]struct { + example types.ExpiresAt + valid bool + zero bool + before types.ExpiresAt + after types.ExpiresAt + }{ + "basic": { + example: types.ExpiresAtHeight(100), + valid: true, + before: types.ExpiresAtHeight(50), + after: types.ExpiresAtHeight(122), + }, + "zero": { + example: types.ExpiresAt{}, + zero: true, + valid: true, + before: types.ExpiresAtHeight(1), + }, + "match height": { + example: types.ExpiresAtHeight(1000), + valid: true, + before: types.ExpiresAtHeight(999), + after: types.ExpiresAtHeight(1000), + }, + "match time": { + example: types.ExpiresAtTime(now), + valid: true, + before: types.ExpiresAtTime(now.Add(-1 * time.Second)), + after: types.ExpiresAtTime(now.Add(1 * time.Second)), + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + t.Run(name, func(t *testing.T) { + err := tc.example.ValidateBasic() + assert.Equal(t, tc.zero, tc.example.Undefined()) + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + + if !tc.before.Undefined() { + assert.Equal(t, false, tc.example.IsExpired(tc.before.GetTime(), tc.before.GetHeight())) + } + if !tc.after.Undefined() { + assert.Equal(t, true, tc.example.IsExpired(tc.after.GetTime(), tc.after.GetHeight())) + } + }) + } +} + +func TestDurationValid(t *testing.T) { + now := time.Now() + + cases := map[string]struct { + period types.Duration + valid bool + compatible types.ExpiresAt + incompatible types.ExpiresAt + }{ + "basic height": { + period: types.BlockDuration(100), + valid: true, + compatible: types.ExpiresAtHeight(50), + incompatible: types.ExpiresAtTime(now), + }, + "basic time": { + period: types.ClockDuration(time.Hour), + valid: true, + compatible: types.ExpiresAtTime(now), + incompatible: types.ExpiresAtHeight(50), + }, + "zero": { + period: types.Duration{}, + valid: false, + }, + "negative clock": { + period: types.ClockDuration(-1 * time.Hour), + valid: false, + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + t.Run(name, func(t *testing.T) { + err := tc.period.ValidateBasic() + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + + assert.Equal(t, true, tc.compatible.IsCompatible(tc.period)) + assert.Equal(t, false, tc.incompatible.IsCompatible(tc.period)) + }) + } +} + +func TestDurationStep(t *testing.T) { + now := time.Now() + + cases := map[string]struct { + expires types.ExpiresAt + period types.Duration + valid bool + result types.ExpiresAt + }{ + "add height": { + expires: types.ExpiresAtHeight(789), + period: types.BlockDuration(100), + valid: true, + result: types.ExpiresAtHeight(889), + }, + "add time": { + expires: types.ExpiresAtTime(now), + period: types.ClockDuration(time.Hour), + valid: true, + result: types.ExpiresAtTime(now.Add(time.Hour)), + }, + "mismatch": { + expires: types.ExpiresAtHeight(789), + period: types.ClockDuration(time.Hour), + valid: false, + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + t.Run(name, func(t *testing.T) { + err := tc.period.ValidateBasic() + require.NoError(t, err) + err = tc.expires.ValidateBasic() + require.NoError(t, err) + + next, err := tc.expires.Step(tc.period) + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tc.result, next) + }) + } +} diff --git a/x/feegrant/types/feegrant.pb.go b/x/feegrant/types/feegrant.pb.go new file mode 100644 index 0000000000..2897bcc392 --- /dev/null +++ b/x/feegrant/types/feegrant.pb.go @@ -0,0 +1,1701 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/feegrant/v1beta1/feegrant.proto + +package types + +import ( + fmt "fmt" + types1 "github.com/cosmos/cosmos-sdk/codec/types" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" + _ "github.com/golang/protobuf/ptypes/duration" + _ "github.com/golang/protobuf/ptypes/timestamp" + _ "github.com/regen-network/cosmos-proto" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// BasicFeeAllowance implements FeeAllowance with a one-time grant of tokens +// that optionally expires. The delegatee can use up to SpendLimit to cover fees. +type BasicFeeAllowance struct { + // spend_limit specifies the maximum amount of tokens that can be spent + // by this allowance and will be updated as tokens are spent. If it is + // empty, there is no spend limit and any amount of coins can be spent. + SpendLimit github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=spend_limit,json=spendLimit,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"spend_limit"` + // expiration specifies an optional time when this allowance expires + Expiration ExpiresAt `protobuf:"bytes,2,opt,name=expiration,proto3" json:"expiration"` +} + +func (m *BasicFeeAllowance) Reset() { *m = BasicFeeAllowance{} } +func (m *BasicFeeAllowance) String() string { return proto.CompactTextString(m) } +func (*BasicFeeAllowance) ProtoMessage() {} +func (*BasicFeeAllowance) Descriptor() ([]byte, []int) { + return fileDescriptor_7279582900c30aea, []int{0} +} +func (m *BasicFeeAllowance) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BasicFeeAllowance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BasicFeeAllowance.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 *BasicFeeAllowance) XXX_Merge(src proto.Message) { + xxx_messageInfo_BasicFeeAllowance.Merge(m, src) +} +func (m *BasicFeeAllowance) XXX_Size() int { + return m.Size() +} +func (m *BasicFeeAllowance) XXX_DiscardUnknown() { + xxx_messageInfo_BasicFeeAllowance.DiscardUnknown(m) +} + +var xxx_messageInfo_BasicFeeAllowance proto.InternalMessageInfo + +func (m *BasicFeeAllowance) GetSpendLimit() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.SpendLimit + } + return nil +} + +func (m *BasicFeeAllowance) GetExpiration() ExpiresAt { + if m != nil { + return m.Expiration + } + return ExpiresAt{} +} + +// PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, +// as well as a limit per time period. +type PeriodicFeeAllowance struct { + // basic specifies a struct of `BasicFeeAllowance` + Basic BasicFeeAllowance `protobuf:"bytes,1,opt,name=basic,proto3" json:"basic"` + // period specifies the time duration in which period_spend_limit coins can + // be spent before that allowance is reset + Period Duration `protobuf:"bytes,2,opt,name=period,proto3" json:"period"` + // period_spend_limit specifies the maximum number of coins that can be spent + // in the period + PeriodSpendLimit github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=period_spend_limit,json=periodSpendLimit,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"period_spend_limit"` + // period_can_spend is the number of coins left to be spent before the period_reset time + PeriodCanSpend github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,4,rep,name=period_can_spend,json=periodCanSpend,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"period_can_spend"` + // period_reset is the time at which this period resets and a new one begins, + // it is calculated from the start time of the first transaction after the + // last period ended + PeriodReset ExpiresAt `protobuf:"bytes,5,opt,name=period_reset,json=periodReset,proto3" json:"period_reset"` +} + +func (m *PeriodicFeeAllowance) Reset() { *m = PeriodicFeeAllowance{} } +func (m *PeriodicFeeAllowance) String() string { return proto.CompactTextString(m) } +func (*PeriodicFeeAllowance) ProtoMessage() {} +func (*PeriodicFeeAllowance) Descriptor() ([]byte, []int) { + return fileDescriptor_7279582900c30aea, []int{1} +} +func (m *PeriodicFeeAllowance) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PeriodicFeeAllowance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PeriodicFeeAllowance.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 *PeriodicFeeAllowance) XXX_Merge(src proto.Message) { + xxx_messageInfo_PeriodicFeeAllowance.Merge(m, src) +} +func (m *PeriodicFeeAllowance) XXX_Size() int { + return m.Size() +} +func (m *PeriodicFeeAllowance) XXX_DiscardUnknown() { + xxx_messageInfo_PeriodicFeeAllowance.DiscardUnknown(m) +} + +var xxx_messageInfo_PeriodicFeeAllowance proto.InternalMessageInfo + +func (m *PeriodicFeeAllowance) GetBasic() BasicFeeAllowance { + if m != nil { + return m.Basic + } + return BasicFeeAllowance{} +} + +func (m *PeriodicFeeAllowance) GetPeriod() Duration { + if m != nil { + return m.Period + } + return Duration{} +} + +func (m *PeriodicFeeAllowance) GetPeriodSpendLimit() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.PeriodSpendLimit + } + return nil +} + +func (m *PeriodicFeeAllowance) GetPeriodCanSpend() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.PeriodCanSpend + } + return nil +} + +func (m *PeriodicFeeAllowance) GetPeriodReset() ExpiresAt { + if m != nil { + return m.PeriodReset + } + return ExpiresAt{} +} + +// Duration is a span of a clock time or number of blocks. +// This is designed to be added to an ExpiresAt struct. +type Duration struct { + // sum is the oneof that represents either duration or block + // + // Types that are valid to be assigned to Sum: + // *Duration_Duration + // *Duration_Blocks + Sum isDuration_Sum `protobuf_oneof:"sum"` +} + +func (m *Duration) Reset() { *m = Duration{} } +func (m *Duration) String() string { return proto.CompactTextString(m) } +func (*Duration) ProtoMessage() {} +func (*Duration) Descriptor() ([]byte, []int) { + return fileDescriptor_7279582900c30aea, []int{2} +} +func (m *Duration) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Duration.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 *Duration) XXX_Merge(src proto.Message) { + xxx_messageInfo_Duration.Merge(m, src) +} +func (m *Duration) XXX_Size() int { + return m.Size() +} +func (m *Duration) XXX_DiscardUnknown() { + xxx_messageInfo_Duration.DiscardUnknown(m) +} + +var xxx_messageInfo_Duration proto.InternalMessageInfo + +type isDuration_Sum interface { + isDuration_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type Duration_Duration struct { + Duration *time.Duration `protobuf:"bytes,1,opt,name=duration,proto3,oneof,stdduration" json:"duration,omitempty"` +} +type Duration_Blocks struct { + Blocks uint64 `protobuf:"varint,2,opt,name=blocks,proto3,oneof" json:"blocks,omitempty"` +} + +func (*Duration_Duration) isDuration_Sum() {} +func (*Duration_Blocks) isDuration_Sum() {} + +func (m *Duration) GetSum() isDuration_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *Duration) GetDuration() *time.Duration { + if x, ok := m.GetSum().(*Duration_Duration); ok { + return x.Duration + } + return nil +} + +func (m *Duration) GetBlocks() uint64 { + if x, ok := m.GetSum().(*Duration_Blocks); ok { + return x.Blocks + } + return 0 +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*Duration) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*Duration_Duration)(nil), + (*Duration_Blocks)(nil), + } +} + +// ExpiresAt is a point in time where something expires. +// It may be *either* block time or block height +type ExpiresAt struct { + // sum is the oneof that represents either time or height + // + // Types that are valid to be assigned to Sum: + // *ExpiresAt_Time + // *ExpiresAt_Height + Sum isExpiresAt_Sum `protobuf_oneof:"sum"` +} + +func (m *ExpiresAt) Reset() { *m = ExpiresAt{} } +func (m *ExpiresAt) String() string { return proto.CompactTextString(m) } +func (*ExpiresAt) ProtoMessage() {} +func (*ExpiresAt) Descriptor() ([]byte, []int) { + return fileDescriptor_7279582900c30aea, []int{3} +} +func (m *ExpiresAt) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ExpiresAt) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ExpiresAt.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 *ExpiresAt) XXX_Merge(src proto.Message) { + xxx_messageInfo_ExpiresAt.Merge(m, src) +} +func (m *ExpiresAt) XXX_Size() int { + return m.Size() +} +func (m *ExpiresAt) XXX_DiscardUnknown() { + xxx_messageInfo_ExpiresAt.DiscardUnknown(m) +} + +var xxx_messageInfo_ExpiresAt proto.InternalMessageInfo + +type isExpiresAt_Sum interface { + isExpiresAt_Sum() + MarshalTo([]byte) (int, error) + Size() int +} + +type ExpiresAt_Time struct { + Time *time.Time `protobuf:"bytes,1,opt,name=time,proto3,oneof,stdtime" json:"time,omitempty"` +} +type ExpiresAt_Height struct { + Height int64 `protobuf:"varint,2,opt,name=height,proto3,oneof" json:"height,omitempty"` +} + +func (*ExpiresAt_Time) isExpiresAt_Sum() {} +func (*ExpiresAt_Height) isExpiresAt_Sum() {} + +func (m *ExpiresAt) GetSum() isExpiresAt_Sum { + if m != nil { + return m.Sum + } + return nil +} + +func (m *ExpiresAt) GetTime() *time.Time { + if x, ok := m.GetSum().(*ExpiresAt_Time); ok { + return x.Time + } + return nil +} + +func (m *ExpiresAt) GetHeight() int64 { + if x, ok := m.GetSum().(*ExpiresAt_Height); ok { + return x.Height + } + return 0 +} + +// XXX_OneofWrappers is for the internal use of the proto package. +func (*ExpiresAt) XXX_OneofWrappers() []interface{} { + return []interface{}{ + (*ExpiresAt_Time)(nil), + (*ExpiresAt_Height)(nil), + } +} + +// FeeAllowanceGrant is stored in the KVStore to record a grant with full context +type FeeAllowanceGrant struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + Allowance *types1.Any `protobuf:"bytes,3,opt,name=allowance,proto3" json:"allowance,omitempty"` +} + +func (m *FeeAllowanceGrant) Reset() { *m = FeeAllowanceGrant{} } +func (m *FeeAllowanceGrant) String() string { return proto.CompactTextString(m) } +func (*FeeAllowanceGrant) ProtoMessage() {} +func (*FeeAllowanceGrant) Descriptor() ([]byte, []int) { + return fileDescriptor_7279582900c30aea, []int{4} +} +func (m *FeeAllowanceGrant) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *FeeAllowanceGrant) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_FeeAllowanceGrant.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 *FeeAllowanceGrant) XXX_Merge(src proto.Message) { + xxx_messageInfo_FeeAllowanceGrant.Merge(m, src) +} +func (m *FeeAllowanceGrant) XXX_Size() int { + return m.Size() +} +func (m *FeeAllowanceGrant) XXX_DiscardUnknown() { + xxx_messageInfo_FeeAllowanceGrant.DiscardUnknown(m) +} + +var xxx_messageInfo_FeeAllowanceGrant proto.InternalMessageInfo + +func (m *FeeAllowanceGrant) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *FeeAllowanceGrant) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *FeeAllowanceGrant) GetAllowance() *types1.Any { + if m != nil { + return m.Allowance + } + return nil +} + +func init() { + proto.RegisterType((*BasicFeeAllowance)(nil), "cosmos.feegrant.v1beta1.BasicFeeAllowance") + proto.RegisterType((*PeriodicFeeAllowance)(nil), "cosmos.feegrant.v1beta1.PeriodicFeeAllowance") + proto.RegisterType((*Duration)(nil), "cosmos.feegrant.v1beta1.Duration") + proto.RegisterType((*ExpiresAt)(nil), "cosmos.feegrant.v1beta1.ExpiresAt") + proto.RegisterType((*FeeAllowanceGrant)(nil), "cosmos.feegrant.v1beta1.FeeAllowanceGrant") +} + +func init() { + proto.RegisterFile("cosmos/feegrant/v1beta1/feegrant.proto", fileDescriptor_7279582900c30aea) +} + +var fileDescriptor_7279582900c30aea = []byte{ + // 599 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x4f, 0x6e, 0xd3, 0x40, + 0x14, 0xc6, 0x6d, 0x9c, 0x96, 0x76, 0x02, 0x88, 0x8c, 0x22, 0xe1, 0x64, 0xe1, 0x94, 0x2c, 0x50, + 0x84, 0x14, 0x9b, 0x16, 0x89, 0x05, 0x12, 0x42, 0x71, 0x69, 0x1b, 0x04, 0x0b, 0x64, 0x58, 0xb1, + 0x89, 0x6c, 0x67, 0xea, 0x0c, 0xb5, 0x3d, 0x96, 0x67, 0x02, 0xcd, 0x25, 0x50, 0x97, 0x9c, 0x81, + 0x35, 0x87, 0xa8, 0x58, 0x55, 0xac, 0x58, 0xb5, 0x28, 0x39, 0x01, 0x37, 0x40, 0xf3, 0xc7, 0x4e, + 0x94, 0x10, 0x24, 0xa4, 0xae, 0xe2, 0x99, 0x79, 0xef, 0xfb, 0xbd, 0xf7, 0xbd, 0x99, 0x80, 0x07, + 0x21, 0xa1, 0x09, 0xa1, 0xce, 0x31, 0x42, 0x51, 0xee, 0xa7, 0xcc, 0xf9, 0xb8, 0x1b, 0x20, 0xe6, + 0xef, 0x96, 0x1b, 0x76, 0x96, 0x13, 0x46, 0xe0, 0x3d, 0x19, 0x67, 0x97, 0xdb, 0x2a, 0xae, 0x59, + 0x8f, 0x48, 0x44, 0x44, 0x8c, 0xc3, 0xbf, 0x64, 0x78, 0xb3, 0x11, 0x11, 0x12, 0xc5, 0xc8, 0x11, + 0xab, 0x60, 0x7c, 0xec, 0xf8, 0xe9, 0xa4, 0x38, 0x92, 0x4a, 0x03, 0x99, 0xa3, 0x64, 0xe5, 0x91, + 0xa5, 0x8a, 0x09, 0x7c, 0x8a, 0xca, 0x42, 0x42, 0x82, 0x53, 0x75, 0xde, 0x5a, 0x56, 0x65, 0x38, + 0x41, 0x94, 0xf9, 0x49, 0x56, 0x08, 0x2c, 0x07, 0x0c, 0xc7, 0xb9, 0xcf, 0x30, 0x51, 0x02, 0xed, + 0x4b, 0x1d, 0xd4, 0x5c, 0x9f, 0xe2, 0xf0, 0x10, 0xa1, 0x5e, 0x1c, 0x93, 0x4f, 0x7e, 0x1a, 0x22, + 0x18, 0x83, 0x2a, 0xcd, 0x50, 0x3a, 0x1c, 0xc4, 0x38, 0xc1, 0xcc, 0xd4, 0x77, 0x8c, 0x4e, 0x75, + 0xaf, 0x61, 0xab, 0xd2, 0x78, 0x31, 0x45, 0xb7, 0xf6, 0x3e, 0xc1, 0xa9, 0xfb, 0xe8, 0xfc, 0xb2, + 0xa5, 0x7d, 0xbd, 0x6a, 0x75, 0x22, 0xcc, 0x46, 0xe3, 0xc0, 0x0e, 0x49, 0xa2, 0xfa, 0x50, 0x3f, + 0x5d, 0x3a, 0x3c, 0x71, 0xd8, 0x24, 0x43, 0x54, 0x24, 0x50, 0x0f, 0x08, 0xfd, 0xd7, 0x5c, 0x1e, + 0xf6, 0x01, 0x40, 0xa7, 0x19, 0x96, 0x75, 0x99, 0x37, 0x76, 0xf4, 0x4e, 0x75, 0xaf, 0x6d, 0xaf, + 0xb1, 0xd7, 0x3e, 0xe0, 0xa1, 0x88, 0xf6, 0x98, 0x5b, 0xe1, 0x54, 0x6f, 0x21, 0xf7, 0x69, 0xed, + 0xc7, 0xb7, 0xee, 0xed, 0xc5, 0x4e, 0x5e, 0xb6, 0x7f, 0x1b, 0xa0, 0xfe, 0x06, 0xe5, 0x98, 0x0c, + 0x97, 0x7a, 0x3c, 0x04, 0x1b, 0x01, 0x6f, 0xdc, 0xd4, 0x05, 0xf0, 0xe1, 0x5a, 0xe0, 0x8a, 0x3d, + 0x0a, 0x2c, 0xd3, 0xe1, 0x73, 0xb0, 0x99, 0x09, 0x7d, 0x55, 0xf9, 0xfd, 0xb5, 0x42, 0x2f, 0x94, + 0xf5, 0x2a, 0x5f, 0xa5, 0xc1, 0x09, 0x80, 0xf2, 0x6b, 0xb0, 0xe8, 0xb9, 0x71, 0xfd, 0x9e, 0xdf, + 0x95, 0x98, 0xb7, 0x73, 0xe7, 0xc7, 0x40, 0xed, 0x0d, 0x42, 0x3f, 0x95, 0x78, 0xb3, 0x72, 0xfd, + 0xe0, 0x3b, 0x12, 0xb2, 0xef, 0xa7, 0x82, 0x0d, 0x5f, 0x81, 0x5b, 0x0a, 0x9b, 0x23, 0x8a, 0x98, + 0xb9, 0xf1, 0x9f, 0x23, 0xaf, 0xca, 0x6c, 0x8f, 0x27, 0xff, 0x6d, 0xe6, 0x1f, 0xc0, 0x56, 0xe1, + 0x35, 0x7c, 0x06, 0xb6, 0x8a, 0x2b, 0xaf, 0x26, 0xdd, 0xb0, 0xe5, 0x9b, 0xb0, 0x8b, 0x37, 0xb1, + 0x30, 0x98, 0x2f, 0x57, 0x2d, 0xbd, 0xaf, 0x79, 0x65, 0x0a, 0x34, 0xc1, 0x66, 0x10, 0x93, 0xf0, + 0x84, 0x8a, 0xe9, 0x56, 0xfa, 0x9a, 0xa7, 0xd6, 0xee, 0x06, 0x30, 0xe8, 0x38, 0x69, 0x0f, 0xc1, + 0x76, 0x59, 0x1e, 0x7c, 0x02, 0x2a, 0xfc, 0x01, 0x2a, 0x50, 0x73, 0x05, 0xf4, 0xae, 0x78, 0x9d, + 0x6e, 0xe5, 0x4c, 0x92, 0x44, 0x3c, 0xa7, 0x8c, 0x10, 0x8e, 0x46, 0x4c, 0x50, 0x0c, 0x4e, 0x91, + 0xeb, 0x82, 0xf2, 0x59, 0x07, 0xb5, 0xc5, 0x1e, 0x8f, 0xb8, 0x3f, 0xd0, 0x04, 0x37, 0x85, 0x51, + 0x28, 0x17, 0xc4, 0x6d, 0xaf, 0x58, 0xce, 0x4f, 0x90, 0x50, 0x2c, 0x4f, 0x10, 0x3c, 0x00, 0xdb, + 0x7e, 0xa1, 0x62, 0x1a, 0xa2, 0xce, 0xfa, 0x4a, 0x9d, 0xbd, 0x74, 0xe2, 0xd6, 0xbe, 0x2f, 0xfb, + 0xea, 0xcd, 0x33, 0xdd, 0xa3, 0xf3, 0xa9, 0xa5, 0x5f, 0x4c, 0x2d, 0xfd, 0xd7, 0xd4, 0xd2, 0xcf, + 0x66, 0x96, 0x76, 0x31, 0xb3, 0xb4, 0x9f, 0x33, 0x4b, 0x7b, 0xdf, 0xfd, 0xe7, 0xb5, 0x38, 0x9d, + 0xff, 0xaf, 0x8a, 0x1b, 0x12, 0x6c, 0x0a, 0xe8, 0xe3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x74, + 0x27, 0xe6, 0x00, 0x77, 0x05, 0x00, 0x00, +} + +func (m *BasicFeeAllowance) 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 *BasicFeeAllowance) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BasicFeeAllowance) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Expiration.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.SpendLimit) > 0 { + for iNdEx := len(m.SpendLimit) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SpendLimit[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *PeriodicFeeAllowance) 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 *PeriodicFeeAllowance) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PeriodicFeeAllowance) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.PeriodReset.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if len(m.PeriodCanSpend) > 0 { + for iNdEx := len(m.PeriodCanSpend) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PeriodCanSpend[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.PeriodSpendLimit) > 0 { + for iNdEx := len(m.PeriodSpendLimit) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.PeriodSpendLimit[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size, err := m.Period.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.Basic.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func (m *Duration) 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 *Duration) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Duration) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *Duration_Duration) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Duration_Duration) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Duration != nil { + n5, err5 := github_com_gogo_protobuf_types.StdDurationMarshalTo(*m.Duration, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdDuration(*m.Duration):]) + if err5 != nil { + return 0, err5 + } + i -= n5 + i = encodeVarintFeegrant(dAtA, i, uint64(n5)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *Duration_Blocks) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Duration_Blocks) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + i = encodeVarintFeegrant(dAtA, i, uint64(m.Blocks)) + i-- + dAtA[i] = 0x10 + return len(dAtA) - i, nil +} +func (m *ExpiresAt) 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 *ExpiresAt) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExpiresAt) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sum != nil { + { + size := m.Sum.Size() + i -= size + if _, err := m.Sum.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + } + } + return len(dAtA) - i, nil +} + +func (m *ExpiresAt_Time) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExpiresAt_Time) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Time != nil { + n6, err6 := github_com_gogo_protobuf_types.StdTimeMarshalTo(*m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(*m.Time):]) + if err6 != nil { + return 0, err6 + } + i -= n6 + i = encodeVarintFeegrant(dAtA, i, uint64(n6)) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} +func (m *ExpiresAt_Height) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ExpiresAt_Height) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + i = encodeVarintFeegrant(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + return len(dAtA) - i, nil +} +func (m *FeeAllowanceGrant) 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 *FeeAllowanceGrant) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *FeeAllowanceGrant) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Allowance != nil { + { + size, err := m.Allowance.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintFeegrant(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintFeegrant(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintFeegrant(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintFeegrant(dAtA []byte, offset int, v uint64) int { + offset -= sovFeegrant(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *BasicFeeAllowance) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.SpendLimit) > 0 { + for _, e := range m.SpendLimit { + l = e.Size() + n += 1 + l + sovFeegrant(uint64(l)) + } + } + l = m.Expiration.Size() + n += 1 + l + sovFeegrant(uint64(l)) + return n +} + +func (m *PeriodicFeeAllowance) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Basic.Size() + n += 1 + l + sovFeegrant(uint64(l)) + l = m.Period.Size() + n += 1 + l + sovFeegrant(uint64(l)) + if len(m.PeriodSpendLimit) > 0 { + for _, e := range m.PeriodSpendLimit { + l = e.Size() + n += 1 + l + sovFeegrant(uint64(l)) + } + } + if len(m.PeriodCanSpend) > 0 { + for _, e := range m.PeriodCanSpend { + l = e.Size() + n += 1 + l + sovFeegrant(uint64(l)) + } + } + l = m.PeriodReset.Size() + n += 1 + l + sovFeegrant(uint64(l)) + return n +} + +func (m *Duration) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *Duration_Duration) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Duration != nil { + l = github_com_gogo_protobuf_types.SizeOfStdDuration(*m.Duration) + n += 1 + l + sovFeegrant(uint64(l)) + } + return n +} +func (m *Duration_Blocks) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovFeegrant(uint64(m.Blocks)) + return n +} +func (m *ExpiresAt) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Sum != nil { + n += m.Sum.Size() + } + return n +} + +func (m *ExpiresAt_Time) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Time != nil { + l = github_com_gogo_protobuf_types.SizeOfStdTime(*m.Time) + n += 1 + l + sovFeegrant(uint64(l)) + } + return n +} +func (m *ExpiresAt_Height) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += 1 + sovFeegrant(uint64(m.Height)) + return n +} +func (m *FeeAllowanceGrant) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovFeegrant(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovFeegrant(uint64(l)) + } + if m.Allowance != nil { + l = m.Allowance.Size() + n += 1 + l + sovFeegrant(uint64(l)) + } + return n +} + +func sovFeegrant(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozFeegrant(x uint64) (n int) { + return sovFeegrant(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *BasicFeeAllowance) 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 ErrIntOverflowFeegrant + } + 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: BasicFeeAllowance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BasicFeeAllowance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SpendLimit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SpendLimit = append(m.SpendLimit, types.Coin{}) + if err := m.SpendLimit[len(m.SpendLimit)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Expiration.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipFeegrant(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeegrant + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *PeriodicFeeAllowance) 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 ErrIntOverflowFeegrant + } + 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: PeriodicFeeAllowance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PeriodicFeeAllowance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Basic", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Basic.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Period", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Period.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PeriodSpendLimit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PeriodSpendLimit = append(m.PeriodSpendLimit, types.Coin{}) + if err := m.PeriodSpendLimit[len(m.PeriodSpendLimit)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PeriodCanSpend", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.PeriodCanSpend = append(m.PeriodCanSpend, types.Coin{}) + if err := m.PeriodCanSpend[len(m.PeriodCanSpend)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PeriodReset", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PeriodReset.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipFeegrant(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeegrant + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Duration) 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 ErrIntOverflowFeegrant + } + 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: Duration: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Duration: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Duration", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := new(time.Duration) + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(v, dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &Duration_Duration{v} + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Blocks", wireType) + } + var v uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Sum = &Duration_Blocks{v} + default: + iNdEx = preIndex + skippy, err := skipFeegrant(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeegrant + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ExpiresAt) 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 ErrIntOverflowFeegrant + } + 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: ExpiresAt: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ExpiresAt: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := new(time.Time) + if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(v, dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Sum = &ExpiresAt_Time{v} + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + var v int64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Sum = &ExpiresAt_Height{v} + default: + iNdEx = preIndex + skippy, err := skipFeegrant(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeegrant + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *FeeAllowanceGrant) 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 ErrIntOverflowFeegrant + } + 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: FeeAllowanceGrant: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FeeAllowanceGrant: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + 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 ErrInvalidLengthFeegrant + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + 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 ErrInvalidLengthFeegrant + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Allowance", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFeegrant + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthFeegrant + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthFeegrant + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Allowance == nil { + m.Allowance = &types1.Any{} + } + if err := m.Allowance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipFeegrant(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthFeegrant + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipFeegrant(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, ErrIntOverflowFeegrant + } + 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, ErrIntOverflowFeegrant + } + 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, ErrIntOverflowFeegrant + } + 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, ErrInvalidLengthFeegrant + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupFeegrant + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthFeegrant + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthFeegrant = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowFeegrant = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupFeegrant = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/feegrant/types/fees.go b/x/feegrant/types/fees.go new file mode 100644 index 0000000000..cc526628f5 --- /dev/null +++ b/x/feegrant/types/fees.go @@ -0,0 +1,32 @@ +package types + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// FeeAllowance implementations are tied to a given fee delegator and delegatee, +// and are used to enforce fee grant limits. +type FeeAllowanceI interface { + // Accept can use fee payment requested as well as timestamp/height of the current block + // to determine whether or not to process this. This is checked in + // Keeper.UseGrantedFees and the return values should match how it is handled there. + // + // If it returns an error, the fee payment is rejected, otherwise it is accepted. + // The FeeAllowance implementation is expected to update it's internal state + // and will be saved again after an acceptance. + // + // If remove is true (regardless of the error), the FeeAllowance will be deleted from storage + // (eg. when it is used up). (See call to RevokeFeeAllowance in Keeper.UseGrantedFees) + Accept(fee sdk.Coins, blockTime time.Time, blockHeight int64) (remove bool, err error) + + // If we export fee allowances the timing info will be quite off (eg. go from height 100000 to 0) + // This callback allows the fee-allowance to change it's state and return a copy that is adjusted + // given the time and height of the actual dump (may safely return self if no changes needed) + PrepareForExport(dumpTime time.Time, dumpHeight int64) FeeAllowanceI + + // ValidateBasic should evaluate this FeeAllowance for internal consistency. + // Don't allow negative amounts, or negative periods for example. + ValidateBasic() error +} diff --git a/x/feegrant/types/genesis.go b/x/feegrant/types/genesis.go new file mode 100644 index 0000000000..57ade9b43d --- /dev/null +++ b/x/feegrant/types/genesis.go @@ -0,0 +1,40 @@ +package types + +import "github.com/cosmos/cosmos-sdk/codec/types" + +var _ types.UnpackInterfacesMessage = GenesisState{} + +// NewGenesisState creates new GenesisState object +func NewGenesisState(entries []FeeAllowanceGrant) *GenesisState { + return &GenesisState{ + FeeAllowances: entries, + } +} + +// ValidateGenesis ensures all grants in the genesis state are valid +func ValidateGenesis(data GenesisState) error { + for _, f := range data.FeeAllowances { + err := f.GetFeeGrant().ValidateBasic() + if err != nil { + return err + } + } + return nil +} + +// DefaultGenesisState returns default state for feegrant module. +func DefaultGenesisState() *GenesisState { + return &GenesisState{} +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (data GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error { + for _, f := range data.FeeAllowances { + err := f.UnpackInterfaces(unpacker) + if err != nil { + return err + } + } + + return nil +} diff --git a/x/feegrant/types/genesis.pb.go b/x/feegrant/types/genesis.pb.go new file mode 100644 index 0000000000..499f57d626 --- /dev/null +++ b/x/feegrant/types/genesis.pb.go @@ -0,0 +1,333 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/feegrant/v1beta1/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/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 contains a set of fee allowances, persisted from the store +type GenesisState struct { + FeeAllowances []FeeAllowanceGrant `protobuf:"bytes,1,rep,name=fee_allowances,json=feeAllowances,proto3" json:"fee_allowances"` +} + +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_ac719d2d0954d1bf, []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) GetFeeAllowances() []FeeAllowanceGrant { + if m != nil { + return m.FeeAllowances + } + return nil +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "cosmos.feegrant.v1beta1.GenesisState") +} + +func init() { + proto.RegisterFile("cosmos/feegrant/v1beta1/genesis.proto", fileDescriptor_ac719d2d0954d1bf) +} + +var fileDescriptor_ac719d2d0954d1bf = []byte{ + // 221 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0xce, 0x2f, 0xce, + 0xcd, 0x2f, 0xd6, 0x4f, 0x4b, 0x4d, 0x4d, 0x2f, 0x4a, 0xcc, 0x2b, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, + 0x2d, 0x49, 0x34, 0xd4, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, + 0xc9, 0x17, 0x12, 0x87, 0x28, 0xd3, 0x83, 0x29, 0xd3, 0x83, 0x2a, 0x93, 0x12, 0x49, 0xcf, 0x4f, + 0xcf, 0x07, 0xab, 0xd1, 0x07, 0xb1, 0x20, 0xca, 0xa5, 0xd4, 0x70, 0x99, 0x0a, 0xd7, 0x0f, 0x56, + 0xa7, 0x94, 0xce, 0xc5, 0xe3, 0x0e, 0xb1, 0x27, 0xb8, 0x24, 0xb1, 0x24, 0x55, 0x28, 0x9c, 0x8b, + 0x2f, 0x2d, 0x35, 0x35, 0x3e, 0x31, 0x27, 0x27, 0xbf, 0x3c, 0x31, 0x2f, 0x39, 0xb5, 0x58, 0x82, + 0x51, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x4b, 0x0f, 0x87, 0xfd, 0x7a, 0x6e, 0xa9, 0xa9, 0x8e, 0x30, + 0xd5, 0xee, 0x20, 0x19, 0x27, 0x96, 0x13, 0xf7, 0xe4, 0x19, 0x82, 0x78, 0xd3, 0x90, 0x24, 0x8a, + 0x9d, 0xdc, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, + 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a, 0x37, 0x3d, 0xb3, + 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0xea, 0x6a, 0x08, 0xa5, 0x5b, 0x9c, 0x92, + 0xad, 0x5f, 0x81, 0xf0, 0x42, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0xe1, 0xc6, 0x80, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xaf, 0x53, 0x6e, 0xc5, 0x38, 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 + if len(m.FeeAllowances) > 0 { + for iNdEx := len(m.FeeAllowances) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.FeeAllowances[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.FeeAllowances) > 0 { + for _, e := range m.FeeAllowances { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *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 FeeAllowances", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FeeAllowances = append(m.FeeAllowances, FeeAllowanceGrant{}) + if err := m.FeeAllowances[len(m.FeeAllowances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/feegrant/types/grant.go b/x/feegrant/types/grant.go new file mode 100644 index 0000000000..ca2c93d9ef --- /dev/null +++ b/x/feegrant/types/grant.go @@ -0,0 +1,92 @@ +package types + +import ( + "time" + + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + proto "github.com/gogo/protobuf/proto" +) + +var ( + _ types.UnpackInterfacesMessage = &FeeAllowanceGrant{} +) + +// NewFeeAllowanceGrant creates a new FeeAllowanceGrant. +//nolint:interfacer +func NewFeeAllowanceGrant(granter, grantee sdk.AccAddress, feeAllowance FeeAllowanceI) (FeeAllowanceGrant, error) { + msg, ok := feeAllowance.(proto.Message) + if !ok { + return FeeAllowanceGrant{}, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", feeAllowance) + } + + any, err := types.NewAnyWithValue(msg) + if err != nil { + return FeeAllowanceGrant{}, err + } + + return FeeAllowanceGrant{ + Granter: granter.String(), + Grantee: grantee.String(), + Allowance: any, + }, nil +} + +// ValidateBasic performs basic validation on +// FeeAllowanceGrant +func (a FeeAllowanceGrant) ValidateBasic() error { + if a.Granter == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing granter address") + } + if a.Grantee == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing grantee address") + } + if a.Grantee == a.Granter { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "cannot self-grant fee authorization") + } + + return a.GetFeeGrant().ValidateBasic() +} + +// GetFeeGrant unpacks allowance +func (a FeeAllowanceGrant) GetFeeGrant() FeeAllowanceI { + allowance, ok := a.Allowance.GetCachedValue().(FeeAllowanceI) + if !ok { + return nil + } + + return allowance +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (a FeeAllowanceGrant) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var allowance FeeAllowanceI + return unpacker.UnpackAny(a.Allowance, &allowance) +} + +// PrepareForExport will make all needed changes to the allowance to prepare to be +// re-imported at height 0, and return a copy of this grant. +func (a FeeAllowanceGrant) PrepareForExport(dumpTime time.Time, dumpHeight int64) FeeAllowanceGrant { + feegrant := a.GetFeeGrant().PrepareForExport(dumpTime, dumpHeight) + if feegrant == nil { + return FeeAllowanceGrant{} + } + + granter, err := sdk.AccAddressFromBech32(a.Granter) + if err != nil { + return FeeAllowanceGrant{} + } + + grantee, err := sdk.AccAddressFromBech32(a.Grantee) + if err != nil { + return FeeAllowanceGrant{} + } + + grant, err := NewFeeAllowanceGrant(granter, grantee, feegrant) + if err != nil { + return FeeAllowanceGrant{} + } + + return grant +} diff --git a/x/feegrant/types/grant_test.go b/x/feegrant/types/grant_test.go new file mode 100644 index 0000000000..a4819b102c --- /dev/null +++ b/x/feegrant/types/grant_test.go @@ -0,0 +1,99 @@ +package types_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/simapp" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGrant(t *testing.T) { + app := simapp.Setup(false) + addr, err := sdk.AccAddressFromBech32("cosmos1qk93t4j0yyzgqgt6k5qf8deh8fq6smpn3ntu3x") + require.NoError(t, err) + addr2, err := sdk.AccAddressFromBech32("cosmos1p9qh4ldfd6n0qehujsal4k7g0e37kel90rc4ts") + require.NoError(t, err) + atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555)) + + goodGrant, err := types.NewFeeAllowanceGrant(addr2, addr, &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }) + require.NoError(t, err) + + noGranteeGrant, err := types.NewFeeAllowanceGrant(addr2, nil, &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }) + require.NoError(t, err) + + noGranterGrant, err := types.NewFeeAllowanceGrant(nil, addr, &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }) + require.NoError(t, err) + + selfGrant, err := types.NewFeeAllowanceGrant(addr2, addr2, &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }) + require.NoError(t, err) + + badAllowanceGrant, err := types.NewFeeAllowanceGrant(addr2, addr, &types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(-1), + }) + require.NoError(t, err) + + cdc := app.AppCodec() + // RegisterLegacyAminoCodec(cdc) + + cases := map[string]struct { + grant types.FeeAllowanceGrant + valid bool + }{ + "good": { + grant: goodGrant, + valid: true, + }, + "no grantee": { + grant: noGranteeGrant, + }, + "no granter": { + grant: noGranterGrant, + }, + "self-grant": { + grant: selfGrant, + }, + "bad allowance": { + grant: badAllowanceGrant, + }, + } + + for name, tc := range cases { + tc := tc + t.Run(name, func(t *testing.T) { + err := tc.grant.ValidateBasic() + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + + // if it is valid, let's try to serialize, deserialize, and make sure it matches + bz, err := cdc.MarshalBinaryBare(&tc.grant) + require.NoError(t, err) + var loaded types.FeeAllowanceGrant + err = cdc.UnmarshalBinaryBare(bz, &loaded) + require.NoError(t, err) + + err = loaded.ValidateBasic() + require.NoError(t, err) + + assert.Equal(t, tc.grant, loaded) + }) + } +} diff --git a/x/feegrant/types/key.go b/x/feegrant/types/key.go new file mode 100644 index 0000000000..e30427b136 --- /dev/null +++ b/x/feegrant/types/key.go @@ -0,0 +1,35 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // ModuleName is the module name constant used in many places + ModuleName = "feegrant" + + // StoreKey is the store key string for supply + StoreKey = ModuleName + + // RouterKey is the message route for supply + RouterKey = ModuleName + + // QuerierRoute is the querier route for supply + QuerierRoute = ModuleName +) + +var ( + // FeeAllowanceKeyPrefix is the set of the kvstore for fee allowance data + FeeAllowanceKeyPrefix = []byte{0x00} +) + +// FeeAllowanceKey is the canonical key to store a grant from granter to grantee +// We store by grantee first to allow searching by everyone who granted to you +func FeeAllowanceKey(granter sdk.AccAddress, grantee sdk.AccAddress) []byte { + return append(append(FeeAllowanceKeyPrefix, grantee.Bytes()...), granter.Bytes()...) +} + +// FeeAllowancePrefixByGrantee returns a prefix to scan for all grants to this given address. +func FeeAllowancePrefixByGrantee(grantee sdk.AccAddress) []byte { + return append(FeeAllowanceKeyPrefix, grantee.Bytes()...) +} diff --git a/x/feegrant/types/msgs.go b/x/feegrant/types/msgs.go new file mode 100644 index 0000000000..5a25016f87 --- /dev/null +++ b/x/feegrant/types/msgs.go @@ -0,0 +1,101 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/gogo/protobuf/proto" +) + +var ( + _, _ sdk.MsgRequest = &MsgGrantFeeAllowance{}, &MsgRevokeFeeAllowance{} + _ types.UnpackInterfacesMessage = &MsgGrantFeeAllowance{} +) + +// feegrant message types +const ( + TypeMsgGrantFeeAllowance = "grant_fee_allowance" + TypeMsgRevokeFeeAllowance = "revoke_fee_allowance" +) + +// NewMsgGrantFeeAllowance creates a new MsgGrantFeeAllowance. +//nolint:interfacer +func NewMsgGrantFeeAllowance(feeAllowance FeeAllowanceI, granter, grantee sdk.AccAddress) (*MsgGrantFeeAllowance, error) { + msg, ok := feeAllowance.(proto.Message) + if !ok { + return nil, sdkerrors.Wrapf(sdkerrors.ErrPackAny, "cannot proto marshal %T", msg) + } + any, err := types.NewAnyWithValue(msg) + if err != nil { + return nil, err + } + + return &MsgGrantFeeAllowance{ + Granter: granter.String(), + Grantee: grantee.String(), + Allowance: any, + }, nil +} + +// ValidateBasic implements the sdk.Msg interface. +func (msg MsgGrantFeeAllowance) ValidateBasic() error { + if msg.Granter == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing granter address") + } + if msg.Grantee == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing grantee address") + } + if msg.Grantee == msg.Granter { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "cannot self-grant fee authorization") + } + + return msg.GetFeeAllowanceI().ValidateBasic() +} + +func (msg MsgGrantFeeAllowance) GetSigners() []sdk.AccAddress { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{granter} +} + +// GetFeeAllowanceI returns unpacked FeeAllowance +func (msg MsgGrantFeeAllowance) GetFeeAllowanceI() FeeAllowanceI { + allowance, ok := msg.Allowance.GetCachedValue().(FeeAllowanceI) + if !ok { + return nil + } + + return allowance +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (msg MsgGrantFeeAllowance) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var allowance FeeAllowanceI + return unpacker.UnpackAny(msg.Allowance, &allowance) +} + +//nolint:interfacer +func NewMsgRevokeFeeAllowance(granter sdk.AccAddress, grantee sdk.AccAddress) MsgRevokeFeeAllowance { + return MsgRevokeFeeAllowance{Granter: granter.String(), Grantee: grantee.String()} +} + +func (msg MsgRevokeFeeAllowance) ValidateBasic() error { + if msg.Granter == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing granter address") + } + if msg.Grantee == "" { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing grantee address") + } + + return nil +} + +func (msg MsgRevokeFeeAllowance) GetSigners() []sdk.AccAddress { + granter, err := sdk.AccAddressFromBech32(msg.Granter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{granter} +} diff --git a/x/feegrant/types/periodic_fee.go b/x/feegrant/types/periodic_fee.go new file mode 100644 index 0000000000..61c9ba2ffe --- /dev/null +++ b/x/feegrant/types/periodic_fee.go @@ -0,0 +1,120 @@ +package types + +import ( + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var _ FeeAllowanceI = (*PeriodicFeeAllowance)(nil) + +// Accept can use fee payment requested as well as timestamp/height of the current block +// to determine whether or not to process this. This is checked in +// Keeper.UseGrantedFees and the return values should match how it is handled there. +// +// If it returns an error, the fee payment is rejected, otherwise it is accepted. +// The FeeAllowance implementation is expected to update it's internal state +// and will be saved again after an acceptance. +// +// If remove is true (regardless of the error), the FeeAllowance will be deleted from storage +// (eg. when it is used up). (See call to RevokeFeeAllowance in Keeper.UseGrantedFees) +func (a *PeriodicFeeAllowance) Accept(fee sdk.Coins, blockTime time.Time, blockHeight int64) (bool, error) { + if a.Basic.Expiration.IsExpired(&blockTime, blockHeight) { + return true, sdkerrors.Wrap(ErrFeeLimitExpired, "absolute limit") + } + + a.tryResetPeriod(blockTime, blockHeight) + + // deduct from both the current period and the max amount + var isNeg bool + a.PeriodCanSpend, isNeg = a.PeriodCanSpend.SafeSub(fee) + if isNeg { + return false, sdkerrors.Wrap(ErrFeeLimitExceeded, "period limit") + } + + if a.Basic.SpendLimit != nil { + a.Basic.SpendLimit, isNeg = a.Basic.SpendLimit.SafeSub(fee) + if isNeg { + return false, sdkerrors.Wrap(ErrFeeLimitExceeded, "absolute limit") + } + + return a.Basic.SpendLimit.IsZero(), nil + } + + return false, nil +} + +// tryResetPeriod will check if the PeriodReset has been hit. If not, it is a no-op. +// If we hit the reset period, it will top up the PeriodCanSpend amount to +// min(PeriodicSpendLimit, a.Basic.SpendLimit) so it is never more than the maximum allowed. +// It will also update the PeriodReset. If we are within one Period, it will update from the +// last PeriodReset (eg. if you always do one tx per day, it will always reset the same time) +// If we are more then one period out (eg. no activity in a week), reset is one Period from the execution of this method +func (a *PeriodicFeeAllowance) tryResetPeriod(blockTime time.Time, blockHeight int64) { + if !a.PeriodReset.Undefined() && !a.PeriodReset.IsExpired(&blockTime, blockHeight) { + return + } + // set CanSpend to the lesser of PeriodSpendLimit and the TotalLimit + if _, isNeg := a.Basic.SpendLimit.SafeSub(a.PeriodSpendLimit); isNeg { + a.PeriodCanSpend = a.Basic.SpendLimit + } else { + a.PeriodCanSpend = a.PeriodSpendLimit + } + + // If we are within the period, step from expiration (eg. if you always do one tx per day, it will always reset the same time) + // If we are more then one period out (eg. no activity in a week), reset is one period from this time + a.PeriodReset = a.PeriodReset.MustStep(a.Period) + if a.PeriodReset.IsExpired(&blockTime, blockHeight) { + a.PeriodReset = a.PeriodReset.FastForward(blockTime, blockHeight).MustStep(a.Period) + } +} + +// PrepareForExport will adjust the expiration based on export time. In particular, +// it will subtract the dumpHeight from any height-based expiration to ensure that +// the elapsed number of blocks this allowance is valid for is fixed. +// (For PeriodReset and Basic.Expiration) +func (a *PeriodicFeeAllowance) PrepareForExport(dumpTime time.Time, dumpHeight int64) FeeAllowanceI { + return &PeriodicFeeAllowance{ + Basic: BasicFeeAllowance{ + SpendLimit: a.Basic.SpendLimit, + Expiration: a.Basic.Expiration.PrepareForExport(dumpTime, dumpHeight), + }, + PeriodSpendLimit: a.PeriodSpendLimit, + PeriodCanSpend: a.PeriodCanSpend, + Period: a.Period, + PeriodReset: a.PeriodReset.PrepareForExport(dumpTime, dumpHeight), + } +} + +// ValidateBasic implements FeeAllowance and enforces basic sanity checks +func (a PeriodicFeeAllowance) ValidateBasic() error { + if err := a.Basic.ValidateBasic(); err != nil { + return err + } + + if !a.PeriodSpendLimit.IsValid() { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "spend amount is invalid: %s", a.PeriodSpendLimit) + } + if !a.PeriodSpendLimit.IsAllPositive() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "spend limit must be positive") + } + if !a.PeriodCanSpend.IsValid() { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, "can spend amount is invalid: %s", a.PeriodCanSpend) + } + // We allow 0 for CanSpend + if a.PeriodCanSpend.IsAnyNegative() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "can spend must not be negative") + } + + // ensure PeriodSpendLimit can be subtracted from total (same coin types) + if a.Basic.SpendLimit != nil && !a.PeriodSpendLimit.DenomsSubsetOf(a.Basic.SpendLimit) { + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "period spend limit has different currency than basic spend limit") + } + + // check times + if err := a.Period.ValidateBasic(); err != nil { + return err + } + return a.PeriodReset.ValidateBasic() +} diff --git a/x/feegrant/types/periodic_fee_test.go b/x/feegrant/types/periodic_fee_test.go new file mode 100644 index 0000000000..cc54f40808 --- /dev/null +++ b/x/feegrant/types/periodic_fee_test.go @@ -0,0 +1,205 @@ +package types_test + +import ( + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPeriodicFeeValidAllow(t *testing.T) { + atom := sdk.NewCoins(sdk.NewInt64Coin("atom", 555)) + smallAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 43)) + leftAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 512)) + oneAtom := sdk.NewCoins(sdk.NewInt64Coin("atom", 1)) + eth := sdk.NewCoins(sdk.NewInt64Coin("eth", 1)) + + cases := map[string]struct { + allow types.PeriodicFeeAllowance + // all other checks are ignored if valid=false + fee sdk.Coins + blockTime time.Time + blockHeight int64 + valid bool + accept bool + remove bool + remains sdk.Coins + remainsPeriod sdk.Coins + periodReset types.ExpiresAt + }{ + "empty": { + allow: types.PeriodicFeeAllowance{}, + valid: false, + }, + "only basic": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + }, + valid: false, + }, + "empty basic": { + allow: types.PeriodicFeeAllowance{ + Period: types.BlockDuration(10), + PeriodSpendLimit: smallAtom, + PeriodReset: types.ExpiresAtHeight(70), + }, + blockHeight: 75, + valid: true, + accept: true, + remove: false, + periodReset: types.ExpiresAtHeight(80), + }, + "mismatched currencies": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodSpendLimit: eth, + }, + valid: false, + }, + "first time": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodSpendLimit: smallAtom, + }, + valid: true, + fee: smallAtom, + blockHeight: 75, + accept: true, + remove: false, + remainsPeriod: nil, + remains: leftAtom, + periodReset: types.ExpiresAtHeight(85), + }, + "same period": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodReset: types.ExpiresAtHeight(80), + PeriodSpendLimit: leftAtom, + PeriodCanSpend: smallAtom, + }, + valid: true, + fee: smallAtom, + blockHeight: 75, + accept: true, + remove: false, + remainsPeriod: nil, + remains: leftAtom, + periodReset: types.ExpiresAtHeight(80), + }, + "step one period": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodReset: types.ExpiresAtHeight(70), + PeriodSpendLimit: leftAtom, + }, + valid: true, + fee: leftAtom, + blockHeight: 75, + accept: true, + remove: false, + remainsPeriod: nil, + remains: smallAtom, + periodReset: types.ExpiresAtHeight(80), // one step from last reset, not now + }, + "step limited by global allowance": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: smallAtom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodReset: types.ExpiresAtHeight(70), + PeriodSpendLimit: atom, + }, + valid: true, + fee: oneAtom, + blockHeight: 75, + accept: true, + remove: false, + remainsPeriod: smallAtom.Sub(oneAtom), + remains: smallAtom.Sub(oneAtom), + periodReset: types.ExpiresAtHeight(80), // one step from last reset, not now + }, + "expired": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodSpendLimit: smallAtom, + }, + valid: true, + fee: smallAtom, + blockHeight: 101, + accept: false, + remove: true, + }, + "over period limit": { + allow: types.PeriodicFeeAllowance{ + Basic: types.BasicFeeAllowance{ + SpendLimit: atom, + Expiration: types.ExpiresAtHeight(100), + }, + Period: types.BlockDuration(10), + PeriodReset: types.ExpiresAtHeight(80), + PeriodSpendLimit: leftAtom, + PeriodCanSpend: smallAtom, + }, + valid: true, + fee: leftAtom, + blockHeight: 70, + accept: false, + remove: true, + }, + } + + for name, stc := range cases { + tc := stc // to make scopelint happy + t.Run(name, func(t *testing.T) { + err := tc.allow.ValidateBasic() + if !tc.valid { + require.Error(t, err) + return + } + require.NoError(t, err) + + // now try to deduct + remove, err := tc.allow.Accept(tc.fee, tc.blockTime, tc.blockHeight) + if !tc.accept { + require.Error(t, err) + return + } + require.NoError(t, err) + + require.Equal(t, tc.remove, remove) + if !remove { + assert.Equal(t, tc.remains, tc.allow.Basic.SpendLimit) + assert.Equal(t, tc.remainsPeriod, tc.allow.PeriodCanSpend) + assert.Equal(t, tc.periodReset, tc.allow.PeriodReset) + } + }) + } +} diff --git a/x/feegrant/types/query.pb.go b/x/feegrant/types/query.pb.go new file mode 100644 index 0000000000..e2597c3bc8 --- /dev/null +++ b/x/feegrant/types/query.pb.go @@ -0,0 +1,1172 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/feegrant/v1beta1/query.proto + +package types + +import ( + context "context" + fmt "fmt" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/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 + +// QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. +type QueryFeeAllowanceRequest struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` +} + +func (m *QueryFeeAllowanceRequest) Reset() { *m = QueryFeeAllowanceRequest{} } +func (m *QueryFeeAllowanceRequest) String() string { return proto.CompactTextString(m) } +func (*QueryFeeAllowanceRequest) ProtoMessage() {} +func (*QueryFeeAllowanceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_59efc303945de53f, []int{0} +} +func (m *QueryFeeAllowanceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeeAllowanceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeeAllowanceRequest.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 *QueryFeeAllowanceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeeAllowanceRequest.Merge(m, src) +} +func (m *QueryFeeAllowanceRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryFeeAllowanceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeeAllowanceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeeAllowanceRequest proto.InternalMessageInfo + +func (m *QueryFeeAllowanceRequest) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *QueryFeeAllowanceRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +// QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. +type QueryFeeAllowanceResponse struct { + // fee_allowance is a fee_allowance granted for grantee by granter. + FeeAllowance *FeeAllowanceGrant `protobuf:"bytes,1,opt,name=fee_allowance,json=feeAllowance,proto3" json:"fee_allowance,omitempty"` +} + +func (m *QueryFeeAllowanceResponse) Reset() { *m = QueryFeeAllowanceResponse{} } +func (m *QueryFeeAllowanceResponse) String() string { return proto.CompactTextString(m) } +func (*QueryFeeAllowanceResponse) ProtoMessage() {} +func (*QueryFeeAllowanceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_59efc303945de53f, []int{1} +} +func (m *QueryFeeAllowanceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeeAllowanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeeAllowanceResponse.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 *QueryFeeAllowanceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeeAllowanceResponse.Merge(m, src) +} +func (m *QueryFeeAllowanceResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryFeeAllowanceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeeAllowanceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeeAllowanceResponse proto.InternalMessageInfo + +func (m *QueryFeeAllowanceResponse) GetFeeAllowance() *FeeAllowanceGrant { + if m != nil { + return m.FeeAllowance + } + return nil +} + +// QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. +type QueryFeeAllowancesRequest struct { + Grantee string `protobuf:"bytes,1,opt,name=grantee,proto3" json:"grantee,omitempty"` + // pagination defines an pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryFeeAllowancesRequest) Reset() { *m = QueryFeeAllowancesRequest{} } +func (m *QueryFeeAllowancesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryFeeAllowancesRequest) ProtoMessage() {} +func (*QueryFeeAllowancesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_59efc303945de53f, []int{2} +} +func (m *QueryFeeAllowancesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeeAllowancesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeeAllowancesRequest.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 *QueryFeeAllowancesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeeAllowancesRequest.Merge(m, src) +} +func (m *QueryFeeAllowancesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryFeeAllowancesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeeAllowancesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeeAllowancesRequest proto.InternalMessageInfo + +func (m *QueryFeeAllowancesRequest) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *QueryFeeAllowancesRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. +type QueryFeeAllowancesResponse struct { + // fee_allowances are fee_allowance's granted for grantee by granter. + FeeAllowances []*FeeAllowanceGrant `protobuf:"bytes,1,rep,name=fee_allowances,json=feeAllowances,proto3" json:"fee_allowances,omitempty"` + // pagination defines an pagination for the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryFeeAllowancesResponse) Reset() { *m = QueryFeeAllowancesResponse{} } +func (m *QueryFeeAllowancesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryFeeAllowancesResponse) ProtoMessage() {} +func (*QueryFeeAllowancesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_59efc303945de53f, []int{3} +} +func (m *QueryFeeAllowancesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryFeeAllowancesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryFeeAllowancesResponse.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 *QueryFeeAllowancesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryFeeAllowancesResponse.Merge(m, src) +} +func (m *QueryFeeAllowancesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryFeeAllowancesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryFeeAllowancesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryFeeAllowancesResponse proto.InternalMessageInfo + +func (m *QueryFeeAllowancesResponse) GetFeeAllowances() []*FeeAllowanceGrant { + if m != nil { + return m.FeeAllowances + } + return nil +} + +func (m *QueryFeeAllowancesResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +func init() { + proto.RegisterType((*QueryFeeAllowanceRequest)(nil), "cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest") + proto.RegisterType((*QueryFeeAllowanceResponse)(nil), "cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse") + proto.RegisterType((*QueryFeeAllowancesRequest)(nil), "cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest") + proto.RegisterType((*QueryFeeAllowancesResponse)(nil), "cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse") +} + +func init() { + proto.RegisterFile("cosmos/feegrant/v1beta1/query.proto", fileDescriptor_59efc303945de53f) +} + +var fileDescriptor_59efc303945de53f = []byte{ + // 455 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x31, 0x8f, 0xd3, 0x30, + 0x14, 0xc7, 0xeb, 0x22, 0x40, 0xf8, 0xae, 0x0c, 0x16, 0x12, 0x21, 0x42, 0xd1, 0x29, 0x48, 0x07, + 0x3a, 0xe9, 0x62, 0x35, 0x9d, 0x40, 0x2c, 0xdc, 0x70, 0xdd, 0x80, 0xcb, 0xc8, 0x82, 0x9c, 0xf2, + 0x6a, 0x22, 0x72, 0x71, 0x2e, 0x76, 0x81, 0x13, 0xea, 0xc2, 0x27, 0x40, 0xe2, 0xa3, 0xb0, 0xc0, + 0x37, 0x60, 0x3c, 0x89, 0x85, 0x11, 0xb5, 0x7c, 0x09, 0x36, 0x14, 0x3b, 0x6e, 0x52, 0x91, 0x00, + 0x99, 0xe2, 0xe4, 0xfd, 0xdf, 0x7b, 0xbf, 0xf7, 0xcf, 0x33, 0xbe, 0x33, 0x13, 0xf2, 0x54, 0x48, + 0x3a, 0x07, 0xe0, 0x05, 0xcb, 0x14, 0x7d, 0x3d, 0x8e, 0x41, 0xb1, 0x31, 0x3d, 0x5b, 0x40, 0x71, + 0x1e, 0xe4, 0x85, 0x50, 0x82, 0xdc, 0x34, 0xa2, 0xc0, 0x8a, 0x82, 0x4a, 0xe4, 0xde, 0xe0, 0x82, + 0x0b, 0xad, 0xa1, 0xe5, 0xc9, 0xc8, 0xdd, 0xfd, 0xae, 0x9a, 0x9b, 0x7c, 0xa3, 0x3b, 0xa8, 0x74, + 0x31, 0x93, 0x60, 0xfa, 0x6d, 0x94, 0x39, 0xe3, 0x49, 0xc6, 0x54, 0x22, 0xb2, 0x4a, 0x7b, 0x9b, + 0x0b, 0xc1, 0x53, 0xa0, 0x2c, 0x4f, 0x28, 0xcb, 0x32, 0xa1, 0x74, 0x50, 0x9a, 0xa8, 0xff, 0x18, + 0x3b, 0x27, 0x65, 0xfe, 0x31, 0xc0, 0xa3, 0x34, 0x15, 0x6f, 0x58, 0x36, 0x83, 0x08, 0xce, 0x16, + 0x20, 0x15, 0x71, 0xf0, 0x55, 0xdd, 0x14, 0x0a, 0x07, 0xed, 0xa1, 0x7b, 0xd7, 0x22, 0xfb, 0x5a, + 0x47, 0xc0, 0x19, 0x36, 0x23, 0xe0, 0xa7, 0xf8, 0x56, 0x4b, 0x3d, 0x99, 0x8b, 0x4c, 0x02, 0x79, + 0x82, 0x47, 0x73, 0x80, 0xe7, 0xcc, 0x06, 0x74, 0xd9, 0x9d, 0xf0, 0x20, 0xe8, 0x70, 0x29, 0x68, + 0x56, 0x99, 0x96, 0x91, 0x68, 0x77, 0xde, 0xf8, 0xe4, 0x2f, 0x5b, 0xba, 0xc9, 0x3f, 0xf0, 0x61, + 0x1b, 0x1f, 0xc8, 0x31, 0xc6, 0xb5, 0x4d, 0x7a, 0x82, 0x9d, 0x70, 0xdf, 0x42, 0x94, 0x9e, 0x06, + 0xe6, 0x1f, 0x5a, 0x8c, 0xa7, 0x8c, 0x5b, 0x53, 0xa2, 0x46, 0xa6, 0xff, 0x19, 0x61, 0xb7, 0xad, + 0x7f, 0x35, 0xee, 0x09, 0xbe, 0xbe, 0x35, 0xae, 0x74, 0xd0, 0xde, 0xa5, 0x9e, 0xf3, 0x8e, 0x9a, + 0xf3, 0x4a, 0x32, 0x6d, 0x21, 0xbf, 0xfb, 0x4f, 0x72, 0xc3, 0xd3, 0x44, 0x0f, 0x7f, 0x0d, 0xf1, + 0x65, 0x8d, 0x4e, 0xbe, 0x20, 0xbc, 0xdb, 0xec, 0x4b, 0xc6, 0x9d, 0x78, 0x5d, 0x9b, 0xe2, 0x86, + 0x7d, 0x52, 0x0c, 0x8d, 0x7f, 0xf4, 0xfe, 0xdb, 0xcf, 0x8f, 0xc3, 0x87, 0xe4, 0x01, 0xfd, 0xcb, + 0xd2, 0xd7, 0xe6, 0xd1, 0x77, 0xd5, 0xf2, 0x2d, 0xed, 0x09, 0x96, 0xe4, 0x13, 0xc2, 0xa3, 0x2d, + 0xef, 0x49, 0x0f, 0x12, 0xbb, 0x28, 0xee, 0xa4, 0x57, 0x4e, 0x85, 0x7f, 0x5f, 0xe3, 0x4f, 0xc8, + 0xf8, 0xff, 0xf0, 0x65, 0x4d, 0x7d, 0x34, 0xfd, 0xba, 0xf2, 0xd0, 0xc5, 0xca, 0x43, 0x3f, 0x56, + 0x1e, 0xfa, 0xb0, 0xf6, 0x06, 0x17, 0x6b, 0x6f, 0xf0, 0x7d, 0xed, 0x0d, 0x9e, 0x1d, 0xf2, 0x44, + 0xbd, 0x5c, 0xc4, 0xc1, 0x4c, 0x9c, 0xda, 0xb2, 0xe6, 0x71, 0x28, 0x5f, 0xbc, 0xa2, 0x6f, 0xeb, + 0x1e, 0xea, 0x3c, 0x07, 0x19, 0x5f, 0xd1, 0x77, 0x78, 0xf2, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xb8, + 0x46, 0x4c, 0xba, 0x8b, 0x04, 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 { + // FeeAllowance returns fee granted to the grantee by the granter. + FeeAllowance(ctx context.Context, in *QueryFeeAllowanceRequest, opts ...grpc.CallOption) (*QueryFeeAllowanceResponse, error) + // FeeAllowances returns all the grants for address. + FeeAllowances(ctx context.Context, in *QueryFeeAllowancesRequest, opts ...grpc.CallOption) (*QueryFeeAllowancesResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) FeeAllowance(ctx context.Context, in *QueryFeeAllowanceRequest, opts ...grpc.CallOption) (*QueryFeeAllowanceResponse, error) { + out := new(QueryFeeAllowanceResponse) + err := c.cc.Invoke(ctx, "/cosmos.feegrant.v1beta1.Query/FeeAllowance", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) FeeAllowances(ctx context.Context, in *QueryFeeAllowancesRequest, opts ...grpc.CallOption) (*QueryFeeAllowancesResponse, error) { + out := new(QueryFeeAllowancesResponse) + err := c.cc.Invoke(ctx, "/cosmos.feegrant.v1beta1.Query/FeeAllowances", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // FeeAllowance returns fee granted to the grantee by the granter. + FeeAllowance(context.Context, *QueryFeeAllowanceRequest) (*QueryFeeAllowanceResponse, error) + // FeeAllowances returns all the grants for address. + FeeAllowances(context.Context, *QueryFeeAllowancesRequest) (*QueryFeeAllowancesResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) FeeAllowance(ctx context.Context, req *QueryFeeAllowanceRequest) (*QueryFeeAllowanceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FeeAllowance not implemented") +} +func (*UnimplementedQueryServer) FeeAllowances(ctx context.Context, req *QueryFeeAllowancesRequest) (*QueryFeeAllowancesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method FeeAllowances not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_FeeAllowance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFeeAllowanceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).FeeAllowance(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.feegrant.v1beta1.Query/FeeAllowance", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).FeeAllowance(ctx, req.(*QueryFeeAllowanceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_FeeAllowances_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryFeeAllowancesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).FeeAllowances(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.feegrant.v1beta1.Query/FeeAllowances", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).FeeAllowances(ctx, req.(*QueryFeeAllowancesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cosmos.feegrant.v1beta1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "FeeAllowance", + Handler: _Query_FeeAllowance_Handler, + }, + { + MethodName: "FeeAllowances", + Handler: _Query_FeeAllowances_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cosmos/feegrant/v1beta1/query.proto", +} + +func (m *QueryFeeAllowanceRequest) 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 *QueryFeeAllowanceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeeAllowanceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryFeeAllowanceResponse) 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 *QueryFeeAllowanceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeeAllowanceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.FeeAllowance != nil { + { + size, err := m.FeeAllowance.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 (m *QueryFeeAllowancesRequest) 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 *QueryFeeAllowancesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeeAllowancesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryFeeAllowancesResponse) 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 *QueryFeeAllowancesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryFeeAllowancesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.FeeAllowances) > 0 { + for iNdEx := len(m.FeeAllowances) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.FeeAllowances[iNdEx].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 *QueryFeeAllowanceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryFeeAllowanceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.FeeAllowance != nil { + l = m.FeeAllowance.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryFeeAllowancesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryFeeAllowancesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.FeeAllowances) > 0 { + for _, e := range m.FeeAllowances { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.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 *QueryFeeAllowanceRequest) 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: QueryFeeAllowanceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeeAllowanceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", 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.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", 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.Grantee = 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 *QueryFeeAllowanceResponse) 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: QueryFeeAllowanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeeAllowanceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FeeAllowance", 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.FeeAllowance == nil { + m.FeeAllowance = &FeeAllowanceGrant{} + } + if err := m.FeeAllowance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryFeeAllowancesRequest) 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: QueryFeeAllowancesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeeAllowancesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", 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.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", 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.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryFeeAllowancesResponse) 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: QueryFeeAllowancesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryFeeAllowancesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FeeAllowances", 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 + } + m.FeeAllowances = append(m.FeeAllowances, &FeeAllowanceGrant{}) + if err := m.FeeAllowances[len(m.FeeAllowances)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", 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.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.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/feegrant/types/query.pb.gw.go b/x/feegrant/types/query.pb.gw.go new file mode 100644 index 0000000000..499e4a441d --- /dev/null +++ b/x/feegrant/types/query.pb.gw.go @@ -0,0 +1,322 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: cosmos/feegrant/v1beta1/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/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 + +func request_Query_FeeAllowance_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeeAllowanceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + msg, err := client.FeeAllowance(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_FeeAllowance_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeeAllowanceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["granter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "granter") + } + + protoReq.Granter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "granter", err) + } + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + msg, err := server.FeeAllowance(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_FeeAllowances_0 = &utilities.DoubleArray{Encoding: map[string]int{"grantee": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_FeeAllowances_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeeAllowancesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_FeeAllowances_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.FeeAllowances(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_FeeAllowances_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryFeeAllowancesRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["grantee"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "grantee") + } + + protoReq.Grantee, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "grantee", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_FeeAllowances_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.FeeAllowances(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 (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_FeeAllowance_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_FeeAllowance_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_FeeAllowance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_FeeAllowances_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.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_FeeAllowances_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_FeeAllowances_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_FeeAllowance_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_FeeAllowance_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_FeeAllowance_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_FeeAllowances_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_FeeAllowances_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_FeeAllowances_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_FeeAllowance_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"cosmos", "feegrant", "v1beta1", "fee_allowance", "granter", "grantee"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_FeeAllowances_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "feegrant", "v1beta1", "fee_allowances", "grantee"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_FeeAllowance_0 = runtime.ForwardResponseMessage + + forward_Query_FeeAllowances_0 = runtime.ForwardResponseMessage +) diff --git a/x/feegrant/types/tx.pb.go b/x/feegrant/types/tx.pb.go new file mode 100644 index 0000000000..d3080f10e3 --- /dev/null +++ b/x/feegrant/types/tx.pb.go @@ -0,0 +1,1033 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: cosmos/feegrant/v1beta1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "github.com/regen-network/cosmos-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 + +// MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance +// of fees from the account of Granter. +type MsgGrantFeeAllowance struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` + Allowance *types.Any `protobuf:"bytes,3,opt,name=allowance,proto3" json:"allowance,omitempty"` +} + +func (m *MsgGrantFeeAllowance) Reset() { *m = MsgGrantFeeAllowance{} } +func (m *MsgGrantFeeAllowance) String() string { return proto.CompactTextString(m) } +func (*MsgGrantFeeAllowance) ProtoMessage() {} +func (*MsgGrantFeeAllowance) Descriptor() ([]byte, []int) { + return fileDescriptor_dd44ad7946dad783, []int{0} +} +func (m *MsgGrantFeeAllowance) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgGrantFeeAllowance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgGrantFeeAllowance.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 *MsgGrantFeeAllowance) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgGrantFeeAllowance.Merge(m, src) +} +func (m *MsgGrantFeeAllowance) XXX_Size() int { + return m.Size() +} +func (m *MsgGrantFeeAllowance) XXX_DiscardUnknown() { + xxx_messageInfo_MsgGrantFeeAllowance.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgGrantFeeAllowance proto.InternalMessageInfo + +func (m *MsgGrantFeeAllowance) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *MsgGrantFeeAllowance) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +func (m *MsgGrantFeeAllowance) GetAllowance() *types.Any { + if m != nil { + return m.Allowance + } + return nil +} + +// MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. +type MsgGrantFeeAllowanceResponse struct { +} + +func (m *MsgGrantFeeAllowanceResponse) Reset() { *m = MsgGrantFeeAllowanceResponse{} } +func (m *MsgGrantFeeAllowanceResponse) String() string { return proto.CompactTextString(m) } +func (*MsgGrantFeeAllowanceResponse) ProtoMessage() {} +func (*MsgGrantFeeAllowanceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_dd44ad7946dad783, []int{1} +} +func (m *MsgGrantFeeAllowanceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgGrantFeeAllowanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgGrantFeeAllowanceResponse.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 *MsgGrantFeeAllowanceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgGrantFeeAllowanceResponse.Merge(m, src) +} +func (m *MsgGrantFeeAllowanceResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgGrantFeeAllowanceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgGrantFeeAllowanceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgGrantFeeAllowanceResponse proto.InternalMessageInfo + +// MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. +type MsgRevokeFeeAllowance struct { + Granter string `protobuf:"bytes,1,opt,name=granter,proto3" json:"granter,omitempty"` + Grantee string `protobuf:"bytes,2,opt,name=grantee,proto3" json:"grantee,omitempty"` +} + +func (m *MsgRevokeFeeAllowance) Reset() { *m = MsgRevokeFeeAllowance{} } +func (m *MsgRevokeFeeAllowance) String() string { return proto.CompactTextString(m) } +func (*MsgRevokeFeeAllowance) ProtoMessage() {} +func (*MsgRevokeFeeAllowance) Descriptor() ([]byte, []int) { + return fileDescriptor_dd44ad7946dad783, []int{2} +} +func (m *MsgRevokeFeeAllowance) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRevokeFeeAllowance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRevokeFeeAllowance.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 *MsgRevokeFeeAllowance) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRevokeFeeAllowance.Merge(m, src) +} +func (m *MsgRevokeFeeAllowance) XXX_Size() int { + return m.Size() +} +func (m *MsgRevokeFeeAllowance) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRevokeFeeAllowance.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRevokeFeeAllowance proto.InternalMessageInfo + +func (m *MsgRevokeFeeAllowance) GetGranter() string { + if m != nil { + return m.Granter + } + return "" +} + +func (m *MsgRevokeFeeAllowance) GetGrantee() string { + if m != nil { + return m.Grantee + } + return "" +} + +// MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. +type MsgRevokeFeeAllowanceResponse struct { +} + +func (m *MsgRevokeFeeAllowanceResponse) Reset() { *m = MsgRevokeFeeAllowanceResponse{} } +func (m *MsgRevokeFeeAllowanceResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRevokeFeeAllowanceResponse) ProtoMessage() {} +func (*MsgRevokeFeeAllowanceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_dd44ad7946dad783, []int{3} +} +func (m *MsgRevokeFeeAllowanceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRevokeFeeAllowanceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRevokeFeeAllowanceResponse.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 *MsgRevokeFeeAllowanceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRevokeFeeAllowanceResponse.Merge(m, src) +} +func (m *MsgRevokeFeeAllowanceResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRevokeFeeAllowanceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRevokeFeeAllowanceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRevokeFeeAllowanceResponse proto.InternalMessageInfo + +func init() { + proto.RegisterType((*MsgGrantFeeAllowance)(nil), "cosmos.feegrant.v1beta1.MsgGrantFeeAllowance") + proto.RegisterType((*MsgGrantFeeAllowanceResponse)(nil), "cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse") + proto.RegisterType((*MsgRevokeFeeAllowance)(nil), "cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance") + proto.RegisterType((*MsgRevokeFeeAllowanceResponse)(nil), "cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse") +} + +func init() { proto.RegisterFile("cosmos/feegrant/v1beta1/tx.proto", fileDescriptor_dd44ad7946dad783) } + +var fileDescriptor_dd44ad7946dad783 = []byte{ + // 345 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x48, 0xce, 0x2f, 0xce, + 0xcd, 0x2f, 0xd6, 0x4f, 0x4b, 0x4d, 0x4d, 0x2f, 0x4a, 0xcc, 0x2b, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, + 0x2d, 0x49, 0x34, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x87, 0xa8, + 0xd0, 0x83, 0xa9, 0xd0, 0x83, 0xaa, 0x90, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xab, 0xd1, 0x07, + 0xb1, 0x20, 0xca, 0xa5, 0x24, 0xd3, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0xc1, 0xbc, 0xa4, 0xd2, + 0x34, 0xfd, 0xc4, 0xbc, 0x4a, 0x98, 0x14, 0xc4, 0xa4, 0x78, 0x88, 0x1e, 0xa8, 0xb1, 0x60, 0x8e, + 0xd2, 0x44, 0x46, 0x2e, 0x11, 0xdf, 0xe2, 0x74, 0x77, 0x90, 0x05, 0x6e, 0xa9, 0xa9, 0x8e, 0x39, + 0x39, 0xf9, 0xe5, 0x89, 0x79, 0xc9, 0xa9, 0x42, 0x12, 0x5c, 0xec, 0x60, 0x5b, 0x53, 0x8b, 0x24, + 0x18, 0x15, 0x18, 0x35, 0x38, 0x83, 0x60, 0x5c, 0x84, 0x4c, 0xaa, 0x04, 0x13, 0xb2, 0x4c, 0xaa, + 0x90, 0x2b, 0x17, 0x67, 0x22, 0xcc, 0x00, 0x09, 0x66, 0x05, 0x46, 0x0d, 0x6e, 0x23, 0x11, 0x3d, + 0x88, 0xb3, 0xf4, 0x60, 0xce, 0xd2, 0x73, 0xcc, 0xab, 0x74, 0x12, 0x3c, 0xb5, 0x45, 0x97, 0x17, + 0xd9, 0x3a, 0xcf, 0x20, 0x84, 0x4e, 0x25, 0x39, 0x2e, 0x19, 0x6c, 0x4e, 0x0a, 0x4a, 0x2d, 0x2e, + 0xc8, 0xcf, 0x2b, 0x4e, 0x55, 0xf2, 0xe6, 0x12, 0xf5, 0x2d, 0x4e, 0x0f, 0x4a, 0x2d, 0xcb, 0xcf, + 0x4e, 0xa5, 0xd4, 0xcd, 0x4a, 0xf2, 0x5c, 0xb2, 0x58, 0x0d, 0x83, 0xd9, 0x66, 0xf4, 0x8f, 0x91, + 0x8b, 0xd9, 0xb7, 0x38, 0x5d, 0xa8, 0x92, 0x4b, 0x10, 0x33, 0x94, 0x74, 0xf5, 0x70, 0x44, 0x92, + 0x1e, 0x36, 0x1f, 0x48, 0x99, 0x92, 0xa4, 0x1c, 0xe6, 0x04, 0xa1, 0x1a, 0x2e, 0x21, 0x2c, 0xbe, + 0xd5, 0xc3, 0x67, 0x18, 0xa6, 0x7a, 0x29, 0x33, 0xd2, 0xd4, 0xc3, 0x6c, 0x77, 0x72, 0x3f, 0xf1, + 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, + 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xdd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, + 0xbd, 0xe4, 0xfc, 0x5c, 0x68, 0xaa, 0x82, 0x52, 0xba, 0xc5, 0x29, 0xd9, 0xfa, 0x15, 0x88, 0xb4, + 0x5d, 0x52, 0x59, 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0x4e, 0x03, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x7b, 0xbe, 0x24, 0x15, 0xfb, 0x02, 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 { + // GrantFeeAllowance grants fee allowance to the grantee on the granter's + // account with the provided expiration time. + GrantFeeAllowance(ctx context.Context, in *MsgGrantFeeAllowance, opts ...grpc.CallOption) (*MsgGrantFeeAllowanceResponse, error) + // RevokeFeeAllowance revokes any fee allowance of granter's account that + // has been granted to the grantee. + RevokeFeeAllowance(ctx context.Context, in *MsgRevokeFeeAllowance, opts ...grpc.CallOption) (*MsgRevokeFeeAllowanceResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) GrantFeeAllowance(ctx context.Context, in *MsgGrantFeeAllowance, opts ...grpc.CallOption) (*MsgGrantFeeAllowanceResponse, error) { + out := new(MsgGrantFeeAllowanceResponse) + err := c.cc.Invoke(ctx, "/cosmos.feegrant.v1beta1.Msg/GrantFeeAllowance", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) RevokeFeeAllowance(ctx context.Context, in *MsgRevokeFeeAllowance, opts ...grpc.CallOption) (*MsgRevokeFeeAllowanceResponse, error) { + out := new(MsgRevokeFeeAllowanceResponse) + err := c.cc.Invoke(ctx, "/cosmos.feegrant.v1beta1.Msg/RevokeFeeAllowance", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // GrantFeeAllowance grants fee allowance to the grantee on the granter's + // account with the provided expiration time. + GrantFeeAllowance(context.Context, *MsgGrantFeeAllowance) (*MsgGrantFeeAllowanceResponse, error) + // RevokeFeeAllowance revokes any fee allowance of granter's account that + // has been granted to the grantee. + RevokeFeeAllowance(context.Context, *MsgRevokeFeeAllowance) (*MsgRevokeFeeAllowanceResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) GrantFeeAllowance(ctx context.Context, req *MsgGrantFeeAllowance) (*MsgGrantFeeAllowanceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GrantFeeAllowance not implemented") +} +func (*UnimplementedMsgServer) RevokeFeeAllowance(ctx context.Context, req *MsgRevokeFeeAllowance) (*MsgRevokeFeeAllowanceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RevokeFeeAllowance not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_GrantFeeAllowance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgGrantFeeAllowance) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).GrantFeeAllowance(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.feegrant.v1beta1.Msg/GrantFeeAllowance", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).GrantFeeAllowance(ctx, req.(*MsgGrantFeeAllowance)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_RevokeFeeAllowance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRevokeFeeAllowance) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RevokeFeeAllowance(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/cosmos.feegrant.v1beta1.Msg/RevokeFeeAllowance", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RevokeFeeAllowance(ctx, req.(*MsgRevokeFeeAllowance)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "cosmos.feegrant.v1beta1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GrantFeeAllowance", + Handler: _Msg_GrantFeeAllowance_Handler, + }, + { + MethodName: "RevokeFeeAllowance", + Handler: _Msg_RevokeFeeAllowance_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "cosmos/feegrant/v1beta1/tx.proto", +} + +func (m *MsgGrantFeeAllowance) 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 *MsgGrantFeeAllowance) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgGrantFeeAllowance) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Allowance != nil { + { + size, err := m.Allowance.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintTx(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgGrantFeeAllowanceResponse) 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 *MsgGrantFeeAllowanceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgGrantFeeAllowanceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgRevokeFeeAllowance) 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 *MsgRevokeFeeAllowance) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRevokeFeeAllowance) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Grantee) > 0 { + i -= len(m.Grantee) + copy(dAtA[i:], m.Grantee) + i = encodeVarintTx(dAtA, i, uint64(len(m.Grantee))) + i-- + dAtA[i] = 0x12 + } + if len(m.Granter) > 0 { + i -= len(m.Granter) + copy(dAtA[i:], m.Granter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Granter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRevokeFeeAllowanceResponse) 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 *MsgRevokeFeeAllowanceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRevokeFeeAllowanceResponse) 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 *MsgGrantFeeAllowance) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Allowance != nil { + l = m.Allowance.Size() + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgGrantFeeAllowanceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgRevokeFeeAllowance) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Granter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Grantee) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgRevokeFeeAllowanceResponse) 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 *MsgGrantFeeAllowance) 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: MsgGrantFeeAllowance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgGrantFeeAllowance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", 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.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", 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.Grantee = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Allowance", 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 m.Allowance == nil { + m.Allowance = &types.Any{} + } + if err := m.Allowance.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 *MsgGrantFeeAllowanceResponse) 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: MsgGrantFeeAllowanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgGrantFeeAllowanceResponse: 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 (m *MsgRevokeFeeAllowance) 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: MsgRevokeFeeAllowance: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRevokeFeeAllowance: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Granter", 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.Granter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Grantee", 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.Grantee = string(dAtA[iNdEx:postIndex]) + 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 *MsgRevokeFeeAllowanceResponse) 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: MsgRevokeFeeAllowanceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRevokeFeeAllowanceResponse: 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") +) diff --git a/x/mint/simulation/decoder.go b/x/mint/simulation/decoder.go index 37d9930f7d..f0a89be439 100644 --- a/x/mint/simulation/decoder.go +++ b/x/mint/simulation/decoder.go @@ -9,7 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/mint/types" ) -// NewDecodeStore returns a decoder function closure that umarshals the KVPair's +// NewDecodeStore returns a decoder function closure that unmarshals the KVPair's // Value to the corresponding mint type. func NewDecodeStore(cdc codec.Marshaler) func(kvA, kvB kv.Pair) string { return func(kvA, kvB kv.Pair) string { From d6e4a2e9bcd9eff87d6f4b43ae13378e2ba6ac63 Mon Sep 17 00:00:00 2001 From: yihuang Date: Sat, 30 Jan 2021 04:05:24 +0800 Subject: [PATCH 23/40] fix bech32 prefix in evidence (#8461) Co-authored-by: Tomas Tauber <2410580+tomtau@users.noreply.github.com> Co-authored-by: Tomas Tauber <2410580+tomtau@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 1 + x/evidence/types/evidence.go | 3 ++- x/evidence/types/evidence_test.go | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ea84cb347..6bfebd9d2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* (x/evidence) [#8461](https://github.com/cosmos/cosmos-sdk/pull/8461) Fix bech32 prefix in evidence validator address conversion * (x/slashing) [\#8427](https://github.com/cosmos/cosmos-sdk/pull/8427) Fix query signing infos command * (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account * (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis diff --git a/x/evidence/types/evidence.go b/x/evidence/types/evidence.go index 95705cc5b9..fca6126ec3 100644 --- a/x/evidence/types/evidence.go +++ b/x/evidence/types/evidence.go @@ -88,7 +88,8 @@ func (e Equivocation) GetTotalPower() int64 { return 0 } // FromABCIEvidence converts a Tendermint concrete Evidence type to // SDK Evidence using Equivocation as the concrete type. func FromABCIEvidence(e abci.Evidence) exported.Evidence { - consAddr, err := sdk.Bech32ifyAddressBytes(sdk.Bech32PrefixConsAddr, e.Validator.Address) + bech32PrefixConsAddr := sdk.GetConfig().GetBech32ConsensusAddrPrefix() + consAddr, err := sdk.Bech32ifyAddressBytes(bech32PrefixConsAddr, e.Validator.Address) if err != nil { panic(err) } diff --git a/x/evidence/types/evidence_test.go b/x/evidence/types/evidence_test.go index 07b9352f57..c78f0b059c 100644 --- a/x/evidence/types/evidence_test.go +++ b/x/evidence/types/evidence_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/evidence/types" @@ -57,3 +58,22 @@ func TestEquivocationValidateBasic(t *testing.T) { }) } } + +func TestEvidenceAddressConversion(t *testing.T) { + sdk.GetConfig().SetBech32PrefixForConsensusNode("testcnclcons", "testcnclconspub") + tmEvidence := abci.Evidence{ + Type: abci.EvidenceType_DUPLICATE_VOTE, + Validator: abci.Validator{ + Address: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Power: 100, + }, + Height: 1, + Time: time.Now(), + TotalVotingPower: 100, + } + evidence := types.FromABCIEvidence(tmEvidence).(*types.Equivocation) + consAddr := evidence.GetConsensusAddress() + // Check the address is the same after conversion + require.Equal(t, tmEvidence.Validator.Address, consAddr.Bytes()) + sdk.GetConfig().SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub) +} From 1d75e0e984e7132efd54c3526e36b3585e2d91c0 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Fri, 29 Jan 2021 23:48:26 -0300 Subject: [PATCH 24/40] bank: additional client metadata validation (#8479) * bank: additional client metadata validation * changelog and comment * fix tab --- CHANGELOG.md | 1 + x/bank/types/metadata.go | 39 +++++++++++++++++++++++-- x/bank/types/metadata_test.go | 55 ++++++++++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bfebd9d2b..5bcb99bd84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/bank) [\#8479](https://github.com/cosmos/cosmos-sdk/pull/8479) Adittional client denom metadata validation for `base` and `display` denoms. * (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. * [\#8396](https://github.com/cosmos/cosmos-sdk/pull/8396) Add support for ARM platform diff --git a/x/bank/types/metadata.go b/x/bank/types/metadata.go index 5106964e99..ce7794053d 100644 --- a/x/bank/types/metadata.go +++ b/x/bank/types/metadata.go @@ -1,13 +1,19 @@ package types import ( + "errors" "fmt" "strings" sdk "github.com/cosmos/cosmos-sdk/types" ) -// Validate performs a basic validation of the coin metadata fields +// Validate performs a basic validation of the coin metadata fields. It checks: +// - Base and Display denominations are valid coin denominations +// - Base and Display denominations are present in the DenomUnit slice +// - Base denomination has exponent 0 +// - Denomination units are sorted in ascending order +// - Denomination units not duplicated func (m Metadata) Validate() error { if err := sdk.ValidateDenom(m.Base); err != nil { return fmt.Errorf("invalid metadata base denom: %w", err) @@ -17,12 +23,37 @@ func (m Metadata) Validate() error { return fmt.Errorf("invalid metadata display denom: %w", err) } + var ( + hasDisplay bool + currentExponent uint32 // check that the exponents are increasing + ) + seenUnits := make(map[string]bool) - for _, denomUnit := range m.DenomUnits { + + for i, denomUnit := range m.DenomUnits { + // The first denomination unit MUST be the base + if i == 0 { + // validate denomination and exponent + if denomUnit.Denom != m.Base { + return fmt.Errorf("metadata's first denomination unit must be the one with base denom '%s'", m.Base) + } + if denomUnit.Exponent != 0 { + return fmt.Errorf("the exponent for base denomination unit %s must be 0", m.Base) + } + } else if currentExponent >= denomUnit.Exponent { + return errors.New("denom units should be sorted asc by exponent") + } + + currentExponent = denomUnit.Exponent + if seenUnits[denomUnit.Denom] { return fmt.Errorf("duplicate denomination unit %s", denomUnit.Denom) } + if denomUnit.Denom == m.Display { + hasDisplay = true + } + if err := denomUnit.Validate(); err != nil { return err } @@ -30,6 +61,10 @@ func (m Metadata) Validate() error { seenUnits[denomUnit.Denom] = true } + if !hasDisplay { + return fmt.Errorf("metadata must contain a denomination unit with display denom '%s'", m.Display) + } + return nil } diff --git a/x/bank/types/metadata_test.go b/x/bank/types/metadata_test.go index 29f4d220f9..64241e6098 100644 --- a/x/bank/types/metadata_test.go +++ b/x/bank/types/metadata_test.go @@ -51,7 +51,7 @@ func TestMetadataValidate(t *testing.T) { Description: "The native staking token of the Cosmos Hub.", DenomUnits: []*types.DenomUnit{ {"uatom", uint32(0), []string{"microatom"}}, - {"uatom", uint32(0), []string{"microatom"}}, + {"uatom", uint32(1), []string{"microatom"}}, }, Base: "uatom", Display: "atom", @@ -94,6 +94,59 @@ func TestMetadataValidate(t *testing.T) { }, true, }, + { + "no base denom unit", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "base denom exponent not zero", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(1), []string{"microatom"}}, + {"matom", uint32(3), []string{"milliatom"}}, + {"atom", uint32(6), nil}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "no display denom unit", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, + { + "denom units not sorted", + types.Metadata{ + Description: "The native staking token of the Cosmos Hub.", + DenomUnits: []*types.DenomUnit{ + {"uatom", uint32(0), []string{"microatom"}}, + {"atom", uint32(6), nil}, + {"matom", uint32(3), []string{"milliatom"}}, + }, + Base: "uatom", + Display: "atom", + }, + true, + }, } for _, tc := range testCases { From 812835795693bd6202a5c19d5f37724e69e204b2 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 1 Feb 2021 10:48:32 +0000 Subject: [PATCH 25/40] snapshots: fix flaky tests (#8475) The use testing.T.TempDir() seems to cause test failures in CI environvements in those cases where temporary directories' subdirs are created with permissions that are different from the defaults used by testing.T.TempDir(). The snapshots package's tests seem to be heavily affected, thus this replaces testing.T.TempDir() occurrences with ioutil.TempDir() calls. Related upstream issue: - https://github.com/golang/go/issues/40853 Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- snapshots/helpers_test.go | 6 +++++- snapshots/store_test.go | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/snapshots/helpers_test.go b/snapshots/helpers_test.go index 5dbdd31753..751ac212d3 100644 --- a/snapshots/helpers_test.go +++ b/snapshots/helpers_test.go @@ -6,6 +6,7 @@ import ( "errors" "io" "io/ioutil" + "os" "testing" "time" @@ -100,7 +101,10 @@ func (m *mockSnapshotter) Snapshot(height uint64, format uint32) (<-chan io.Read // setupBusyManager creates a manager with an empty store that is busy creating a snapshot at height 1. // The snapshot will complete when the returned closer is called. func setupBusyManager(t *testing.T) *snapshots.Manager { - tempdir := t.TempDir() + tempdir, err := ioutil.TempDir("", "") + require.NoError(t, err) + t.Cleanup(func() { _ = os.RemoveAll(tempdir) }) + store, err := snapshots.NewStore(db.NewMemDB(), tempdir) require.NoError(t, err) hung := newHungSnapshotter() diff --git a/snapshots/store_test.go b/snapshots/store_test.go index 1a04a393c1..325fd3410b 100644 --- a/snapshots/store_test.go +++ b/snapshots/store_test.go @@ -5,6 +5,7 @@ import ( "errors" "io" "io/ioutil" + "os" "path/filepath" "testing" "time" @@ -19,7 +20,10 @@ import ( ) func setupStore(t *testing.T) *snapshots.Store { - tempdir := t.TempDir() + tempdir, err := ioutil.TempDir("", "") + require.NoError(t, err) + t.Cleanup(func() { _ = os.RemoveAll(tempdir) }) + store, err := snapshots.NewStore(db.NewMemDB(), tempdir) require.NoError(t, err) From 896eee213ae39a327826000f5ef87f251789fbaf Mon Sep 17 00:00:00 2001 From: Amaury Date: Mon, 1 Feb 2021 13:35:18 +0100 Subject: [PATCH 26/40] docs: Update x/staking spec (#8395) * Finish updating state * Add messages * Update events * proto-gen * Update proto/cosmos/staking/v1beta1/staking.proto Co-authored-by: Anil Kumar Kammari * progo-gen * Update Msg with slash * Rerun proto docs Co-authored-by: Anil Kumar Kammari Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/core/proto-docs.md | 9390 ++++++++++---------- proto/cosmos/staking/v1beta1/staking.proto | 44 + x/staking/spec/01_state.md | 142 +- x/staking/spec/02_state_transitions.md | 25 +- x/staking/spec/03_messages.md | 101 +- x/staking/spec/07_events.md | 16 +- x/staking/spec/README.md | 18 +- x/staking/types/staking.pb.go | 120 +- 8 files changed, 4921 insertions(+), 4935 deletions(-) diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 6b5909a3db..b06aaf2461 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -4,116 +4,70 @@ ## Table of Contents -- [cosmos/tx/v1beta1/tx.proto](#cosmos/tx/v1beta1/tx.proto) - - [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) - - [Fee](#cosmos.tx.v1beta1.Fee) - - [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) - - [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) - - [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) - - [SignDoc](#cosmos.tx.v1beta1.SignDoc) - - [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) - - [Tx](#cosmos.tx.v1beta1.Tx) - - [TxBody](#cosmos.tx.v1beta1.TxBody) - - [TxRaw](#cosmos.tx.v1beta1.TxRaw) +- [cosmos/auth/v1beta1/auth.proto](#cosmos/auth/v1beta1/auth.proto) + - [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) + - [ModuleAccount](#cosmos.auth.v1beta1.ModuleAccount) + - [Params](#cosmos.auth.v1beta1.Params) -- [cosmos/tx/v1beta1/service.proto](#cosmos/tx/v1beta1/service.proto) - - [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) - - [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) - - [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) - - [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) - - [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) - - [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) - - [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) - - [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) +- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) + - [GenesisState](#cosmos.auth.v1beta1.GenesisState) - - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) +- [cosmos/auth/v1beta1/query.proto](#cosmos/auth/v1beta1/query.proto) + - [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) + - [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) + - [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) - - [Service](#cosmos.tx.v1beta1.Service) + - [Query](#cosmos.auth.v1beta1.Query) -- [cosmos/tx/signing/v1beta1/signing.proto](#cosmos/tx/signing/v1beta1/signing.proto) - - [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) - - [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) - - [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) - - [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) - - [SignatureDescriptors](#cosmos.tx.signing.v1beta1.SignatureDescriptors) +- [cosmos/base/v1beta1/coin.proto](#cosmos/base/v1beta1/coin.proto) + - [Coin](#cosmos.base.v1beta1.Coin) + - [DecCoin](#cosmos.base.v1beta1.DecCoin) + - [DecProto](#cosmos.base.v1beta1.DecProto) + - [IntProto](#cosmos.base.v1beta1.IntProto) - - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) +- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) + - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) + - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) + - [SendAuthorization](#cosmos.authz.v1beta1.SendAuthorization) -- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) - - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) - - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) +- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) + - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) + - [Attribute](#cosmos.base.abci.v1beta1.Attribute) + - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) + - [MsgData](#cosmos.base.abci.v1beta1.MsgData) + - [Result](#cosmos.base.abci.v1beta1.Result) + - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) + - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) + - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) + - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) + - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) - - [Msg](#cosmos.crisis.v1beta1.Msg) +- [cosmos/authz/v1beta1/tx.proto](#cosmos/authz/v1beta1/tx.proto) + - [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) + - [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) + - [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) + - [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) + - [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) + - [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) -- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) - - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) + - [Msg](#cosmos.authz.v1beta1.Msg) -- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) - - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) +- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) + - [GenesisState](#cosmos.authz.v1beta1.GenesisState) + - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) -- [cosmos/crypto/multisig/v1beta1/multisig.proto](#cosmos/crypto/multisig/v1beta1/multisig.proto) - - [CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) - - [MultiSignature](#cosmos.crypto.multisig.v1beta1.MultiSignature) +- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) + - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) + - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) -- [cosmos/crypto/secp256k1/keys.proto](#cosmos/crypto/secp256k1/keys.proto) - - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) - - [PubKey](#cosmos.crypto.secp256k1.PubKey) +- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto) + - [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) + - [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) + - [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) + - [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) -- [cosmos/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) - - [PrivKey](#cosmos.crypto.ed25519.PrivKey) - - [PubKey](#cosmos.crypto.ed25519.PubKey) - -- [cosmos/mint/v1beta1/query.proto](#cosmos/mint/v1beta1/query.proto) - - [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) - - [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) - - [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) - - [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) - - [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) - - - [Query](#cosmos.mint.v1beta1.Query) - -- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) - - [GenesisState](#cosmos.mint.v1beta1.GenesisState) - -- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) - - [Minter](#cosmos.mint.v1beta1.Minter) - - [Params](#cosmos.mint.v1beta1.Params) - -- [cosmos/feegrant/v1beta1/feegrant.proto](#cosmos/feegrant/v1beta1/feegrant.proto) - - [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) - - [Duration](#cosmos.feegrant.v1beta1.Duration) - - [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) - - [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) - - [PeriodicFeeAllowance](#cosmos.feegrant.v1beta1.PeriodicFeeAllowance) - -- [cosmos/feegrant/v1beta1/query.proto](#cosmos/feegrant/v1beta1/query.proto) - - [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) - - [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) - - [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) - - [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) - - - [Query](#cosmos.feegrant.v1beta1.Query) - -- [cosmos/feegrant/v1beta1/tx.proto](#cosmos/feegrant/v1beta1/tx.proto) - - [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) - - [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) - - [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) - - [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) - - - [Msg](#cosmos.feegrant.v1beta1.Msg) - -- [cosmos/feegrant/v1beta1/genesis.proto](#cosmos/feegrant/v1beta1/genesis.proto) - - [GenesisState](#cosmos.feegrant.v1beta1.GenesisState) - -- [cosmos/capability/v1beta1/capability.proto](#cosmos/capability/v1beta1/capability.proto) - - [Capability](#cosmos.capability.v1beta1.Capability) - - [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) - - [Owner](#cosmos.capability.v1beta1.Owner) - -- [cosmos/capability/v1beta1/genesis.proto](#cosmos/capability/v1beta1/genesis.proto) - - [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) - - [GenesisState](#cosmos.capability.v1beta1.GenesisState) + - [Query](#cosmos.authz.v1beta1.Query) - [cosmos/bank/v1beta1/bank.proto](#cosmos/bank/v1beta1/bank.proto) - [DenomUnit](#cosmos.bank.v1beta1.DenomUnit) @@ -124,6 +78,10 @@ - [SendEnabled](#cosmos.bank.v1beta1.SendEnabled) - [Supply](#cosmos.bank.v1beta1.Supply) +- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) + - [Balance](#cosmos.bank.v1beta1.Balance) + - [GenesisState](#cosmos.bank.v1beta1.GenesisState) + - [cosmos/bank/v1beta1/query.proto](#cosmos/bank/v1beta1/query.proto) - [QueryAllBalancesRequest](#cosmos.bank.v1beta1.QueryAllBalancesRequest) - [QueryAllBalancesResponse](#cosmos.bank.v1beta1.QueryAllBalancesResponse) @@ -150,85 +108,107 @@ - [Msg](#cosmos.bank.v1beta1.Msg) -- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto) - - [Balance](#cosmos.bank.v1beta1.Balance) - - [GenesisState](#cosmos.bank.v1beta1.GenesisState) +- [cosmos/base/kv/v1beta1/kv.proto](#cosmos/base/kv/v1beta1/kv.proto) + - [Pair](#cosmos.base.kv.v1beta1.Pair) + - [Pairs](#cosmos.base.kv.v1beta1.Pairs) -- [cosmos/authz/v1beta1/authz.proto](#cosmos/authz/v1beta1/authz.proto) - - [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) - - [GenericAuthorization](#cosmos.authz.v1beta1.GenericAuthorization) - - [SendAuthorization](#cosmos.authz.v1beta1.SendAuthorization) +- [cosmos/base/reflection/v1beta1/reflection.proto](#cosmos/base/reflection/v1beta1/reflection.proto) + - [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) + - [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) + - [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) + - [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) -- [cosmos/authz/v1beta1/query.proto](#cosmos/authz/v1beta1/query.proto) - - [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) - - [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) - - [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) - - [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) + - [ReflectionService](#cosmos.base.reflection.v1beta1.ReflectionService) - - [Query](#cosmos.authz.v1beta1.Query) +- [cosmos/base/snapshots/v1beta1/snapshot.proto](#cosmos/base/snapshots/v1beta1/snapshot.proto) + - [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) + - [Snapshot](#cosmos.base.snapshots.v1beta1.Snapshot) -- [cosmos/authz/v1beta1/tx.proto](#cosmos/authz/v1beta1/tx.proto) - - [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) - - [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) - - [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) - - [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) - - [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) - - [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) +- [cosmos/base/store/v1beta1/commit_info.proto](#cosmos/base/store/v1beta1/commit_info.proto) + - [CommitID](#cosmos.base.store.v1beta1.CommitID) + - [CommitInfo](#cosmos.base.store.v1beta1.CommitInfo) + - [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) - - [Msg](#cosmos.authz.v1beta1.Msg) +- [cosmos/base/store/v1beta1/snapshot.proto](#cosmos/base/store/v1beta1/snapshot.proto) + - [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) + - [SnapshotItem](#cosmos.base.store.v1beta1.SnapshotItem) + - [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) -- [cosmos/authz/v1beta1/genesis.proto](#cosmos/authz/v1beta1/genesis.proto) - - [GenesisState](#cosmos.authz.v1beta1.GenesisState) - - [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) +- [cosmos/base/tendermint/v1beta1/query.proto](#cosmos/base/tendermint/v1beta1/query.proto) + - [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) + - [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) + - [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) + - [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) + - [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) + - [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) + - [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) + - [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) + - [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) + - [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) + - [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) + - [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) + - [Module](#cosmos.base.tendermint.v1beta1.Module) + - [Validator](#cosmos.base.tendermint.v1beta1.Validator) + - [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) -- [cosmos/gov/v1beta1/gov.proto](#cosmos/gov/v1beta1/gov.proto) - - [Deposit](#cosmos.gov.v1beta1.Deposit) - - [DepositParams](#cosmos.gov.v1beta1.DepositParams) - - [Proposal](#cosmos.gov.v1beta1.Proposal) - - [TallyParams](#cosmos.gov.v1beta1.TallyParams) - - [TallyResult](#cosmos.gov.v1beta1.TallyResult) - - [TextProposal](#cosmos.gov.v1beta1.TextProposal) - - [Vote](#cosmos.gov.v1beta1.Vote) - - [VotingParams](#cosmos.gov.v1beta1.VotingParams) + - [Service](#cosmos.base.tendermint.v1beta1.Service) - - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) - - [VoteOption](#cosmos.gov.v1beta1.VoteOption) +- [cosmos/capability/v1beta1/capability.proto](#cosmos/capability/v1beta1/capability.proto) + - [Capability](#cosmos.capability.v1beta1.Capability) + - [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) + - [Owner](#cosmos.capability.v1beta1.Owner) -- [cosmos/gov/v1beta1/query.proto](#cosmos/gov/v1beta1/query.proto) - - [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) - - [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) - - [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) - - [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) - - [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) - - [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) - - [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) - - [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) - - [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) - - [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) - - [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) - - [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) - - [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) - - [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) - - [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) +- [cosmos/capability/v1beta1/genesis.proto](#cosmos/capability/v1beta1/genesis.proto) + - [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) + - [GenesisState](#cosmos.capability.v1beta1.GenesisState) - - [Query](#cosmos.gov.v1beta1.Query) +- [cosmos/crisis/v1beta1/genesis.proto](#cosmos/crisis/v1beta1/genesis.proto) + - [GenesisState](#cosmos.crisis.v1beta1.GenesisState) -- [cosmos/gov/v1beta1/tx.proto](#cosmos/gov/v1beta1/tx.proto) - - [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) - - [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) - - [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) - - [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) - - [MsgVote](#cosmos.gov.v1beta1.MsgVote) - - [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) +- [cosmos/crisis/v1beta1/tx.proto](#cosmos/crisis/v1beta1/tx.proto) + - [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) + - [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) - - [Msg](#cosmos.gov.v1beta1.Msg) + - [Msg](#cosmos.crisis.v1beta1.Msg) -- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) - - [GenesisState](#cosmos.gov.v1beta1.GenesisState) +- [cosmos/crypto/ed25519/keys.proto](#cosmos/crypto/ed25519/keys.proto) + - [PrivKey](#cosmos.crypto.ed25519.PrivKey) + - [PubKey](#cosmos.crypto.ed25519.PubKey) -- [cosmos/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) - - [GenesisState](#cosmos.genutil.v1beta1.GenesisState) +- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto) + - [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey) + +- [cosmos/crypto/multisig/v1beta1/multisig.proto](#cosmos/crypto/multisig/v1beta1/multisig.proto) + - [CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) + - [MultiSignature](#cosmos.crypto.multisig.v1beta1.MultiSignature) + +- [cosmos/crypto/secp256k1/keys.proto](#cosmos/crypto/secp256k1/keys.proto) + - [PrivKey](#cosmos.crypto.secp256k1.PrivKey) + - [PubKey](#cosmos.crypto.secp256k1.PubKey) + +- [cosmos/distribution/v1beta1/distribution.proto](#cosmos/distribution/v1beta1/distribution.proto) + - [CommunityPoolSpendProposal](#cosmos.distribution.v1beta1.CommunityPoolSpendProposal) + - [CommunityPoolSpendProposalWithDeposit](#cosmos.distribution.v1beta1.CommunityPoolSpendProposalWithDeposit) + - [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) + - [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) + - [FeePool](#cosmos.distribution.v1beta1.FeePool) + - [Params](#cosmos.distribution.v1beta1.Params) + - [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) + - [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) + - [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) + - [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) + - [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) + - [ValidatorSlashEvents](#cosmos.distribution.v1beta1.ValidatorSlashEvents) + +- [cosmos/distribution/v1beta1/genesis.proto](#cosmos/distribution/v1beta1/genesis.proto) + - [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) + - [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) + - [GenesisState](#cosmos.distribution.v1beta1.GenesisState) + - [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) + - [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) + - [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) + - [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) + - [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) - [cosmos/distribution/v1beta1/query.proto](#cosmos/distribution/v1beta1/query.proto) - [QueryCommunityPoolRequest](#cosmos.distribution.v1beta1.QueryCommunityPoolRequest) @@ -264,116 +244,138 @@ - [Msg](#cosmos.distribution.v1beta1.Msg) -- [cosmos/distribution/v1beta1/genesis.proto](#cosmos/distribution/v1beta1/genesis.proto) - - [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) - - [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) - - [GenesisState](#cosmos.distribution.v1beta1.GenesisState) - - [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) - - [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) - - [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) - - [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) - - [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) +- [cosmos/evidence/v1beta1/evidence.proto](#cosmos/evidence/v1beta1/evidence.proto) + - [Equivocation](#cosmos.evidence.v1beta1.Equivocation) -- [cosmos/distribution/v1beta1/distribution.proto](#cosmos/distribution/v1beta1/distribution.proto) - - [CommunityPoolSpendProposal](#cosmos.distribution.v1beta1.CommunityPoolSpendProposal) - - [CommunityPoolSpendProposalWithDeposit](#cosmos.distribution.v1beta1.CommunityPoolSpendProposalWithDeposit) - - [DelegationDelegatorReward](#cosmos.distribution.v1beta1.DelegationDelegatorReward) - - [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) - - [FeePool](#cosmos.distribution.v1beta1.FeePool) - - [Params](#cosmos.distribution.v1beta1.Params) - - [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) - - [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) - - [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) - - [ValidatorOutstandingRewards](#cosmos.distribution.v1beta1.ValidatorOutstandingRewards) - - [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) - - [ValidatorSlashEvents](#cosmos.distribution.v1beta1.ValidatorSlashEvents) +- [cosmos/evidence/v1beta1/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) + - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) -- [cosmos/upgrade/v1beta1/query.proto](#cosmos/upgrade/v1beta1/query.proto) - - [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) - - [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) - - [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) - - [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) - - [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) - - [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) +- [cosmos/evidence/v1beta1/query.proto](#cosmos/evidence/v1beta1/query.proto) + - [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) + - [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) + - [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) + - [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) - - [Query](#cosmos.upgrade.v1beta1.Query) + - [Query](#cosmos.evidence.v1beta1.Query) -- [cosmos/upgrade/v1beta1/upgrade.proto](#cosmos/upgrade/v1beta1/upgrade.proto) - - [CancelSoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal) - - [Plan](#cosmos.upgrade.v1beta1.Plan) - - [SoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.SoftwareUpgradeProposal) +- [cosmos/evidence/v1beta1/tx.proto](#cosmos/evidence/v1beta1/tx.proto) + - [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) + - [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) -- [cosmos/base/kv/v1beta1/kv.proto](#cosmos/base/kv/v1beta1/kv.proto) - - [Pair](#cosmos.base.kv.v1beta1.Pair) - - [Pairs](#cosmos.base.kv.v1beta1.Pairs) + - [Msg](#cosmos.evidence.v1beta1.Msg) -- [cosmos/base/abci/v1beta1/abci.proto](#cosmos/base/abci/v1beta1/abci.proto) - - [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) - - [Attribute](#cosmos.base.abci.v1beta1.Attribute) - - [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) - - [MsgData](#cosmos.base.abci.v1beta1.MsgData) - - [Result](#cosmos.base.abci.v1beta1.Result) - - [SearchTxsResult](#cosmos.base.abci.v1beta1.SearchTxsResult) - - [SimulationResponse](#cosmos.base.abci.v1beta1.SimulationResponse) - - [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) - - [TxMsgData](#cosmos.base.abci.v1beta1.TxMsgData) - - [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) +- [cosmos/feegrant/v1beta1/feegrant.proto](#cosmos/feegrant/v1beta1/feegrant.proto) + - [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) + - [Duration](#cosmos.feegrant.v1beta1.Duration) + - [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) + - [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) + - [PeriodicFeeAllowance](#cosmos.feegrant.v1beta1.PeriodicFeeAllowance) -- [cosmos/base/query/v1beta1/pagination.proto](#cosmos/base/query/v1beta1/pagination.proto) - - [PageRequest](#cosmos.base.query.v1beta1.PageRequest) - - [PageResponse](#cosmos.base.query.v1beta1.PageResponse) +- [cosmos/feegrant/v1beta1/genesis.proto](#cosmos/feegrant/v1beta1/genesis.proto) + - [GenesisState](#cosmos.feegrant.v1beta1.GenesisState) -- [cosmos/base/store/v1beta1/snapshot.proto](#cosmos/base/store/v1beta1/snapshot.proto) - - [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) - - [SnapshotItem](#cosmos.base.store.v1beta1.SnapshotItem) - - [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) +- [cosmos/feegrant/v1beta1/query.proto](#cosmos/feegrant/v1beta1/query.proto) + - [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) + - [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) + - [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) + - [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) -- [cosmos/base/store/v1beta1/commit_info.proto](#cosmos/base/store/v1beta1/commit_info.proto) - - [CommitID](#cosmos.base.store.v1beta1.CommitID) - - [CommitInfo](#cosmos.base.store.v1beta1.CommitInfo) - - [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) + - [Query](#cosmos.feegrant.v1beta1.Query) -- [cosmos/base/v1beta1/coin.proto](#cosmos/base/v1beta1/coin.proto) - - [Coin](#cosmos.base.v1beta1.Coin) - - [DecCoin](#cosmos.base.v1beta1.DecCoin) - - [DecProto](#cosmos.base.v1beta1.DecProto) - - [IntProto](#cosmos.base.v1beta1.IntProto) +- [cosmos/feegrant/v1beta1/tx.proto](#cosmos/feegrant/v1beta1/tx.proto) + - [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) + - [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) + - [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) + - [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) -- [cosmos/base/tendermint/v1beta1/query.proto](#cosmos/base/tendermint/v1beta1/query.proto) - - [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) - - [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) - - [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) - - [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) - - [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) - - [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) - - [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) - - [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) - - [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) - - [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) - - [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) - - [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) - - [Module](#cosmos.base.tendermint.v1beta1.Module) - - [Validator](#cosmos.base.tendermint.v1beta1.Validator) - - [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) + - [Msg](#cosmos.feegrant.v1beta1.Msg) - - [Service](#cosmos.base.tendermint.v1beta1.Service) +- [cosmos/genutil/v1beta1/genesis.proto](#cosmos/genutil/v1beta1/genesis.proto) + - [GenesisState](#cosmos.genutil.v1beta1.GenesisState) -- [cosmos/base/snapshots/v1beta1/snapshot.proto](#cosmos/base/snapshots/v1beta1/snapshot.proto) - - [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) - - [Snapshot](#cosmos.base.snapshots.v1beta1.Snapshot) +- [cosmos/gov/v1beta1/gov.proto](#cosmos/gov/v1beta1/gov.proto) + - [Deposit](#cosmos.gov.v1beta1.Deposit) + - [DepositParams](#cosmos.gov.v1beta1.DepositParams) + - [Proposal](#cosmos.gov.v1beta1.Proposal) + - [TallyParams](#cosmos.gov.v1beta1.TallyParams) + - [TallyResult](#cosmos.gov.v1beta1.TallyResult) + - [TextProposal](#cosmos.gov.v1beta1.TextProposal) + - [Vote](#cosmos.gov.v1beta1.Vote) + - [VotingParams](#cosmos.gov.v1beta1.VotingParams) -- [cosmos/base/reflection/v1beta1/reflection.proto](#cosmos/base/reflection/v1beta1/reflection.proto) - - [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) - - [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) - - [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) - - [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) + - [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) + - [VoteOption](#cosmos.gov.v1beta1.VoteOption) - - [ReflectionService](#cosmos.base.reflection.v1beta1.ReflectionService) +- [cosmos/gov/v1beta1/genesis.proto](#cosmos/gov/v1beta1/genesis.proto) + - [GenesisState](#cosmos.gov.v1beta1.GenesisState) + +- [cosmos/gov/v1beta1/query.proto](#cosmos/gov/v1beta1/query.proto) + - [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) + - [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) + - [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) + - [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) + - [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) + - [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) + - [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) + - [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) + - [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) + - [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) + - [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) + - [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) + - [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) + - [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) + - [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) + + - [Query](#cosmos.gov.v1beta1.Query) + +- [cosmos/gov/v1beta1/tx.proto](#cosmos/gov/v1beta1/tx.proto) + - [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) + - [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) + - [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) + - [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) + - [MsgVote](#cosmos.gov.v1beta1.MsgVote) + - [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) + + - [Msg](#cosmos.gov.v1beta1.Msg) + +- [cosmos/mint/v1beta1/mint.proto](#cosmos/mint/v1beta1/mint.proto) + - [Minter](#cosmos.mint.v1beta1.Minter) + - [Params](#cosmos.mint.v1beta1.Params) + +- [cosmos/mint/v1beta1/genesis.proto](#cosmos/mint/v1beta1/genesis.proto) + - [GenesisState](#cosmos.mint.v1beta1.GenesisState) + +- [cosmos/mint/v1beta1/query.proto](#cosmos/mint/v1beta1/query.proto) + - [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) + - [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) + - [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) + - [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) + - [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) + + - [Query](#cosmos.mint.v1beta1.Query) + +- [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) + - [ParamChange](#cosmos.params.v1beta1.ParamChange) + - [ParameterChangeProposal](#cosmos.params.v1beta1.ParameterChangeProposal) + +- [cosmos/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto) + - [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) + - [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) + + - [Query](#cosmos.params.v1beta1.Query) - [cosmos/slashing/v1beta1/slashing.proto](#cosmos/slashing/v1beta1/slashing.proto) - [Params](#cosmos.slashing.v1beta1.Params) - [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) +- [cosmos/slashing/v1beta1/genesis.proto](#cosmos/slashing/v1beta1/genesis.proto) + - [GenesisState](#cosmos.slashing.v1beta1.GenesisState) + - [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) + - [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) + - [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) + - [cosmos/slashing/v1beta1/query.proto](#cosmos/slashing/v1beta1/query.proto) - [QueryParamsRequest](#cosmos.slashing.v1beta1.QueryParamsRequest) - [QueryParamsResponse](#cosmos.slashing.v1beta1.QueryParamsResponse) @@ -390,47 +392,33 @@ - [Msg](#cosmos.slashing.v1beta1.Msg) -- [cosmos/slashing/v1beta1/genesis.proto](#cosmos/slashing/v1beta1/genesis.proto) - - [GenesisState](#cosmos.slashing.v1beta1.GenesisState) - - [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) - - [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) - - [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) +- [cosmos/staking/v1beta1/staking.proto](#cosmos/staking/v1beta1/staking.proto) + - [Commission](#cosmos.staking.v1beta1.Commission) + - [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) + - [DVPair](#cosmos.staking.v1beta1.DVPair) + - [DVPairs](#cosmos.staking.v1beta1.DVPairs) + - [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) + - [DVVTriplets](#cosmos.staking.v1beta1.DVVTriplets) + - [Delegation](#cosmos.staking.v1beta1.Delegation) + - [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) + - [Description](#cosmos.staking.v1beta1.Description) + - [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) + - [Params](#cosmos.staking.v1beta1.Params) + - [Pool](#cosmos.staking.v1beta1.Pool) + - [Redelegation](#cosmos.staking.v1beta1.Redelegation) + - [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) + - [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) + - [RedelegationResponse](#cosmos.staking.v1beta1.RedelegationResponse) + - [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) + - [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) + - [ValAddresses](#cosmos.staking.v1beta1.ValAddresses) + - [Validator](#cosmos.staking.v1beta1.Validator) -- [cosmos/evidence/v1beta1/evidence.proto](#cosmos/evidence/v1beta1/evidence.proto) - - [Equivocation](#cosmos.evidence.v1beta1.Equivocation) + - [BondStatus](#cosmos.staking.v1beta1.BondStatus) -- [cosmos/evidence/v1beta1/query.proto](#cosmos/evidence/v1beta1/query.proto) - - [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) - - [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) - - [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) - - [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) - - - [Query](#cosmos.evidence.v1beta1.Query) - -- [cosmos/evidence/v1beta1/tx.proto](#cosmos/evidence/v1beta1/tx.proto) - - [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) - - [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) - - - [Msg](#cosmos.evidence.v1beta1.Msg) - -- [cosmos/evidence/v1beta1/genesis.proto](#cosmos/evidence/v1beta1/genesis.proto) - - [GenesisState](#cosmos.evidence.v1beta1.GenesisState) - -- [cosmos/auth/v1beta1/auth.proto](#cosmos/auth/v1beta1/auth.proto) - - [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) - - [ModuleAccount](#cosmos.auth.v1beta1.ModuleAccount) - - [Params](#cosmos.auth.v1beta1.Params) - -- [cosmos/auth/v1beta1/query.proto](#cosmos/auth/v1beta1/query.proto) - - [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) - - [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) - - [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) - - - [Query](#cosmos.auth.v1beta1.Query) - -- [cosmos/auth/v1beta1/genesis.proto](#cosmos/auth/v1beta1/genesis.proto) - - [GenesisState](#cosmos.auth.v1beta1.GenesisState) +- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) + - [GenesisState](#cosmos.staking.v1beta1.GenesisState) + - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) - [cosmos/staking/v1beta1/query.proto](#cosmos/staking/v1beta1/query.proto) - [QueryDelegationRequest](#cosmos.staking.v1beta1.QueryDelegationRequest) @@ -478,33 +466,55 @@ - [Msg](#cosmos.staking.v1beta1.Msg) -- [cosmos/staking/v1beta1/genesis.proto](#cosmos/staking/v1beta1/genesis.proto) - - [GenesisState](#cosmos.staking.v1beta1.GenesisState) - - [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) +- [cosmos/tx/signing/v1beta1/signing.proto](#cosmos/tx/signing/v1beta1/signing.proto) + - [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) + - [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) + - [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) + - [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) + - [SignatureDescriptors](#cosmos.tx.signing.v1beta1.SignatureDescriptors) -- [cosmos/staking/v1beta1/staking.proto](#cosmos/staking/v1beta1/staking.proto) - - [Commission](#cosmos.staking.v1beta1.Commission) - - [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) - - [DVPair](#cosmos.staking.v1beta1.DVPair) - - [DVPairs](#cosmos.staking.v1beta1.DVPairs) - - [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) - - [DVVTriplets](#cosmos.staking.v1beta1.DVVTriplets) - - [Delegation](#cosmos.staking.v1beta1.Delegation) - - [DelegationResponse](#cosmos.staking.v1beta1.DelegationResponse) - - [Description](#cosmos.staking.v1beta1.Description) - - [HistoricalInfo](#cosmos.staking.v1beta1.HistoricalInfo) - - [Params](#cosmos.staking.v1beta1.Params) - - [Pool](#cosmos.staking.v1beta1.Pool) - - [Redelegation](#cosmos.staking.v1beta1.Redelegation) - - [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) - - [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) - - [RedelegationResponse](#cosmos.staking.v1beta1.RedelegationResponse) - - [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) - - [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) - - [ValAddresses](#cosmos.staking.v1beta1.ValAddresses) - - [Validator](#cosmos.staking.v1beta1.Validator) + - [SignMode](#cosmos.tx.signing.v1beta1.SignMode) - - [BondStatus](#cosmos.staking.v1beta1.BondStatus) +- [cosmos/tx/v1beta1/tx.proto](#cosmos/tx/v1beta1/tx.proto) + - [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) + - [Fee](#cosmos.tx.v1beta1.Fee) + - [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) + - [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) + - [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) + - [SignDoc](#cosmos.tx.v1beta1.SignDoc) + - [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) + - [Tx](#cosmos.tx.v1beta1.Tx) + - [TxBody](#cosmos.tx.v1beta1.TxBody) + - [TxRaw](#cosmos.tx.v1beta1.TxRaw) + +- [cosmos/tx/v1beta1/service.proto](#cosmos/tx/v1beta1/service.proto) + - [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) + - [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) + - [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) + - [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) + - [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) + - [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) + - [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) + - [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) + + - [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) + + - [Service](#cosmos.tx.v1beta1.Service) + +- [cosmos/upgrade/v1beta1/upgrade.proto](#cosmos/upgrade/v1beta1/upgrade.proto) + - [CancelSoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.CancelSoftwareUpgradeProposal) + - [Plan](#cosmos.upgrade.v1beta1.Plan) + - [SoftwareUpgradeProposal](#cosmos.upgrade.v1beta1.SoftwareUpgradeProposal) + +- [cosmos/upgrade/v1beta1/query.proto](#cosmos/upgrade/v1beta1/query.proto) + - [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) + - [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) + - [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) + - [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) + - [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) + - [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) + + - [Query](#cosmos.upgrade.v1beta1.Query) - [cosmos/vesting/v1beta1/tx.proto](#cosmos/vesting/v1beta1/tx.proto) - [MsgCreateVestingAccount](#cosmos.vesting.v1beta1.MsgCreateVestingAccount) @@ -519,15 +529,13 @@ - [Period](#cosmos.vesting.v1beta1.Period) - [PeriodicVestingAccount](#cosmos.vesting.v1beta1.PeriodicVestingAccount) -- [cosmos/params/v1beta1/query.proto](#cosmos/params/v1beta1/query.proto) - - [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) - - [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) +- [ibc/applications/transfer/v1/transfer.proto](#ibc/applications/transfer/v1/transfer.proto) + - [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) + - [FungibleTokenPacketData](#ibc.applications.transfer.v1.FungibleTokenPacketData) + - [Params](#ibc.applications.transfer.v1.Params) - - [Query](#cosmos.params.v1beta1.Query) - -- [cosmos/params/v1beta1/params.proto](#cosmos/params/v1beta1/params.proto) - - [ParamChange](#cosmos.params.v1beta1.ParamChange) - - [ParameterChangeProposal](#cosmos.params.v1beta1.ParameterChangeProposal) +- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) + - [GenesisState](#ibc.applications.transfer.v1.GenesisState) - [ibc/applications/transfer/v1/query.proto](#ibc/applications/transfer/v1/query.proto) - [QueryDenomTraceRequest](#ibc.applications.transfer.v1.QueryDenomTraceRequest) @@ -539,20 +547,6 @@ - [Query](#ibc.applications.transfer.v1.Query) -- [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) - - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) - - [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) - - - [Msg](#ibc.applications.transfer.v1.Msg) - -- [ibc/applications/transfer/v1/transfer.proto](#ibc/applications/transfer/v1/transfer.proto) - - [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) - - [FungibleTokenPacketData](#ibc.applications.transfer.v1.FungibleTokenPacketData) - - [Params](#ibc.applications.transfer.v1.Params) - -- [ibc/applications/transfer/v1/genesis.proto](#ibc/applications/transfer/v1/genesis.proto) - - [GenesisState](#ibc.applications.transfer.v1.GenesisState) - - [ibc/core/client/v1/client.proto](#ibc/core/client/v1/client.proto) - [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) - [ClientUpdateProposal](#ibc.core.client.v1.ClientUpdateProposal) @@ -561,36 +555,11 @@ - [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) - [Params](#ibc.core.client.v1.Params) -- [ibc/core/client/v1/query.proto](#ibc/core/client/v1/query.proto) - - [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) - - [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) - - [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) - - [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) - - [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) - - [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) - - [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) - - [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) - - [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) - - [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) +- [ibc/applications/transfer/v1/tx.proto](#ibc/applications/transfer/v1/tx.proto) + - [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) + - [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) - - [Query](#ibc.core.client.v1.Query) - -- [ibc/core/client/v1/tx.proto](#ibc/core/client/v1/tx.proto) - - [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) - - [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) - - [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) - - [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) - - [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) - - [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) - - [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) - - [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) - - - [Msg](#ibc.core.client.v1.Msg) - -- [ibc/core/client/v1/genesis.proto](#ibc/core/client/v1/genesis.proto) - - [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) - - [GenesisState](#ibc.core.client.v1.GenesisState) - - [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) + - [Msg](#ibc.applications.transfer.v1.Msg) - [ibc/core/channel/v1/channel.proto](#ibc/core/channel/v1/channel.proto) - [Acknowledgement](#ibc.core.channel.v1.Acknowledgement) @@ -603,6 +572,10 @@ - [Order](#ibc.core.channel.v1.Order) - [State](#ibc.core.channel.v1.State) +- [ibc/core/channel/v1/genesis.proto](#ibc/core/channel/v1/genesis.proto) + - [GenesisState](#ibc.core.channel.v1.GenesisState) + - [PacketSequence](#ibc.core.channel.v1.PacketSequence) + - [ibc/core/channel/v1/query.proto](#ibc/core/channel/v1/query.proto) - [QueryChannelClientStateRequest](#ibc.core.channel.v1.QueryChannelClientStateRequest) - [QueryChannelClientStateResponse](#ibc.core.channel.v1.QueryChannelClientStateResponse) @@ -657,9 +630,36 @@ - [Msg](#ibc.core.channel.v1.Msg) -- [ibc/core/channel/v1/genesis.proto](#ibc/core/channel/v1/genesis.proto) - - [GenesisState](#ibc.core.channel.v1.GenesisState) - - [PacketSequence](#ibc.core.channel.v1.PacketSequence) +- [ibc/core/client/v1/genesis.proto](#ibc/core/client/v1/genesis.proto) + - [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) + - [GenesisState](#ibc.core.client.v1.GenesisState) + - [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) + +- [ibc/core/client/v1/query.proto](#ibc/core/client/v1/query.proto) + - [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) + - [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) + - [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) + - [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) + - [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) + - [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) + - [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) + - [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) + - [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) + - [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) + + - [Query](#ibc.core.client.v1.Query) + +- [ibc/core/client/v1/tx.proto](#ibc/core/client/v1/tx.proto) + - [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) + - [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) + - [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) + - [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) + - [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) + - [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) + - [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) + - [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) + + - [Msg](#ibc.core.client.v1.Msg) - [ibc/core/commitment/v1/commitment.proto](#ibc/core/commitment/v1/commitment.proto) - [MerklePath](#ibc.core.commitment.v1.MerklePath) @@ -677,6 +677,9 @@ - [State](#ibc.core.connection.v1.State) +- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) + - [GenesisState](#ibc.core.connection.v1.GenesisState) + - [ibc/core/connection/v1/query.proto](#ibc/core/connection/v1/query.proto) - [QueryClientConnectionsRequest](#ibc.core.connection.v1.QueryClientConnectionsRequest) - [QueryClientConnectionsResponse](#ibc.core.connection.v1.QueryClientConnectionsResponse) @@ -703,22 +706,12 @@ - [Msg](#ibc.core.connection.v1.Msg) -- [ibc/core/connection/v1/genesis.proto](#ibc/core/connection/v1/genesis.proto) - - [GenesisState](#ibc.core.connection.v1.GenesisState) - - [ibc/core/types/v1/genesis.proto](#ibc/core/types/v1/genesis.proto) - [GenesisState](#ibc.core.types.v1.GenesisState) - [ibc/lightclients/localhost/v1/localhost.proto](#ibc/lightclients/localhost/v1/localhost.proto) - [ClientState](#ibc.lightclients.localhost.v1.ClientState) -- [ibc/lightclients/tendermint/v1/tendermint.proto](#ibc/lightclients/tendermint/v1/tendermint.proto) - - [ClientState](#ibc.lightclients.tendermint.v1.ClientState) - - [ConsensusState](#ibc.lightclients.tendermint.v1.ConsensusState) - - [Fraction](#ibc.lightclients.tendermint.v1.Fraction) - - [Header](#ibc.lightclients.tendermint.v1.Header) - - [Misbehaviour](#ibc.lightclients.tendermint.v1.Misbehaviour) - - [ibc/lightclients/solomachine/v1/solomachine.proto](#ibc/lightclients/solomachine/v1/solomachine.proto) - [ChannelStateData](#ibc.lightclients.solomachine.v1.ChannelStateData) - [ClientState](#ibc.lightclients.solomachine.v1.ClientState) @@ -739,190 +732,74 @@ - [DataType](#ibc.lightclients.solomachine.v1.DataType) +- [ibc/lightclients/tendermint/v1/tendermint.proto](#ibc/lightclients/tendermint/v1/tendermint.proto) + - [ClientState](#ibc.lightclients.tendermint.v1.ClientState) + - [ConsensusState](#ibc.lightclients.tendermint.v1.ConsensusState) + - [Fraction](#ibc.lightclients.tendermint.v1.Fraction) + - [Header](#ibc.lightclients.tendermint.v1.Header) + - [Misbehaviour](#ibc.lightclients.tendermint.v1.Misbehaviour) + - [Scalar Value Types](#scalar-value-types) - +

    Top

    -## cosmos/tx/v1beta1/tx.proto +## cosmos/auth/v1beta1/auth.proto - + -### AuthInfo -AuthInfo describes the fee and signer modes that are used to sign a -transaction. +### BaseAccount +BaseAccount defines a base account type. It contains all the necessary fields +for basic account functionality. Any custom account type should extend this +type for additional functionality (e.g. vesting). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `signer_infos` | [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) | repeated | signer_infos defines the signing modes for the required signers. The number and order of elements must match the required signers from TxBody's messages. The first element is the primary signer and the one which pays the fee. | -| `fee` | [Fee](#cosmos.tx.v1beta1.Fee) | | Fee is the fee and gas limit for the transaction. The first signer is the primary signer and the one which pays the fee. The fee can be calculated based on the cost of evaluating the body and doing signature verification of the signers. This can be estimated via simulation. | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `account_number` | [uint64](#uint64) | | | +| `sequence` | [uint64](#uint64) | | | - + -### Fee -Fee includes the amount of coins paid in fees and the maximum -gas to be used by the transaction. The ratio yields an effective "gasprice", -which must be above some miminum to be accepted into the mempool. +### ModuleAccount +ModuleAccount defines an account for modules that holds coins on a pool. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | amount is the amount of coins to be paid as a fee | -| `gas_limit` | [uint64](#uint64) | | gas_limit is the maximum gas that can be used in transaction processing before an out of gas error occurs | -| `payer` | [string](#string) | | if unset, the first signer is responsible for paying the fees. If set, the specified account must pay the fees. the payer must be a tx signer (and thus have signed this field in AuthInfo). setting this field does *not* change the ordering of required signers for the transaction. | -| `granter` | [string](#string) | | if set, the fee payer (either the first signer or the value of the payer field) requests that a fee grant be used to pay fees instead of the fee payer's own balance. If an appropriate fee grant does not exist or the chain does not support fee grants, this will fail | +| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | +| `name` | [string](#string) | | | +| `permissions` | [string](#string) | repeated | | - + -### ModeInfo -ModeInfo describes the signing mode of a single or nested multisig signer. +### Params +Params defines the parameters for the auth module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `single` | [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) | | single represents a single signer | -| `multi` | [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) | | multi represents a nested multisig signer | - - - - - - - - -### ModeInfo.Multi -Multi is the mode info for a multisig public key - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | -| `mode_infos` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | repeated | mode_infos is the corresponding modes of the signers of the multisig which could include nested multisig public keys | - - - - - - - - -### ModeInfo.Single -Single is the mode info for a single signer. It is structured as a message -to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the -future - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | - - - - - - - - -### SignDoc -SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `body_bytes` | [bytes](#bytes) | | body_bytes is protobuf serialization of a TxBody that matches the representation in TxRaw. | -| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in TxRaw. | -| `chain_id` | [string](#string) | | chain_id is the unique identifier of the chain this transaction targets. It prevents signed transactions from being used on another chain by an attacker | -| `account_number` | [uint64](#uint64) | | account_number is the account number of the account in state | - - - - - - - - -### SignerInfo -SignerInfo describes the public key and signing mode of a single top-level -signer. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer. It is optional for accounts that already exist in state. If unset, the verifier can use the required \ signer address for this position and lookup the public key. | -| `mode_info` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | | mode_info describes the signing mode of the signer and is a nested structure to support nested multisig pubkey's | -| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | - - - - - - - - -### Tx -Tx is the standard type used for broadcasting transactions. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `body` | [TxBody](#cosmos.tx.v1beta1.TxBody) | | body is the processable content of the transaction | -| `auth_info` | [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) | | auth_info is the authorization related content of the transaction, specifically signers, signer modes and fee | -| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | - - - - - - - - -### TxBody -TxBody is the body of a transaction that all signers sign over. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `messages` | [google.protobuf.Any](#google.protobuf.Any) | repeated | messages is a list of messages to be executed. The required signers of those messages define the number and order of elements in AuthInfo's signer_infos and Tx's signatures. Each required signer address is added to the list only the first time it occurs. By convention, the first required signer (usually from the first message) is referred to as the primary signer and pays the fee for the whole transaction. | -| `memo` | [string](#string) | | memo is any arbitrary memo to be added to the transaction | -| `timeout_height` | [uint64](#uint64) | | timeout is the block height after which this transaction will not be processed by the chain | -| `extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, the transaction will be rejected | -| `non_critical_extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, they will be ignored | - - - - - - - - -### TxRaw -TxRaw is a variant of Tx that pins the signer's exact binary representation -of body and auth_info. This is used for signing, broadcasting and -verification. The binary `serialize(tx: TxRaw)` is stored in Tendermint and -the hash `sha256(serialize(tx: TxRaw))` becomes the "txhash", commonly used -as the transaction ID. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `body_bytes` | [bytes](#bytes) | | body_bytes is a protobuf serialization of a TxBody that matches the representation in SignDoc. | -| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in SignDoc. | -| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | +| `max_memo_characters` | [uint64](#uint64) | | | +| `tx_sig_limit` | [uint64](#uint64) | | | +| `tx_size_cost_per_byte` | [uint64](#uint64) | | | +| `sig_verify_cost_ed25519` | [uint64](#uint64) | | | +| `sig_verify_cost_secp256k1` | [uint64](#uint64) | | | @@ -938,364 +815,23 @@ as the transaction ID. - +

    Top

    -## cosmos/tx/v1beta1/service.proto +## cosmos/auth/v1beta1/genesis.proto - - -### BroadcastTxRequest -BroadcastTxRequest is the request type for the Service.BroadcastTxRequest -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | -| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | - - - - - - - - -### BroadcastTxResponse -BroadcastTxResponse is the response type for the -Service.BroadcastTx method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - - - - - - - - -### GetTxRequest -GetTxRequest is the request type for the Service.GetTx -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | - - - - - - - - -### GetTxResponse -GetTxResponse is the response type for the Service.GetTx method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the queried transaction. | -| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - - - - - - - - -### GetTxsEventRequest -GetTxsEventRequest is the request type for the Service.TxsByEvents -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `events` | [string](#string) | repeated | events is the list of transaction event type. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - - - - - - - - -### GetTxsEventResponse -GetTxsEventResponse is the response type for the Service.TxsByEvents -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `txs` | [Tx](#cosmos.tx.v1beta1.Tx) | repeated | txs is the list of queried transactions. | -| `tx_responses` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | tx_responses is the list of queried TxResponses. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - - - - - - - - -### SimulateRequest -SimulateRequest is the request type for the Service.Simulate -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | - - - - - - - - -### SimulateResponse -SimulateResponse is the response type for the -Service.SimulateRPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `gas_info` | [cosmos.base.abci.v1beta1.GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | gas_info is the information about gas used in the simulation. | -| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | result is the result of the simulation. | - - - - - - - - - - -### BroadcastMode -BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| BROADCAST_MODE_UNSPECIFIED | 0 | zero-value for mode ordering | -| BROADCAST_MODE_BLOCK | 1 | BROADCAST_MODE_BLOCK defines a tx broadcasting mode where the client waits for the tx to be committed in a block. | -| BROADCAST_MODE_SYNC | 2 | BROADCAST_MODE_SYNC defines a tx broadcasting mode where the client waits for a CheckTx execution response only. | -| BROADCAST_MODE_ASYNC | 3 | BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns immediately. | - - - - - - - - - -### Service -Service defines a gRPC service for interacting with transactions. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Simulate` | [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) | [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) | Simulate simulates executing a transaction for estimating gas usage. | POST|/cosmos/tx/v1beta1/simulate| -| `GetTx` | [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) | [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) | GetTx fetches a tx by hash. | GET|/cosmos/tx/v1beta1/txs/{hash}| -| `BroadcastTx` | [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) | [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) | BroadcastTx broadcast transaction. | POST|/cosmos/tx/v1beta1/txs| -| `GetTxsEvent` | [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) | [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) | GetTxsEvent fetches txs by event. | GET|/cosmos/tx/v1beta1/txs| - - - - - - -

    Top

    - -## cosmos/tx/signing/v1beta1/signing.proto - - - - - -### SignatureDescriptor -SignatureDescriptor is a convenience type which represents the full data for -a signature including the public key of the signer, signing modes and the -signature itself. It is primarily used for coordinating signatures between -clients. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer | -| `data` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | | | -| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | - - - - - - - - -### SignatureDescriptor.Data -Data represents signature data - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `single` | [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) | | single represents a single signer | -| `multi` | [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) | | multi represents a multisig signer | - - - - - - - - -### SignatureDescriptor.Data.Multi -Multi is the signature data for a multisig public key - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | -| `signatures` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | repeated | signatures is the signatures of the multi-signature | - - - - - - - - -### SignatureDescriptor.Data.Single -Single is the signature data for a single signer - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `mode` | [SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | -| `signature` | [bytes](#bytes) | | signature is the raw signature bytes | - - - - - - - - -### SignatureDescriptors -SignatureDescriptors wraps multiple SignatureDescriptor's. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | - - - - - - - - - - -### SignMode -SignMode represents a signing mode with its own security guarantees. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| SIGN_MODE_UNSPECIFIED | 0 | SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected | -| SIGN_MODE_DIRECT | 1 | SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified with raw bytes from Tx | -| SIGN_MODE_TEXTUAL | 2 | SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable textual representation on top of the binary representation from SIGN_MODE_DIRECT | -| SIGN_MODE_LEGACY_AMINO_JSON | 127 | SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses Amino JSON and will be removed in the future | - - - - - - - - - - - -

    Top

    - -## cosmos/crisis/v1beta1/tx.proto - - - - - -### MsgVerifyInvariant -MsgVerifyInvariant represents a message to verify a particular invariance. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `sender` | [string](#string) | | | -| `invariant_module_name` | [string](#string) | | | -| `invariant_route` | [string](#string) | | | - - - - - - - - -### MsgVerifyInvariantResponse -MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. - - - - - - - - - - - - - - -### Msg -Msg defines the bank Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `VerifyInvariant` | [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) | [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) | VerifyInvariant defines a method to verify a particular invariance. | | - - - - - - -

    Top

    - -## cosmos/crisis/v1beta1/genesis.proto - - - - + ### GenesisState -GenesisState defines the crisis module's genesis state. +GenesisState defines the auth module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `constant_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | constant_fee is the fee used to verify the invariant in the crisis module. | +| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines all the paramaters of the module. | +| `accounts` | [google.protobuf.Any](#google.protobuf.Any) | repeated | accounts are the accounts present at genesis. | @@ -1311,253 +847,44 @@ GenesisState defines the crisis module's genesis state. - +

    Top

    -## cosmos/crypto/multisig/keys.proto +## cosmos/auth/v1beta1/query.proto - + -### LegacyAminoPubKey -LegacyAminoPubKey specifies a public key type -which nests multiple public keys and a threshold, -it uses legacy amino address rules. +### QueryAccountRequest +QueryAccountRequest is the request type for the Query/Account RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `threshold` | [uint32](#uint32) | | | -| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | +| `address` | [string](#string) | | address defines the address to query for. | - - + - - - - - - - -

    Top

    - -## cosmos/crypto/multisig/v1beta1/multisig.proto - - - - - -### CompactBitArray -CompactBitArray is an implementation of a space efficient bit array. -This is used to ensure that the encoded data takes up a minimal amount of -space after proto encoding. -This is not thread safe, and is not intended for concurrent usage. +### QueryAccountResponse +QueryAccountResponse is the response type for the Query/Account RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `extra_bits_stored` | [uint32](#uint32) | | | -| `elems` | [bytes](#bytes) | | | +| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | - - -### MultiSignature -MultiSignature wraps the signatures from a multisig.LegacyAminoPubKey. -See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers -signed and with which modes. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signatures` | [bytes](#bytes) | repeated | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/crypto/secp256k1/keys.proto - - - - - -### PrivKey -PrivKey defines a secp256k1 private key. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | - - - - - - - - -### PubKey -PubKey defines a secp256k1 public key -Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -if the y-coordinate is the lexicographically largest of the two associated with -the x-coordinate. Otherwise the first byte is a 0x03. -This prefix is followed with the x-coordinate. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/crypto/ed25519/keys.proto - - - - - -### PrivKey -PrivKey defines a ed25519 private key. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | - - - - - - - - -### PubKey -PubKey defines a ed25519 public key -Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte -if the y-coordinate is the lexicographically largest of the two associated with -the x-coordinate. Otherwise the first byte is a 0x03. -This prefix is followed with the x-coordinate. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/mint/v1beta1/query.proto - - - - - -### QueryAnnualProvisionsRequest -QueryAnnualProvisionsRequest is the request type for the -Query/AnnualProvisions RPC method. - - - - - - - - -### QueryAnnualProvisionsResponse -QueryAnnualProvisionsResponse is the response type for the -Query/AnnualProvisions RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | - - - - - - - - -### QueryInflationRequest -QueryInflationRequest is the request type for the Query/Inflation RPC method. - - - - - - - - -### QueryInflationResponse -QueryInflationResponse is the response type for the Query/Inflation RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | - - - - - - - + ### QueryParamsRequest QueryParamsRequest is the request type for the Query/Params RPC method. @@ -1567,7 +894,7 @@ QueryParamsRequest is the request type for the Query/Params RPC method. - + ### QueryParamsResponse QueryParamsResponse is the response type for the Query/Params RPC method. @@ -1575,7 +902,7 @@ QueryParamsResponse is the response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | +| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines the parameters of the module. | @@ -1588,38 +915,89 @@ QueryParamsResponse is the response type for the Query/Params RPC method. - + ### Query -Query provides defines the gRPC querier service. +Query defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Params` | [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) | Params returns the total set of minting parameters. | GET|/cosmos/mint/v1beta1/params| -| `Inflation` | [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) | [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) | Inflation returns the current minting inflation value. | GET|/cosmos/mint/v1beta1/inflation| -| `AnnualProvisions` | [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) | [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) | AnnualProvisions current minting annual provisions value. | GET|/cosmos/mint/v1beta1/annual_provisions| +| `Account` | [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) | [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) | Account returns account details based on address. | GET|/cosmos/auth/v1beta1/accounts/{address}| +| `Params` | [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) | Params queries all parameters. | GET|/cosmos/auth/v1beta1/params| - +

    Top

    -## cosmos/mint/v1beta1/genesis.proto +## cosmos/base/v1beta1/coin.proto - + -### GenesisState -GenesisState defines the mint module's genesis state. +### Coin +Coin defines a token with a denomination and an amount. + +NOTE: The amount field is an Int which implements the custom method +signatures required by gogoproto. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `minter` | [Minter](#cosmos.mint.v1beta1.Minter) | | minter is a space for holding current inflation information. | -| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines all the paramaters of the module. | +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | + + + + + + + + +### DecCoin +DecCoin defines a token with a denomination and a decimal amount. + +NOTE: The amount field is an Dec which implements the custom method +signatures required by gogoproto. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `denom` | [string](#string) | | | +| `amount` | [string](#string) | | | + + + + + + + + +### DecProto +DecProto defines a Protobuf wrapper around a Dec object. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `dec` | [string](#string) | | | + + + + + + + + +### IntProto +IntProto defines a Protobuf wrapper around an Int object. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `int` | [string](#string) | | | @@ -1635,147 +1013,56 @@ GenesisState defines the mint module's genesis state. - +

    Top

    -## cosmos/mint/v1beta1/mint.proto +## cosmos/authz/v1beta1/authz.proto - + -### Minter -Minter represents the minting state. +### AuthorizationGrant +AuthorizationGrant gives permissions to execute +the provide method with expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `inflation` | [string](#string) | | current annual inflation rate | -| `annual_provisions` | [string](#string) | | current annual expected provisions | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### Params -Params holds parameters for the mint module. +### GenericAuthorization +GenericAuthorization gives the grantee unrestricted permissions to execute +the provided method on behalf of the granter's account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `mint_denom` | [string](#string) | | type of coin to mint | -| `inflation_rate_change` | [string](#string) | | maximum annual change in inflation rate | -| `inflation_max` | [string](#string) | | maximum inflation rate | -| `inflation_min` | [string](#string) | | minimum inflation rate | -| `goal_bonded` | [string](#string) | | goal of percent bonded atoms | -| `blocks_per_year` | [uint64](#uint64) | | expected blocks per year | +| `method_name` | [string](#string) | | method name to grant unrestricted permissions to execute Note: MethodName() is already a method on `GenericAuthorization` type, we need some custom naming here so using `MessageName` | - - + - - - - - - - -

    Top

    - -## cosmos/feegrant/v1beta1/feegrant.proto - - - - - -### BasicFeeAllowance -BasicFeeAllowance implements FeeAllowance with a one-time grant of tokens -that optionally expires. The delegatee can use up to SpendLimit to cover fees. +### SendAuthorization +SendAuthorization allows the grantee to spend up to spend_limit coins from +the granter's account. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `expiration` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | | - - - - - - - - -### Duration -Duration is a span of a clock time or number of blocks. -This is designed to be added to an ExpiresAt struct. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | -| `blocks` | [uint64](#uint64) | | | - - - - - - - - -### ExpiresAt -ExpiresAt is a point in time where something expires. -It may be *either* block time or block height - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `height` | [int64](#int64) | | | - - - - - - - - -### FeeAllowanceGrant -FeeAllowanceGrant is stored in the KVStore to record a grant with full context - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | - - - - - - - - -### PeriodicFeeAllowance -PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, -as well as a limit per time period. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `basic` | [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) | | | -| `period` | [Duration](#cosmos.feegrant.v1beta1.Duration) | | | -| `period_spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `period_can_spend` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `period_reset` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | | @@ -1791,52 +1078,480 @@ as well as a limit per time period. - +

    Top

    -## cosmos/feegrant/v1beta1/query.proto +## cosmos/base/abci/v1beta1/abci.proto - + -### QueryFeeAllowanceRequest -QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. +### ABCIMessageLog +ABCIMessageLog defines a structure containing an indexed tx ABCI message log. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `msg_index` | [uint32](#uint32) | | | +| `log` | [string](#string) | | | +| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | + + + + + + + + +### Attribute +Attribute defines an attribute wrapper where the key and value are +strings instead of raw bytes. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [string](#string) | | | +| `value` | [string](#string) | | | + + + + + + + + +### GasInfo +GasInfo defines tx execution gas context. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | +| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | + + + + + + + + +### MsgData +MsgData defines the data returned in a Result object during message +execution. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `msg_type` | [string](#string) | | | +| `data` | [bytes](#bytes) | | | + + + + + + + + +### Result +Result is the union of ResponseFormat and ResponseCheckTx. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | +| `log` | [string](#string) | | Log contains the log information from message or handler execution. | +| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | + + + + + + + + +### SearchTxsResult +SearchTxsResult defines a structure for querying txs pageable + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `total_count` | [uint64](#uint64) | | Count of all txs | +| `count` | [uint64](#uint64) | | Count of txs in current page | +| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | +| `page_total` | [uint64](#uint64) | | Count of total pages | +| `limit` | [uint64](#uint64) | | Max count txs per page | +| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | + + + + + + + + +### SimulationResponse +SimulationResponse defines the response generated when a transaction is +successfully simulated. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | +| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | + + + + + + + + +### StringEvent +StringEvent defines en Event object wrapper where all the attributes +contain key/value pairs that are strings instead of raw bytes. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `type` | [string](#string) | | | +| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | + + + + + + + + +### TxMsgData +TxMsgData defines a list of MsgData. A transaction will have a MsgData object +for each message. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | + + + + + + + + +### TxResponse +TxResponse defines a structure containing relevant tx data and metadata. The +tags are stringified and the log is JSON decoded. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | The block height | +| `txhash` | [string](#string) | | The transaction hash. | +| `codespace` | [string](#string) | | Namespace for the Code | +| `code` | [uint32](#uint32) | | Response code. | +| `data` | [string](#string) | | Result bytes, if any. | +| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | +| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | +| `info` | [string](#string) | | Additional information. May be non-deterministic. | +| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | +| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | +| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | +| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/authz/v1beta1/tx.proto + + + + + +### MsgExecAuthorizedRequest +MsgExecAuthorizedRequest attempts to execute the provided messages using +authorizations granted to the grantee. Each message should have only +one signer corresponding to the granter of the authorization. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `grantee` | [string](#string) | | | +| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | + + + + + + + + +### MsgExecAuthorizedResponse +MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | + + + + + + + + +### MsgGrantAuthorizationRequest +MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's +account with the provided expiration time. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `granter` | [string](#string) | | | | `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - + -### QueryFeeAllowanceResponse -QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. +### MsgGrantAuthorizationResponse +MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. + + + + + + + + +### MsgRevokeAuthorizationRequest +MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the +granter's account with that has been granted to the grantee. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `fee_allowance` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | | fee_allowance is a fee_allowance granted for grantee by granter. | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | - + -### QueryFeeAllowancesRequest -QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. +### MsgRevokeAuthorizationResponse +MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. + + + + + + + + + + + + + + +### Msg +Msg defines the authz Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `GrantAuthorization` | [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) | [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) | GrantAuthorization grants the provided authorization to the grantee on the granter's account with the provided expiration time. | | +| `ExecAuthorized` | [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) | [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) | ExecAuthorized attempts to execute the provided messages using authorizations granted to the grantee. Each message should have only one signer corresponding to the granter of the authorization. | | +| `RevokeAuthorization` | [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) | [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) | RevokeAuthorization revokes any authorization corresponding to the provided method name on the granter's account that has been granted to the grantee. | | + + + + + + +

    Top

    + +## cosmos/authz/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the authz module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | +| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | + + + + + + + + +### GrantAuthorization +GrantAuthorization defines the GenesisState/GrantAuthorization type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/base/query/v1beta1/pagination.proto + + + + + +### PageRequest +PageRequest is to be embedded in gRPC request messages for efficient +pagination. Ex: + + message SomeRequest { + Foo some_parameter = 1; + PageRequest pagination = 2; + } + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | +| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | +| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | +| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | + + + + + + + + +### PageResponse +PageResponse is to be embedded in gRPC response messages where the +corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | +| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/authz/v1beta1/query.proto + + + + + +### QueryAuthorizationRequest +QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `method_name` | [string](#string) | | | + + + + + + + + +### QueryAuthorizationResponse +QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | + + + + + + + + +### QueryAuthorizationsRequest +QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | | `grantee` | [string](#string) | | | | `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | @@ -1845,15 +1560,15 @@ QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC me - + -### QueryFeeAllowancesResponse -QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. +### QueryAuthorizationsResponse +QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | fee_allowances are fee_allowance's granted for grantee by granter. | +| `authorizations` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | repeated | authorizations is a list of grants granted for grantee by granter. | | `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | @@ -1867,240 +1582,15 @@ QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC - + ### Query Query defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `FeeAllowance` | [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) | [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) | FeeAllowance returns fee granted to the grantee by the granter. | GET|/cosmos/feegrant/v1beta1/fee_allowance/{granter}/{grantee}| -| `FeeAllowances` | [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) | [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) | FeeAllowances returns all the grants for address. | GET|/cosmos/feegrant/v1beta1/fee_allowances/{grantee}| - - - - - - -

    Top

    - -## cosmos/feegrant/v1beta1/tx.proto - - - - - -### MsgGrantFeeAllowance -MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance -of fees from the account of Granter. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | - - - - - - - - -### MsgGrantFeeAllowanceResponse -MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. - - - - - - - - -### MsgRevokeFeeAllowance -MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | - - - - - - - - -### MsgRevokeFeeAllowanceResponse -MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. - - - - - - - - - - - - - - -### Msg -Msg defines the feegrant msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `GrantFeeAllowance` | [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) | [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) | GrantFeeAllowance grants fee allowance to the grantee on the granter's account with the provided expiration time. | | -| `RevokeFeeAllowance` | [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) | [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) | RevokeFeeAllowance revokes any fee allowance of granter's account that has been granted to the grantee. | | - - - - - - -

    Top

    - -## cosmos/feegrant/v1beta1/genesis.proto - - - - - -### GenesisState -GenesisState contains a set of fee allowances, persisted from the store - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/capability/v1beta1/capability.proto - - - - - -### Capability -Capability defines an implementation of an object capability. The index -provided to a Capability must be globally unique. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | | - - - - - - - - -### CapabilityOwners -CapabilityOwners defines a set of owners of a single Capability. The set of -owners must be unique. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | - - - - - - - - -### Owner -Owner defines a single capability owner. An owner is defined by the name of -capability and the module name. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `module` | [string](#string) | | | -| `name` | [string](#string) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/capability/v1beta1/genesis.proto - - - - - -### GenesisOwners -GenesisOwners defines the capability owners with their corresponding index. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | index is the index of the capability owner. | -| `index_owners` | [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) | | index_owners are the owners at the given index. | - - - - - - - - -### GenesisState -GenesisState defines the capability module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `index` | [uint64](#uint64) | | index is the capability global index. | -| `owners` | [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) | repeated | owners represents a map from index to owners of the capability index index key is string to allow amino marshalling. | - - - - - - - - - - +| `Authorization` | [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) | [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) | Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the provided msg type. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant| +| `Authorizations` | [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) | [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants| @@ -2230,6 +1720,57 @@ amounts in the network. + + + + + + + + + + + +

    Top

    + +## cosmos/bank/v1beta1/genesis.proto + + + + + +### Balance +Balance defines an account address and balance pair used in the bank module's +genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address is the address of the balance holder. | +| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | coins defines the different coins this balance holds. | + + + + + + + + +### GenesisState +GenesisState defines the bank module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. | +| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. | +| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. | +| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. | + + + + + @@ -2561,42 +2102,38 @@ Msg defines the bank Msg service. - +

    Top

    -## cosmos/bank/v1beta1/genesis.proto +## cosmos/base/kv/v1beta1/kv.proto - + -### Balance -Balance defines an account address and balance pair used in the bank module's -genesis state. +### Pair +Pair defines a key/value bytes tuple. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address of the balance holder. | -| `coins` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | coins defines the different coins this balance holds. | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | - + -### GenesisState -GenesisState defines the bank module's genesis state. +### Pairs +Pairs defines a repeated slice of Pair objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. | -| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. | -| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. | -| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. | +| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | @@ -2612,56 +2149,125 @@ GenesisState defines the bank module's genesis state. - +

    Top

    -## cosmos/authz/v1beta1/authz.proto +## cosmos/base/reflection/v1beta1/reflection.proto - + -### AuthorizationGrant -AuthorizationGrant gives permissions to execute -the provide method with expiration time. +### ListAllInterfacesRequest +ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. + + + + + + + + +### ListAllInterfacesResponse +ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | - + -### GenericAuthorization -GenericAuthorization gives the grantee unrestricted permissions to execute -the provided method on behalf of the granter's account. +### ListImplementationsRequest +ListImplementationsRequest is the request type of the ListImplementations +RPC. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `method_name` | [string](#string) | | method name to grant unrestricted permissions to execute Note: MethodName() is already a method on `GenericAuthorization` type, we need some custom naming here so using `MessageName` | +| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | - + -### SendAuthorization -SendAuthorization allows the grantee to spend up to spend_limit coins from -the granter's account. +### ListImplementationsResponse +ListImplementationsResponse is the response type of the ListImplementations +RPC. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `implementation_message_names` | [string](#string) | repeated | | + + + + + + + + + + + + + + +### ReflectionService +ReflectionService defines a service for interface reflection. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ListAllInterfaces` | [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) | [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) | ListAllInterfaces lists all the interfaces registered in the interface registry. | GET|/cosmos/base/reflection/v1beta1/interfaces| +| `ListImplementations` | [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) | [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) | ListImplementations list all the concrete types that implement a given interface. | GET|/cosmos/base/reflection/v1beta1/interfaces/{interface_name}/implementations| + + + + + + +

    Top

    + +## cosmos/base/snapshots/v1beta1/snapshot.proto + + + + + +### Metadata +Metadata contains SDK-specific snapshot metadata. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | + + + + + + + + +### Snapshot +Snapshot contains Tendermint state sync snapshot info. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [uint64](#uint64) | | | +| `format` | [uint32](#uint32) | | | +| `chunks` | [uint32](#uint32) | | | +| `hash` | [bytes](#bytes) | | | +| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | @@ -2677,55 +2283,210 @@ the granter's account. - +

    Top

    -## cosmos/authz/v1beta1/query.proto +## cosmos/base/store/v1beta1/commit_info.proto - + -### QueryAuthorizationRequest -QueryAuthorizationRequest is the request type for the Query/Authorization RPC method. +### CommitID +CommitID defines the committment information when a specific store is +committed. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | +| `version` | [int64](#int64) | | | +| `hash` | [bytes](#bytes) | | | - + -### QueryAuthorizationResponse -QueryAuthorizationResponse is the response type for the Query/Authorization RPC method. +### CommitInfo +CommitInfo defines commit information used by the multi-store when committing +a version/height. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | | authorization is a authorization granted for grantee by granter. | +| `version` | [int64](#int64) | | | +| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | - + -### QueryAuthorizationsRequest -QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC method. +### StoreInfo +StoreInfo defines store-specific commit information. It contains a reference +between a store name and the commit ID. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `name` | [string](#string) | | | +| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/base/store/v1beta1/snapshot.proto + + + + + +### SnapshotIAVLItem +SnapshotIAVLItem is an exported IAVL node. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | +| `value` | [bytes](#bytes) | | | +| `version` | [int64](#int64) | | | +| `height` | [int32](#int32) | | | + + + + + + + + +### SnapshotItem +SnapshotItem is an item contained in a rootmulti.Store snapshot. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | +| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | + + + + + + + + +### SnapshotStoreItem +SnapshotStoreItem contains metadata about a snapshotted store. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `name` | [string](#string) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/base/tendermint/v1beta1/query.proto + + + + + +### GetBlockByHeightRequest +GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | | + + + + + + + + +### GetBlockByHeightResponse +GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | +| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | + + + + + + + + +### GetLatestBlockRequest +GetLatestBlockRequest is the request type for the Query/GetLatestBlock RPC method. + + + + + + + + +### GetLatestBlockResponse +GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | +| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | + + + + + + + + +### GetLatestValidatorSetRequest +GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | | `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | @@ -2733,133 +2494,157 @@ QueryAuthorizationsRequest is the request type for the Query/Authorizations RPC - + -### QueryAuthorizationsResponse -QueryAuthorizationsResponse is the response type for the Query/Authorizations RPC method. +### GetLatestValidatorSetResponse +GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorizations` | [AuthorizationGrant](#cosmos.authz.v1beta1.AuthorizationGrant) | repeated | authorizations is a list of grants granted for grantee by granter. | +| `block_height` | [int64](#int64) | | | +| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | | `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - - + - - - - - -### Query -Query defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Authorization` | [QueryAuthorizationRequest](#cosmos.authz.v1beta1.QueryAuthorizationRequest) | [QueryAuthorizationResponse](#cosmos.authz.v1beta1.QueryAuthorizationResponse) | Returns any `Authorization` (or `nil`), with the expiration time, granted to the grantee by the granter for the provided msg type. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grant| -| `Authorizations` | [QueryAuthorizationsRequest](#cosmos.authz.v1beta1.QueryAuthorizationsRequest) | [QueryAuthorizationsResponse](#cosmos.authz.v1beta1.QueryAuthorizationsResponse) | Returns list of `Authorization`, granted to the grantee by the granter. | GET|/cosmos/authz/v1beta1/granters/{granter}/grantees/{grantee}/grants| - - +### GetNodeInfoRequest +GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. - -

    Top

    - -## cosmos/authz/v1beta1/tx.proto - + -### MsgExecAuthorizedRequest -MsgExecAuthorizedRequest attempts to execute the provided messages using -authorizations granted to the grantee. Each message should have only -one signer corresponding to the granter of the authorization. +### GetNodeInfoResponse +GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `grantee` | [string](#string) | | | -| `msgs` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | +| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | +| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | - + -### MsgExecAuthorizedResponse -MsgExecAuthorizedResponse defines the Msg/MsgExecAuthorizedResponse response type. +### GetSyncingRequest +GetSyncingRequest is the request type for the Query/GetSyncing RPC method. + + + + + + + + +### GetSyncingResponse +GetSyncingResponse is the response type for the Query/GetSyncing RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | | +| `syncing` | [bool](#bool) | | | - + -### MsgGrantAuthorizationRequest -MsgGrantAuthorizationRequest grants the provided authorization to the grantee on the granter's -account with the provided expiration time. +### GetValidatorSetByHeightRequest +GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `height` | [int64](#int64) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### MsgGrantAuthorizationResponse -MsgGrantAuthorizationResponse defines the Msg/MsgGrantAuthorization response type. - - - - - - - - -### MsgRevokeAuthorizationRequest -MsgRevokeAuthorizationRequest revokes any authorization with the provided sdk.Msg type on the -granter's account with that has been granted to the grantee. +### GetValidatorSetByHeightResponse +GetValidatorSetByHeightResponse is the response type for the Query/GetValidatorSetByHeight RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `method_name` | [string](#string) | | | +| `block_height` | [int64](#int64) | | | +| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - + -### MsgRevokeAuthorizationResponse -MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse response type. +### Module +Module is the type for VersionInfo + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `path` | [string](#string) | | module path | +| `version` | [string](#string) | | module version | +| `sum` | [string](#string) | | checksum | + + + + + + + + +### Validator +Validator is the type for the validator-set. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | | +| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `voting_power` | [int64](#int64) | | | +| `proposer_priority` | [int64](#int64) | | | + + + + + + + + +### VersionInfo +VersionInfo is the type for the GetNodeInfoResponse message. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `name` | [string](#string) | | | +| `app_name` | [string](#string) | | | +| `version` | [string](#string) | | | +| `git_commit` | [string](#string) | | | +| `build_tags` | [string](#string) | | | +| `go_version` | [string](#string) | | | +| `build_deps` | [Module](#cosmos.base.tendermint.v1beta1.Module) | repeated | | @@ -2872,55 +2657,122 @@ MsgRevokeAuthorizationResponse defines the Msg/MsgRevokeAuthorizationResponse re - + -### Msg -Msg defines the authz Msg service. +### Service +Service defines the gRPC querier service for tendermint queries. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `GrantAuthorization` | [MsgGrantAuthorizationRequest](#cosmos.authz.v1beta1.MsgGrantAuthorizationRequest) | [MsgGrantAuthorizationResponse](#cosmos.authz.v1beta1.MsgGrantAuthorizationResponse) | GrantAuthorization grants the provided authorization to the grantee on the granter's account with the provided expiration time. | | -| `ExecAuthorized` | [MsgExecAuthorizedRequest](#cosmos.authz.v1beta1.MsgExecAuthorizedRequest) | [MsgExecAuthorizedResponse](#cosmos.authz.v1beta1.MsgExecAuthorizedResponse) | ExecAuthorized attempts to execute the provided messages using authorizations granted to the grantee. Each message should have only one signer corresponding to the granter of the authorization. | | -| `RevokeAuthorization` | [MsgRevokeAuthorizationRequest](#cosmos.authz.v1beta1.MsgRevokeAuthorizationRequest) | [MsgRevokeAuthorizationResponse](#cosmos.authz.v1beta1.MsgRevokeAuthorizationResponse) | RevokeAuthorization revokes any authorization corresponding to the provided method name on the granter's account that has been granted to the grantee. | | +| `GetNodeInfo` | [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) | [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) | GetNodeInfo queries the current node info. | GET|/cosmos/base/tendermint/v1beta1/node_info| +| `GetSyncing` | [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) | [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) | GetSyncing queries node syncing. | GET|/cosmos/base/tendermint/v1beta1/syncing| +| `GetLatestBlock` | [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) | [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) | GetLatestBlock returns the latest block. | GET|/cosmos/base/tendermint/v1beta1/blocks/latest| +| `GetBlockByHeight` | [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) | [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) | GetBlockByHeight queries block for given height. | GET|/cosmos/base/tendermint/v1beta1/blocks/{height}| +| `GetLatestValidatorSet` | [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) | [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) | GetLatestValidatorSet queries latest validator-set. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/latest| +| `GetValidatorSetByHeight` | [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) | [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) | GetValidatorSetByHeight queries validator-set at a given height. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/{height}| - +

    Top

    -## cosmos/authz/v1beta1/genesis.proto +## cosmos/capability/v1beta1/capability.proto - + + +### Capability +Capability defines an implementation of an object capability. The index +provided to a Capability must be globally unique. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `index` | [uint64](#uint64) | | | + + + + + + + + +### CapabilityOwners +CapabilityOwners defines a set of owners of a single Capability. The set of +owners must be unique. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `owners` | [Owner](#cosmos.capability.v1beta1.Owner) | repeated | | + + + + + + + + +### Owner +Owner defines a single capability owner. An owner is defined by the name of +capability and the module name. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `module` | [string](#string) | | | +| `name` | [string](#string) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/capability/v1beta1/genesis.proto + + + + + +### GenesisOwners +GenesisOwners defines the capability owners with their corresponding index. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `index` | [uint64](#uint64) | | index is the index of the capability owner. | +| `index_owners` | [CapabilityOwners](#cosmos.capability.v1beta1.CapabilityOwners) | | index_owners are the owners at the given index. | + + + + + + + ### GenesisState -GenesisState defines the authz module's genesis state. +GenesisState defines the capability module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `authorization` | [GrantAuthorization](#cosmos.authz.v1beta1.GrantAuthorization) | repeated | | - - - - - - - - -### GrantAuthorization -GrantAuthorization defines the GenesisState/GrantAuthorization type. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `granter` | [string](#string) | | | -| `grantee` | [string](#string) | | | -| `authorization` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `expiration` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `index` | [uint64](#uint64) | | index is the capability global index. | +| `owners` | [GenesisOwners](#cosmos.capability.v1beta1.GenesisOwners) | repeated | owners represents a map from index to owners of the capability index index key is string to allow amino marshalling. | @@ -2936,149 +2788,22 @@ GrantAuthorization defines the GenesisState/GrantAuthorization type. - +

    Top

    -## cosmos/gov/v1beta1/gov.proto +## cosmos/crisis/v1beta1/genesis.proto - + -### Deposit -Deposit defines an amount deposited by an account address to an active -proposal. +### GenesisState +GenesisState defines the crisis module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - - - - - - - -### DepositParams -DepositParams defines the params for deposits on governance proposals. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `min_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Minimum deposit for a proposal to enter voting period. | -| `max_deposit_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months. | - - - - - - - - -### Proposal -Proposal defines the core field members of a governance proposal. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | | -| `final_tally_result` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | | -| `submit_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `deposit_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `total_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `voting_start_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `voting_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | - - - - - - - - -### TallyParams -TallyParams defines the params for tallying votes on governance proposals. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `quorum` | [bytes](#bytes) | | Minimum percentage of total stake needed to vote for a result to be considered valid. | -| `threshold` | [bytes](#bytes) | | Minimum proportion of Yes votes for proposal to pass. Default value: 0.5. | -| `veto_threshold` | [bytes](#bytes) | | Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Default value: 1/3. | - - - - - - - - -### TallyResult -TallyResult defines a standard tally for a governance proposal. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `yes` | [string](#string) | | | -| `abstain` | [string](#string) | | | -| `no` | [string](#string) | | | -| `no_with_veto` | [string](#string) | | | - - - - - - - - -### TextProposal -TextProposal defines a standard text proposal whose changes need to be -manually updated in case of approval. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | - - - - - - - - -### Vote -Vote defines a vote on a governance proposal. -A Vote consists of a proposal ID, the voter, and the vote option. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - - - - - - - - -### VotingParams -VotingParams defines the params for voting on governance proposals. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. | +| `constant_fee` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | constant_fee is the fee used to verify the invariant in the crisis module. | @@ -3086,37 +2811,6 @@ VotingParams defines the params for voting on governance proposals. - - - -### ProposalStatus -ProposalStatus enumerates the valid statuses of a proposal. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| PROPOSAL_STATUS_UNSPECIFIED | 0 | PROPOSAL_STATUS_UNSPECIFIED defines the default propopsal status. | -| PROPOSAL_STATUS_DEPOSIT_PERIOD | 1 | PROPOSAL_STATUS_DEPOSIT_PERIOD defines a proposal status during the deposit period. | -| PROPOSAL_STATUS_VOTING_PERIOD | 2 | PROPOSAL_STATUS_VOTING_PERIOD defines a proposal status during the voting period. | -| PROPOSAL_STATUS_PASSED | 3 | PROPOSAL_STATUS_PASSED defines a proposal status of a proposal that has passed. | -| PROPOSAL_STATUS_REJECTED | 4 | PROPOSAL_STATUS_REJECTED defines a proposal status of a proposal that has been rejected. | -| PROPOSAL_STATUS_FAILED | 5 | PROPOSAL_STATUS_FAILED defines a proposal status of a proposal that has failed. | - - - - - -### VoteOption -VoteOption enumerates the valid vote options for a given governance proposal. - -| Name | Number | Description | -| ---- | ------ | ----------- | -| VOTE_OPTION_UNSPECIFIED | 0 | VOTE_OPTION_UNSPECIFIED defines a no-op vote option. | -| VOTE_OPTION_YES | 1 | VOTE_OPTION_YES defines a yes vote option. | -| VOTE_OPTION_ABSTAIN | 2 | VOTE_OPTION_ABSTAIN defines an abstain vote option. | -| VOTE_OPTION_NO | 3 | VOTE_OPTION_NO defines a no vote option. | -| VOTE_OPTION_NO_WITH_VETO | 4 | VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. | - - @@ -3125,260 +2819,34 @@ VoteOption enumerates the valid vote options for a given governance proposal. - +

    Top

    -## cosmos/gov/v1beta1/query.proto +## cosmos/crisis/v1beta1/tx.proto - + -### QueryDepositRequest -QueryDepositRequest is the request type for the Query/Deposit RPC method. +### MsgVerifyInvariant +MsgVerifyInvariant represents a message to verify a particular invariance. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | +| `sender` | [string](#string) | | | +| `invariant_module_name` | [string](#string) | | | +| `invariant_route` | [string](#string) | | | - + -### QueryDepositResponse -QueryDepositResponse is the response type for the Query/Deposit RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | - - - - - - - - -### QueryDepositsRequest -QueryDepositsRequest is the request type for the Query/Deposits RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - - - - - - - -### QueryDepositsResponse -QueryDepositsResponse is the response type for the Query/Deposits RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - - - - - - - - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | - - - - - - - - -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | voting_params defines the parameters related to voting. | -| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | deposit_params defines the parameters related to deposit. | -| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | tally_params defines the parameters related to tally. | - - - - - - - - -### QueryProposalRequest -QueryProposalRequest is the request type for the Query/Proposal RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - - - - - - - - -### QueryProposalResponse -QueryProposalResponse is the response type for the Query/Proposal RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | - - - - - - - - -### QueryProposalsRequest -QueryProposalsRequest is the request type for the Query/Proposals RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | proposal_status defines the status of the proposals. | -| `voter` | [string](#string) | | voter defines the voter address for the proposals. | -| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - - - - - - - -### QueryProposalsResponse -QueryProposalsResponse is the response type for the Query/Proposals RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - - - - - - - - -### QueryTallyResultRequest -QueryTallyResultRequest is the request type for the Query/Tally RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - - - - - - - - -### QueryTallyResultResponse -QueryTallyResultResponse is the response type for the Query/Tally RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | - - - - - - - - -### QueryVoteRequest -QueryVoteRequest is the request type for the Query/Vote RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `voter` | [string](#string) | | voter defines the oter address for the proposals. | - - - - - - - - -### QueryVoteResponse -QueryVoteResponse is the response type for the Query/Vote RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | - - - - - - - - -### QueryVotesRequest -QueryVotesRequest is the request type for the Query/Votes RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | - - - - - - - - -### QueryVotesResponse -QueryVotesResponse is the response type for the Query/Votes RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defined the queried votes. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +### MsgVerifyInvariantResponse +MsgVerifyInvariantResponse defines the Msg/VerifyInvariant response type. @@ -3391,163 +2859,54 @@ QueryVotesResponse is the response type for the Query/Votes RPC method. - - -### Query -Query defines the gRPC querier service for gov module - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Proposal` | [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) | [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) | Proposal queries proposal details based on ProposalID. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}| -| `Proposals` | [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) | [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) | Proposals queries all proposals based on given status. | GET|/cosmos/gov/v1beta1/proposals| -| `Vote` | [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) | [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) | Vote queries voted information based on proposalID, voterAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}| -| `Votes` | [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) | [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) | Votes queries votes of a given proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes| -| `Params` | [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) | Params queries all parameters of the gov module. | GET|/cosmos/gov/v1beta1/params/{params_type}| -| `Deposit` | [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) | [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) | Deposit queries single deposit information based proposalID, depositAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}| -| `Deposits` | [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) | [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) | Deposits queries all deposits of a single proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits| -| `TallyResult` | [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) | [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) | TallyResult queries the tally of a proposal vote. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/tally| - - - - - - -

    Top

    - -## cosmos/gov/v1beta1/tx.proto - - - - - -### MsgDeposit -MsgDeposit defines a message to submit a deposit to an existing proposal. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `depositor` | [string](#string) | | | -| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - - - - - - - - -### MsgDepositResponse -MsgDepositResponse defines the Msg/Deposit response type. - - - - - - - - -### MsgSubmitProposal -MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary -proposal Content. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `initial_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | -| `proposer` | [string](#string) | | | - - - - - - - - -### MsgSubmitProposalResponse -MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | - - - - - - - - -### MsgVote -MsgVote defines a message to cast a vote. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `proposal_id` | [uint64](#uint64) | | | -| `voter` | [string](#string) | | | -| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - - - - - - - - -### MsgVoteResponse -MsgVoteResponse defines the Msg/Vote response type. - - - - - - - - - - - - - + ### Msg Msg defines the bank Msg service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SubmitProposal` | [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) | [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) | SubmitProposal defines a method to create new proposal given a content. | | -| `Vote` | [MsgVote](#cosmos.gov.v1beta1.MsgVote) | [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) | Vote defines a method to add a vote on a specific proposal. | | -| `Deposit` | [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) | [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) | Deposit defines a method to add deposit on a specific proposal. | | +| `VerifyInvariant` | [MsgVerifyInvariant](#cosmos.crisis.v1beta1.MsgVerifyInvariant) | [MsgVerifyInvariantResponse](#cosmos.crisis.v1beta1.MsgVerifyInvariantResponse) | VerifyInvariant defines a method to verify a particular invariance. | | - +

    Top

    -## cosmos/gov/v1beta1/genesis.proto +## cosmos/crypto/ed25519/keys.proto - + -### GenesisState -GenesisState defines the gov module's genesis state. +### PrivKey +PrivKey defines a ed25519 private key. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `starting_proposal_id` | [uint64](#uint64) | | starting_proposal_id is the ID of the starting proposal. | -| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | deposits defines all the deposits present at genesis. | -| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defines all the votes present at genesis. | -| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | proposals defines all the proposals present at genesis. | -| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | params defines all the paramaters of related to deposit. | -| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | params defines all the paramaters of related to voting. | -| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | params defines all the paramaters of related to tally. | +| `key` | [bytes](#bytes) | | | + + + + + + + + +### PubKey +PubKey defines a ed25519 public key +Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte +if the y-coordinate is the lexicographically largest of the two associated with +the x-coordinate. Otherwise the first byte is a 0x03. +This prefix is followed with the x-coordinate. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | @@ -3563,22 +2922,526 @@ GenesisState defines the gov module's genesis state. - +

    Top

    -## cosmos/genutil/v1beta1/genesis.proto +## cosmos/crypto/multisig/keys.proto - + -### GenesisState -GenesisState defines the raw genesis transaction in JSON. +### LegacyAminoPubKey +LegacyAminoPubKey specifies a public key type +which nests multiple public keys and a threshold, +it uses legacy amino address rules. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | +| `threshold` | [uint32](#uint32) | | | +| `public_keys` | [google.protobuf.Any](#google.protobuf.Any) | repeated | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/crypto/multisig/v1beta1/multisig.proto + + + + + +### CompactBitArray +CompactBitArray is an implementation of a space efficient bit array. +This is used to ensure that the encoded data takes up a minimal amount of +space after proto encoding. +This is not thread safe, and is not intended for concurrent usage. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `extra_bits_stored` | [uint32](#uint32) | | | +| `elems` | [bytes](#bytes) | | | + + + + + + + + +### MultiSignature +MultiSignature wraps the signatures from a multisig.LegacyAminoPubKey. +See cosmos.tx.v1betata1.ModeInfo.Multi for how to specify which signers +signed and with which modes. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `signatures` | [bytes](#bytes) | repeated | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/crypto/secp256k1/keys.proto + + + + + +### PrivKey +PrivKey defines a secp256k1 private key. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | + + + + + + + + +### PubKey +PubKey defines a secp256k1 public key +Key is the compressed form of the pubkey. The first byte depends is a 0x02 byte +if the y-coordinate is the lexicographically largest of the two associated with +the x-coordinate. Otherwise the first byte is a 0x03. +This prefix is followed with the x-coordinate. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/distribution/v1beta1/distribution.proto + + + + + +### CommunityPoolSpendProposal +CommunityPoolSpendProposal details a proposal for use of community funds, +together with how many coins are proposed to be spent, and to which +recipient account. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | + + + + + + + + +### CommunityPoolSpendProposalWithDeposit +CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal +with a deposit + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `recipient` | [string](#string) | | | +| `amount` | [string](#string) | | | +| `deposit` | [string](#string) | | | + + + + + + + + +### DelegationDelegatorReward +DelegationDelegatorReward represents the properties +of a delegator's delegation reward. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | | +| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | + + + + + + + + +### DelegatorStartingInfo +DelegatorStartingInfo represents the starting info for a delegator reward +period. It tracks the previous validator period, the delegation's amount of +staking token, and the creation height (to check later on if any slashes have +occurred). NOTE: Even though validators are slashed to whole staking tokens, +the delegators within the validator may be left with less than a full token, +thus sdk.Dec is used. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `previous_period` | [uint64](#uint64) | | | +| `stake` | [string](#string) | | | +| `height` | [uint64](#uint64) | | | + + + + + + + + +### FeePool +FeePool is the global fee pool for distribution. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | + + + + + + + + +### Params +Params defines the set of params for the distribution module. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `community_tax` | [string](#string) | | | +| `base_proposer_reward` | [string](#string) | | | +| `bonus_proposer_reward` | [string](#string) | | | +| `withdraw_addr_enabled` | [bool](#bool) | | | + + + + + + + + +### ValidatorAccumulatedCommission +ValidatorAccumulatedCommission represents accumulated commission +for a validator kept as a running counter, can be withdrawn at any time. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | + + + + + + + + +### ValidatorCurrentRewards +ValidatorCurrentRewards represents current rewards and current +period for a validator kept as a running counter and incremented +each block as long as the validator's tokens remain constant. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `period` | [uint64](#uint64) | | | + + + + + + + + +### ValidatorHistoricalRewards +ValidatorHistoricalRewards represents historical rewards for a validator. +Height is implicit within the store key. +Cumulative reward ratio is the sum from the zeroeth period +until this period of rewards / tokens, per the spec. +The reference count indicates the number of objects +which might need to reference this historical entry at any point. +ReferenceCount = + number of outstanding delegations which ended the associated period (and + might need to read that record) + + number of slashes which ended the associated period (and might need to + read that record) + + one per validator for the zeroeth period, set on initialization + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `reference_count` | [uint32](#uint32) | | | + + + + + + + + +### ValidatorOutstandingRewards +ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards +for a validator inexpensive to track, allows simple sanity checks. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | + + + + + + + + +### ValidatorSlashEvent +ValidatorSlashEvent represents a validator slash event. +Height is implicit within the store key. +This is needed to calculate appropriate amount of staking tokens +for delegations which are withdrawn after a slash has occurred. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_period` | [uint64](#uint64) | | | +| `fraction` | [string](#string) | | | + + + + + + + + +### ValidatorSlashEvents +ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/distribution/v1beta1/genesis.proto + + + + + +### DelegatorStartingInfoRecord +DelegatorStartingInfoRecord used for import / export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `starting_info` | [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) | | starting_info defines the starting info of a delegator. | + + + + + + + + +### DelegatorWithdrawInfo +DelegatorWithdrawInfo is the address for where distributions rewards are +withdrawn to by default this struct is only used at genesis to feed in +default withdraw addresses. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | +| `withdraw_address` | [string](#string) | | withdraw_address is the address to withdraw the delegation rewards to. | + + + + + + + + +### GenesisState +GenesisState defines the distribution module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines all the paramaters of the module. | +| `fee_pool` | [FeePool](#cosmos.distribution.v1beta1.FeePool) | | fee_pool defines the fee pool at genesis. | +| `delegator_withdraw_infos` | [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) | repeated | fee_pool defines the delegator withdraw infos at genesis. | +| `previous_proposer` | [string](#string) | | fee_pool defines the previous proposer at genesis. | +| `outstanding_rewards` | [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) | repeated | fee_pool defines the outstanding rewards of all validators at genesis. | +| `validator_accumulated_commissions` | [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) | repeated | fee_pool defines the accumulated commisions of all validators at genesis. | +| `validator_historical_rewards` | [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) | repeated | fee_pool defines the historical rewards of all validators at genesis. | +| `validator_current_rewards` | [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) | repeated | fee_pool defines the current rewards of all validators at genesis. | +| `delegator_starting_infos` | [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) | repeated | fee_pool defines the delegator starting infos at genesis. | +| `validator_slash_events` | [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) | repeated | fee_pool defines the validator slash events at genesis. | + + + + + + + + +### ValidatorAccumulatedCommissionRecord +ValidatorAccumulatedCommissionRecord is used for import / export via genesis +json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `accumulated` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | accumulated is the accumulated commission of a validator. | + + + + + + + + +### ValidatorCurrentRewardsRecord +ValidatorCurrentRewardsRecord is used for import / export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `rewards` | [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) | | rewards defines the current rewards of a validator. | + + + + + + + + +### ValidatorHistoricalRewardsRecord +ValidatorHistoricalRewardsRecord is used for import / export via genesis +json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `period` | [uint64](#uint64) | | period defines the period the historical rewards apply to. | +| `rewards` | [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) | | rewards defines the historical rewards of a validator. | + + + + + + + + +### ValidatorOutstandingRewardsRecord +ValidatorOutstandingRewardsRecord is used for import/export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `outstanding_rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | outstanding_rewards represents the oustanding rewards of a validator. | + + + + + + + + +### ValidatorSlashEventRecord +ValidatorSlashEventRecord is used for import / export via genesis json. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `validator_address` | [string](#string) | | validator_address is the address of the validator. | +| `height` | [uint64](#uint64) | | height defines the block height at which the slash event occured. | +| `period` | [uint64](#uint64) | | period is the period of the slash event. | +| `validator_slash_event` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | | validator_slash_event describes the slash event. | @@ -4046,151 +3909,26 @@ Msg defines the distribution Msg service. - +

    Top

    -## cosmos/distribution/v1beta1/genesis.proto +## cosmos/evidence/v1beta1/evidence.proto - + -### DelegatorStartingInfoRecord -DelegatorStartingInfoRecord used for import / export via genesis json. +### Equivocation +Equivocation implements the Evidence interface and defines evidence of double +signing misbehavior. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `starting_info` | [DelegatorStartingInfo](#cosmos.distribution.v1beta1.DelegatorStartingInfo) | | starting_info defines the starting info of a delegator. | - - - - - - - - -### DelegatorWithdrawInfo -DelegatorWithdrawInfo is the address for where distributions rewards are -withdrawn to by default this struct is only used at genesis to feed in -default withdraw addresses. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | delegator_address is the address of the delegator. | -| `withdraw_address` | [string](#string) | | withdraw_address is the address to withdraw the delegation rewards to. | - - - - - - - - -### GenesisState -GenesisState defines the distribution module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.distribution.v1beta1.Params) | | params defines all the paramaters of the module. | -| `fee_pool` | [FeePool](#cosmos.distribution.v1beta1.FeePool) | | fee_pool defines the fee pool at genesis. | -| `delegator_withdraw_infos` | [DelegatorWithdrawInfo](#cosmos.distribution.v1beta1.DelegatorWithdrawInfo) | repeated | fee_pool defines the delegator withdraw infos at genesis. | -| `previous_proposer` | [string](#string) | | fee_pool defines the previous proposer at genesis. | -| `outstanding_rewards` | [ValidatorOutstandingRewardsRecord](#cosmos.distribution.v1beta1.ValidatorOutstandingRewardsRecord) | repeated | fee_pool defines the outstanding rewards of all validators at genesis. | -| `validator_accumulated_commissions` | [ValidatorAccumulatedCommissionRecord](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommissionRecord) | repeated | fee_pool defines the accumulated commisions of all validators at genesis. | -| `validator_historical_rewards` | [ValidatorHistoricalRewardsRecord](#cosmos.distribution.v1beta1.ValidatorHistoricalRewardsRecord) | repeated | fee_pool defines the historical rewards of all validators at genesis. | -| `validator_current_rewards` | [ValidatorCurrentRewardsRecord](#cosmos.distribution.v1beta1.ValidatorCurrentRewardsRecord) | repeated | fee_pool defines the current rewards of all validators at genesis. | -| `delegator_starting_infos` | [DelegatorStartingInfoRecord](#cosmos.distribution.v1beta1.DelegatorStartingInfoRecord) | repeated | fee_pool defines the delegator starting infos at genesis. | -| `validator_slash_events` | [ValidatorSlashEventRecord](#cosmos.distribution.v1beta1.ValidatorSlashEventRecord) | repeated | fee_pool defines the validator slash events at genesis. | - - - - - - - - -### ValidatorAccumulatedCommissionRecord -ValidatorAccumulatedCommissionRecord is used for import / export via genesis -json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `accumulated` | [ValidatorAccumulatedCommission](#cosmos.distribution.v1beta1.ValidatorAccumulatedCommission) | | accumulated is the accumulated commission of a validator. | - - - - - - - - -### ValidatorCurrentRewardsRecord -ValidatorCurrentRewardsRecord is used for import / export via genesis json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `rewards` | [ValidatorCurrentRewards](#cosmos.distribution.v1beta1.ValidatorCurrentRewards) | | rewards defines the current rewards of a validator. | - - - - - - - - -### ValidatorHistoricalRewardsRecord -ValidatorHistoricalRewardsRecord is used for import / export via genesis -json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `period` | [uint64](#uint64) | | period defines the period the historical rewards apply to. | -| `rewards` | [ValidatorHistoricalRewards](#cosmos.distribution.v1beta1.ValidatorHistoricalRewards) | | rewards defines the historical rewards of a validator. | - - - - - - - - -### ValidatorOutstandingRewardsRecord -ValidatorOutstandingRewardsRecord is used for import/export via genesis json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `outstanding_rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | outstanding_rewards represents the oustanding rewards of a validator. | - - - - - - - - -### ValidatorSlashEventRecord -ValidatorSlashEventRecord is used for import / export via genesis json. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | validator_address is the address of the validator. | -| `height` | [uint64](#uint64) | | height defines the block height at which the slash event occured. | -| `period` | [uint64](#uint64) | | period is the period of the slash event. | -| `validator_slash_event` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | | validator_slash_event describes the slash event. | +| `height` | [int64](#int64) | | | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `power` | [int64](#int64) | | | +| `consensus_address` | [string](#string) | | | @@ -4206,26 +3944,540 @@ ValidatorSlashEventRecord is used for import / export via genesis json. - +

    Top

    -## cosmos/distribution/v1beta1/distribution.proto +## cosmos/evidence/v1beta1/genesis.proto - + -### CommunityPoolSpendProposal -CommunityPoolSpendProposal details a proposal for use of community funds, -together with how many coins are proposed to be spent, and to which -recipient account. +### GenesisState +GenesisState defines the evidence module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/evidence/v1beta1/query.proto + + + + + +### QueryAllEvidenceRequest +QueryEvidenceRequest is the request type for the Query/AllEvidence RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryAllEvidenceResponse +QueryAllEvidenceResponse is the response type for the Query/AllEvidence RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence returns all evidences. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + + + +### QueryEvidenceRequest +QueryEvidenceRequest is the request type for the Query/Evidence RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | + + + + + + + + +### QueryEvidenceResponse +QueryEvidenceResponse is the response type for the Query/Evidence RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | evidence returns the requested evidence. | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Evidence` | [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) | [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) | Evidence queries evidence based on evidence hash. | GET|/cosmos/evidence/v1beta1/evidence/{evidence_hash}| +| `AllEvidence` | [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) | [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) | AllEvidence queries all evidence. | GET|/cosmos/evidence/v1beta1/evidence| + + + + + + +

    Top

    + +## cosmos/evidence/v1beta1/tx.proto + + + + + +### MsgSubmitEvidence +MsgSubmitEvidence represents a message that supports submitting arbitrary +Evidence of misbehavior such as equivocation or counterfactual signing. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `submitter` | [string](#string) | | | +| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | + + + + + + + + +### MsgSubmitEvidenceResponse +MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | + + + + + + + + + + + + + + +### Msg +Msg defines the evidence Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `SubmitEvidence` | [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) | [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) | SubmitEvidence submits an arbitrary Evidence of misbehavior such as equivocation or counterfactual signing. | | + + + + + + +

    Top

    + +## cosmos/feegrant/v1beta1/feegrant.proto + + + + + +### BasicFeeAllowance +BasicFeeAllowance implements FeeAllowance with a one-time grant of tokens +that optionally expires. The delegatee can use up to SpendLimit to cover fees. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | spend_limit specifies the maximum amount of tokens that can be spent by this allowance and will be updated as tokens are spent. If it is empty, there is no spend limit and any amount of coins can be spent. | +| `expiration` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | expiration specifies an optional time when this allowance expires | + + + + + + + + +### Duration +Duration is a span of a clock time or number of blocks. +This is designed to be added to an ExpiresAt struct. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `duration` | [google.protobuf.Duration](#google.protobuf.Duration) | | | +| `blocks` | [uint64](#uint64) | | | + + + + + + + + +### ExpiresAt +ExpiresAt is a point in time where something expires. +It may be *either* block time or block height + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `height` | [int64](#int64) | | | + + + + + + + + +### FeeAllowanceGrant +FeeAllowanceGrant is stored in the KVStore to record a grant with full context + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | + + + + + + + + +### PeriodicFeeAllowance +PeriodicFeeAllowance extends FeeAllowance to allow for both a maximum cap, +as well as a limit per time period. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `basic` | [BasicFeeAllowance](#cosmos.feegrant.v1beta1.BasicFeeAllowance) | | basic specifies a struct of `BasicFeeAllowance` | +| `period` | [Duration](#cosmos.feegrant.v1beta1.Duration) | | period specifies the time duration in which period_spend_limit coins can be spent before that allowance is reset | +| `period_spend_limit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | period_spend_limit specifies the maximum number of coins that can be spent in the period | +| `period_can_spend` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | period_can_spend is the number of coins left to be spent before the period_reset time | +| `period_reset` | [ExpiresAt](#cosmos.feegrant.v1beta1.ExpiresAt) | | period_reset is the time at which this period resets and a new one begins, it is calculated from the start time of the first transaction after the last period ended | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/feegrant/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState contains a set of fee allowances, persisted from the store + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/feegrant/v1beta1/query.proto + + + + + +### QueryFeeAllowanceRequest +QueryFeeAllowanceRequest is the request type for the Query/FeeAllowance RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | + + + + + + + + +### QueryFeeAllowanceResponse +QueryFeeAllowanceResponse is the response type for the Query/FeeAllowance RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `fee_allowance` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | | fee_allowance is a fee_allowance granted for grantee by granter. | + + + + + + + + +### QueryFeeAllowancesRequest +QueryFeeAllowancesRequest is the request type for the Query/FeeAllowances RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `grantee` | [string](#string) | | | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | + + + + + + + + +### QueryFeeAllowancesResponse +QueryFeeAllowancesResponse is the response type for the Query/FeeAllowances RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `fee_allowances` | [FeeAllowanceGrant](#cosmos.feegrant.v1beta1.FeeAllowanceGrant) | repeated | fee_allowances are fee_allowance's granted for grantee by granter. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | + + + + + + + + + + + + + + +### Query +Query defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `FeeAllowance` | [QueryFeeAllowanceRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowanceRequest) | [QueryFeeAllowanceResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowanceResponse) | FeeAllowance returns fee granted to the grantee by the granter. | GET|/cosmos/feegrant/v1beta1/fee_allowance/{granter}/{grantee}| +| `FeeAllowances` | [QueryFeeAllowancesRequest](#cosmos.feegrant.v1beta1.QueryFeeAllowancesRequest) | [QueryFeeAllowancesResponse](#cosmos.feegrant.v1beta1.QueryFeeAllowancesResponse) | FeeAllowances returns all the grants for address. | GET|/cosmos/feegrant/v1beta1/fee_allowances/{grantee}| + + + + + + +

    Top

    + +## cosmos/feegrant/v1beta1/tx.proto + + + + + +### MsgGrantFeeAllowance +MsgGrantFeeAllowance adds permission for Grantee to spend up to Allowance +of fees from the account of Granter. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | +| `allowance` | [google.protobuf.Any](#google.protobuf.Any) | | | + + + + + + + + +### MsgGrantFeeAllowanceResponse +MsgGrantFeeAllowanceResponse defines the Msg/GrantFeeAllowanceResponse response type. + + + + + + + + +### MsgRevokeFeeAllowance +MsgRevokeFeeAllowance removes any existing FeeAllowance from Granter to Grantee. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `granter` | [string](#string) | | | +| `grantee` | [string](#string) | | | + + + + + + + + +### MsgRevokeFeeAllowanceResponse +MsgRevokeFeeAllowanceResponse defines the Msg/RevokeFeeAllowanceResponse response type. + + + + + + + + + + + + + + +### Msg +Msg defines the feegrant msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `GrantFeeAllowance` | [MsgGrantFeeAllowance](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowance) | [MsgGrantFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgGrantFeeAllowanceResponse) | GrantFeeAllowance grants fee allowance to the grantee on the granter's account with the provided expiration time. | | +| `RevokeFeeAllowance` | [MsgRevokeFeeAllowance](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowance) | [MsgRevokeFeeAllowanceResponse](#cosmos.feegrant.v1beta1.MsgRevokeFeeAllowanceResponse) | RevokeFeeAllowance revokes any fee allowance of granter's account that has been granted to the grantee. | | + + + + + + +

    Top

    + +## cosmos/genutil/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the raw genesis transaction in JSON. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `gen_txs` | [bytes](#bytes) | repeated | gen_txs defines the genesis transactions. | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/gov/v1beta1/gov.proto + + + + + +### Deposit +Deposit defines an amount deposited by an account address to an active +proposal. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | | `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | @@ -4233,203 +4485,192 @@ recipient account. - + -### CommunityPoolSpendProposalWithDeposit -CommunityPoolSpendProposalWithDeposit defines a CommunityPoolSpendProposal -with a deposit +### DepositParams +DepositParams defines the params for deposits on governance proposals. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `min_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | Minimum deposit for a proposal to enter voting period. | +| `max_deposit_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Maximum period for Atom holders to deposit on a proposal. Initial value: 2 months. | + + + + + + + + +### Proposal +Proposal defines the core field members of a governance proposal. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | +| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | | +| `final_tally_result` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | | +| `submit_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `deposit_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `total_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `voting_start_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `voting_end_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | + + + + + + + + +### TallyParams +TallyParams defines the params for tallying votes on governance proposals. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `quorum` | [bytes](#bytes) | | Minimum percentage of total stake needed to vote for a result to be considered valid. | +| `threshold` | [bytes](#bytes) | | Minimum proportion of Yes votes for proposal to pass. Default value: 0.5. | +| `veto_threshold` | [bytes](#bytes) | | Minimum value of Veto votes to Total votes ratio for proposal to be vetoed. Default value: 1/3. | + + + + + + + + +### TallyResult +TallyResult defines a standard tally for a governance proposal. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `yes` | [string](#string) | | | +| `abstain` | [string](#string) | | | +| `no` | [string](#string) | | | +| `no_with_veto` | [string](#string) | | | + + + + + + + + +### TextProposal +TextProposal defines a standard text proposal whose changes need to be +manually updated in case of approval. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | `title` | [string](#string) | | | | `description` | [string](#string) | | | -| `recipient` | [string](#string) | | | -| `amount` | [string](#string) | | | -| `deposit` | [string](#string) | | | - + -### DelegationDelegatorReward -DelegationDelegatorReward represents the properties -of a delegator's delegation reward. +### Vote +Vote defines a vote on a governance proposal. +A Vote consists of a proposal ID, the voter, and the vote option. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `validator_address` | [string](#string) | | | -| `reward` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | - + -### DelegatorStartingInfo -DelegatorStartingInfo represents the starting info for a delegator reward -period. It tracks the previous validator period, the delegation's amount of -staking token, and the creation height (to check later on if any slashes have -occurred). NOTE: Even though validators are slashed to whole staking tokens, -the delegators within the validator may be left with less than a full token, -thus sdk.Dec is used. +### VotingParams +VotingParams defines the params for voting on governance proposals. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `previous_period` | [uint64](#uint64) | | | -| `stake` | [string](#string) | | | -| `height` | [uint64](#uint64) | | | +| `voting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | Length of the voting period. | + - -### FeePool -FeePool is the global fee pool for distribution. + + +### ProposalStatus +ProposalStatus enumerates the valid statuses of a proposal. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| PROPOSAL_STATUS_UNSPECIFIED | 0 | PROPOSAL_STATUS_UNSPECIFIED defines the default propopsal status. | +| PROPOSAL_STATUS_DEPOSIT_PERIOD | 1 | PROPOSAL_STATUS_DEPOSIT_PERIOD defines a proposal status during the deposit period. | +| PROPOSAL_STATUS_VOTING_PERIOD | 2 | PROPOSAL_STATUS_VOTING_PERIOD defines a proposal status during the voting period. | +| PROPOSAL_STATUS_PASSED | 3 | PROPOSAL_STATUS_PASSED defines a proposal status of a proposal that has passed. | +| PROPOSAL_STATUS_REJECTED | 4 | PROPOSAL_STATUS_REJECTED defines a proposal status of a proposal that has been rejected. | +| PROPOSAL_STATUS_FAILED | 5 | PROPOSAL_STATUS_FAILED defines a proposal status of a proposal that has failed. | + + + + + +### VoteOption +VoteOption enumerates the valid vote options for a given governance proposal. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| VOTE_OPTION_UNSPECIFIED | 0 | VOTE_OPTION_UNSPECIFIED defines a no-op vote option. | +| VOTE_OPTION_YES | 1 | VOTE_OPTION_YES defines a yes vote option. | +| VOTE_OPTION_ABSTAIN | 2 | VOTE_OPTION_ABSTAIN defines an abstain vote option. | +| VOTE_OPTION_NO | 3 | VOTE_OPTION_NO defines a no vote option. | +| VOTE_OPTION_NO_WITH_VETO | 4 | VOTE_OPTION_NO_WITH_VETO defines a no with veto vote option. | + + + + + + + + + + + +

    Top

    + +## cosmos/gov/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the gov module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `community_pool` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - - - - - - - - -### Params -Params defines the set of params for the distribution module. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `community_tax` | [string](#string) | | | -| `base_proposer_reward` | [string](#string) | | | -| `bonus_proposer_reward` | [string](#string) | | | -| `withdraw_addr_enabled` | [bool](#bool) | | | - - - - - - - - -### ValidatorAccumulatedCommission -ValidatorAccumulatedCommission represents accumulated commission -for a validator kept as a running counter, can be withdrawn at any time. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `commission` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - - - - - - - - -### ValidatorCurrentRewards -ValidatorCurrentRewards represents current rewards and current -period for a validator kept as a running counter and incremented -each block as long as the validator's tokens remain constant. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `period` | [uint64](#uint64) | | | - - - - - - - - -### ValidatorHistoricalRewards -ValidatorHistoricalRewards represents historical rewards for a validator. -Height is implicit within the store key. -Cumulative reward ratio is the sum from the zeroeth period -until this period of rewards / tokens, per the spec. -The reference count indicates the number of objects -which might need to reference this historical entry at any point. -ReferenceCount = - number of outstanding delegations which ended the associated period (and - might need to read that record) - + number of slashes which ended the associated period (and might need to - read that record) - + one per validator for the zeroeth period, set on initialization - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `cumulative_reward_ratio` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | -| `reference_count` | [uint32](#uint32) | | | - - - - - - - - -### ValidatorOutstandingRewards -ValidatorOutstandingRewards represents outstanding (un-withdrawn) rewards -for a validator inexpensive to track, allows simple sanity checks. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `rewards` | [cosmos.base.v1beta1.DecCoin](#cosmos.base.v1beta1.DecCoin) | repeated | | - - - - - - - - -### ValidatorSlashEvent -ValidatorSlashEvent represents a validator slash event. -Height is implicit within the store key. -This is needed to calculate appropriate amount of staking tokens -for delegations which are withdrawn after a slash has occurred. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_period` | [uint64](#uint64) | | | -| `fraction` | [string](#string) | | | - - - - - - - - -### ValidatorSlashEvents -ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `validator_slash_events` | [ValidatorSlashEvent](#cosmos.distribution.v1beta1.ValidatorSlashEvent) | repeated | | +| `starting_proposal_id` | [uint64](#uint64) | | starting_proposal_id is the ID of the starting proposal. | +| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | deposits defines all the deposits present at genesis. | +| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defines all the votes present at genesis. | +| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | proposals defines all the proposals present at genesis. | +| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | params defines all the paramaters of related to deposit. | +| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | params defines all the paramaters of related to voting. | +| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | params defines all the paramaters of related to tally. | @@ -4445,98 +4686,260 @@ ValidatorSlashEvents is a collection of ValidatorSlashEvent messages. - +

    Top

    -## cosmos/upgrade/v1beta1/query.proto +## cosmos/gov/v1beta1/query.proto - + -### QueryAppliedPlanRequest -QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC +### QueryDepositRequest +QueryDepositRequest is the request type for the Query/Deposit RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | + + + + + + + + +### QueryDepositResponse +QueryDepositResponse is the response type for the Query/Deposit RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `deposit` | [Deposit](#cosmos.gov.v1beta1.Deposit) | | deposit defines the requested deposit. | + + + + + + + + +### QueryDepositsRequest +QueryDepositsRequest is the request type for the Query/Deposits RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryDepositsResponse +QueryDepositsResponse is the response type for the Query/Deposits RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `deposits` | [Deposit](#cosmos.gov.v1beta1.Deposit) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | + + + + + + + + +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params_type` | [string](#string) | | params_type defines which parameters to query for, can be one of "voting", "tallying" or "deposit". | + + + + + + + + +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `voting_params` | [VotingParams](#cosmos.gov.v1beta1.VotingParams) | | voting_params defines the parameters related to voting. | +| `deposit_params` | [DepositParams](#cosmos.gov.v1beta1.DepositParams) | | deposit_params defines the parameters related to deposit. | +| `tally_params` | [TallyParams](#cosmos.gov.v1beta1.TallyParams) | | tally_params defines the parameters related to tally. | + + + + + + + + +### QueryProposalRequest +QueryProposalRequest is the request type for the Query/Proposal RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | + + + + + + + + +### QueryProposalResponse +QueryProposalResponse is the response type for the Query/Proposal RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal` | [Proposal](#cosmos.gov.v1beta1.Proposal) | | | + + + + + + + + +### QueryProposalsRequest +QueryProposalsRequest is the request type for the Query/Proposals RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_status` | [ProposalStatus](#cosmos.gov.v1beta1.ProposalStatus) | | proposal_status defines the status of the proposals. | +| `voter` | [string](#string) | | voter defines the voter address for the proposals. | +| `depositor` | [string](#string) | | depositor defines the deposit addresses from the proposals. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryProposalsResponse +QueryProposalsResponse is the response type for the Query/Proposals RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | name is the name of the applied plan to query for. | +| `proposals` | [Proposal](#cosmos.gov.v1beta1.Proposal) | repeated | | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | - + -### QueryAppliedPlanResponse -QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC -method. +### QueryTallyResultRequest +QueryTallyResultRequest is the request type for the Query/Tally RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | - + -### QueryCurrentPlanRequest -QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC -method. - - - - - - - - -### QueryCurrentPlanResponse -QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC -method. +### QueryTallyResultResponse +QueryTallyResultResponse is the response type for the Query/Tally RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | +| `tally` | [TallyResult](#cosmos.gov.v1beta1.TallyResult) | | tally defines the requested tally. | - + -### QueryUpgradedConsensusStateRequest -QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState -RPC method. +### QueryVoteRequest +QueryVoteRequest is the request type for the Query/Vote RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `last_height` | [int64](#int64) | | last height of the current chain must be sent in request as this is the height under which next consensus state is stored | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `voter` | [string](#string) | | voter defines the oter address for the proposals. | - + -### QueryUpgradedConsensusStateResponse -QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState -RPC method. +### QueryVoteResponse +QueryVoteResponse is the response type for the Query/Vote RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `vote` | [Vote](#cosmos.gov.v1beta1.Vote) | | vote defined the queried vote. | + + + + + + + + +### QueryVotesRequest +QueryVotesRequest is the request type for the Query/Votes RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | proposal_id defines the unique id of the proposal. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | + + + + + + + + +### QueryVotesResponse +QueryVotesResponse is the response type for the Query/Votes RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `votes` | [Vote](#cosmos.gov.v1beta1.Vote) | repeated | votes defined the queried votes. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | @@ -4549,76 +4952,178 @@ RPC method. - + ### Query -Query defines the gRPC upgrade querier service. +Query defines the gRPC querier service for gov module | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CurrentPlan` | [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) | [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) | CurrentPlan queries the current upgrade plan. | GET|/cosmos/upgrade/v1beta1/current_plan| -| `AppliedPlan` | [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) | [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) | AppliedPlan queries a previously applied upgrade plan by its name. | GET|/cosmos/upgrade/v1beta1/applied_plan/{name}| -| `UpgradedConsensusState` | [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) | [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) | UpgradedConsensusState queries the consensus state that will serve as a trusted kernel for the next version of this chain. It will only be stored at the last height of this chain. UpgradedConsensusState RPC not supported with legacy querier | GET|/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}| +| `Proposal` | [QueryProposalRequest](#cosmos.gov.v1beta1.QueryProposalRequest) | [QueryProposalResponse](#cosmos.gov.v1beta1.QueryProposalResponse) | Proposal queries proposal details based on ProposalID. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}| +| `Proposals` | [QueryProposalsRequest](#cosmos.gov.v1beta1.QueryProposalsRequest) | [QueryProposalsResponse](#cosmos.gov.v1beta1.QueryProposalsResponse) | Proposals queries all proposals based on given status. | GET|/cosmos/gov/v1beta1/proposals| +| `Vote` | [QueryVoteRequest](#cosmos.gov.v1beta1.QueryVoteRequest) | [QueryVoteResponse](#cosmos.gov.v1beta1.QueryVoteResponse) | Vote queries voted information based on proposalID, voterAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes/{voter}| +| `Votes` | [QueryVotesRequest](#cosmos.gov.v1beta1.QueryVotesRequest) | [QueryVotesResponse](#cosmos.gov.v1beta1.QueryVotesResponse) | Votes queries votes of a given proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/votes| +| `Params` | [QueryParamsRequest](#cosmos.gov.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.gov.v1beta1.QueryParamsResponse) | Params queries all parameters of the gov module. | GET|/cosmos/gov/v1beta1/params/{params_type}| +| `Deposit` | [QueryDepositRequest](#cosmos.gov.v1beta1.QueryDepositRequest) | [QueryDepositResponse](#cosmos.gov.v1beta1.QueryDepositResponse) | Deposit queries single deposit information based proposalID, depositAddr. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits/{depositor}| +| `Deposits` | [QueryDepositsRequest](#cosmos.gov.v1beta1.QueryDepositsRequest) | [QueryDepositsResponse](#cosmos.gov.v1beta1.QueryDepositsResponse) | Deposits queries all deposits of a single proposal. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/deposits| +| `TallyResult` | [QueryTallyResultRequest](#cosmos.gov.v1beta1.QueryTallyResultRequest) | [QueryTallyResultResponse](#cosmos.gov.v1beta1.QueryTallyResultResponse) | TallyResult queries the tally of a proposal vote. | GET|/cosmos/gov/v1beta1/proposals/{proposal_id}/tally| - +

    Top

    -## cosmos/upgrade/v1beta1/upgrade.proto +## cosmos/gov/v1beta1/tx.proto - + -### CancelSoftwareUpgradeProposal -CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software -upgrade. +### MsgDeposit +MsgDeposit defines a message to submit a deposit to an existing proposal. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | +| `proposal_id` | [uint64](#uint64) | | | +| `depositor` | [string](#string) | | | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | - + -### Plan -Plan specifies information about a planned upgrade and when it should occur. +### MsgDepositResponse +MsgDepositResponse defines the Msg/Deposit response type. + + + + + + + + +### MsgSubmitProposal +MsgSubmitProposal defines an sdk.Msg type that supports submitting arbitrary +proposal Content. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | Sets the name for the upgrade. This name will be used by the upgraded version of the software to apply any special "on-upgrade" commands during the first BeginBlock method after the upgrade is applied. It is also used to detect whether a software version can handle a given upgrade. If no upgrade handler with this name has been set in the software, it will be assumed that the software is out-of-date when the upgrade Time or Height is reached and the software will exit. | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | The time after which the upgrade must be performed. Leave set to its zero value to use a pre-defined Height instead. | -| `height` | [int64](#int64) | | The height at which the upgrade must be performed. Only used if Time is not set. | -| `info` | [string](#string) | | Any application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to | -| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | IBC-enabled chains can opt-in to including the upgraded client state in its upgrade plan This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connecting chains can verify that the new upgraded client is valid by verifying a proof on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades | +| `content` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `initial_deposit` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | | +| `proposer` | [string](#string) | | | - + -### SoftwareUpgradeProposal -SoftwareUpgradeProposal is a gov Content type for initiating a software -upgrade. +### MsgSubmitProposalResponse +MsgSubmitProposalResponse defines the Msg/SubmitProposal response type. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | +| `proposal_id` | [uint64](#uint64) | | | + + + + + + + + +### MsgVote +MsgVote defines a message to cast a vote. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `proposal_id` | [uint64](#uint64) | | | +| `voter` | [string](#string) | | | +| `option` | [VoteOption](#cosmos.gov.v1beta1.VoteOption) | | | + + + + + + + + +### MsgVoteResponse +MsgVoteResponse defines the Msg/Vote response type. + + + + + + + + + + + + + + +### Msg +Msg defines the bank Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `SubmitProposal` | [MsgSubmitProposal](#cosmos.gov.v1beta1.MsgSubmitProposal) | [MsgSubmitProposalResponse](#cosmos.gov.v1beta1.MsgSubmitProposalResponse) | SubmitProposal defines a method to create new proposal given a content. | | +| `Vote` | [MsgVote](#cosmos.gov.v1beta1.MsgVote) | [MsgVoteResponse](#cosmos.gov.v1beta1.MsgVoteResponse) | Vote defines a method to add a vote on a specific proposal. | | +| `Deposit` | [MsgDeposit](#cosmos.gov.v1beta1.MsgDeposit) | [MsgDepositResponse](#cosmos.gov.v1beta1.MsgDepositResponse) | Deposit defines a method to add deposit on a specific proposal. | | + + + + + + +

    Top

    + +## cosmos/mint/v1beta1/mint.proto + + + + + +### Minter +Minter represents the minting state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `inflation` | [string](#string) | | current annual inflation rate | +| `annual_provisions` | [string](#string) | | current annual expected provisions | + + + + + + + + +### Params +Params holds parameters for the mint module. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `mint_denom` | [string](#string) | | type of coin to mint | +| `inflation_rate_change` | [string](#string) | | maximum annual change in inflation rate | +| `inflation_max` | [string](#string) | | maximum inflation rate | +| `inflation_min` | [string](#string) | | minimum inflation rate | +| `goal_bonded` | [string](#string) | | goal of percent bonded atoms | +| `blocks_per_year` | [uint64](#uint64) | | expected blocks per year | @@ -4634,38 +5139,23 @@ upgrade. - +

    Top

    -## cosmos/base/kv/v1beta1/kv.proto +## cosmos/mint/v1beta1/genesis.proto - + -### Pair -Pair defines a key/value bytes tuple. +### GenesisState +GenesisState defines the mint module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | - - - - - - - - -### Pairs -Pairs defines a repeated slice of Pair objects. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pairs` | [Pair](#cosmos.base.kv.v1beta1.Pair) | repeated | | +| `minter` | [Minter](#cosmos.mint.v1beta1.Minter) | | minter is a space for holding current inflation information. | +| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines all the paramaters of the module. | @@ -4681,39 +5171,129 @@ Pairs defines a repeated slice of Pair objects. - +

    Top

    -## cosmos/base/abci/v1beta1/abci.proto +## cosmos/mint/v1beta1/query.proto - + -### ABCIMessageLog -ABCIMessageLog defines a structure containing an indexed tx ABCI message log. +### QueryAnnualProvisionsRequest +QueryAnnualProvisionsRequest is the request type for the +Query/AnnualProvisions RPC method. + + + + + + + + +### QueryAnnualProvisionsResponse +QueryAnnualProvisionsResponse is the response type for the +Query/AnnualProvisions RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `msg_index` | [uint32](#uint32) | | | -| `log` | [string](#string) | | | -| `events` | [StringEvent](#cosmos.base.abci.v1beta1.StringEvent) | repeated | Events contains a slice of Event objects that were emitted during some execution. | +| `annual_provisions` | [bytes](#bytes) | | annual_provisions is the current minting annual provisions value. | - + -### Attribute -Attribute defines an attribute wrapper where the key and value are -strings instead of raw bytes. +### QueryInflationRequest +QueryInflationRequest is the request type for the Query/Inflation RPC method. + + + + + + + + +### QueryInflationResponse +QueryInflationResponse is the response type for the Query/Inflation RPC +method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | +| `inflation` | [bytes](#bytes) | | inflation is the current minting inflation value. | + + + + + + + + +### QueryParamsRequest +QueryParamsRequest is the request type for the Query/Params RPC method. + + + + + + + + +### QueryParamsResponse +QueryParamsResponse is the response type for the Query/Params RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.mint.v1beta1.Params) | | params defines the parameters of the module. | + + + + + + + + + + + + + + +### Query +Query provides defines the gRPC querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Params` | [QueryParamsRequest](#cosmos.mint.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.mint.v1beta1.QueryParamsResponse) | Params returns the total set of minting parameters. | GET|/cosmos/mint/v1beta1/params| +| `Inflation` | [QueryInflationRequest](#cosmos.mint.v1beta1.QueryInflationRequest) | [QueryInflationResponse](#cosmos.mint.v1beta1.QueryInflationResponse) | Inflation returns the current minting inflation value. | GET|/cosmos/mint/v1beta1/inflation| +| `AnnualProvisions` | [QueryAnnualProvisionsRequest](#cosmos.mint.v1beta1.QueryAnnualProvisionsRequest) | [QueryAnnualProvisionsResponse](#cosmos.mint.v1beta1.QueryAnnualProvisionsResponse) | AnnualProvisions current minting annual provisions value. | GET|/cosmos/mint/v1beta1/annual_provisions| + + + + + + +

    Top

    + +## cosmos/params/v1beta1/params.proto + + + + + +### ParamChange +ParamChange defines an individual parameter change, for use in +ParameterChangeProposal. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `subspace` | [string](#string) | | | | `key` | [string](#string) | | | | `value` | [string](#string) | | | @@ -4722,147 +5302,17 @@ strings instead of raw bytes. - + -### GasInfo -GasInfo defines tx execution gas context. +### ParameterChangeProposal +ParameterChangeProposal defines a proposal to change one or more parameters. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `gas_wanted` | [uint64](#uint64) | | GasWanted is the maximum units of work we allow this tx to perform. | -| `gas_used` | [uint64](#uint64) | | GasUsed is the amount of gas actually consumed. | - - - - - - - - -### MsgData -MsgData defines the data returned in a Result object during message -execution. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `msg_type` | [string](#string) | | | -| `data` | [bytes](#bytes) | | | - - - - - - - - -### Result -Result is the union of ResponseFormat and ResponseCheckTx. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `data` | [bytes](#bytes) | | Data is any data returned from message or handler execution. It MUST be length prefixed in order to separate data from multiple message executions. | -| `log` | [string](#string) | | Log contains the log information from message or handler execution. | -| `events` | [tendermint.abci.Event](#tendermint.abci.Event) | repeated | Events contains a slice of Event objects that were emitted during message or handler execution. | - - - - - - - - -### SearchTxsResult -SearchTxsResult defines a structure for querying txs pageable - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `total_count` | [uint64](#uint64) | | Count of all txs | -| `count` | [uint64](#uint64) | | Count of txs in current page | -| `page_number` | [uint64](#uint64) | | Index of current page, start from 1 | -| `page_total` | [uint64](#uint64) | | Count of total pages | -| `limit` | [uint64](#uint64) | | Max count txs per page | -| `txs` | [TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | List of txs in current page | - - - - - - - - -### SimulationResponse -SimulationResponse defines the response generated when a transaction is -successfully simulated. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `gas_info` | [GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | | -| `result` | [Result](#cosmos.base.abci.v1beta1.Result) | | | - - - - - - - - -### StringEvent -StringEvent defines en Event object wrapper where all the attributes -contain key/value pairs that are strings instead of raw bytes. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `type` | [string](#string) | | | -| `attributes` | [Attribute](#cosmos.base.abci.v1beta1.Attribute) | repeated | | - - - - - - - - -### TxMsgData -TxMsgData defines a list of MsgData. A transaction will have a MsgData object -for each message. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `data` | [MsgData](#cosmos.base.abci.v1beta1.MsgData) | repeated | | - - - - - - - - -### TxResponse -TxResponse defines a structure containing relevant tx data and metadata. The -tags are stringified and the log is JSON decoded. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | The block height | -| `txhash` | [string](#string) | | The transaction hash. | -| `codespace` | [string](#string) | | Namespace for the Code | -| `code` | [uint32](#uint32) | | Response code. | -| `data` | [string](#string) | | Result bytes, if any. | -| `raw_log` | [string](#string) | | The output of the application's logger (raw string). May be non-deterministic. | -| `logs` | [ABCIMessageLog](#cosmos.base.abci.v1beta1.ABCIMessageLog) | repeated | The output of the application's logger (typed). May be non-deterministic. | -| `info` | [string](#string) | | Additional information. May be non-deterministic. | -| `gas_wanted` | [int64](#int64) | | Amount of gas requested for transaction. | -| `gas_used` | [int64](#int64) | | Amount of gas consumed by transaction. | -| `tx` | [google.protobuf.Any](#google.protobuf.Any) | | The request transaction bytes. | -| `timestamp` | [string](#string) | | Time of the previous block. For heights > 1, it's the weighted median of the timestamps of the valid votes in the block.LastCommit. For height == 1, it's genesis time. | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | repeated | | @@ -4878,514 +5328,38 @@ tags are stringified and the log is JSON decoded. - +

    Top

    -## cosmos/base/query/v1beta1/pagination.proto +## cosmos/params/v1beta1/query.proto - + -### PageRequest -PageRequest is to be embedded in gRPC request messages for efficient -pagination. Ex: - - message SomeRequest { - Foo some_parameter = 1; - PageRequest pagination = 2; - } +### QueryParamsRequest +QueryParamsRequest is request type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | key is a value returned in PageResponse.next_key to begin querying the next page most efficiently. Only one of offset or key should be set. | -| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. | -| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. | -| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. | +| `subspace` | [string](#string) | | subspace defines the module to query the parameter for. | +| `key` | [string](#string) | | key defines the key of the parameter in the subspace. | - + -### PageResponse -PageResponse is to be embedded in gRPC response messages where the -corresponding request message has used PageRequest. - - message SomeResponse { - repeated Bar results = 1; - PageResponse page = 2; - } +### QueryParamsResponse +QueryParamsResponse is response type for the Query/Params RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `next_key` | [bytes](#bytes) | | next_key is the key to be passed to PageRequest.key to query the next page most efficiently | -| `total` | [uint64](#uint64) | | total is total number of results available if PageRequest.count_total was set, its value is undefined otherwise | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/base/store/v1beta1/snapshot.proto - - - - - -### SnapshotIAVLItem -SnapshotIAVLItem is an exported IAVL node. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | | -| `value` | [bytes](#bytes) | | | -| `version` | [int64](#int64) | | | -| `height` | [int32](#int32) | | | - - - - - - - - -### SnapshotItem -SnapshotItem is an item contained in a rootmulti.Store snapshot. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `store` | [SnapshotStoreItem](#cosmos.base.store.v1beta1.SnapshotStoreItem) | | | -| `iavl` | [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem) | | | - - - - - - - - -### SnapshotStoreItem -SnapshotStoreItem contains metadata about a snapshotted store. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/base/store/v1beta1/commit_info.proto - - - - - -### CommitID -CommitID defines the committment information when a specific store is -committed. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `hash` | [bytes](#bytes) | | | - - - - - - - - -### CommitInfo -CommitInfo defines commit information used by the multi-store when committing -a version/height. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `version` | [int64](#int64) | | | -| `store_infos` | [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo) | repeated | | - - - - - - - - -### StoreInfo -StoreInfo defines store-specific commit information. It contains a reference -between a store name and the commit ID. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `commit_id` | [CommitID](#cosmos.base.store.v1beta1.CommitID) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/base/v1beta1/coin.proto - - - - - -### Coin -Coin defines a token with a denomination and an amount. - -NOTE: The amount field is an Int which implements the custom method -signatures required by gogoproto. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | - - - - - - - - -### DecCoin -DecCoin defines a token with a denomination and a decimal amount. - -NOTE: The amount field is an Dec which implements the custom method -signatures required by gogoproto. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | | -| `amount` | [string](#string) | | | - - - - - - - - -### DecProto -DecProto defines a Protobuf wrapper around a Dec object. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `dec` | [string](#string) | | | - - - - - - - - -### IntProto -IntProto defines a Protobuf wrapper around an Int object. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `int` | [string](#string) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/base/tendermint/v1beta1/query.proto - - - - - -### GetBlockByHeightRequest -GetBlockByHeightRequest is the request type for the Query/GetBlockByHeight RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | - - - - - - - - -### GetBlockByHeightResponse -GetBlockByHeightResponse is the response type for the Query/GetBlockByHeight RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - - - - - - - - -### GetLatestBlockRequest -GetLatestBlockRequest is the request type for the Query/GetLatestBlock RPC method. - - - - - - - - -### GetLatestBlockResponse -GetLatestBlockResponse is the response type for the Query/GetLatestBlock RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `block_id` | [tendermint.types.BlockID](#tendermint.types.BlockID) | | | -| `block` | [tendermint.types.Block](#tendermint.types.Block) | | | - - - - - - - - -### GetLatestValidatorSetRequest -GetLatestValidatorSetRequest is the request type for the Query/GetValidatorSetByHeight RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - - - - - - - - -### GetLatestValidatorSetResponse -GetLatestValidatorSetResponse is the response type for the Query/GetValidatorSetByHeight RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `block_height` | [int64](#int64) | | | -| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - - - - - - - - -### GetNodeInfoRequest -GetNodeInfoRequest is the request type for the Query/GetNodeInfo RPC method. - - - - - - - - -### GetNodeInfoResponse -GetNodeInfoResponse is the request type for the Query/GetNodeInfo RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `default_node_info` | [tendermint.p2p.DefaultNodeInfo](#tendermint.p2p.DefaultNodeInfo) | | | -| `application_version` | [VersionInfo](#cosmos.base.tendermint.v1beta1.VersionInfo) | | | - - - - - - - - -### GetSyncingRequest -GetSyncingRequest is the request type for the Query/GetSyncing RPC method. - - - - - - - - -### GetSyncingResponse -GetSyncingResponse is the response type for the Query/GetSyncing RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `syncing` | [bool](#bool) | | | - - - - - - - - -### GetValidatorSetByHeightRequest -GetValidatorSetByHeightRequest is the request type for the Query/GetValidatorSetByHeight RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - - - - - - - - -### GetValidatorSetByHeightResponse -GetValidatorSetByHeightResponse is the response type for the Query/GetValidatorSetByHeight RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `block_height` | [int64](#int64) | | | -| `validators` | [Validator](#cosmos.base.tendermint.v1beta1.Validator) | repeated | | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - - - - - - - - -### Module -Module is the type for VersionInfo - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [string](#string) | | module path | -| `version` | [string](#string) | | module version | -| `sum` | [string](#string) | | checksum | - - - - - - - - -### Validator -Validator is the type for the validator-set. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `voting_power` | [int64](#int64) | | | -| `proposer_priority` | [int64](#int64) | | | - - - - - - - - -### VersionInfo -VersionInfo is the type for the GetNodeInfoResponse message. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `name` | [string](#string) | | | -| `app_name` | [string](#string) | | | -| `version` | [string](#string) | | | -| `git_commit` | [string](#string) | | | -| `build_tags` | [string](#string) | | | -| `go_version` | [string](#string) | | | -| `build_deps` | [Module](#cosmos.base.tendermint.v1beta1.Module) | repeated | | +| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | @@ -5398,153 +5372,14 @@ VersionInfo is the type for the GetNodeInfoResponse message. - + -### Service -Service defines the gRPC querier service for tendermint queries. +### Query +Query defines the gRPC querier service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `GetNodeInfo` | [GetNodeInfoRequest](#cosmos.base.tendermint.v1beta1.GetNodeInfoRequest) | [GetNodeInfoResponse](#cosmos.base.tendermint.v1beta1.GetNodeInfoResponse) | GetNodeInfo queries the current node info. | GET|/cosmos/base/tendermint/v1beta1/node_info| -| `GetSyncing` | [GetSyncingRequest](#cosmos.base.tendermint.v1beta1.GetSyncingRequest) | [GetSyncingResponse](#cosmos.base.tendermint.v1beta1.GetSyncingResponse) | GetSyncing queries node syncing. | GET|/cosmos/base/tendermint/v1beta1/syncing| -| `GetLatestBlock` | [GetLatestBlockRequest](#cosmos.base.tendermint.v1beta1.GetLatestBlockRequest) | [GetLatestBlockResponse](#cosmos.base.tendermint.v1beta1.GetLatestBlockResponse) | GetLatestBlock returns the latest block. | GET|/cosmos/base/tendermint/v1beta1/blocks/latest| -| `GetBlockByHeight` | [GetBlockByHeightRequest](#cosmos.base.tendermint.v1beta1.GetBlockByHeightRequest) | [GetBlockByHeightResponse](#cosmos.base.tendermint.v1beta1.GetBlockByHeightResponse) | GetBlockByHeight queries block for given height. | GET|/cosmos/base/tendermint/v1beta1/blocks/{height}| -| `GetLatestValidatorSet` | [GetLatestValidatorSetRequest](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetRequest) | [GetLatestValidatorSetResponse](#cosmos.base.tendermint.v1beta1.GetLatestValidatorSetResponse) | GetLatestValidatorSet queries latest validator-set. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/latest| -| `GetValidatorSetByHeight` | [GetValidatorSetByHeightRequest](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightRequest) | [GetValidatorSetByHeightResponse](#cosmos.base.tendermint.v1beta1.GetValidatorSetByHeightResponse) | GetValidatorSetByHeight queries validator-set at a given height. | GET|/cosmos/base/tendermint/v1beta1/validatorsets/{height}| - - - - - - -

    Top

    - -## cosmos/base/snapshots/v1beta1/snapshot.proto - - - - - -### Metadata -Metadata contains SDK-specific snapshot metadata. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `chunk_hashes` | [bytes](#bytes) | repeated | SHA-256 chunk hashes | - - - - - - - - -### Snapshot -Snapshot contains Tendermint state sync snapshot info. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [uint64](#uint64) | | | -| `format` | [uint32](#uint32) | | | -| `chunks` | [uint32](#uint32) | | | -| `hash` | [bytes](#bytes) | | | -| `metadata` | [Metadata](#cosmos.base.snapshots.v1beta1.Metadata) | | | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/base/reflection/v1beta1/reflection.proto - - - - - -### ListAllInterfacesRequest -ListAllInterfacesRequest is the request type of the ListAllInterfaces RPC. - - - - - - - - -### ListAllInterfacesResponse -ListAllInterfacesResponse is the response type of the ListAllInterfaces RPC. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `interface_names` | [string](#string) | repeated | interface_names is an array of all the registered interfaces. | - - - - - - - - -### ListImplementationsRequest -ListImplementationsRequest is the request type of the ListImplementations -RPC. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `interface_name` | [string](#string) | | interface_name defines the interface to query the implementations for. | - - - - - - - - -### ListImplementationsResponse -ListImplementationsResponse is the response type of the ListImplementations -RPC. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `implementation_message_names` | [string](#string) | repeated | | - - - - - - - - - - - - - - -### ReflectionService -ReflectionService defines a service for interface reflection. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ListAllInterfaces` | [ListAllInterfacesRequest](#cosmos.base.reflection.v1beta1.ListAllInterfacesRequest) | [ListAllInterfacesResponse](#cosmos.base.reflection.v1beta1.ListAllInterfacesResponse) | ListAllInterfaces lists all the interfaces registered in the interface registry. | GET|/cosmos/base/reflection/v1beta1/interfaces| -| `ListImplementations` | [ListImplementationsRequest](#cosmos.base.reflection.v1beta1.ListImplementationsRequest) | [ListImplementationsResponse](#cosmos.base.reflection.v1beta1.ListImplementationsResponse) | ListImplementations list all the concrete types that implement a given interface. | GET|/cosmos/base/reflection/v1beta1/interfaces/{interface_name}/implementations| +| `Params` | [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) | Params queries a specific parameter of a module, given its subspace and key. | GET|/cosmos/params/v1beta1/params| @@ -5596,6 +5431,88 @@ liveness activity. + + + + + + + + + + + +

    Top

    + +## cosmos/slashing/v1beta1/genesis.proto + + + + + +### GenesisState +GenesisState defines the slashing module's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | params defines all the paramaters of related to deposit. | +| `signing_infos` | [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) | repeated | signing_infos represents a map between validator addresses and their signing infos. | +| `missed_blocks` | [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) | repeated | signing_infos represents a map between validator addresses and their missed blocks. | + + + + + + + + +### MissedBlock +MissedBlock contains height and missed status as boolean. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `index` | [int64](#int64) | | index is the height at which the block was missed. | +| `missed` | [bool](#bool) | | missed is the missed status. | + + + + + + + + +### SigningInfo +SigningInfo stores validator signing info of corresponding address. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address is the validator address. | +| `validator_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | validator_signing_info represents the signing info of this validator. | + + + + + + + + +### ValidatorMissedBlocks +ValidatorMissedBlocks contains array of missed blocks of corresponding +address. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address is the validator address. | +| `missed_blocks` | [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) | repeated | missed_blocks is an array of missed blocks by the validator. | + + + + + @@ -5775,359 +5692,379 @@ Msg defines the slashing Msg service. - +

    Top

    -## cosmos/slashing/v1beta1/genesis.proto +## cosmos/staking/v1beta1/staking.proto - + -### GenesisState -GenesisState defines the slashing module's genesis state. +### Commission +Commission defines commission parameters for a given validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.slashing.v1beta1.Params) | | params defines all the paramaters of related to deposit. | -| `signing_infos` | [SigningInfo](#cosmos.slashing.v1beta1.SigningInfo) | repeated | signing_infos represents a map between validator addresses and their signing infos. | -| `missed_blocks` | [ValidatorMissedBlocks](#cosmos.slashing.v1beta1.ValidatorMissedBlocks) | repeated | signing_infos represents a map between validator addresses and their missed blocks. | +| `commission_rates` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | commission_rates defines the initial commission rates to be used for creating a validator. | +| `update_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | update_time is the last time the commission rate was changed. | - + -### MissedBlock -MissedBlock contains height and missed status as boolean. +### CommissionRates +CommissionRates defines the initial commission rates to be used for creating +a validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `index` | [int64](#int64) | | index is the height at which the block was missed. | -| `missed` | [bool](#bool) | | missed is the missed status. | +| `rate` | [string](#string) | | rate is the commission rate charged to delegators, as a fraction. | +| `max_rate` | [string](#string) | | max_rate defines the maximum commission rate which validator can ever charge, as a fraction. | +| `max_change_rate` | [string](#string) | | max_change_rate defines the maximum daily increase of the validator commission, as a fraction. | - + -### SigningInfo -SigningInfo stores validator signing info of corresponding address. +### DVPair +DVPair is struct that just has a delegator-validator pair with no other data. +It is intended to be used as a marshalable pointer. For example, a DVPair can +be used to construct the key to getting an UnbondingDelegation from state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the validator address. | -| `validator_signing_info` | [ValidatorSigningInfo](#cosmos.slashing.v1beta1.ValidatorSigningInfo) | | validator_signing_info represents the signing info of this validator. | +| `delegator_address` | [string](#string) | | | +| `validator_address` | [string](#string) | | | - + -### ValidatorMissedBlocks -ValidatorMissedBlocks contains array of missed blocks of corresponding -address. +### DVPairs +DVPairs defines an array of DVPair objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the validator address. | -| `missed_blocks` | [MissedBlock](#cosmos.slashing.v1beta1.MissedBlock) | repeated | missed_blocks is an array of missed blocks by the validator. | +| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | - - + - - - - - - - -

    Top

    - -## cosmos/evidence/v1beta1/evidence.proto - - - - - -### Equivocation -Equivocation implements the Evidence interface and defines evidence of double -signing misbehavior. +### DVVTriplet +DVVTriplet is struct that just has a delegator-validator-validator triplet +with no other data. It is intended to be used as a marshalable pointer. For +example, a DVVTriplet can be used to construct the key to getting a +Redelegation from state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | -| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `power` | [int64](#int64) | | | -| `consensus_address` | [string](#string) | | | +| `delegator_address` | [string](#string) | | | +| `validator_src_address` | [string](#string) | | | +| `validator_dst_address` | [string](#string) | | | - - + - - - - - - - -

    Top

    - -## cosmos/evidence/v1beta1/query.proto - - - - - -### QueryAllEvidenceRequest -QueryEvidenceRequest is the request type for the Query/AllEvidence RPC -method. +### DVVTriplets +DVVTriplets defines an array of DVVTriplet objects. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. | +| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | - + -### QueryAllEvidenceResponse -QueryAllEvidenceResponse is the response type for the Query/AllEvidence RPC -method. +### Delegation +Delegation represents the bond with tokens held by an account. It is +owned by one delegator, and is associated with the voting power of one +validator. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence returns all evidences. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. | +| `delegator_address` | [string](#string) | | delegator_address is the bech32-encoded address of the delegator. | +| `validator_address` | [string](#string) | | validator_address is the bech32-encoded address of the validator. | +| `shares` | [string](#string) | | shares define the delegation shares received. | - + -### QueryEvidenceRequest -QueryEvidenceRequest is the request type for the Query/Evidence RPC method. +### DelegationResponse +DelegationResponse is equivalent to Delegation except that it contains a +balance in addition to shares which is more suitable for client responses. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence_hash` | [bytes](#bytes) | | evidence_hash defines the hash of the requested evidence. | +| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | +| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - + -### QueryEvidenceResponse -QueryEvidenceResponse is the response type for the Query/Evidence RPC method. +### Description +Description defines a validator description. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | evidence returns the requested evidence. | +| `moniker` | [string](#string) | | moniker defines a human-readable name for the validator. | +| `identity` | [string](#string) | | identity defines an optional identity signature (ex. UPort or Keybase). | +| `website` | [string](#string) | | website defines an optional website link. | +| `security_contact` | [string](#string) | | security_contact defines an optional email for security contact. | +| `details` | [string](#string) | | details define other optional details. | - - + - - - - - -### Query -Query defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Evidence` | [QueryEvidenceRequest](#cosmos.evidence.v1beta1.QueryEvidenceRequest) | [QueryEvidenceResponse](#cosmos.evidence.v1beta1.QueryEvidenceResponse) | Evidence queries evidence based on evidence hash. | GET|/cosmos/evidence/v1beta1/evidence/{evidence_hash}| -| `AllEvidence` | [QueryAllEvidenceRequest](#cosmos.evidence.v1beta1.QueryAllEvidenceRequest) | [QueryAllEvidenceResponse](#cosmos.evidence.v1beta1.QueryAllEvidenceResponse) | AllEvidence queries all evidence. | GET|/cosmos/evidence/v1beta1/evidence| - - - - - - -

    Top

    - -## cosmos/evidence/v1beta1/tx.proto - - - - - -### MsgSubmitEvidence -MsgSubmitEvidence represents a message that supports submitting arbitrary -Evidence of misbehavior such as equivocation or counterfactual signing. +### HistoricalInfo +HistoricalInfo contains header and validator information for a given block. +It is stored as part of staking module's state, which persists the `n` most +recent HistoricalInfo +(`n` is set by the staking module's `historical_entries` parameter). | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `submitter` | [string](#string) | | | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | | | +| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | +| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | - - -### MsgSubmitEvidenceResponse -MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `hash` | [bytes](#bytes) | | hash defines the hash of the evidence. | - - - - - - - - - - - - - - -### Msg -Msg defines the evidence Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `SubmitEvidence` | [MsgSubmitEvidence](#cosmos.evidence.v1beta1.MsgSubmitEvidence) | [MsgSubmitEvidenceResponse](#cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse) | SubmitEvidence submits an arbitrary Evidence of misbehavior such as equivocation or counterfactual signing. | | - - - - - - -

    Top

    - -## cosmos/evidence/v1beta1/genesis.proto - - - - - -### GenesisState -GenesisState defines the evidence module's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `evidence` | [google.protobuf.Any](#google.protobuf.Any) | repeated | evidence defines all the evidence at genesis. | - - - - - - - - - - - - - - - - -

    Top

    - -## cosmos/auth/v1beta1/auth.proto - - - - - -### BaseAccount -BaseAccount defines a base account type. It contains all the necessary fields -for basic account functionality. Any custom account type should extend this -type for additional functionality (e.g. vesting). - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | | -| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `account_number` | [uint64](#uint64) | | | -| `sequence` | [uint64](#uint64) | | | - - - - - - - - -### ModuleAccount -ModuleAccount defines an account for modules that holds coins on a pool. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `base_account` | [BaseAccount](#cosmos.auth.v1beta1.BaseAccount) | | | -| `name` | [string](#string) | | | -| `permissions` | [string](#string) | repeated | | - - - - - - - + ### Params -Params defines the parameters for the auth module. +Params defines the parameters for the staking module. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `max_memo_characters` | [uint64](#uint64) | | | -| `tx_sig_limit` | [uint64](#uint64) | | | -| `tx_size_cost_per_byte` | [uint64](#uint64) | | | -| `sig_verify_cost_ed25519` | [uint64](#uint64) | | | -| `sig_verify_cost_secp256k1` | [uint64](#uint64) | | | +| `unbonding_time` | [google.protobuf.Duration](#google.protobuf.Duration) | | unbonding_time is the time duration of unbonding. | +| `max_validators` | [uint32](#uint32) | | max_validators is the maximum number of validators. | +| `max_entries` | [uint32](#uint32) | | max_entries is the max entries for either unbonding delegation or redelegation (per pair/trio). | +| `historical_entries` | [uint32](#uint32) | | historical_entries is the number of historical entries to persist. | +| `bond_denom` | [string](#string) | | bond_denom defines the bondable coin denomination. | + + + + + + + + +### Pool +Pool is used for tracking bonded and not-bonded token supply of the bond +denomination. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `not_bonded_tokens` | [string](#string) | | | +| `bonded_tokens` | [string](#string) | | | + + + + + + + + +### Redelegation +Redelegation contains the list of a particular delegator's redelegating bonds +from a particular source validator to a particular destination validator. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address is the bech32-encoded address of the delegator. | +| `validator_src_address` | [string](#string) | | validator_src_address is the validator redelegation source operator address. | +| `validator_dst_address` | [string](#string) | | validator_dst_address is the validator redelegation destination operator address. | +| `entries` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | repeated | entries are the redelegation entries. + +redelegation entries | + + + + + + + + +### RedelegationEntry +RedelegationEntry defines a redelegation object with relevant metadata. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `creation_height` | [int64](#int64) | | creation_height defines the height which the redelegation took place. | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | completion_time defines the unix time for redelegation completion. | +| `initial_balance` | [string](#string) | | initial_balance defines the initial balance when redelegation started. | +| `shares_dst` | [string](#string) | | shares_dst is the amount of destination-validator shares created by redelegation. | + + + + + + + + +### RedelegationEntryResponse +RedelegationEntryResponse is equivalent to a RedelegationEntry except that it +contains a balance in addition to shares which is more suitable for client +responses. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | +| `balance` | [string](#string) | | | + + + + + + + + +### RedelegationResponse +RedelegationResponse is equivalent to a Redelegation except that its entries +contain a balance in addition to shares which is more suitable for client +responses. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | +| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | + + + + + + + + +### UnbondingDelegation +UnbondingDelegation stores all of a single delegator's unbonding bonds +for a single validator in an time-ordered list. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `delegator_address` | [string](#string) | | delegator_address is the bech32-encoded address of the delegator. | +| `validator_address` | [string](#string) | | validator_address is the bech32-encoded address of the validator. | +| `entries` | [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) | repeated | entries are the unbonding delegation entries. + +unbonding delegation entries | + + + + + + + + +### UnbondingDelegationEntry +UnbondingDelegationEntry defines an unbonding object with relevant metadata. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `creation_height` | [int64](#int64) | | creation_height is the height which the unbonding took place. | +| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | completion_time is the unix time for unbonding completion. | +| `initial_balance` | [string](#string) | | initial_balance defines the tokens initially scheduled to receive at completion. | +| `balance` | [string](#string) | | balance defines the tokens to receive at completion. | + + + + + + + + +### ValAddresses +ValAddresses defines a repeated set of validator addresses. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `addresses` | [string](#string) | repeated | | + + + + + + + + +### Validator +Validator defines a validator, together with the total amount of the +Validator's bond shares and their exchange rate to coins. Slashing results in +a decrease in the exchange rate, allowing correct calculation of future +undelegations without iterating over delegators. When coins are delegated to +this validator, the validator is credited with a delegation whose number of +bond shares is based on the amount of coins delegated divided by the current +exchange rate. Voting power can be calculated as total bonded shares +multiplied by exchange rate. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `operator_address` | [string](#string) | | operator_address defines the address of the validator's operator; bech encoded in JSON. | +| `consensus_pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | consensus_pubkey is the consensus public key of the validator, as a Protobuf Any. | +| `jailed` | [bool](#bool) | | jailed defined whether the validator has been jailed from bonded status or not. | +| `status` | [BondStatus](#cosmos.staking.v1beta1.BondStatus) | | status is the validator status (bonded/unbonding/unbonded). | +| `tokens` | [string](#string) | | tokens define the delegated tokens (incl. self-delegation). | +| `delegator_shares` | [string](#string) | | delegator_shares defines total shares issued to a validator's delegators. | +| `description` | [Description](#cosmos.staking.v1beta1.Description) | | description defines the description terms for the validator. | +| `unbonding_height` | [int64](#int64) | | unbonding_height defines, if unbonding, the height at which this validator has begun unbonding. | +| `unbonding_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | unbonding_time defines, if unbonding, the min time for the validator to complete unbonding. | +| `commission` | [Commission](#cosmos.staking.v1beta1.Commission) | | commission defines the commission parameters. | +| `min_self_delegation` | [string](#string) | | min_self_delegation is the validator's self declared minimum self delegation. | @@ -6135,6 +6072,20 @@ Params defines the parameters for the auth module. + + + +### BondStatus +BondStatus is the status of a validator. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| BOND_STATUS_UNSPECIFIED | 0 | UNSPECIFIED defines an invalid validator status. | +| BOND_STATUS_UNBONDED | 1 | UNBONDED defines a validator that is not bonded. | +| BOND_STATUS_UNBONDING | 2 | UNBONDING defines a validator that is unbonding. | +| BOND_STATUS_BONDED | 3 | BONDED defines a validator that is bonded. | + + @@ -6143,105 +6094,45 @@ Params defines the parameters for the auth module. - +

    Top

    -## cosmos/auth/v1beta1/query.proto +## cosmos/staking/v1beta1/genesis.proto - - -### QueryAccountRequest -QueryAccountRequest is the request type for the Query/Account RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address defines the address to query for. | - - - - - - - - -### QueryAccountResponse -QueryAccountResponse is the response type for the Query/Account RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `account` | [google.protobuf.Any](#google.protobuf.Any) | | account defines the account of the corresponding address. | - - - - - - - - -### QueryParamsRequest -QueryParamsRequest is the request type for the Query/Params RPC method. - - - - - - - - -### QueryParamsResponse -QueryParamsResponse is the response type for the Query/Params RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines the parameters of the module. | - - - - - - - - - - - - - - -### Query -Query defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Account` | [QueryAccountRequest](#cosmos.auth.v1beta1.QueryAccountRequest) | [QueryAccountResponse](#cosmos.auth.v1beta1.QueryAccountResponse) | Account returns account details based on address. | GET|/cosmos/auth/v1beta1/accounts/{address}| -| `Params` | [QueryParamsRequest](#cosmos.auth.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.auth.v1beta1.QueryParamsResponse) | Params queries all parameters. | GET|/cosmos/auth/v1beta1/params| - - - - - - -

    Top

    - -## cosmos/auth/v1beta1/genesis.proto - - - - + ### GenesisState -GenesisState defines the auth module's genesis state. +GenesisState defines the staking module's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.auth.v1beta1.Params) | | params defines all the paramaters of the module. | -| `accounts` | [google.protobuf.Any](#google.protobuf.Any) | repeated | accounts are the accounts present at genesis. | +| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params defines all the paramaters of related to deposit. | +| `last_total_power` | [bytes](#bytes) | | last_total_power tracks the total amounts of bonded tokens recorded during the previous end block. | +| `last_validator_powers` | [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) | repeated | last_validator_powers is a special index that provides a historical list of the last-block's bonded validators. | +| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | delegations defines the validator set at genesis. | +| `delegations` | [Delegation](#cosmos.staking.v1beta1.Delegation) | repeated | delegations defines the delegations active at genesis. | +| `unbonding_delegations` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | unbonding_delegations defines the unbonding delegations active at genesis. | +| `redelegations` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | repeated | redelegations defines the redelegations active at genesis. | +| `exported` | [bool](#bool) | | | + + + + + + + + +### LastValidatorPower +LastValidatorPower required for validator set update logic. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `address` | [string](#string) | | address is the address of the validator. | +| `power` | [int64](#int64) | | power defines the power of the validator. | @@ -6927,45 +6818,299 @@ Msg defines the staking Msg service. - +

    Top

    -## cosmos/staking/v1beta1/genesis.proto +## cosmos/tx/signing/v1beta1/signing.proto - + -### GenesisState -GenesisState defines the staking module's genesis state. +### SignatureDescriptor +SignatureDescriptor is a convenience type which represents the full data for +a signature including the public key of the signer, signing modes and the +signature itself. It is primarily used for coordinating signatures between +clients. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#cosmos.staking.v1beta1.Params) | | params defines all the paramaters of related to deposit. | -| `last_total_power` | [bytes](#bytes) | | last_total_power tracks the total amounts of bonded tokens recorded during the previous end block. | -| `last_validator_powers` | [LastValidatorPower](#cosmos.staking.v1beta1.LastValidatorPower) | repeated | last_validator_powers is a special index that provides a historical list of the last-block's bonded validators. | -| `validators` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | delegations defines the validator set at genesis. | -| `delegations` | [Delegation](#cosmos.staking.v1beta1.Delegation) | repeated | delegations defines the delegations active at genesis. | -| `unbonding_delegations` | [UnbondingDelegation](#cosmos.staking.v1beta1.UnbondingDelegation) | repeated | unbonding_delegations defines the unbonding delegations active at genesis. | -| `redelegations` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | repeated | redelegations defines the redelegations active at genesis. | -| `exported` | [bool](#bool) | | | +| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer | +| `data` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | | | +| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | - + -### LastValidatorPower -LastValidatorPower required for validator set update logic. +### SignatureDescriptor.Data +Data represents signature data | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `address` | [string](#string) | | address is the address of the validator. | -| `power` | [int64](#int64) | | power defines the power of the validator. | +| `single` | [SignatureDescriptor.Data.Single](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Single) | | single represents a single signer | +| `multi` | [SignatureDescriptor.Data.Multi](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data.Multi) | | multi represents a multisig signer | + + + + + + + + +### SignatureDescriptor.Data.Multi +Multi is the signature data for a multisig public key + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | +| `signatures` | [SignatureDescriptor.Data](#cosmos.tx.signing.v1beta1.SignatureDescriptor.Data) | repeated | signatures is the signatures of the multi-signature | + + + + + + + + +### SignatureDescriptor.Data.Single +Single is the signature data for a single signer + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `mode` | [SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | +| `signature` | [bytes](#bytes) | | signature is the raw signature bytes | + + + + + + + + +### SignatureDescriptors +SignatureDescriptors wraps multiple SignatureDescriptor's. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `signatures` | [SignatureDescriptor](#cosmos.tx.signing.v1beta1.SignatureDescriptor) | repeated | signatures are the signature descriptors | + + + + + + + + + + +### SignMode +SignMode represents a signing mode with its own security guarantees. + +| Name | Number | Description | +| ---- | ------ | ----------- | +| SIGN_MODE_UNSPECIFIED | 0 | SIGN_MODE_UNSPECIFIED specifies an unknown signing mode and will be rejected | +| SIGN_MODE_DIRECT | 1 | SIGN_MODE_DIRECT specifies a signing mode which uses SignDoc and is verified with raw bytes from Tx | +| SIGN_MODE_TEXTUAL | 2 | SIGN_MODE_TEXTUAL is a future signing mode that will verify some human-readable textual representation on top of the binary representation from SIGN_MODE_DIRECT | +| SIGN_MODE_LEGACY_AMINO_JSON | 127 | SIGN_MODE_LEGACY_AMINO_JSON is a backwards compatibility mode which uses Amino JSON and will be removed in the future | + + + + + + + + + + + +

    Top

    + +## cosmos/tx/v1beta1/tx.proto + + + + + +### AuthInfo +AuthInfo describes the fee and signer modes that are used to sign a +transaction. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `signer_infos` | [SignerInfo](#cosmos.tx.v1beta1.SignerInfo) | repeated | signer_infos defines the signing modes for the required signers. The number and order of elements must match the required signers from TxBody's messages. The first element is the primary signer and the one which pays the fee. | +| `fee` | [Fee](#cosmos.tx.v1beta1.Fee) | | Fee is the fee and gas limit for the transaction. The first signer is the primary signer and the one which pays the fee. The fee can be calculated based on the cost of evaluating the body and doing signature verification of the signers. This can be estimated via simulation. | + + + + + + + + +### Fee +Fee includes the amount of coins paid in fees and the maximum +gas to be used by the transaction. The ratio yields an effective "gasprice", +which must be above some miminum to be accepted into the mempool. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `amount` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | amount is the amount of coins to be paid as a fee | +| `gas_limit` | [uint64](#uint64) | | gas_limit is the maximum gas that can be used in transaction processing before an out of gas error occurs | +| `payer` | [string](#string) | | if unset, the first signer is responsible for paying the fees. If set, the specified account must pay the fees. the payer must be a tx signer (and thus have signed this field in AuthInfo). setting this field does *not* change the ordering of required signers for the transaction. | +| `granter` | [string](#string) | | if set, the fee payer (either the first signer or the value of the payer field) requests that a fee grant be used to pay fees instead of the fee payer's own balance. If an appropriate fee grant does not exist or the chain does not support fee grants, this will fail | + + + + + + + + +### ModeInfo +ModeInfo describes the signing mode of a single or nested multisig signer. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `single` | [ModeInfo.Single](#cosmos.tx.v1beta1.ModeInfo.Single) | | single represents a single signer | +| `multi` | [ModeInfo.Multi](#cosmos.tx.v1beta1.ModeInfo.Multi) | | multi represents a nested multisig signer | + + + + + + + + +### ModeInfo.Multi +Multi is the mode info for a multisig public key + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `bitarray` | [cosmos.crypto.multisig.v1beta1.CompactBitArray](#cosmos.crypto.multisig.v1beta1.CompactBitArray) | | bitarray specifies which keys within the multisig are signing | +| `mode_infos` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | repeated | mode_infos is the corresponding modes of the signers of the multisig which could include nested multisig public keys | + + + + + + + + +### ModeInfo.Single +Single is the mode info for a single signer. It is structured as a message +to allow for additional fields such as locale for SIGN_MODE_TEXTUAL in the +future + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `mode` | [cosmos.tx.signing.v1beta1.SignMode](#cosmos.tx.signing.v1beta1.SignMode) | | mode is the signing mode of the single signer | + + + + + + + + +### SignDoc +SignDoc is the type used for generating sign bytes for SIGN_MODE_DIRECT. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `body_bytes` | [bytes](#bytes) | | body_bytes is protobuf serialization of a TxBody that matches the representation in TxRaw. | +| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in TxRaw. | +| `chain_id` | [string](#string) | | chain_id is the unique identifier of the chain this transaction targets. It prevents signed transactions from being used on another chain by an attacker | +| `account_number` | [uint64](#uint64) | | account_number is the account number of the account in state | + + + + + + + + +### SignerInfo +SignerInfo describes the public key and signing mode of a single top-level +signer. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `public_key` | [google.protobuf.Any](#google.protobuf.Any) | | public_key is the public key of the signer. It is optional for accounts that already exist in state. If unset, the verifier can use the required \ signer address for this position and lookup the public key. | +| `mode_info` | [ModeInfo](#cosmos.tx.v1beta1.ModeInfo) | | mode_info describes the signing mode of the signer and is a nested structure to support nested multisig pubkey's | +| `sequence` | [uint64](#uint64) | | sequence is the sequence of the account, which describes the number of committed transactions signed by a given address. It is used to prevent replay attacks. | + + + + + + + + +### Tx +Tx is the standard type used for broadcasting transactions. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `body` | [TxBody](#cosmos.tx.v1beta1.TxBody) | | body is the processable content of the transaction | +| `auth_info` | [AuthInfo](#cosmos.tx.v1beta1.AuthInfo) | | auth_info is the authorization related content of the transaction, specifically signers, signer modes and fee | +| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | + + + + + + + + +### TxBody +TxBody is the body of a transaction that all signers sign over. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `messages` | [google.protobuf.Any](#google.protobuf.Any) | repeated | messages is a list of messages to be executed. The required signers of those messages define the number and order of elements in AuthInfo's signer_infos and Tx's signatures. Each required signer address is added to the list only the first time it occurs. By convention, the first required signer (usually from the first message) is referred to as the primary signer and pays the fee for the whole transaction. | +| `memo` | [string](#string) | | memo is any arbitrary memo to be added to the transaction | +| `timeout_height` | [uint64](#uint64) | | timeout is the block height after which this transaction will not be processed by the chain | +| `extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, the transaction will be rejected | +| `non_critical_extension_options` | [google.protobuf.Any](#google.protobuf.Any) | repeated | extension_options are arbitrary options that can be added by chains when the default options are not sufficient. If any of these are present and can't be handled, they will be ignored | + + + + + + + + +### TxRaw +TxRaw is a variant of Tx that pins the signer's exact binary representation +of body and auth_info. This is used for signing, broadcasting and +verification. The binary `serialize(tx: TxRaw)` is stored in Tendermint and +the hash `sha256(serialize(tx: TxRaw))` becomes the "txhash", commonly used +as the transaction ID. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `body_bytes` | [bytes](#bytes) | | body_bytes is a protobuf serialization of a TxBody that matches the representation in SignDoc. | +| `auth_info_bytes` | [bytes](#bytes) | | auth_info_bytes is a protobuf serialization of an AuthInfo that matches the representation in SignDoc. | +| `signatures` | [bytes](#bytes) | repeated | signatures is a list of signatures that matches the length and order of AuthInfo's signer_infos to allow connecting signature meta information like public key and signing mode by position. | @@ -6981,375 +7126,140 @@ LastValidatorPower required for validator set update logic. - +

    Top

    -## cosmos/staking/v1beta1/staking.proto +## cosmos/tx/v1beta1/service.proto - + -### Commission -Commission defines commission parameters for a given validator. +### BroadcastTxRequest +BroadcastTxRequest is the request type for the Service.BroadcastTxRequest +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `commission_rates` | [CommissionRates](#cosmos.staking.v1beta1.CommissionRates) | | | -| `update_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | +| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. | +| `mode` | [BroadcastMode](#cosmos.tx.v1beta1.BroadcastMode) | | | - + -### CommissionRates -CommissionRates defines the initial commission rates to be used for creating -a validator. +### BroadcastTxResponse +BroadcastTxResponse is the response type for the +Service.BroadcastTx method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `rate` | [string](#string) | | | -| `max_rate` | [string](#string) | | | -| `max_change_rate` | [string](#string) | | | +| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - + -### DVPair -DVPair is struct that just has a delegator-validator pair with no other data. -It is intended to be used as a marshalable pointer. For example, a DVPair can -be used to construct the key to getting an UnbondingDelegation from state. +### GetTxRequest +GetTxRequest is the request type for the Service.GetTx +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | +| `hash` | [string](#string) | | hash is the tx hash to query, encoded as a hex string. | - + -### DVPairs -DVPairs defines an array of DVPair objects. +### GetTxResponse +GetTxResponse is the response type for the Service.GetTx method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `pairs` | [DVPair](#cosmos.staking.v1beta1.DVPair) | repeated | | +| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the queried transaction. | +| `tx_response` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | | tx_response is the queried TxResponses. | - + -### DVVTriplet -DVVTriplet is struct that just has a delegator-validator-validator triplet -with no other data. It is intended to be used as a marshalable pointer. For -example, a DVVTriplet can be used to construct the key to getting a -Redelegation from state. +### GetTxsEventRequest +GetTxsEventRequest is the request type for the Service.TxsByEvents +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | +| `events` | [string](#string) | repeated | events is the list of transaction event type. | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an pagination for the request. | - + -### DVVTriplets -DVVTriplets defines an array of DVVTriplet objects. +### GetTxsEventResponse +GetTxsEventResponse is the response type for the Service.TxsByEvents +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `triplets` | [DVVTriplet](#cosmos.staking.v1beta1.DVVTriplet) | repeated | | +| `txs` | [Tx](#cosmos.tx.v1beta1.Tx) | repeated | txs is the list of queried transactions. | +| `tx_responses` | [cosmos.base.abci.v1beta1.TxResponse](#cosmos.base.abci.v1beta1.TxResponse) | repeated | tx_responses is the list of queried TxResponses. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines an pagination for the response. | - + -### Delegation -Delegation represents the bond with tokens held by an account. It is -owned by one delegator, and is associated with the voting power of one -validator. +### SimulateRequest +SimulateRequest is the request type for the Service.Simulate +RPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `shares` | [string](#string) | | | +| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. | - + -### DelegationResponse -DelegationResponse is equivalent to Delegation except that it contains a -balance in addition to shares which is more suitable for client responses. +### SimulateResponse +SimulateResponse is the response type for the +Service.SimulateRPC method. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `delegation` | [Delegation](#cosmos.staking.v1beta1.Delegation) | | | -| `balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | | - - - - - - - - -### Description -Description defines a validator description. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `moniker` | [string](#string) | | | -| `identity` | [string](#string) | | | -| `website` | [string](#string) | | | -| `security_contact` | [string](#string) | | | -| `details` | [string](#string) | | | - - - - - - - - -### HistoricalInfo -HistoricalInfo contains header and validator information for a given block. -It is stored as part of staking module's state, which persists the `n` most -recent HistoricalInfo -(`n` is set by the staking module's `historical_entries` parameter). - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `header` | [tendermint.types.Header](#tendermint.types.Header) | | | -| `valset` | [Validator](#cosmos.staking.v1beta1.Validator) | repeated | | - - - - - - - - -### Params -Params defines the parameters for the staking module. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `unbonding_time` | [google.protobuf.Duration](#google.protobuf.Duration) | | | -| `max_validators` | [uint32](#uint32) | | | -| `max_entries` | [uint32](#uint32) | | | -| `historical_entries` | [uint32](#uint32) | | | -| `bond_denom` | [string](#string) | | | - - - - - - - - -### Pool -Pool is used for tracking bonded and not-bonded token supply of the bond -denomination. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `not_bonded_tokens` | [string](#string) | | | -| `bonded_tokens` | [string](#string) | | | - - - - - - - - -### Redelegation -Redelegation contains the list of a particular delegator's redelegating bonds -from a particular source validator to a particular destination validator. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_src_address` | [string](#string) | | | -| `validator_dst_address` | [string](#string) | | | -| `entries` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | repeated | redelegation entries | - - - - - - - - -### RedelegationEntry -RedelegationEntry defines a redelegation object with relevant metadata. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `creation_height` | [int64](#int64) | | | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `initial_balance` | [string](#string) | | | -| `shares_dst` | [string](#string) | | | - - - - - - - - -### RedelegationEntryResponse -RedelegationEntryResponse is equivalent to a RedelegationEntry except that it -contains a balance in addition to shares which is more suitable for client -responses. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `redelegation_entry` | [RedelegationEntry](#cosmos.staking.v1beta1.RedelegationEntry) | | | -| `balance` | [string](#string) | | | - - - - - - - - -### RedelegationResponse -RedelegationResponse is equivalent to a Redelegation except that its entries -contain a balance in addition to shares which is more suitable for client -responses. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `redelegation` | [Redelegation](#cosmos.staking.v1beta1.Redelegation) | | | -| `entries` | [RedelegationEntryResponse](#cosmos.staking.v1beta1.RedelegationEntryResponse) | repeated | | - - - - - - - - -### UnbondingDelegation -UnbondingDelegation stores all of a single delegator's unbonding bonds -for a single validator in an time-ordered list. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `delegator_address` | [string](#string) | | | -| `validator_address` | [string](#string) | | | -| `entries` | [UnbondingDelegationEntry](#cosmos.staking.v1beta1.UnbondingDelegationEntry) | repeated | unbonding delegation entries | - - - - - - - - -### UnbondingDelegationEntry -UnbondingDelegationEntry defines an unbonding object with relevant metadata. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `creation_height` | [int64](#int64) | | | -| `completion_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `initial_balance` | [string](#string) | | | -| `balance` | [string](#string) | | | - - - - - - - - -### ValAddresses -ValAddresses defines a repeated set of validator addresses. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `addresses` | [string](#string) | repeated | | - - - - - - - - -### Validator -Validator defines a validator, together with the total amount of the -Validator's bond shares and their exchange rate to coins. Slashing results in -a decrease in the exchange rate, allowing correct calculation of future -undelegations without iterating over delegators. When coins are delegated to -this validator, the validator is credited with a delegation whose number of -bond shares is based on the amount of coins delegated divided by the current -exchange rate. Voting power can be calculated as total bonded shares -multiplied by exchange rate. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `operator_address` | [string](#string) | | | -| `consensus_pubkey` | [google.protobuf.Any](#google.protobuf.Any) | | | -| `jailed` | [bool](#bool) | | | -| `status` | [BondStatus](#cosmos.staking.v1beta1.BondStatus) | | | -| `tokens` | [string](#string) | | | -| `delegator_shares` | [string](#string) | | | -| `description` | [Description](#cosmos.staking.v1beta1.Description) | | | -| `unbonding_height` | [int64](#int64) | | | -| `unbonding_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | | -| `commission` | [Commission](#cosmos.staking.v1beta1.Commission) | | | -| `min_self_delegation` | [string](#string) | | | +| `gas_info` | [cosmos.base.abci.v1beta1.GasInfo](#cosmos.base.abci.v1beta1.GasInfo) | | gas_info is the information about gas used in the simulation. | +| `result` | [cosmos.base.abci.v1beta1.Result](#cosmos.base.abci.v1beta1.Result) | | result is the result of the simulation. | @@ -7358,23 +7268,225 @@ multiplied by exchange rate. - + -### BondStatus -BondStatus is the status of a validator. +### BroadcastMode +BroadcastMode specifies the broadcast mode for the TxService.Broadcast RPC method. | Name | Number | Description | | ---- | ------ | ----------- | -| BOND_STATUS_UNSPECIFIED | 0 | UNSPECIFIED defines an invalid validator status. | -| BOND_STATUS_UNBONDED | 1 | UNBONDED defines a validator that is not bonded. | -| BOND_STATUS_UNBONDING | 2 | UNBONDING defines a validator that is unbonding. | -| BOND_STATUS_BONDED | 3 | BONDED defines a validator that is bonded. | +| BROADCAST_MODE_UNSPECIFIED | 0 | zero-value for mode ordering | +| BROADCAST_MODE_BLOCK | 1 | BROADCAST_MODE_BLOCK defines a tx broadcasting mode where the client waits for the tx to be committed in a block. | +| BROADCAST_MODE_SYNC | 2 | BROADCAST_MODE_SYNC defines a tx broadcasting mode where the client waits for a CheckTx execution response only. | +| BROADCAST_MODE_ASYNC | 3 | BROADCAST_MODE_ASYNC defines a tx broadcasting mode where the client returns immediately. | + + + +### Service +Service defines a gRPC service for interacting with transactions. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `Simulate` | [SimulateRequest](#cosmos.tx.v1beta1.SimulateRequest) | [SimulateResponse](#cosmos.tx.v1beta1.SimulateResponse) | Simulate simulates executing a transaction for estimating gas usage. | POST|/cosmos/tx/v1beta1/simulate| +| `GetTx` | [GetTxRequest](#cosmos.tx.v1beta1.GetTxRequest) | [GetTxResponse](#cosmos.tx.v1beta1.GetTxResponse) | GetTx fetches a tx by hash. | GET|/cosmos/tx/v1beta1/txs/{hash}| +| `BroadcastTx` | [BroadcastTxRequest](#cosmos.tx.v1beta1.BroadcastTxRequest) | [BroadcastTxResponse](#cosmos.tx.v1beta1.BroadcastTxResponse) | BroadcastTx broadcast transaction. | POST|/cosmos/tx/v1beta1/txs| +| `GetTxsEvent` | [GetTxsEventRequest](#cosmos.tx.v1beta1.GetTxsEventRequest) | [GetTxsEventResponse](#cosmos.tx.v1beta1.GetTxsEventResponse) | GetTxsEvent fetches txs by event. | GET|/cosmos/tx/v1beta1/txs| + + + + + + +

    Top

    + +## cosmos/upgrade/v1beta1/upgrade.proto + + + + + +### CancelSoftwareUpgradeProposal +CancelSoftwareUpgradeProposal is a gov Content type for cancelling a software +upgrade. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | + + + + + + + + +### Plan +Plan specifies information about a planned upgrade and when it should occur. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `name` | [string](#string) | | Sets the name for the upgrade. This name will be used by the upgraded version of the software to apply any special "on-upgrade" commands during the first BeginBlock method after the upgrade is applied. It is also used to detect whether a software version can handle a given upgrade. If no upgrade handler with this name has been set in the software, it will be assumed that the software is out-of-date when the upgrade Time or Height is reached and the software will exit. | +| `time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | The time after which the upgrade must be performed. Leave set to its zero value to use a pre-defined Height instead. | +| `height` | [int64](#int64) | | The height at which the upgrade must be performed. Only used if Time is not set. | +| `info` | [string](#string) | | Any application specific upgrade info to be included on-chain such as a git commit that validators could automatically upgrade to | +| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | IBC-enabled chains can opt-in to including the upgraded client state in its upgrade plan This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connecting chains can verify that the new upgraded client is valid by verifying a proof on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades | + + + + + + + + +### SoftwareUpgradeProposal +SoftwareUpgradeProposal is a gov Content type for initiating a software +upgrade. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `title` | [string](#string) | | | +| `description` | [string](#string) | | | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | | + + + + + + + + + + + + + + + + +

    Top

    + +## cosmos/upgrade/v1beta1/query.proto + + + + + +### QueryAppliedPlanRequest +QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `name` | [string](#string) | | name is the name of the applied plan to query for. | + + + + + + + + +### QueryAppliedPlanResponse +QueryAppliedPlanResponse is the response type for the Query/AppliedPlan RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `height` | [int64](#int64) | | height is the block height at which the plan was applied. | + + + + + + + + +### QueryCurrentPlanRequest +QueryCurrentPlanRequest is the request type for the Query/CurrentPlan RPC +method. + + + + + + + + +### QueryCurrentPlanResponse +QueryCurrentPlanResponse is the response type for the Query/CurrentPlan RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `plan` | [Plan](#cosmos.upgrade.v1beta1.Plan) | | plan is the current upgrade plan. | + + + + + + + + +### QueryUpgradedConsensusStateRequest +QueryUpgradedConsensusStateRequest is the request type for the Query/UpgradedConsensusState +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `last_height` | [int64](#int64) | | last height of the current chain must be sent in request as this is the height under which next consensus state is stored | + + + + + + + + +### QueryUpgradedConsensusStateResponse +QueryUpgradedConsensusStateResponse is the response type for the Query/UpgradedConsensusState +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `upgraded_consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | | + + + + + + + + + + + + + + +### Query +Query defines the gRPC upgrade querier service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CurrentPlan` | [QueryCurrentPlanRequest](#cosmos.upgrade.v1beta1.QueryCurrentPlanRequest) | [QueryCurrentPlanResponse](#cosmos.upgrade.v1beta1.QueryCurrentPlanResponse) | CurrentPlan queries the current upgrade plan. | GET|/cosmos/upgrade/v1beta1/current_plan| +| `AppliedPlan` | [QueryAppliedPlanRequest](#cosmos.upgrade.v1beta1.QueryAppliedPlanRequest) | [QueryAppliedPlanResponse](#cosmos.upgrade.v1beta1.QueryAppliedPlanResponse) | AppliedPlan queries a previously applied upgrade plan by its name. | GET|/cosmos/upgrade/v1beta1/applied_plan/{name}| +| `UpgradedConsensusState` | [QueryUpgradedConsensusStateRequest](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateRequest) | [QueryUpgradedConsensusStateResponse](#cosmos.upgrade.v1beta1.QueryUpgradedConsensusStateResponse) | UpgradedConsensusState queries the consensus state that will serve as a trusted kernel for the next version of this chain. It will only be stored at the last height of this chain. UpgradedConsensusState RPC not supported with legacy querier | GET|/cosmos/upgrade/v1beta1/upgraded_consensus_state/{last_height}| + @@ -7539,38 +7651,63 @@ periodically vests by unlocking coins during each specified period. - +

    Top

    -## cosmos/params/v1beta1/query.proto +## ibc/applications/transfer/v1/transfer.proto - + -### QueryParamsRequest -QueryParamsRequest is request type for the Query/Params RPC method. +### DenomTrace +DenomTrace contains the base denomination for ICS20 fungible tokens and the +source tracing information path. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `subspace` | [string](#string) | | subspace defines the module to query the parameter for. | -| `key` | [string](#string) | | key defines the key of the parameter in the subspace. | +| `path` | [string](#string) | | path defines the chain of port/channel identifiers used for tracing the source of the fungible token. | +| `base_denom` | [string](#string) | | base denomination of the relayed fungible token. | - + -### QueryParamsResponse -QueryParamsResponse is response type for the Query/Params RPC method. +### FungibleTokenPacketData +FungibleTokenPacketData defines a struct for the packet payload +See FungibleTokenPacketData spec: +https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `param` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | | param defines the queried parameter. | +| `denom` | [string](#string) | | the token denomination to be transferred | +| `amount` | [uint64](#uint64) | | the token amount to be transferred | +| `sender` | [string](#string) | | the sender address | +| `receiver` | [string](#string) | | the recipient address on the destination chain | + + + + + + + + +### Params +Params defines the set of IBC transfer parameters. +NOTE: To prevent a single token from being transferred, set the +TransfersEnabled parameter to true and then set the bank module's SendEnabled +parameter for the denomination to false. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `send_enabled` | [bool](#bool) | | send_enabled enables or disables all cross-chain token transfers from this chain. | +| `receive_enabled` | [bool](#bool) | | receive_enabled enables or disables all cross-chain token transfers to this chain. | @@ -7582,56 +7719,28 @@ QueryParamsResponse is response type for the Query/Params RPC method. - - - -### Query -Query defines the gRPC querier service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Params` | [QueryParamsRequest](#cosmos.params.v1beta1.QueryParamsRequest) | [QueryParamsResponse](#cosmos.params.v1beta1.QueryParamsResponse) | Params queries a specific parameter of a module, given its subspace and key. | GET|/cosmos/params/v1beta1/params| - - +

    Top

    -## cosmos/params/v1beta1/params.proto +## ibc/applications/transfer/v1/genesis.proto - + -### ParamChange -ParamChange defines an individual parameter change, for use in -ParameterChangeProposal. +### GenesisState +GenesisState defines the ibc-transfer genesis state | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `subspace` | [string](#string) | | | -| `key` | [string](#string) | | | -| `value` | [string](#string) | | | - - - - - - - - -### ParameterChangeProposal -ParameterChangeProposal defines a proposal to change one or more parameters. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `title` | [string](#string) | | | -| `description` | [string](#string) | | | -| `changes` | [ParamChange](#cosmos.params.v1beta1.ParamChange) | repeated | | +| `port_id` | [string](#string) | | | +| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | +| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | @@ -7765,170 +7874,6 @@ Query provides defines the gRPC querier service. - -

    Top

    - -## ibc/applications/transfer/v1/tx.proto - - - - - -### MsgTransfer -MsgTransfer defines a msg to transfer fungible tokens (i.e Coins) between -ICS20 enabled chains. See ICS Spec here: -https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `source_port` | [string](#string) | | the port on which the packet will be sent | -| `source_channel` | [string](#string) | | the channel by which the packet will be sent | -| `token` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | the tokens to be transferred | -| `sender` | [string](#string) | | the sender address | -| `receiver` | [string](#string) | | the recipient address on the destination chain | -| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Timeout height relative to the current block height. The timeout is disabled when set to 0. | -| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp (in nanoseconds) relative to the current block timestamp. The timeout is disabled when set to 0. | - - - - - - - - -### MsgTransferResponse -MsgTransferResponse defines the Msg/Transfer response type. - - - - - - - - - - - - - - -### Msg -Msg defines the ibc/transfer Msg service. - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `Transfer` | [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) | [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) | Transfer defines a rpc handler method for MsgTransfer. | | - - - - - - -

    Top

    - -## ibc/applications/transfer/v1/transfer.proto - - - - - -### DenomTrace -DenomTrace contains the base denomination for ICS20 fungible tokens and the -source tracing information path. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `path` | [string](#string) | | path defines the chain of port/channel identifiers used for tracing the source of the fungible token. | -| `base_denom` | [string](#string) | | base denomination of the relayed fungible token. | - - - - - - - - -### FungibleTokenPacketData -FungibleTokenPacketData defines a struct for the packet payload -See FungibleTokenPacketData spec: -https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `denom` | [string](#string) | | the token denomination to be transferred | -| `amount` | [uint64](#uint64) | | the token amount to be transferred | -| `sender` | [string](#string) | | the sender address | -| `receiver` | [string](#string) | | the recipient address on the destination chain | - - - - - - - - -### Params -Params defines the set of IBC transfer parameters. -NOTE: To prevent a single token from being transferred, set the -TransfersEnabled parameter to true and then set the bank module's SendEnabled -parameter for the denomination to false. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `send_enabled` | [bool](#bool) | | send_enabled enables or disables all cross-chain token transfers from this chain. | -| `receive_enabled` | [bool](#bool) | | receive_enabled enables or disables all cross-chain token transfers to this chain. | - - - - - - - - - - - - - - - - -

    Top

    - -## ibc/applications/transfer/v1/genesis.proto - - - - - -### GenesisState -GenesisState defines the ibc-transfer genesis state - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `denom_traces` | [DenomTrace](#ibc.applications.transfer.v1.DenomTrace) | repeated | | -| `params` | [Params](#ibc.applications.transfer.v1.Params) | | | - - - - - - - - - - - - - - -

    Top

    @@ -8054,172 +7999,40 @@ Params defines the set of IBC light client parameters. - +

    Top

    -## ibc/core/client/v1/query.proto +## ibc/applications/transfer/v1/tx.proto - + -### QueryClientParamsRequest -QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. - - - - - - - - -### QueryClientParamsResponse -QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. +### MsgTransfer +MsgTransfer defines a msg to transfer fungible tokens (i.e Coins) between +ICS20 enabled chains. See ICS Spec here: +https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | +| `source_port` | [string](#string) | | the port on which the packet will be sent | +| `source_channel` | [string](#string) | | the channel by which the packet will be sent | +| `token` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | the tokens to be transferred | +| `sender` | [string](#string) | | the sender address | +| `receiver` | [string](#string) | | the recipient address on the destination chain | +| `timeout_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Timeout height relative to the current block height. The timeout is disabled when set to 0. | +| `timeout_timestamp` | [uint64](#uint64) | | Timeout timestamp (in nanoseconds) relative to the current block timestamp. The timeout is disabled when set to 0. | - + -### QueryClientStateRequest -QueryClientStateRequest is the request type for the Query/ClientState RPC -method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client state unique identifier | - - - - - - - - -### QueryClientStateResponse -QueryClientStateResponse is the response type for the Query/ClientState RPC -method. Besides the client state, it includes a proof and the height from -which the proof was retrieved. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state associated with the request identifier | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - - - - - - - - -### QueryClientStatesRequest -QueryClientStatesRequest is the request type for the Query/ClientStates RPC -method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - - - - - - - -### QueryClientStatesResponse -QueryClientStatesResponse is the response type for the Query/ClientStates RPC -method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_states` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | list of stored ClientStates of the chain. | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | - - - - - - - - -### QueryConsensusStateRequest -QueryConsensusStateRequest is the request type for the Query/ConsensusState -RPC method. Besides the consensus state, it includes a proof and the height -from which the proof was retrieved. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `revision_number` | [uint64](#uint64) | | consensus state revision number | -| `revision_height` | [uint64](#uint64) | | consensus state revision height | -| `latest_height` | [bool](#bool) | | latest_height overrrides the height field and queries the latest stored ConsensusState | - - - - - - - - -### QueryConsensusStateResponse -QueryConsensusStateResponse is the response type for the Query/ConsensusState -RPC method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client identifier at the given height | -| `proof` | [bytes](#bytes) | | merkle proof of existence | -| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | - - - - - - - - -### QueryConsensusStatesRequest -QueryConsensusStatesRequest is the request type for the Query/ConsensusStates -RPC method. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | - - - - - - - - -### QueryConsensusStatesResponse -QueryConsensusStatesResponse is the response type for the -Query/ConsensusStates RPC method - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states associated with the identifier | -| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | +### MsgTransferResponse +MsgTransferResponse defines the Msg/Transfer response type. @@ -8232,229 +8045,14 @@ Query/ConsensusStates RPC method - - -### Query -Query provides defines the gRPC querier service - -| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | -| ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `ClientState` | [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) | [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) | ClientState queries an IBC light client. | GET|/ibc/core/client/v1beta1/client_states/{client_id}| -| `ClientStates` | [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) | [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) | ClientStates queries all the IBC light clients of a chain. | GET|/ibc/core/client/v1beta1/client_states| -| `ConsensusState` | [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) | [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) | ConsensusState queries a consensus state associated with a client state at a given height. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}/revision/{revision_number}/height/{revision_height}| -| `ConsensusStates` | [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) | [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) | ConsensusStates queries all the consensus state associated with a given client. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}| -| `ClientParams` | [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) | [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) | ClientParams queries all parameters of the ibc client. | GET|/ibc/client/v1beta1/params| - - - - - - -

    Top

    - -## ibc/core/client/v1/tx.proto - - - - - -### MsgCreateClient -MsgCreateClient defines a message to create an IBC client - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | light client state | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client that corresponds to a given height. | -| `signer` | [string](#string) | | signer address | - - - - - - - - -### MsgCreateClientResponse -MsgCreateClientResponse defines the Msg/CreateClient response type. - - - - - - - - -### MsgSubmitMisbehaviour -MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for -light client misbehaviour. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `misbehaviour` | [google.protobuf.Any](#google.protobuf.Any) | | misbehaviour used for freezing the light client | -| `signer` | [string](#string) | | signer address | - - - - - - - - -### MsgSubmitMisbehaviourResponse -MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. - - - - - - - - -### MsgUpdateClient -MsgUpdateClient defines an sdk.Msg to update a IBC client state using -the given header. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `header` | [google.protobuf.Any](#google.protobuf.Any) | | header to update the light client | -| `signer` | [string](#string) | | signer address | - - - - - - - - -### MsgUpdateClientResponse -MsgUpdateClientResponse defines the Msg/UpdateClient response type. - - - - - - - - -### MsgUpgradeClient -MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | client unique identifier | -| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded client state | -| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded consensus state, only contains enough information to serve as a basis of trust in update logic | -| `proof_upgrade_client` | [bytes](#bytes) | | proof that old chain committed to new client | -| `proof_upgrade_consensus_state` | [bytes](#bytes) | | proof that old chain committed to new consensus state | -| `signer` | [string](#string) | | signer address | - - - - - - - - -### MsgUpgradeClientResponse -MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. - - - - - - - - - - - - - + ### Msg -Msg defines the ibc/client Msg service. +Msg defines the ibc/transfer Msg service. | Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | | ----------- | ------------ | ------------- | ------------| ------- | -------- | -| `CreateClient` | [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) | [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) | CreateClient defines a rpc handler method for MsgCreateClient. | | -| `UpdateClient` | [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) | [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) | UpdateClient defines a rpc handler method for MsgUpdateClient. | | -| `UpgradeClient` | [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) | [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) | UpgradeClient defines a rpc handler method for MsgUpgradeClient. | | -| `SubmitMisbehaviour` | [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) | [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) | SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. | | - - - - - - -

    Top

    - -## ibc/core/client/v1/genesis.proto - - - - - -### GenesisMetadata -GenesisMetadata defines the genesis type for metadata that clients may return -with ExportMetadata - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | -| `value` | [bytes](#bytes) | | metadata value | - - - - - - - - -### GenesisState -GenesisState defines the ibc client submodule's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `clients` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | client states with their corresponding identifiers | -| `clients_consensus` | [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) | repeated | consensus states from each client | -| `clients_metadata` | [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) | repeated | metadata from each client | -| `params` | [Params](#ibc.core.client.v1.Params) | | | -| `create_localhost` | [bool](#bool) | | create localhost on initialization | -| `next_client_sequence` | [uint64](#uint64) | | the sequence for the next generated client identifier | - - - - - - - - -### IdentifiedGenesisMetadata -IdentifiedGenesisMetadata has the client metadata with the corresponding client id. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | - - - - - - - - - - +| `Transfer` | [MsgTransfer](#ibc.applications.transfer.v1.MsgTransfer) | [MsgTransferResponse](#ibc.applications.transfer.v1.MsgTransferResponse) | Transfer defines a rpc handler method for MsgTransfer. | | @@ -8629,6 +8227,62 @@ CLOSED, INIT, TRYOPEN, OPEN or UNINITIALIZED. + +

    Top

    + +## ibc/core/channel/v1/genesis.proto + + + + + +### GenesisState +GenesisState defines the ibc channel submodule's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | | +| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `receipts` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | +| `send_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `recv_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `ack_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | +| `next_channel_sequence` | [uint64](#uint64) | | the sequence for the next generated channel identifier | + + + + + + + + +### PacketSequence +PacketSequence defines the genesis type necessary to retrieve and store +next send and receive sequences. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `port_id` | [string](#string) | | | +| `channel_id` | [string](#string) | | | +| `sequence` | [uint64](#uint64) | | | + + + + + + + + + + + + + + +

    Top

    @@ -9461,47 +9115,60 @@ Msg defines the ibc/channel Msg service. - +

    Top

    -## ibc/core/channel/v1/genesis.proto +## ibc/core/client/v1/genesis.proto - + + +### GenesisMetadata +GenesisMetadata defines the genesis type for metadata that clients may return +with ExportMetadata + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `key` | [bytes](#bytes) | | store key of metadata without clientID-prefix | +| `value` | [bytes](#bytes) | | metadata value | + + + + + + + ### GenesisState -GenesisState defines the ibc channel submodule's genesis state. +GenesisState defines the ibc client submodule's genesis state. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `channels` | [IdentifiedChannel](#ibc.core.channel.v1.IdentifiedChannel) | repeated | | -| `acknowledgements` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `commitments` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `receipts` | [PacketState](#ibc.core.channel.v1.PacketState) | repeated | | -| `send_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `recv_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `ack_sequences` | [PacketSequence](#ibc.core.channel.v1.PacketSequence) | repeated | | -| `next_channel_sequence` | [uint64](#uint64) | | the sequence for the next generated channel identifier | +| `clients` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | client states with their corresponding identifiers | +| `clients_consensus` | [ClientConsensusStates](#ibc.core.client.v1.ClientConsensusStates) | repeated | consensus states from each client | +| `clients_metadata` | [IdentifiedGenesisMetadata](#ibc.core.client.v1.IdentifiedGenesisMetadata) | repeated | metadata from each client | +| `params` | [Params](#ibc.core.client.v1.Params) | | | +| `create_localhost` | [bool](#bool) | | create localhost on initialization | +| `next_client_sequence` | [uint64](#uint64) | | the sequence for the next generated client identifier | - + -### PacketSequence -PacketSequence defines the genesis type necessary to retrieve and store -next send and receive sequences. +### IdentifiedGenesisMetadata +IdentifiedGenesisMetadata has the client metadata with the corresponding client id. | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| `port_id` | [string](#string) | | | -| `channel_id` | [string](#string) | | | -| `sequence` | [uint64](#uint64) | | | +| `client_id` | [string](#string) | | | +| `client_metadata` | [GenesisMetadata](#ibc.core.client.v1.GenesisMetadata) | repeated | | @@ -9517,6 +9184,343 @@ next send and receive sequences. + +

    Top

    + +## ibc/core/client/v1/query.proto + + + + + +### QueryClientParamsRequest +QueryClientParamsRequest is the request type for the Query/ClientParams RPC method. + + + + + + + + +### QueryClientParamsResponse +QueryClientParamsResponse is the response type for the Query/ClientParams RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `params` | [Params](#ibc.core.client.v1.Params) | | params defines the parameters of the module. | + + + + + + + + +### QueryClientStateRequest +QueryClientStateRequest is the request type for the Query/ClientState RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client state unique identifier | + + + + + + + + +### QueryClientStateResponse +QueryClientStateResponse is the response type for the Query/ClientState RPC +method. Besides the client state, it includes a proof and the height from +which the proof was retrieved. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | client state associated with the request identifier | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | + + + + + + + + +### QueryClientStatesRequest +QueryClientStatesRequest is the request type for the Query/ClientStates RPC +method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | + + + + + + + + +### QueryClientStatesResponse +QueryClientStatesResponse is the response type for the Query/ClientStates RPC +method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_states` | [IdentifiedClientState](#ibc.core.client.v1.IdentifiedClientState) | repeated | list of stored ClientStates of the chain. | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | + + + + + + + + +### QueryConsensusStateRequest +QueryConsensusStateRequest is the request type for the Query/ConsensusState +RPC method. Besides the consensus state, it includes a proof and the height +from which the proof was retrieved. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client identifier | +| `revision_number` | [uint64](#uint64) | | consensus state revision number | +| `revision_height` | [uint64](#uint64) | | consensus state revision height | +| `latest_height` | [bool](#bool) | | latest_height overrrides the height field and queries the latest stored ConsensusState | + + + + + + + + +### QueryConsensusStateResponse +QueryConsensusStateResponse is the response type for the Query/ConsensusState +RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client identifier at the given height | +| `proof` | [bytes](#bytes) | | merkle proof of existence | +| `proof_height` | [Height](#ibc.core.client.v1.Height) | | height at which the proof was retrieved | + + + + + + + + +### QueryConsensusStatesRequest +QueryConsensusStatesRequest is the request type for the Query/ConsensusStates +RPC method. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination request | + + + + + + + + +### QueryConsensusStatesResponse +QueryConsensusStatesResponse is the response type for the +Query/ConsensusStates RPC method + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `consensus_states` | [ConsensusStateWithHeight](#ibc.core.client.v1.ConsensusStateWithHeight) | repeated | consensus states associated with the identifier | +| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination response | + + + + + + + + + + + + + + +### Query +Query provides defines the gRPC querier service + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `ClientState` | [QueryClientStateRequest](#ibc.core.client.v1.QueryClientStateRequest) | [QueryClientStateResponse](#ibc.core.client.v1.QueryClientStateResponse) | ClientState queries an IBC light client. | GET|/ibc/core/client/v1beta1/client_states/{client_id}| +| `ClientStates` | [QueryClientStatesRequest](#ibc.core.client.v1.QueryClientStatesRequest) | [QueryClientStatesResponse](#ibc.core.client.v1.QueryClientStatesResponse) | ClientStates queries all the IBC light clients of a chain. | GET|/ibc/core/client/v1beta1/client_states| +| `ConsensusState` | [QueryConsensusStateRequest](#ibc.core.client.v1.QueryConsensusStateRequest) | [QueryConsensusStateResponse](#ibc.core.client.v1.QueryConsensusStateResponse) | ConsensusState queries a consensus state associated with a client state at a given height. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}/revision/{revision_number}/height/{revision_height}| +| `ConsensusStates` | [QueryConsensusStatesRequest](#ibc.core.client.v1.QueryConsensusStatesRequest) | [QueryConsensusStatesResponse](#ibc.core.client.v1.QueryConsensusStatesResponse) | ConsensusStates queries all the consensus state associated with a given client. | GET|/ibc/core/client/v1beta1/consensus_states/{client_id}| +| `ClientParams` | [QueryClientParamsRequest](#ibc.core.client.v1.QueryClientParamsRequest) | [QueryClientParamsResponse](#ibc.core.client.v1.QueryClientParamsResponse) | ClientParams queries all parameters of the ibc client. | GET|/ibc/client/v1beta1/params| + + + + + + +

    Top

    + +## ibc/core/client/v1/tx.proto + + + + + +### MsgCreateClient +MsgCreateClient defines a message to create an IBC client + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | light client state | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | consensus state associated with the client that corresponds to a given height. | +| `signer` | [string](#string) | | signer address | + + + + + + + + +### MsgCreateClientResponse +MsgCreateClientResponse defines the Msg/CreateClient response type. + + + + + + + + +### MsgSubmitMisbehaviour +MsgSubmitMisbehaviour defines an sdk.Msg type that submits Evidence for +light client misbehaviour. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client unique identifier | +| `misbehaviour` | [google.protobuf.Any](#google.protobuf.Any) | | misbehaviour used for freezing the light client | +| `signer` | [string](#string) | | signer address | + + + + + + + + +### MsgSubmitMisbehaviourResponse +MsgSubmitMisbehaviourResponse defines the Msg/SubmitMisbehaviour response type. + + + + + + + + +### MsgUpdateClient +MsgUpdateClient defines an sdk.Msg to update a IBC client state using +the given header. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client unique identifier | +| `header` | [google.protobuf.Any](#google.protobuf.Any) | | header to update the light client | +| `signer` | [string](#string) | | signer address | + + + + + + + + +### MsgUpdateClientResponse +MsgUpdateClientResponse defines the Msg/UpdateClient response type. + + + + + + + + +### MsgUpgradeClient +MsgUpgradeClient defines an sdk.Msg to upgrade an IBC client to a new client state + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | client unique identifier | +| `client_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded client state | +| `consensus_state` | [google.protobuf.Any](#google.protobuf.Any) | | upgraded consensus state, only contains enough information to serve as a basis of trust in update logic | +| `proof_upgrade_client` | [bytes](#bytes) | | proof that old chain committed to new client | +| `proof_upgrade_consensus_state` | [bytes](#bytes) | | proof that old chain committed to new consensus state | +| `signer` | [string](#string) | | signer address | + + + + + + + + +### MsgUpgradeClientResponse +MsgUpgradeClientResponse defines the Msg/UpgradeClient response type. + + + + + + + + + + + + + + +### Msg +Msg defines the ibc/client Msg service. + +| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint | +| ----------- | ------------ | ------------- | ------------| ------- | -------- | +| `CreateClient` | [MsgCreateClient](#ibc.core.client.v1.MsgCreateClient) | [MsgCreateClientResponse](#ibc.core.client.v1.MsgCreateClientResponse) | CreateClient defines a rpc handler method for MsgCreateClient. | | +| `UpdateClient` | [MsgUpdateClient](#ibc.core.client.v1.MsgUpdateClient) | [MsgUpdateClientResponse](#ibc.core.client.v1.MsgUpdateClientResponse) | UpdateClient defines a rpc handler method for MsgUpdateClient. | | +| `UpgradeClient` | [MsgUpgradeClient](#ibc.core.client.v1.MsgUpgradeClient) | [MsgUpgradeClientResponse](#ibc.core.client.v1.MsgUpgradeClientResponse) | UpgradeClient defines a rpc handler method for MsgUpgradeClient. | | +| `SubmitMisbehaviour` | [MsgSubmitMisbehaviour](#ibc.core.client.v1.MsgSubmitMisbehaviour) | [MsgSubmitMisbehaviourResponse](#ibc.core.client.v1.MsgSubmitMisbehaviourResponse) | SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour. | | + + + + +

    Top

    @@ -9741,6 +9745,39 @@ INIT, TRYOPEN, OPEN or UNINITIALIZED. + +

    Top

    + +## ibc/core/connection/v1/genesis.proto + + + + + +### GenesisState +GenesisState defines the ibc connection submodule's genesis state. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | | +| `client_connection_paths` | [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) | repeated | | +| `next_connection_sequence` | [uint64](#uint64) | | the sequence for the next generated connection identifier | + + + + + + + + + + + + + + +

    Top

    @@ -10105,39 +10142,6 @@ Msg defines the ibc/connection Msg service. - -

    Top

    - -## ibc/core/connection/v1/genesis.proto - - - - - -### GenesisState -GenesisState defines the ibc connection submodule's genesis state. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `connections` | [IdentifiedConnection](#ibc.core.connection.v1.IdentifiedConnection) | repeated | | -| `client_connection_paths` | [ConnectionPaths](#ibc.core.connection.v1.ConnectionPaths) | repeated | | -| `next_connection_sequence` | [uint64](#uint64) | | the sequence for the next generated connection identifier | - - - - - - - - - - - - - - -

    Top

    @@ -10194,128 +10198,6 @@ access to keys outside the client prefix. - - - - - - - - - - - -

    Top

    - -## ibc/lightclients/tendermint/v1/tendermint.proto - - - - - -### ClientState -ClientState from Tendermint tracks the current validator set, latest height, -and a possible frozen height. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `chain_id` | [string](#string) | | | -| `trust_level` | [Fraction](#ibc.lightclients.tendermint.v1.Fraction) | | | -| `trusting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the period since the LastestTimestamp during which the submitted headers are valid for upgrade | -| `unbonding_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the staking unbonding period | -| `max_clock_drift` | [google.protobuf.Duration](#google.protobuf.Duration) | | defines how much new (untrusted) header's Time can drift into the future. | -| `frozen_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Block height when the client was frozen due to a misbehaviour | -| `latest_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Latest height the client was updated to | -| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | Proof specifications used in verifying counterparty state | -| `upgrade_path` | [string](#string) | repeated | Path at which next upgraded client will be committed. Each element corresponds to the key for a single CommitmentProof in the chained proof. NOTE: ClientState must stored under `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using the default upgrade module, upgrade_path should be []string{"upgrade", "upgradedIBCState"}` | -| `allow_update_after_expiry` | [bool](#bool) | | This flag, when set to true, will allow governance to recover a client which has expired | -| `allow_update_after_misbehaviour` | [bool](#bool) | | This flag, when set to true, will allow governance to unfreeze a client whose chain has experienced a misbehaviour event | - - - - - - - - -### ConsensusState -ConsensusState defines the consensus state from Tendermint. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `timestamp` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | timestamp that corresponds to the block height in which the ConsensusState was stored. | -| `root` | [ibc.core.commitment.v1.MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) | | commitment root (i.e app hash) | -| `next_validators_hash` | [bytes](#bytes) | | | - - - - - - - - -### Fraction -Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `numerator` | [uint64](#uint64) | | | -| `denominator` | [uint64](#uint64) | | | - - - - - - - - -### Header -Header defines the Tendermint client consensus Header. -It encapsulates all the information necessary to update from a trusted -Tendermint ConsensusState. The inclusion of TrustedHeight and -TrustedValidators allows this update to process correctly, so long as the -ConsensusState for the TrustedHeight exists, this removes race conditions -among relayers The SignedHeader and ValidatorSet are the new untrusted update -fields for the client. The TrustedHeight is the height of a stored -ConsensusState on the client that will be used to verify the new untrusted -header. The Trusted ConsensusState must be within the unbonding period of -current time in order to correctly verify, and the TrustedValidators must -hash to TrustedConsensusState.NextValidatorsHash since that is the last -trusted validator set at the TrustedHeight. - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `signed_header` | [tendermint.types.SignedHeader](#tendermint.types.SignedHeader) | | | -| `validator_set` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | -| `trusted_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | -| `trusted_validators` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | - - - - - - - - -### Misbehaviour -Misbehaviour is a wrapper over two conflicting Headers -that implements Misbehaviour interface expected by ICS-02 - - -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `client_id` | [string](#string) | | | -| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | -| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | - - - - - @@ -10643,6 +10525,128 @@ data sign byte encodings. + +

    Top

    + +## ibc/lightclients/tendermint/v1/tendermint.proto + + + + + +### ClientState +ClientState from Tendermint tracks the current validator set, latest height, +and a possible frozen height. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `chain_id` | [string](#string) | | | +| `trust_level` | [Fraction](#ibc.lightclients.tendermint.v1.Fraction) | | | +| `trusting_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the period since the LastestTimestamp during which the submitted headers are valid for upgrade | +| `unbonding_period` | [google.protobuf.Duration](#google.protobuf.Duration) | | duration of the staking unbonding period | +| `max_clock_drift` | [google.protobuf.Duration](#google.protobuf.Duration) | | defines how much new (untrusted) header's Time can drift into the future. | +| `frozen_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Block height when the client was frozen due to a misbehaviour | +| `latest_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | Latest height the client was updated to | +| `proof_specs` | [ics23.ProofSpec](#ics23.ProofSpec) | repeated | Proof specifications used in verifying counterparty state | +| `upgrade_path` | [string](#string) | repeated | Path at which next upgraded client will be committed. Each element corresponds to the key for a single CommitmentProof in the chained proof. NOTE: ClientState must stored under `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored under `{upgradepath}/{upgradeHeight}/consensusState` For SDK chains using the default upgrade module, upgrade_path should be []string{"upgrade", "upgradedIBCState"}` | +| `allow_update_after_expiry` | [bool](#bool) | | This flag, when set to true, will allow governance to recover a client which has expired | +| `allow_update_after_misbehaviour` | [bool](#bool) | | This flag, when set to true, will allow governance to unfreeze a client whose chain has experienced a misbehaviour event | + + + + + + + + +### ConsensusState +ConsensusState defines the consensus state from Tendermint. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `timestamp` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | timestamp that corresponds to the block height in which the ConsensusState was stored. | +| `root` | [ibc.core.commitment.v1.MerkleRoot](#ibc.core.commitment.v1.MerkleRoot) | | commitment root (i.e app hash) | +| `next_validators_hash` | [bytes](#bytes) | | | + + + + + + + + +### Fraction +Fraction defines the protobuf message type for tmmath.Fraction that only supports positive values. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `numerator` | [uint64](#uint64) | | | +| `denominator` | [uint64](#uint64) | | | + + + + + + + + +### Header +Header defines the Tendermint client consensus Header. +It encapsulates all the information necessary to update from a trusted +Tendermint ConsensusState. The inclusion of TrustedHeight and +TrustedValidators allows this update to process correctly, so long as the +ConsensusState for the TrustedHeight exists, this removes race conditions +among relayers The SignedHeader and ValidatorSet are the new untrusted update +fields for the client. The TrustedHeight is the height of a stored +ConsensusState on the client that will be used to verify the new untrusted +header. The Trusted ConsensusState must be within the unbonding period of +current time in order to correctly verify, and the TrustedValidators must +hash to TrustedConsensusState.NextValidatorsHash since that is the last +trusted validator set at the TrustedHeight. + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `signed_header` | [tendermint.types.SignedHeader](#tendermint.types.SignedHeader) | | | +| `validator_set` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | +| `trusted_height` | [ibc.core.client.v1.Height](#ibc.core.client.v1.Height) | | | +| `trusted_validators` | [tendermint.types.ValidatorSet](#tendermint.types.ValidatorSet) | | | + + + + + + + + +### Misbehaviour +Misbehaviour is a wrapper over two conflicting Headers +that implements Misbehaviour interface expected by ICS-02 + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| `client_id` | [string](#string) | | | +| `header_1` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | +| `header_2` | [Header](#ibc.lightclients.tendermint.v1.Header) | | | + + + + + + + + + + + + + + + ## Scalar Value Types | .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby | diff --git a/proto/cosmos/staking/v1beta1/staking.proto b/proto/cosmos/staking/v1beta1/staking.proto index eadc86e9d1..e37b28b6d0 100644 --- a/proto/cosmos/staking/v1beta1/staking.proto +++ b/proto/cosmos/staking/v1beta1/staking.proto @@ -27,12 +27,15 @@ message CommissionRates { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // rate is the commission rate charged to delegators, as a fraction. string rate = 1 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; + // max_rate defines the maximum commission rate which validator can ever charge, as a fraction. string max_rate = 2 [ (gogoproto.moretags) = "yaml:\"max_rate\"", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; + // max_change_rate defines the maximum daily increase of the validator commission, as a fraction. string max_change_rate = 3 [ (gogoproto.moretags) = "yaml:\"max_change_rate\"", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", @@ -45,7 +48,9 @@ message Commission { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // commission_rates defines the initial commission rates to be used for creating a validator. CommissionRates commission_rates = 1 [(gogoproto.embed) = true, (gogoproto.nullable) = false]; + // update_time is the last time the commission rate was changed. google.protobuf.Timestamp update_time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"update_time\""]; } @@ -55,10 +60,15 @@ message Description { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // moniker defines a human-readable name for the validator. string moniker = 1; + // identity defines an optional identity signature (ex. UPort or Keybase). string identity = 2; + // website defines an optional website link. string website = 3; + // security_contact defines an optional email for security contact. string security_contact = 4 [(gogoproto.moretags) = "yaml:\"security_contact\""]; + // details define other optional details. string details = 5; } @@ -75,22 +85,33 @@ message Validator { option (gogoproto.goproto_stringer) = false; option (gogoproto.goproto_getters) = false; + // operator_address defines the address of the validator's operator; bech encoded in JSON. string operator_address = 1 [(gogoproto.moretags) = "yaml:\"operator_address\""]; + // consensus_pubkey is the consensus public key of the validator, as a Protobuf Any. google.protobuf.Any consensus_pubkey = 2 [(cosmos_proto.accepts_interface) = "cosmos.crypto.PubKey", (gogoproto.moretags) = "yaml:\"consensus_pubkey\""]; + // jailed defined whether the validator has been jailed from bonded status or not. bool jailed = 3; + // status is the validator status (bonded/unbonding/unbonded). BondStatus status = 4; + // tokens define the delegated tokens (incl. self-delegation). string tokens = 5 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false]; + // delegator_shares defines total shares issued to a validator's delegators. string delegator_shares = 6 [ (gogoproto.moretags) = "yaml:\"delegator_shares\"", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false ]; + // description defines the description terms for the validator. Description description = 7 [(gogoproto.nullable) = false]; + // unbonding_height defines, if unbonding, the height at which this validator has begun unbonding. int64 unbonding_height = 8 [(gogoproto.moretags) = "yaml:\"unbonding_height\""]; + // unbonding_time defines, if unbonding, the min time for the validator to complete unbonding. google.protobuf.Timestamp unbonding_time = 9 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"unbonding_time\""]; + // commission defines the commission parameters. Commission commission = 10 [(gogoproto.nullable) = false]; + // min_self_delegation is the validator's self declared minimum self delegation. string min_self_delegation = 11 [ (gogoproto.moretags) = "yaml:\"min_self_delegation\"", (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", @@ -164,8 +185,11 @@ message Delegation { option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; + // delegator_address is the bech32-encoded address of the delegator. string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; + // validator_address is the bech32-encoded address of the validator. string validator_address = 2 [(gogoproto.moretags) = "yaml:\"validator_address\""]; + // shares define the delegation shares received. string shares = 3 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; } @@ -176,8 +200,11 @@ message UnbondingDelegation { option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; + // delegator_address is the bech32-encoded address of the delegator. string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; + // validator_address is the bech32-encoded address of the validator. string validator_address = 2 [(gogoproto.moretags) = "yaml:\"validator_address\""]; + // entries are the unbonding delegation entries. repeated UnbondingDelegationEntry entries = 3 [(gogoproto.nullable) = false]; // unbonding delegation entries } @@ -186,14 +213,18 @@ message UnbondingDelegationEntry { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // creation_height is the height which the unbonding took place. int64 creation_height = 1 [(gogoproto.moretags) = "yaml:\"creation_height\""]; + // completion_time is the unix time for unbonding completion. google.protobuf.Timestamp completion_time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"completion_time\""]; + // initial_balance defines the tokens initially scheduled to receive at completion. string initial_balance = 3 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"initial_balance\"" ]; + // balance defines the tokens to receive at completion. string balance = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false]; } @@ -202,14 +233,18 @@ message RedelegationEntry { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // creation_height defines the height which the redelegation took place. int64 creation_height = 1 [(gogoproto.moretags) = "yaml:\"creation_height\""]; + // completion_time defines the unix time for redelegation completion. google.protobuf.Timestamp completion_time = 2 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true, (gogoproto.moretags) = "yaml:\"completion_time\""]; + // initial_balance defines the initial balance when redelegation started. string initial_balance = 3 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"initial_balance\"" ]; + // shares_dst is the amount of destination-validator shares created by redelegation. string shares_dst = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", (gogoproto.nullable) = false]; } @@ -221,9 +256,13 @@ message Redelegation { option (gogoproto.goproto_getters) = false; option (gogoproto.goproto_stringer) = false; + // delegator_address is the bech32-encoded address of the delegator. string delegator_address = 1 [(gogoproto.moretags) = "yaml:\"delegator_address\""]; + // validator_src_address is the validator redelegation source operator address. string validator_src_address = 2 [(gogoproto.moretags) = "yaml:\"validator_src_address\""]; + // validator_dst_address is the validator redelegation destination operator address. string validator_dst_address = 3 [(gogoproto.moretags) = "yaml:\"validator_dst_address\""]; + // entries are the redelegation entries. repeated RedelegationEntry entries = 4 [(gogoproto.nullable) = false]; // redelegation entries } @@ -232,11 +271,16 @@ message Params { option (gogoproto.equal) = true; option (gogoproto.goproto_stringer) = false; + // unbonding_time is the time duration of unbonding. google.protobuf.Duration unbonding_time = 1 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true, (gogoproto.moretags) = "yaml:\"unbonding_time\""]; + // max_validators is the maximum number of validators. uint32 max_validators = 2 [(gogoproto.moretags) = "yaml:\"max_validators\""]; + // max_entries is the max entries for either unbonding delegation or redelegation (per pair/trio). uint32 max_entries = 3 [(gogoproto.moretags) = "yaml:\"max_entries\""]; + // historical_entries is the number of historical entries to persist. uint32 historical_entries = 4 [(gogoproto.moretags) = "yaml:\"historical_entries\""]; + // bond_denom defines the bondable coin denomination. string bond_denom = 5 [(gogoproto.moretags) = "yaml:\"bond_denom\""]; } diff --git a/x/staking/spec/01_state.md b/x/staking/spec/01_state.md index c5f7376d76..e090acb015 100644 --- a/x/staking/spec/01_state.md +++ b/x/staking/spec/01_state.md @@ -8,23 +8,16 @@ order: 1 LastTotalPower tracks the total amounts of bonded tokens recorded during the previous end block. -- LastTotalPower: `0x12 -> amino(sdk.Int)` +- LastTotalPower: `0x12 -> ProtocolBuffer(sdk.Int)` ## Params Params is a module-wide configuration structure that stores system parameters and defines overall functioning of the staking module. -- Params: `Paramsspace("staking") -> amino(params)` +- Params: `Paramsspace("staking") -> legacy_amino(params)` -```go -type Params struct { - UnbondingTime time.Duration // time duration of unbonding - MaxValidators uint16 // maximum number of validators - MaxEntries uint16 // max entries for either unbonding delegation or redelegation (per pair/trio) - BondDenom string // bondable coin denomination -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.1/proto/cosmos/staking/v1beta1/staking.proto#L230-L241 ## Validator @@ -37,8 +30,8 @@ Validators can have one of three statuses They are signing blocks and receiving rewards. They can receive further delegations. They can be slashed for misbehavior. Delegators to this validator who unbond their delegation must wait the duration of the UnbondingTime, a chain-specific param. during which time - they are still slashable for offences of the source validator if those offences were committed - during the period of time that the tokens were bonded. + they are still slashable for offences of the source validator if those offences were committed + during the period of time that the tokens were bonded. - `Unbonding`: When a validator leaves the active set, either by choice or due to slashing or tombstoning, an unbonding of all their delegations begins. All delegations must then wait the UnbondingTime before moving receiving their tokens to their accounts from the `BondedPool`. @@ -51,10 +44,10 @@ required lookups for slashing and validator-set updates. A third special index throughout each block, unlike the first two indices which mirror the validator records within a block. -- Validators: `0x21 | OperatorAddr -> amino(validator)` +- Validators: `0x21 | OperatorAddr -> ProtocolBuffer(validator)` - ValidatorsByConsAddr: `0x22 | ConsAddr -> OperatorAddr` - ValidatorsByPower: `0x23 | BigEndian(ConsensusPower) | OperatorAddr -> OperatorAddr` -- LastValidatorsPower: `0x11 OperatorAddr -> amino(ConsensusPower)` +- LastValidatorsPower: `0x11 OperatorAddr -> ProtocolBuffer(ConsensusPower)` `Validators` is the primary index - it ensures that each operator can have only one associated validator, where the public key of that validator can change in the @@ -68,7 +61,7 @@ address which can be derived from the validator's `ConsPubKey`. `ValidatorsByPower` is an additional index that provides a sorted list o potential validators to quickly determine the current active set. Here -ConsensusPower is validator.Tokens/10^6. Note that all validators where +ConsensusPower is validator.Tokens/10^6. Note that all validators where `Jailed` is true are not stored within this index. `LastValidatorsPower` is a special index that provides a historical list of the @@ -77,60 +70,23 @@ is updated during the validator set update process which takes place in [`EndBlo Each validator's state is stored in a `Validator` struct: -```go -type Validator struct { - OperatorAddress sdk.ValAddress // address of the validator's operator; bech encoded in JSON - ConsPubKey crypto.PubKey // the consensus public key of the validator; bech encoded in JSON - Jailed bool // has the validator been jailed from bonded status? - Status sdk.BondStatus // validator status (bonded/unbonding/unbonded) - Tokens sdk.Int // delegated tokens (incl. self-delegation) - DelegatorShares sdk.Dec // total shares issued to a validator's delegators - Description Description // description terms for the validator - UnbondingHeight int64 // if unbonding, height at which this validator has begun unbonding - UnbondingCompletionTime time.Time // if unbonding, min time for the validator to complete unbonding - Commission Commission // commission parameters - MinSelfDelegation sdk.Int // validator's self declared minimum self delegation -} ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L65-L99 -type Commission struct { - CommissionRates - UpdateTime time.Time // the last time the commission rate was changed -} - -CommissionRates struct { - Rate sdk.Dec // the commission rate charged to delegators, as a fraction - MaxRate sdk.Dec // maximum commission rate which validator can ever charge, as a fraction - MaxChangeRate sdk.Dec // maximum daily increase of the validator commission, as a fraction -} - -type Description struct { - Moniker string // name - Identity string // optional identity signature (ex. UPort or Keybase) - Website string // optional website link - SecurityContact string // optional email for security contact - Details string // optional details -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L24-L63 ## Delegation Delegations are identified by combining `DelegatorAddr` (the address of the delegator) with the `ValidatorAddr` Delegators are indexed in the store as follows: -- Delegation: `0x31 | DelegatorAddr | ValidatorAddr -> amino(delegation)` +- Delegation: `0x31 | DelegatorAddr | ValidatorAddr -> ProtocolBuffer(delegation)` Stake holders may delegate coins to validators; under this circumstance their funds are held in a `Delegation` data structure. It is owned by one delegator, and is associated with the shares for one validator. The sender of the transaction is the owner of the bond. -```go -type Delegation struct { - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress - Shares sdk.Dec // delegation shares received -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L159-L170 ### Delegator Shares @@ -159,10 +115,8 @@ detected. `UnbondingDelegation` are indexed in the store as: -- UnbondingDelegation: `0x32 | DelegatorAddr | ValidatorAddr -> - amino(unbondingDelegation)` -- UnbondingDelegationsFromValidator: `0x33 | ValidatorAddr | DelegatorAddr -> - nil` +- UnbondingDelegation: `0x32 | DelegatorAddr | ValidatorAddr -> ProtocolBuffer(unbondingDelegation)` +- UnbondingDelegationsFromValidator: `0x33 | ValidatorAddr | DelegatorAddr -> nil` The first map here is used in queries, to lookup all unbonding delegations for a given delegator, while the second map is used in slashing, to lookup all @@ -171,20 +125,7 @@ slashed. A UnbondingDelegation object is created every time an unbonding is initiated. -```go -type UnbondingDelegation struct { - DelegatorAddr sdk.AccAddress // delegator - ValidatorAddr sdk.ValAddress // validator unbonding from operator addr - Entries []UnbondingDelegationEntry // unbonding delegation entries -} - -type UnbondingDelegationEntry struct { - CreationHeight int64 // height which the unbonding took place - CompletionTime time.Time // unix time for unbonding completion - InitialBalance sdk.Coin // atoms initially scheduled to receive at completion - Balance sdk.Coin // atoms to receive at completion -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L172-L198 ## Redelegation @@ -196,7 +137,7 @@ committed by the source validator. `Redelegation` are indexed in the store as: -- Redelegations: `0x34 | DelegatorAddr | ValidatorSrcAddr | ValidatorDstAddr -> amino(redelegation)` +- Redelegations: `0x34 | DelegatorAddr | ValidatorSrcAddr | ValidatorDstAddr -> ProtocolBuffer(redelegation)` - RedelegationsBySrc: `0x35 | ValidatorSrcAddr | ValidatorDstAddr | DelegatorAddr -> nil` - RedelegationsByDst: `0x36 | ValidatorDstAddr | ValidatorSrcAddr | DelegatorAddr -> nil` @@ -204,30 +145,15 @@ The first map here is used for queries, to lookup all redelegations for a given delegator. The second map is used for slashing based on the `ValidatorSrcAddr`, while the third map is for slashing based on the `ValidatorDstAddr`. -A redelegation object is created every time a redelegation occurs. To prevent +A redelegation object is created every time a redelegation occurs. To prevent "redelegation hopping" redelegations may not occur under the situation that: - the (re)delegator already has another immature redelegation in progress -with a destination to a validator (let's call it `Validator X`) + with a destination to a validator (let's call it `Validator X`) - and, the (re)delegator is attempting to create a _new_ redelegation -where the source validator for this new redelegation is `Validator-X`. + where the source validator for this new redelegation is `Validator-X`. -```go -type Redelegation struct { - DelegatorAddr sdk.AccAddress // delegator - ValidatorSrcAddr sdk.ValAddress // validator redelegation source operator addr - ValidatorDstAddr sdk.ValAddress // validator redelegation destination operator addr - Entries []RedelegationEntry // redelegation entries -} - -type RedelegationEntry struct { - CreationHeight int64 // height which the redelegation took place - CompletionTime time.Time // unix time for redelegation completion - InitialBalance sdk.Coin // initial balance when redelegation started - Balance sdk.Coin // current balance (current value held in destination validator) - SharesDst sdk.Dec // amount of destination-validator shares created by redelegation -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L200-L228 ## Queues @@ -249,12 +175,7 @@ delegations queue is kept. - UnbondingDelegation: `0x41 | format(time) -> []DVPair` -```go -type DVPair struct { - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L123-L133 ### RedelegationQueue @@ -263,13 +184,7 @@ kept. - UnbondingDelegation: `0x42 | format(time) -> []DVVTriplet` -```go -type DVVTriplet struct { - DelegatorAddr sdk.AccAddress - ValidatorSrcAddr sdk.ValAddress - ValidatorDstAddr sdk.ValAddress -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L140-L152 ### ValidatorQueue @@ -279,7 +194,7 @@ queue is kept. - ValidatorQueueTime: `0x43 | format(time) -> []sdk.ValAddress` The stored object as each key is an array of validator operator addresses from -which the validator object can be accessed. Typically it is expected that only +which the validator object can be accessed. Typically it is expected that only a single validator record will be associated with a given timestamp however it is possible that multiple validators exist in the queue at the same location. @@ -288,15 +203,10 @@ that multiple validators exist in the queue at the same location. HistoricalInfo objects are stored and pruned at each block such that the staking keeper persists the `n` most recent historical info defined by staking module parameter: `HistoricalEntries`. -```go -type HistoricalInfo struct { - Header tmproto.Header - ValSet []types.Validator -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/staking.proto#L15-L22 At each BeginBlock, the staking keeper will persist the current Header and the Validators that committed -the current block in a `HistoricalInfo` object. The Validators are sorted on their address to ensure that +the current block in a `HistoricalInfo` object. The Validators are sorted on their address to ensure that they are in a determisnistic order. -The oldest HistoricalEntries will be pruned to ensure that there only exist the parameter-defined number of +The oldest HistoricalEntries will be pruned to ensure that there only exist the parameter-defined number of historical entries. diff --git a/x/staking/spec/02_state_transitions.md b/x/staking/spec/02_state_transitions.md index c2766aa43b..9e245719cc 100644 --- a/x/staking/spec/02_state_transitions.md +++ b/x/staking/spec/02_state_transitions.md @@ -11,12 +11,13 @@ This document describes the state transition operations pertaining to: 3. [Slashing](./02_state_transitions.md#slashing) ## Validators -State transitions in validators are performed on every [`EndBlock`](./05_end_block.md#validator-set-changes) + +State transitions in validators are performed on every [`EndBlock`](./05_end_block.md#validator-set-changes) in order to check for changes in the active `ValidatorSet`. ### Unbonded to Bonded -The following transition occurs when a validator's ranking in the `ValidatorPowerIndex` surpasses +The following transition occurs when a validator's ranking in the `ValidatorPowerIndex` surpasses that of the `LastValidator`. - set `validator.Status` to `Bonded` @@ -98,9 +99,9 @@ Redelegations affect the delegation, source and destination validators. - perform an `unbond` delegation from the source validator to retrieve the tokens worth of the unbonded shares - using the unbonded tokens, `Delegate` them to the destination validator -- if the `sourceValidator.Status` is `Bonded`, and the `destinationValidator` is not, +- if the `sourceValidator.Status` is `Bonded`, and the `destinationValidator` is not, transfer the newly delegated tokens from the `BondedPool` to the `NotBondedPool` `ModuleAccount` -- otherwise, if the `sourceValidator.Status` is not `Bonded`, and the `destinationValidator` +- otherwise, if the `sourceValidator.Status` is not `Bonded`, and the `destinationValidator` is `Bonded`, transfer the newly delegated tokens from the `NotBondedPool` to the `BondedPool` `ModuleAccount` - record the token amount in an new entry in the relevant `Redelegation` @@ -116,20 +117,20 @@ When a redelegations complete the following occurs: When a Validator is slashed, the following occurs: -- The total `slashAmount` is calculated as the `slashFactor` (a chain parameter) * `TokensFromConsensusPower`, -the total number of tokens bonded to the validator at the time of the infraction. +- The total `slashAmount` is calculated as the `slashFactor` (a chain parameter) \* `TokensFromConsensusPower`, + the total number of tokens bonded to the validator at the time of the infraction. - Every unbonding delegation and redelegation from the validator are slashed by the `slashFactor` -percentage of the initialBalance. + percentage of the initialBalance. - Each amount slashed from redelegations and unbonding delegations is subtracted from the -total slash amount. + total slash amount. - The `remaingSlashAmount` is then slashed from the validator's tokens in the `BondedPool` or -`NonBondedPool` depending on the validator's status. This reduces the total supply of tokens. + `NonBondedPool` depending on the validator's status. This reduces the total supply of tokens. ### Slash Unbonding Delegation -When a validator is slashed, so are those unbonding delegations from the validator that began unbonding -after the time of the infraction. Every entry in every unbonding delegation from the validator -is slashed by `slashFactor`. The amount slashed is calculated from the `InitialBalance` of the +When a validator is slashed, so are those unbonding delegations from the validator that began unbonding +after the time of the infraction. Every entry in every unbonding delegation from the validator +is slashed by `slashFactor`. The amount slashed is calculated from the `InitialBalance` of the delegation and is capped to prevent a resulting negative balance. Completed (or mature) unbondings are not slashed. ### Slash Redelegation diff --git a/x/staking/spec/03_messages.md b/x/staking/spec/03_messages.md index bd9f21e2ce..1155da93d9 100644 --- a/x/staking/spec/03_messages.md +++ b/x/staking/spec/03_messages.md @@ -6,23 +6,15 @@ order: 3 In this section we describe the processing of the staking messages and the corresponding updates to the state. All created/modified state objects specified by each message are defined within the [state](./02_state_transitions.md) section. -## MsgCreateValidator +## Msg/CreateValidator -A validator is created using the `MsgCreateValidator` message. +A validator is created using the `Msg/CreateValidator` service message. -```go -type MsgCreateValidator struct { - Description Description - Commission Commission ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L16-L17 - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress - PubKey crypto.PubKey - Delegation sdk.Coin -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L35-L51 -This message is expected to fail if: +This service message is expected to fail if: - another validator with this operator address is already registered - another validator with this pubkey is already registered @@ -33,71 +25,63 @@ This message is expected to fail if: - the initial `MaxChangeRate` is either negative or > `MaxRate` - the description fields are too large -This message creates and stores the `Validator` object at appropriate indexes. +This service message creates and stores the `Validator` object at appropriate indexes. Additionally a self-delegation is made with the initial tokens delegation tokens `Delegation`. The validator always starts as unbonded but may be bonded in the first end-block. -## MsgEditValidator +## Msg/EditValidator The `Description`, `CommissionRate` of a validator can be updated using the -`MsgEditCandidacy`. +`Msg/EditCandidacy` service message. -```go -type MsgEditCandidacy struct { - Description Description - ValidatorAddr sdk.ValAddress - CommissionRate sdk.Dec -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L19-L20 -This message is expected to fail if: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L56-L76 + +This service message is expected to fail if: - the initial `CommissionRate` is either negative or > `MaxRate` - the `CommissionRate` has already been updated within the previous 24 hours - the `CommissionRate` is > `MaxChangeRate` - the description fields are too large -This message stores the updated `Validator` object. +This service message stores the updated `Validator` object. -## MsgDelegate +## Msg/Delegate -Within this message the delegator provides coins, and in return receives +Within this service message the delegator provides coins, and in return receives some amount of their validator's (newly created) delegator-shares that are assigned to `Delegation.Shares`. -```go -type MsgDelegate struct { - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress - Amount sdk.Coin -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L22-L24 -This message is expected to fail if: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L81-L90 + +This service message is expected to fail if: - the validator is does not exist - the validator is jailed - the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom` If an existing `Delegation` object for provided addresses does not already -exist than it is created as part of this message otherwise the existing +exist than it is created as part of this service message otherwise the existing `Delegation` is updated to include the newly received shares. -## MsgBeginUnbonding +## Msg/Undelegate -The begin unbonding message allows delegators to undelegate their tokens from +The `Msg/Undelegate` service message allows delegators to undelegate their tokens from validator. -```go -type MsgBeginUnbonding struct { - DelegatorAddr sdk.AccAddress - ValidatorAddr sdk.ValAddress - Amount sdk.Coin -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L30-L32 -This message is expected to fail if: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L112-L121 + +This service message returns a response containing the completion time of the undelegation: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L123-L126 + +This service message is expected to fail if: - the delegation doesn't exist - the validator doesn't exist @@ -105,7 +89,7 @@ This message is expected to fail if: - existing `UnbondingDelegation` has maximum entries as defined by `params.MaxEntries` - the `Amount` has a denomination different than one defined by `params.BondDenom` -When this message is processed the following actions occur: +When this service message is processed the following actions occur: - validator's `DelegatorShares` and the delegation's `Shares` are both reduced by the message `SharesAmount` - calculate the token worth of the shares remove that amount tokens held within the validator @@ -116,22 +100,21 @@ When this message is processed the following actions occur: - if there are no more `Shares` in the delegation, then the delegation object is removed from the store - under this situation if the delegation is the validator's self-delegation then also jail the validator. -## MsgBeginRedelegate +## Msg/BeginRedelegate The redelegation command allows delegators to instantly switch validators. Once the unbonding period has passed, the redelegation is automatically completed in the EndBlocker. -```go -type MsgBeginRedelegate struct { - DelegatorAddr sdk.AccAddress - ValidatorSrcAddr sdk.ValAddress - ValidatorDstAddr sdk.ValAddress - Amount sdk.Coin -} -``` ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L26-L28 -This message is expected to fail if: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L95-L105 + +This service message returns a response containing the completion time of the redelegation: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/cosmos/staking/v1beta1/tx.proto#L107-L110 + +This service message is expected to fail if: - the delegation doesn't exist - the source or destination validators don't exist @@ -140,7 +123,7 @@ This message is expected to fail if: - existing `Redelegation` has maximum entries as defined by `params.MaxEntries` - the `Amount` `Coin` has a denomination different than one defined by `params.BondDenom` -When this message is processed the following actions occur: +When this service message is processed the following actions occur: - the source validator's `DelegatorShares` and the delegations `Shares` are both reduced by the message `SharesAmount` - calculate the token worth of the shares remove that amount tokens held within the source validator. @@ -148,6 +131,6 @@ When this message is processed the following actions occur: - `Bonded` - add an entry to the `Redelegation` (create `Redelegation` if it doesn't exist) with a completion time a full unbonding period from the current time. Update pool shares to reduce BondedTokens and increase NotBondedTokens by token worth of the shares (this may be effectively reversed in the next step however). - `Unbonding` - add an entry to the `Redelegation` (create `Redelegation` if it doesn't exist) with the same completion time as the validator (`UnbondingMinTime`). - `Unbonded` - no action required in this step -- Delegate the token worth to the destination validator, possibly moving tokens back to the bonded state. +- Delegate the token worth to the destination validator, possibly moving tokens back to the bonded state. - if there are no more `Shares` in the source delegation, then the source delegation object is removed from the store - under this situation if the delegation is the validator's self-delegation then also jail the validator. diff --git a/x/staking/spec/07_events.md b/x/staking/spec/07_events.md index d8255ca92b..660319b3c1 100644 --- a/x/staking/spec/07_events.md +++ b/x/staking/spec/07_events.md @@ -18,9 +18,9 @@ The staking module emits the following events: | complete_redelegation | destination_validator | {dstValidatorAddress} | | complete_redelegation | delegator | {delegatorAddress} | -## Handlers +## Service Messages -### MsgCreateValidator +### Msg/CreateValidator | Type | Attribute Key | Attribute Value | | ---------------- | ------------- | ------------------ | @@ -30,7 +30,7 @@ The staking module emits the following events: | message | action | create_validator | | message | sender | {senderAddress} | -### MsgEditValidator +### Msg/EditValidator | Type | Attribute Key | Attribute Value | | -------------- | ------------------- | ------------------- | @@ -40,7 +40,7 @@ The staking module emits the following events: | message | action | edit_validator | | message | sender | {senderAddress} | -### MsgDelegate +### Msg/Delegate | Type | Attribute Key | Attribute Value | | -------- | ------------- | ------------------ | @@ -50,7 +50,7 @@ The staking module emits the following events: | message | action | delegate | | message | sender | {senderAddress} | -### MsgUndelegate +### Msg/Undelegate | Type | Attribute Key | Attribute Value | | ------- | ------------------- | ------------------ | @@ -61,9 +61,9 @@ The staking module emits the following events: | message | action | begin_unbonding | | message | sender | {senderAddress} | -* [0] Time is formatted in the RFC3339 standard +- [0] Time is formatted in the RFC3339 standard -### MsgBeginRedelegate +### Msg/BeginRedelegate | Type | Attribute Key | Attribute Value | | ---------- | --------------------- | --------------------- | @@ -75,4 +75,4 @@ The staking module emits the following events: | message | action | begin_redelegate | | message | sender | {senderAddress} | -* [0] Time is formatted in the RFC3339 standard +- [0] Time is formatted in the RFC3339 standard diff --git a/x/staking/spec/README.md b/x/staking/spec/README.md index 0005088ae8..a2cb7cf3a8 100644 --- a/x/staking/spec/README.md +++ b/x/staking/spec/README.md @@ -38,18 +38,18 @@ network. - [Delegations](02_state_transitions.md#delegations) - [Slashing](02_state_transitions.md#slashing) 3. **[Messages](03_messages.md)** - - [MsgCreateValidator](03_messages.md#msgcreatevalidator) - - [MsgEditValidator](03_messages.md#msgeditvalidator) - - [MsgDelegate](03_messages.md#msgdelegate) - - [MsgBeginUnbonding](03_messages.md#msgbeginunbonding) - - [MsgBeginRedelegate](03_messages.md#msgbeginredelegate) + - [Msg/CreateValidator](03_messages.md#msgcreatevalidator) + - [Msg/EditValidator](03_messages.md#msgeditvalidator) + - [Msg/Delegate](03_messages.md#msgdelegate) + - [Msg/BeginUnbonding](03_messages.md#msgbeginunbonding) + - [Msg/BeginRedelegate](03_messages.md#msgbeginredelegate) 4. **[Begin-Block](04_begin_block.md)** - [Historical Info Tracking](04_begin_block.md#historical-info-tracking) -4. **[End-Block ](05_end_block.md)** +5. **[End-Block ](05_end_block.md)** - [Validator Set Changes](05_end_block.md#validator-set-changes) - [Queues ](05_end_block.md#queues-) -5. **[Hooks](06_hooks.md)** -6. **[Events](07_events.md)** +6. **[Hooks](06_hooks.md)** +7. **[Events](07_events.md)** - [EndBlocker](07_events.md#endblocker) - [Handlers](07_events.md#handlers) -7. **[Parameters](08_params.md)** +8. **[Parameters](08_params.md)** diff --git a/x/staking/types/staking.pb.go b/x/staking/types/staking.pb.go index b97e1224c4..45b30b7a0e 100644 --- a/x/staking/types/staking.pb.go +++ b/x/staking/types/staking.pb.go @@ -135,8 +135,11 @@ func (m *HistoricalInfo) GetValset() []Validator { // CommissionRates defines the initial commission rates to be used for creating // a validator. type CommissionRates struct { - Rate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,1,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"rate"` - MaxRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=max_rate,json=maxRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_rate" yaml:"max_rate"` + // rate is the commission rate charged to delegators, as a fraction. + Rate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,1,opt,name=rate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"rate"` + // max_rate defines the maximum commission rate which validator can ever charge, as a fraction. + MaxRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=max_rate,json=maxRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_rate" yaml:"max_rate"` + // max_change_rate defines the maximum daily increase of the validator commission, as a fraction. MaxChangeRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=max_change_rate,json=maxChangeRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_change_rate" yaml:"max_change_rate"` } @@ -174,8 +177,10 @@ var xxx_messageInfo_CommissionRates proto.InternalMessageInfo // Commission defines commission parameters for a given validator. type Commission struct { + // commission_rates defines the initial commission rates to be used for creating a validator. CommissionRates `protobuf:"bytes,1,opt,name=commission_rates,json=commissionRates,proto3,embedded=commission_rates" json:"commission_rates"` - UpdateTime time.Time `protobuf:"bytes,2,opt,name=update_time,json=updateTime,proto3,stdtime" json:"update_time" yaml:"update_time"` + // update_time is the last time the commission rate was changed. + UpdateTime time.Time `protobuf:"bytes,2,opt,name=update_time,json=updateTime,proto3,stdtime" json:"update_time" yaml:"update_time"` } func (m *Commission) Reset() { *m = Commission{} } @@ -219,11 +224,16 @@ func (m *Commission) GetUpdateTime() time.Time { // Description defines a validator description. type Description struct { - Moniker string `protobuf:"bytes,1,opt,name=moniker,proto3" json:"moniker,omitempty"` - Identity string `protobuf:"bytes,2,opt,name=identity,proto3" json:"identity,omitempty"` - Website string `protobuf:"bytes,3,opt,name=website,proto3" json:"website,omitempty"` + // moniker defines a human-readable name for the validator. + Moniker string `protobuf:"bytes,1,opt,name=moniker,proto3" json:"moniker,omitempty"` + // identity defines an optional identity signature (ex. UPort or Keybase). + Identity string `protobuf:"bytes,2,opt,name=identity,proto3" json:"identity,omitempty"` + // website defines an optional website link. + Website string `protobuf:"bytes,3,opt,name=website,proto3" json:"website,omitempty"` + // security_contact defines an optional email for security contact. SecurityContact string `protobuf:"bytes,4,opt,name=security_contact,json=securityContact,proto3" json:"security_contact,omitempty" yaml:"security_contact"` - Details string `protobuf:"bytes,5,opt,name=details,proto3" json:"details,omitempty"` + // details define other optional details. + Details string `protobuf:"bytes,5,opt,name=details,proto3" json:"details,omitempty"` } func (m *Description) Reset() { *m = Description{} } @@ -302,16 +312,27 @@ func (m *Description) GetDetails() string { // exchange rate. Voting power can be calculated as total bonded shares // multiplied by exchange rate. type Validator struct { - OperatorAddress string `protobuf:"bytes,1,opt,name=operator_address,json=operatorAddress,proto3" json:"operator_address,omitempty" yaml:"operator_address"` - ConsensusPubkey *types1.Any `protobuf:"bytes,2,opt,name=consensus_pubkey,json=consensusPubkey,proto3" json:"consensus_pubkey,omitempty" yaml:"consensus_pubkey"` - Jailed bool `protobuf:"varint,3,opt,name=jailed,proto3" json:"jailed,omitempty"` - Status BondStatus `protobuf:"varint,4,opt,name=status,proto3,enum=cosmos.staking.v1beta1.BondStatus" json:"status,omitempty"` - Tokens github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,5,opt,name=tokens,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"tokens"` - DelegatorShares github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=delegator_shares,json=delegatorShares,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"delegator_shares" yaml:"delegator_shares"` - Description Description `protobuf:"bytes,7,opt,name=description,proto3" json:"description"` - UnbondingHeight int64 `protobuf:"varint,8,opt,name=unbonding_height,json=unbondingHeight,proto3" json:"unbonding_height,omitempty" yaml:"unbonding_height"` - UnbondingTime time.Time `protobuf:"bytes,9,opt,name=unbonding_time,json=unbondingTime,proto3,stdtime" json:"unbonding_time" yaml:"unbonding_time"` - Commission Commission `protobuf:"bytes,10,opt,name=commission,proto3" json:"commission"` + // operator_address defines the address of the validator's operator; bech encoded in JSON. + OperatorAddress string `protobuf:"bytes,1,opt,name=operator_address,json=operatorAddress,proto3" json:"operator_address,omitempty" yaml:"operator_address"` + // consensus_pubkey is the consensus public key of the validator, as a Protobuf Any. + ConsensusPubkey *types1.Any `protobuf:"bytes,2,opt,name=consensus_pubkey,json=consensusPubkey,proto3" json:"consensus_pubkey,omitempty" yaml:"consensus_pubkey"` + // jailed defined whether the validator has been jailed from bonded status or not. + Jailed bool `protobuf:"varint,3,opt,name=jailed,proto3" json:"jailed,omitempty"` + // status is the validator status (bonded/unbonding/unbonded). + Status BondStatus `protobuf:"varint,4,opt,name=status,proto3,enum=cosmos.staking.v1beta1.BondStatus" json:"status,omitempty"` + // tokens define the delegated tokens (incl. self-delegation). + Tokens github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,5,opt,name=tokens,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"tokens"` + // delegator_shares defines total shares issued to a validator's delegators. + DelegatorShares github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,6,opt,name=delegator_shares,json=delegatorShares,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"delegator_shares" yaml:"delegator_shares"` + // description defines the description terms for the validator. + Description Description `protobuf:"bytes,7,opt,name=description,proto3" json:"description"` + // unbonding_height defines, if unbonding, the height at which this validator has begun unbonding. + UnbondingHeight int64 `protobuf:"varint,8,opt,name=unbonding_height,json=unbondingHeight,proto3" json:"unbonding_height,omitempty" yaml:"unbonding_height"` + // unbonding_time defines, if unbonding, the min time for the validator to complete unbonding. + UnbondingTime time.Time `protobuf:"bytes,9,opt,name=unbonding_time,json=unbondingTime,proto3,stdtime" json:"unbonding_time" yaml:"unbonding_time"` + // commission defines the commission parameters. + Commission Commission `protobuf:"bytes,10,opt,name=commission,proto3" json:"commission"` + // min_self_delegation is the validator's self declared minimum self delegation. MinSelfDelegation github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,11,opt,name=min_self_delegation,json=minSelfDelegation,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"min_self_delegation" yaml:"min_self_delegation"` } @@ -567,9 +588,12 @@ func (m *DVVTriplets) GetTriplets() []DVVTriplet { // owned by one delegator, and is associated with the voting power of one // validator. type Delegation struct { - DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` - ValidatorAddress string `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty" yaml:"validator_address"` - Shares github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=shares,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"shares"` + // delegator_address is the bech32-encoded address of the delegator. + DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` + // validator_address is the bech32-encoded address of the validator. + ValidatorAddress string `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty" yaml:"validator_address"` + // shares define the delegation shares received. + Shares github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=shares,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"shares"` } func (m *Delegation) Reset() { *m = Delegation{} } @@ -607,9 +631,12 @@ var xxx_messageInfo_Delegation proto.InternalMessageInfo // UnbondingDelegation stores all of a single delegator's unbonding bonds // for a single validator in an time-ordered list. type UnbondingDelegation struct { - DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` - ValidatorAddress string `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty" yaml:"validator_address"` - Entries []UnbondingDelegationEntry `protobuf:"bytes,3,rep,name=entries,proto3" json:"entries"` + // delegator_address is the bech32-encoded address of the delegator. + DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` + // validator_address is the bech32-encoded address of the validator. + ValidatorAddress string `protobuf:"bytes,2,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty" yaml:"validator_address"` + // entries are the unbonding delegation entries. + Entries []UnbondingDelegationEntry `protobuf:"bytes,3,rep,name=entries,proto3" json:"entries"` } func (m *UnbondingDelegation) Reset() { *m = UnbondingDelegation{} } @@ -646,10 +673,14 @@ var xxx_messageInfo_UnbondingDelegation proto.InternalMessageInfo // UnbondingDelegationEntry defines an unbonding object with relevant metadata. type UnbondingDelegationEntry struct { - CreationHeight int64 `protobuf:"varint,1,opt,name=creation_height,json=creationHeight,proto3" json:"creation_height,omitempty" yaml:"creation_height"` - CompletionTime time.Time `protobuf:"bytes,2,opt,name=completion_time,json=completionTime,proto3,stdtime" json:"completion_time" yaml:"completion_time"` + // creation_height is the height which the unbonding took place. + CreationHeight int64 `protobuf:"varint,1,opt,name=creation_height,json=creationHeight,proto3" json:"creation_height,omitempty" yaml:"creation_height"` + // completion_time is the unix time for unbonding completion. + CompletionTime time.Time `protobuf:"bytes,2,opt,name=completion_time,json=completionTime,proto3,stdtime" json:"completion_time" yaml:"completion_time"` + // initial_balance defines the tokens initially scheduled to receive at completion. InitialBalance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=initial_balance,json=initialBalance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"initial_balance" yaml:"initial_balance"` - Balance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=balance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"balance"` + // balance defines the tokens to receive at completion. + Balance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=balance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"balance"` } func (m *UnbondingDelegationEntry) Reset() { *m = UnbondingDelegationEntry{} } @@ -700,10 +731,14 @@ func (m *UnbondingDelegationEntry) GetCompletionTime() time.Time { // RedelegationEntry defines a redelegation object with relevant metadata. type RedelegationEntry struct { - CreationHeight int64 `protobuf:"varint,1,opt,name=creation_height,json=creationHeight,proto3" json:"creation_height,omitempty" yaml:"creation_height"` - CompletionTime time.Time `protobuf:"bytes,2,opt,name=completion_time,json=completionTime,proto3,stdtime" json:"completion_time" yaml:"completion_time"` + // creation_height defines the height which the redelegation took place. + CreationHeight int64 `protobuf:"varint,1,opt,name=creation_height,json=creationHeight,proto3" json:"creation_height,omitempty" yaml:"creation_height"` + // completion_time defines the unix time for redelegation completion. + CompletionTime time.Time `protobuf:"bytes,2,opt,name=completion_time,json=completionTime,proto3,stdtime" json:"completion_time" yaml:"completion_time"` + // initial_balance defines the initial balance when redelegation started. InitialBalance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=initial_balance,json=initialBalance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"initial_balance" yaml:"initial_balance"` - SharesDst github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=shares_dst,json=sharesDst,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"shares_dst"` + // shares_dst is the amount of destination-validator shares created by redelegation. + SharesDst github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=shares_dst,json=sharesDst,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"shares_dst"` } func (m *RedelegationEntry) Reset() { *m = RedelegationEntry{} } @@ -755,10 +790,14 @@ func (m *RedelegationEntry) GetCompletionTime() time.Time { // Redelegation contains the list of a particular delegator's redelegating bonds // from a particular source validator to a particular destination validator. type Redelegation struct { - DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` - ValidatorSrcAddress string `protobuf:"bytes,2,opt,name=validator_src_address,json=validatorSrcAddress,proto3" json:"validator_src_address,omitempty" yaml:"validator_src_address"` - ValidatorDstAddress string `protobuf:"bytes,3,opt,name=validator_dst_address,json=validatorDstAddress,proto3" json:"validator_dst_address,omitempty" yaml:"validator_dst_address"` - Entries []RedelegationEntry `protobuf:"bytes,4,rep,name=entries,proto3" json:"entries"` + // delegator_address is the bech32-encoded address of the delegator. + DelegatorAddress string `protobuf:"bytes,1,opt,name=delegator_address,json=delegatorAddress,proto3" json:"delegator_address,omitempty" yaml:"delegator_address"` + // validator_src_address is the validator redelegation source operator address. + ValidatorSrcAddress string `protobuf:"bytes,2,opt,name=validator_src_address,json=validatorSrcAddress,proto3" json:"validator_src_address,omitempty" yaml:"validator_src_address"` + // validator_dst_address is the validator redelegation destination operator address. + ValidatorDstAddress string `protobuf:"bytes,3,opt,name=validator_dst_address,json=validatorDstAddress,proto3" json:"validator_dst_address,omitempty" yaml:"validator_dst_address"` + // entries are the redelegation entries. + Entries []RedelegationEntry `protobuf:"bytes,4,rep,name=entries,proto3" json:"entries"` } func (m *Redelegation) Reset() { *m = Redelegation{} } @@ -795,11 +834,16 @@ var xxx_messageInfo_Redelegation proto.InternalMessageInfo // Params defines the parameters for the staking module. type Params struct { - UnbondingTime time.Duration `protobuf:"bytes,1,opt,name=unbonding_time,json=unbondingTime,proto3,stdduration" json:"unbonding_time" yaml:"unbonding_time"` - MaxValidators uint32 `protobuf:"varint,2,opt,name=max_validators,json=maxValidators,proto3" json:"max_validators,omitempty" yaml:"max_validators"` - MaxEntries uint32 `protobuf:"varint,3,opt,name=max_entries,json=maxEntries,proto3" json:"max_entries,omitempty" yaml:"max_entries"` - HistoricalEntries uint32 `protobuf:"varint,4,opt,name=historical_entries,json=historicalEntries,proto3" json:"historical_entries,omitempty" yaml:"historical_entries"` - BondDenom string `protobuf:"bytes,5,opt,name=bond_denom,json=bondDenom,proto3" json:"bond_denom,omitempty" yaml:"bond_denom"` + // unbonding_time is the time duration of unbonding. + UnbondingTime time.Duration `protobuf:"bytes,1,opt,name=unbonding_time,json=unbondingTime,proto3,stdduration" json:"unbonding_time" yaml:"unbonding_time"` + // max_validators is the maximum number of validators. + MaxValidators uint32 `protobuf:"varint,2,opt,name=max_validators,json=maxValidators,proto3" json:"max_validators,omitempty" yaml:"max_validators"` + // max_entries is the max entries for either unbonding delegation or redelegation (per pair/trio). + MaxEntries uint32 `protobuf:"varint,3,opt,name=max_entries,json=maxEntries,proto3" json:"max_entries,omitempty" yaml:"max_entries"` + // historical_entries is the number of historical entries to persist. + HistoricalEntries uint32 `protobuf:"varint,4,opt,name=historical_entries,json=historicalEntries,proto3" json:"historical_entries,omitempty" yaml:"historical_entries"` + // bond_denom defines the bondable coin denomination. + BondDenom string `protobuf:"bytes,5,opt,name=bond_denom,json=bondDenom,proto3" json:"bond_denom,omitempty" yaml:"bond_denom"` } func (m *Params) Reset() { *m = Params{} } From 17d7e9a8d51e11340aab1705a3d47b6f98abff6f Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 1 Feb 2021 14:01:53 +0100 Subject: [PATCH 27/40] Add packet_connection attribute to packet lifecycle methods (#8458) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add packet_connection attribute to packet lifecycle methods Added to: * SendPacket * ReceivePacket * WriteAcknowledgement * AcknowledgePacket * Add CHANGELOG * Update CHANGELOG.md Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- CHANGELOG.md | 1 + x/ibc/core/04-channel/keeper/packet.go | 12 ++++++++++++ x/ibc/core/04-channel/types/events.go | 1 + 3 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bcb99bd84..12f0ff2d30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/ibc) [\#8458](https://github.com/cosmos/cosmos-sdk/pull/8458) Add `packet_connection` attribute to ibc events to enable relayer filtering * (x/bank) [\#8479](https://github.com/cosmos/cosmos-sdk/pull/8479) Adittional client denom metadata validation for `base` and `display` denoms. * (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks. * [\#8396](https://github.com/cosmos/cosmos-sdk/pull/8396) Add support for ARM platform diff --git a/x/ibc/core/04-channel/keeper/packet.go b/x/ibc/core/04-channel/keeper/packet.go index 9af59745d5..49b59733c5 100644 --- a/x/ibc/core/04-channel/keeper/packet.go +++ b/x/ibc/core/04-channel/keeper/packet.go @@ -129,6 +129,9 @@ func (k Keeper) SendPacket( sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()), sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()), sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()), + // we only support 1-hop packets now, and that is the most important hop for a relayer + // (is it going to a chain I am connected to) + sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]), ), sdk.NewEvent( sdk.EventTypeMessage, @@ -289,6 +292,9 @@ func (k Keeper) RecvPacket( sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()), sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()), sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()), + // we only support 1-hop packets now, and that is the most important hop for a relayer + // (is it going to a chain I am connected to) + sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]), ), sdk.NewEvent( sdk.EventTypeMessage, @@ -370,6 +376,9 @@ func (k Keeper) WriteAcknowledgement( sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()), sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()), sdk.NewAttribute(types.AttributeKeyAck, string(acknowledgement)), + // we only support 1-hop packets now, and that is the most important hop for a relayer + // (is it going to a chain I am connected to) + sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]), ), sdk.NewEvent( sdk.EventTypeMessage, @@ -505,6 +514,9 @@ func (k Keeper) AcknowledgePacket( sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()), sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()), sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()), + // we only support 1-hop packets now, and that is the most important hop for a relayer + // (is it going to a chain I am connected to) + sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]), ), sdk.NewEvent( sdk.EventTypeMessage, diff --git a/x/ibc/core/04-channel/types/events.go b/x/ibc/core/04-channel/types/events.go index 923587d439..b9ddb3052c 100644 --- a/x/ibc/core/04-channel/types/events.go +++ b/x/ibc/core/04-channel/types/events.go @@ -30,6 +30,7 @@ const ( AttributeKeyDstPort = "packet_dst_port" AttributeKeyDstChannel = "packet_dst_channel" AttributeKeyChannelOrdering = "packet_channel_ordering" + AttributeKeyConnection = "packet_connection" ) // IBC channel events vars From c1b567f44c093ae68c551dc88b0e4886a187c213 Mon Sep 17 00:00:00 2001 From: Amaury Date: Mon, 1 Feb 2021 14:17:44 +0100 Subject: [PATCH 28/40] Refactor store keys for variable-length addresses (#8363) * Change account store key in x/bank * Fix pagination test * Fix merge master * Fix staking keys.go * Use bech32 in val state change map * Fix sortNoLongerBonded * Use length-prefix function * Use length prefix function * Fix test accountStore * Fix ExamplePaginate * Fix staking keys * Use shorter balances prefix * Do slashing keys * Fix gov keys * Fix x/gov tests * Fix x/distrib * Address reviews * add change log entry * Add changelog * Fix failing tests * Fix sim tests * fix after-export sim * Fix lint * Address review * Fix x/authz * Fix global config in test * Update x/staking/keeper/val_state_change.go Co-authored-by: Robert Zaremba * Address comments * Fix comments * Address review * Fix authz test * Update comment * Rename to LengthPrefixedAddressStoreKey * Use variable * Rename function * Fix test build * chore: update rosetta CI (#8453) * Rename again * Rename yet again * Update feegrant keys * Add function to create prefix Co-authored-by: Robert Zaremba Co-authored-by: Frojdi Dymylja <33157909+fdymylja@users.noreply.github.com> Co-authored-by: Aaron Craelius Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- CHANGELOG.md | 5 + contrib/rosetta/configuration/bootstrap.json | 4 +- contrib/rosetta/configuration/data.sh | 5 +- contrib/rosetta/configuration/staking.ros | 4 +- contrib/rosetta/node/data.tar.gz | Bin 34626 -> 36558 bytes simapp/export.go | 2 +- types/address.go | 14 +- types/address/store_key.go | 33 ++++ types/address/store_key_test.go | 38 +++++ types/address_test.go | 40 +++-- types/query/filtered_pagination_test.go | 5 +- types/query/pagination_test.go | 3 +- x/authz/types/keys.go | 19 ++- x/bank/keeper/grpc_query.go | 4 +- x/bank/keeper/send.go | 9 +- x/bank/keeper/view.go | 15 +- x/bank/types/key.go | 18 ++- x/bank/types/key_test.go | 5 +- x/bank/types/msgs_test.go | 21 ++- x/distribution/types/keys.go | 143 +++++++++-------- x/feegrant/types/key.go | 5 +- x/gov/types/keys.go | 17 +- x/gov/types/keys_test.go | 10 -- x/slashing/types/keys.go | 23 +-- x/staking/keeper/val_state_change.go | 63 +++++--- x/staking/keeper/validator.go | 2 +- x/staking/types/keys.go | 155 ++++++++++--------- x/staking/types/keys_test.go | 20 +-- 28 files changed, 411 insertions(+), 271 deletions(-) create mode 100644 types/address/store_key.go create mode 100644 types/address/store_key_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 12f0ff2d30..1a5fa83652 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,8 +36,13 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Client Breaking Changes + +* [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Addresses no longer have a fixed 20-byte length. From the SDK modules' point of view, any 1-255 bytes-long byte array is a valid address. + ### State Machine Breaking +* (x/{bank,distrib,gov,slashing,staking}) [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Store keys have been modified to allow for variable-length addresses. * (x/ibc) [\#8266](https://github.com/cosmos/cosmos-sdk/issues/8266) Add amino JSON for IBC messages in order to support Ledger text signing. ### Improvements diff --git a/contrib/rosetta/configuration/bootstrap.json b/contrib/rosetta/configuration/bootstrap.json index 15b75b5508..1793988f37 100644 --- a/contrib/rosetta/configuration/bootstrap.json +++ b/contrib/rosetta/configuration/bootstrap.json @@ -1,12 +1,12 @@ [ { "account_identifier": { - "address":"cosmos1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjjqfl87e" + "address":"cosmos158nkd0l9tyemv2crp579rmj8dg37qty8lzff88" }, "currency":{ "symbol":"stake", "decimals":0 }, - "value": "999900000000" + "value": "999990000000" } ] \ No newline at end of file diff --git a/contrib/rosetta/configuration/data.sh b/contrib/rosetta/configuration/data.sh index dc4f2cb59a..45297d5a21 100644 --- a/contrib/rosetta/configuration/data.sh +++ b/contrib/rosetta/configuration/data.sh @@ -16,12 +16,13 @@ simd init simd --chain-id testing simd keys add fd --keyring-backend=test addr=$(simd keys show fd -a --keyring-backend=test) +val_addr=$(simd keys show fd --keyring-backend=test --bech val -a) # give the accounts some money simd add-genesis-account "$addr" 1000000000000stake --keyring-backend=test # save configs for the daemon -simd gentx fd --chain-id testing --keyring-backend=test +simd gentx fd 10000000stake --chain-id testing --keyring-backend=test # input genTx to the genesis file simd collect-gentxs @@ -55,4 +56,4 @@ echo zipping data dir and saving to /tmp/data.tar.gz tar -czvf /tmp/data.tar.gz /root/.simapp -echo new address for bootstrap.json "$addr" +echo new address for bootstrap.json "$addr" "$val_addr" diff --git a/contrib/rosetta/configuration/staking.ros b/contrib/rosetta/configuration/staking.ros index 1d9de1d180..4f89a43b98 100644 --- a/contrib/rosetta/configuration/staking.ros +++ b/contrib/rosetta/configuration/staking.ros @@ -94,7 +94,7 @@ staking(1){ "account": { "address": "staking_account", "sub_account": { - "address" : "cosmosvaloper1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjj9atjj2" + "address" : "cosmosvaloper158nkd0l9tyemv2crp579rmj8dg37qty86kaut5" } }, "amount":{ @@ -134,7 +134,7 @@ staking(1){ "account": { "address": "staking_account", "sub_account": { - "address" : "cosmosvaloper1hdmjfmqmf8ck4pv4evu0s3up0ucm0yjj9atjj2" + "address" : "cosmosvaloper158nkd0l9tyemv2crp579rmj8dg37qty86kaut5" } }, "amount":{ diff --git a/contrib/rosetta/node/data.tar.gz b/contrib/rosetta/node/data.tar.gz index a7bed60579ea098baa390af3a29e05b08d16dcc8..ad285ac62e75198c4945859e12ccf7b563c7c29b 100644 GIT binary patch literal 36558 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 W{ds@hpZDkg{P{11*Qv_@PyztMa6X;@ literal 34626 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 O?DZF9r!))zMgjoC3=_)$ diff --git a/simapp/export.go b/simapp/export.go index 887308d30a..8d09e333a2 100644 --- a/simapp/export.go +++ b/simapp/export.go @@ -157,7 +157,7 @@ func (app *SimApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs [] counter := int16(0) for ; iter.Valid(); iter.Next() { - addr := sdk.ValAddress(iter.Key()[1:]) + addr := sdk.ValAddress(stakingtypes.AddressFromValidatorsKey(iter.Key())) validator, found := app.StakingKeeper.GetValidator(ctx, addr) if !found { panic("expected validator, not found") diff --git a/types/address.go b/types/address.go index ba9e5b303b..eabff6fa97 100644 --- a/types/address.go +++ b/types/address.go @@ -12,7 +12,9 @@ import ( "github.com/cosmos/cosmos-sdk/codec/legacy" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/bech32" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) const ( @@ -28,8 +30,6 @@ const ( // config.SetFullFundraiserPath(yourFullFundraiserPath) // config.Seal() - // AddrLen defines a valid address length - AddrLen = 20 // Bech32MainPrefix defines the main SDK Bech32 prefix of an account's address Bech32MainPrefix = "cosmos" @@ -110,9 +110,15 @@ func VerifyAddressFormat(bz []byte) error { if verifier != nil { return verifier(bz) } - if len(bz) != AddrLen { - return fmt.Errorf("incorrect address length (expected: %d, actual: %d)", AddrLen, len(bz)) + + if len(bz) == 0 { + return sdkerrors.Wrap(sdkerrors.ErrUnknownAddress, "addresses cannot be empty") } + + if len(bz) > address.MaxAddrLen { + return sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "address max length is %d, got %d", address.MaxAddrLen, len(bz)) + } + return nil } diff --git a/types/address/store_key.go b/types/address/store_key.go new file mode 100644 index 0000000000..9484919729 --- /dev/null +++ b/types/address/store_key.go @@ -0,0 +1,33 @@ +package address + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// MaxAddrLen is the maximum allowed length (in bytes) for an address. +const MaxAddrLen = 255 + +// LengthPrefix prefixes the address bytes with its length, this is used +// for example for variable-length components in store keys. +func LengthPrefix(bz []byte) ([]byte, error) { + bzLen := len(bz) + if bzLen == 0 { + return bz, nil + } + + if bzLen > MaxAddrLen { + return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownAddress, "address length should be max %d bytes, got %d", MaxAddrLen, bzLen) + } + + return append([]byte{byte(bzLen)}, bz...), nil +} + +// MustLengthPrefix is LengthPrefix with panic on error. +func MustLengthPrefix(bz []byte) []byte { + res, err := LengthPrefix(bz) + if err != nil { + panic(err) + } + + return res +} diff --git a/types/address/store_key_test.go b/types/address/store_key_test.go new file mode 100644 index 0000000000..3bb00bd022 --- /dev/null +++ b/types/address/store_key_test.go @@ -0,0 +1,38 @@ +package address_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/types/address" +) + +func TestLengthPrefixedAddressStoreKey(t *testing.T) { + addr10byte := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} + addr20byte := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19} + addr256byte := make([]byte, 256) + + tests := []struct { + name string + addr []byte + expStoreKey []byte + expErr bool + }{ + {"10-byte address", addr10byte, append([]byte{byte(10)}, addr10byte...), false}, + {"20-byte address", addr20byte, append([]byte{byte(20)}, addr20byte...), false}, + {"256-byte address (too long)", addr256byte, nil, true}, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + storeKey, err := address.LengthPrefix(tt.addr) + if tt.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.expStoreKey, storeKey) + } + }) + } +} diff --git a/types/address_test.go b/types/address_test.go index 5796c891ac..b9bc0c3c53 100644 --- a/types/address_test.go +++ b/types/address_test.go @@ -347,15 +347,18 @@ func (s *addressTestSuite) TestVerifyAddressFormat() { addr5 := make([]byte, 5) addr20 := make([]byte, 20) addr32 := make([]byte, 32) + addr256 := make([]byte, 256) err := types.VerifyAddressFormat(addr0) - s.Require().EqualError(err, "incorrect address length 0") + s.Require().EqualError(err, "addresses cannot be empty: unknown address") err = types.VerifyAddressFormat(addr5) - s.Require().EqualError(err, "incorrect address length 5") + s.Require().NoError(err) err = types.VerifyAddressFormat(addr20) - s.Require().Nil(err) + s.Require().NoError(err) err = types.VerifyAddressFormat(addr32) - s.Require().EqualError(err, "incorrect address length 32") + s.Require().NoError(err) + err = types.VerifyAddressFormat(addr256) + s.Require().EqualError(err, "address max length is 255, got 256: unknown address") } func (s *addressTestSuite) TestCustomAddressVerifier() { @@ -364,34 +367,39 @@ func (s *addressTestSuite) TestCustomAddressVerifier() { accBech := types.AccAddress(addr).String() valBech := types.ValAddress(addr).String() consBech := types.ConsAddress(addr).String() - // Verifiy that the default logic rejects this 10 byte address + // Verify that the default logic doesn't reject this 10 byte address + // The default verifier is nil, we're only checking address length is + // between 1-255 bytes. err := types.VerifyAddressFormat(addr) - s.Require().NotNil(err) + s.Require().Nil(err) _, err = types.AccAddressFromBech32(accBech) - s.Require().NotNil(err) + s.Require().Nil(err) _, err = types.ValAddressFromBech32(valBech) - s.Require().NotNil(err) + s.Require().Nil(err) _, err = types.ConsAddressFromBech32(consBech) - s.Require().NotNil(err) + s.Require().Nil(err) - // Set a custom address verifier that accepts 10 or 20 byte addresses + // Set a custom address verifier only accepts 20 byte addresses types.GetConfig().SetAddressVerifier(func(bz []byte) error { n := len(bz) - if n == 10 || n == types.AddrLen { + if n == 20 { return nil } return fmt.Errorf("incorrect address length %d", n) }) - // Verifiy that the custom logic accepts this 10 byte address + // Verifiy that the custom logic rejects this 10 byte address err = types.VerifyAddressFormat(addr) - s.Require().Nil(err) + s.Require().NotNil(err) _, err = types.AccAddressFromBech32(accBech) - s.Require().Nil(err) + s.Require().NotNil(err) _, err = types.ValAddressFromBech32(valBech) - s.Require().Nil(err) + s.Require().NotNil(err) _, err = types.ConsAddressFromBech32(consBech) - s.Require().Nil(err) + s.Require().NotNil(err) + + // Reinitialize the global config to default address verifier (nil) + types.GetConfig().SetAddressVerifier(nil) } func (s *addressTestSuite) TestBech32ifyAddressBytes() { diff --git a/types/query/filtered_pagination_test.go b/types/query/filtered_pagination_test.go index dbd2057da4..2622f7b8e7 100644 --- a/types/query/filtered_pagination_test.go +++ b/types/query/filtered_pagination_test.go @@ -6,6 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/query" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -111,7 +112,7 @@ func ExampleFilteredPaginate() { pageReq := &query.PageRequest{Key: nil, Limit: 1, CountTotal: true} store := ctx.KVStore(app.GetKey(authtypes.StoreKey)) balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr1.Bytes()) + accountStore := prefix.NewStore(balancesStore, address.MustLengthPrefix(addr1)) var balResult sdk.Coins pageRes, err := query.FilteredPaginate(accountStore, pageReq, func(key []byte, value []byte, accumulate bool) (bool, error) { @@ -143,7 +144,7 @@ func ExampleFilteredPaginate() { func execFilterPaginate(store sdk.KVStore, pageReq *query.PageRequest, appCodec codec.Marshaler) (balances sdk.Coins, res *query.PageResponse, err error) { balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr1.Bytes()) + accountStore := prefix.NewStore(balancesStore, address.MustLengthPrefix(addr1)) var balResult sdk.Coins res, err = query.FilteredPaginate(accountStore, pageReq, func(key []byte, value []byte, accumulate bool) (bool, error) { diff --git a/types/query/pagination_test.go b/types/query/pagination_test.go index f0e1377a1e..18853e97cc 100644 --- a/types/query/pagination_test.go +++ b/types/query/pagination_test.go @@ -17,6 +17,7 @@ import ( "github.com/cosmos/cosmos-sdk/store" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/types/query" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -193,7 +194,7 @@ func ExamplePaginate() { balResult := sdk.NewCoins() authStore := ctx.KVStore(app.GetKey(authtypes.StoreKey)) balancesStore := prefix.NewStore(authStore, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr1.Bytes()) + accountStore := prefix.NewStore(balancesStore, address.MustLengthPrefix(addr1)) pageRes, err := query.Paginate(accountStore, request.Pagination, func(key []byte, value []byte) error { var tempRes sdk.Coin err := app.AppCodec().UnmarshalBinaryBare(value, &tempRes) diff --git a/x/authz/types/keys.go b/x/authz/types/keys.go index 3be659c5ae..7ee571b27f 100644 --- a/x/authz/types/keys.go +++ b/x/authz/types/keys.go @@ -2,6 +2,7 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -21,7 +22,7 @@ const ( // Keys for authz store // Items are stored with the following key: values // -// - 0x01: Grant +// - 0x01: Grant var ( // Keys for store prefixes @@ -30,12 +31,22 @@ var ( // GetAuthorizationStoreKey - return authorization store key func GetAuthorizationStoreKey(grantee sdk.AccAddress, granter sdk.AccAddress, msgType string) []byte { - return append(append(append(GrantKey, granter.Bytes()...), grantee.Bytes()...), []byte(msgType)...) + return append(append(append( + GrantKey, + address.MustLengthPrefix(granter)...), + address.MustLengthPrefix(grantee)...), + []byte(msgType)..., + ) } // ExtractAddressesFromGrantKey - split granter & grantee address from the authorization key func ExtractAddressesFromGrantKey(key []byte) (granterAddr, granteeAddr sdk.AccAddress) { - granterAddr = sdk.AccAddress(key[1 : sdk.AddrLen+1]) - granteeAddr = sdk.AccAddress(key[sdk.AddrLen+1 : sdk.AddrLen*2+1]) + // key if of format: + // 0x01 + granterAddrLen := key[1] // remove prefix key + granterAddr = sdk.AccAddress(key[2 : 2+granterAddrLen]) + granteeAddrLen := int(key[2+granterAddrLen]) + granteeAddr = sdk.AccAddress(key[3+granterAddrLen : 3+granterAddrLen+byte(granteeAddrLen)]) + return granterAddr, granteeAddr } diff --git a/x/bank/keeper/grpc_query.go b/x/bank/keeper/grpc_query.go index ae00d1b873..b8f69ef127 100644 --- a/x/bank/keeper/grpc_query.go +++ b/x/bank/keeper/grpc_query.go @@ -57,9 +57,7 @@ func (k BaseKeeper) AllBalances(ctx context.Context, req *types.QueryAllBalances sdkCtx := sdk.UnwrapSDKContext(ctx) balances := sdk.NewCoins() - store := sdkCtx.KVStore(k.storeKey) - balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr.Bytes()) + accountStore := k.getAccountStore(sdkCtx, addr) pageRes, err := query.Paginate(accountStore, req.Pagination, func(_, value []byte) error { var result sdk.Coin diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go index c1000b7d30..694c43211e 100644 --- a/x/bank/keeper/send.go +++ b/x/bank/keeper/send.go @@ -2,7 +2,6 @@ package keeper import ( "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/store/prefix" "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -233,9 +232,7 @@ func (k BaseSendKeeper) ClearBalances(ctx sdk.Context, addr sdk.AccAddress) { return false }) - store := ctx.KVStore(k.storeKey) - balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr.Bytes()) + accountStore := k.getAccountStore(ctx, addr) for _, key := range keys { accountStore.Delete(key) @@ -264,9 +261,7 @@ func (k BaseSendKeeper) SetBalance(ctx sdk.Context, addr sdk.AccAddress, balance return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, balance.String()) } - store := ctx.KVStore(k.storeKey) - balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr.Bytes()) + accountStore := k.getAccountStore(ctx, addr) bz := k.cdc.MustMarshalBinaryBare(&balance) accountStore.Set([]byte(balance.Denom), bz) diff --git a/x/bank/keeper/view.go b/x/bank/keeper/view.go index d4bcabad2b..1b50fb81d3 100644 --- a/x/bank/keeper/view.go +++ b/x/bank/keeper/view.go @@ -97,9 +97,7 @@ func (k BaseViewKeeper) GetAccountsBalances(ctx sdk.Context) []types.Balance { // GetBalance returns the balance of a specific denomination for a given account // by address. func (k BaseViewKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { - store := ctx.KVStore(k.storeKey) - balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr.Bytes()) + accountStore := k.getAccountStore(ctx, addr) bz := accountStore.Get([]byte(denom)) if bz == nil { @@ -116,9 +114,7 @@ func (k BaseViewKeeper) GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom s // provides the token balance to a callback. If true is returned from the // callback, iteration is halted. func (k BaseViewKeeper) IterateAccountBalances(ctx sdk.Context, addr sdk.AccAddress, cb func(sdk.Coin) bool) { - store := ctx.KVStore(k.storeKey) - balancesStore := prefix.NewStore(store, types.BalancesPrefix) - accountStore := prefix.NewStore(balancesStore, addr.Bytes()) + accountStore := k.getAccountStore(ctx, addr) iterator := accountStore.Iterator(nil, nil) defer iterator.Close() @@ -214,3 +210,10 @@ func (k BaseViewKeeper) ValidateBalance(ctx sdk.Context, addr sdk.AccAddress) er return nil } + +// getAccountStore gets the account store of the given address. +func (k BaseViewKeeper) getAccountStore(ctx sdk.Context, addr sdk.AccAddress) prefix.Store { + store := ctx.KVStore(k.storeKey) + + return prefix.NewStore(store, types.CreateAccountBalancesPrefix(addr)) +} diff --git a/x/bank/types/key.go b/x/bank/types/key.go index ec8619d001..858fd2480a 100644 --- a/x/bank/types/key.go +++ b/x/bank/types/key.go @@ -1,9 +1,8 @@ package types import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -22,7 +21,9 @@ const ( // KVStore keys var ( - BalancesPrefix = []byte("balances") + // BalancesPrefix is the for the account balances store. We use a byte + // (instead of say `[]]byte("balances")` to save some disk space). + BalancesPrefix = []byte{0x02} SupplyKey = []byte{0x00} DenomMetadataPrefix = []byte{0x1} ) @@ -37,10 +38,13 @@ func DenomMetadataKey(denom string) []byte { // store. The key must not contain the perfix BalancesPrefix as the prefix store // iterator discards the actual prefix. func AddressFromBalancesStore(key []byte) sdk.AccAddress { - addr := key[:sdk.AddrLen] - if len(addr) != sdk.AddrLen { - panic(fmt.Sprintf("unexpected account address key length; got: %d, expected: %d", len(addr), sdk.AddrLen)) - } + addrLen := key[0] + addr := key[1 : addrLen+1] return sdk.AccAddress(addr) } + +// CreateAccountBalancesPrefix creates the prefix for an account's balances. +func CreateAccountBalancesPrefix(addr []byte) []byte { + return append(BalancesPrefix, address.MustLengthPrefix(addr)...) +} diff --git a/x/bank/types/key_test.go b/x/bank/types/key_test.go index f3b5717fbe..206ef8335c 100644 --- a/x/bank/types/key_test.go +++ b/x/bank/types/key_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -19,8 +20,10 @@ func cloneAppend(bz []byte, tail []byte) (res []byte) { func TestAddressFromBalancesStore(t *testing.T) { addr, err := sdk.AccAddressFromBech32("cosmos1n88uc38xhjgxzw9nwre4ep2c8ga4fjxcar6mn7") require.NoError(t, err) + addrLen := len(addr) + require.Equal(t, 20, addrLen) - key := cloneAppend(addr.Bytes(), []byte("stake")) + key := cloneAppend(address.MustLengthPrefix(addr), []byte("stake")) res := types.AddressFromBalancesStore(key) require.Equal(t, res, addr) } diff --git a/x/bank/types/msgs_test.go b/x/bank/types/msgs_test.go index 96132150ad..334d72c132 100644 --- a/x/bank/types/msgs_test.go +++ b/x/bank/types/msgs_test.go @@ -23,7 +23,7 @@ func TestMsgSendValidation(t *testing.T) { addr1 := sdk.AccAddress([]byte("from________________")) addr2 := sdk.AccAddress([]byte("to__________________")) addrEmpty := sdk.AccAddress([]byte("")) - addrTooLong := sdk.AccAddress([]byte("Accidentally used 33 bytes pubkey")) + addrLong := sdk.AccAddress([]byte("Purposefully long address")) atom123 := sdk.NewCoins(sdk.NewInt64Coin("atom", 123)) atom0 := sdk.NewCoins(sdk.NewInt64Coin("atom", 0)) @@ -36,12 +36,12 @@ func TestMsgSendValidation(t *testing.T) { }{ {"", NewMsgSend(addr1, addr2, atom123)}, // valid send {"", NewMsgSend(addr1, addr2, atom123eth123)}, // valid send with multiple coins + {"", NewMsgSend(addrLong, addr2, atom123)}, // valid send with long addr sender + {"", NewMsgSend(addr1, addrLong, atom123)}, // valid send with long addr recipient {": invalid coins", NewMsgSend(addr1, addr2, atom0)}, // non positive coin {"123atom,0eth: invalid coins", NewMsgSend(addr1, addr2, atom123eth0)}, // non positive coin in multicoins {"Invalid sender address (empty address string is not allowed): invalid address", NewMsgSend(addrEmpty, addr2, atom123)}, - {"Invalid sender address (incorrect address length (expected: 20, actual: 33)): invalid address", NewMsgSend(addrTooLong, addr2, atom123)}, {"Invalid recipient address (empty address string is not allowed): invalid address", NewMsgSend(addr1, addrEmpty, atom123)}, - {"Invalid recipient address (incorrect address length (expected: 20, actual: 33)): invalid address", NewMsgSend(addr1, addrTooLong, atom123)}, } for _, tc := range cases { @@ -91,7 +91,7 @@ func TestInputValidation(t *testing.T) { addr1 := sdk.AccAddress([]byte("_______alice________")) addr2 := sdk.AccAddress([]byte("________bob_________")) addrEmpty := sdk.AccAddress([]byte("")) - addrTooLong := sdk.AccAddress([]byte("Accidentally used 33 bytes pubkey")) + addrLong := sdk.AccAddress([]byte("Purposefully long address")) someCoins := sdk.NewCoins(sdk.NewInt64Coin("atom", 123)) multiCoins := sdk.NewCoins(sdk.NewInt64Coin("atom", 123), sdk.NewInt64Coin("eth", 20)) @@ -109,9 +109,9 @@ func TestInputValidation(t *testing.T) { {"", NewInput(addr1, someCoins)}, {"", NewInput(addr2, someCoins)}, {"", NewInput(addr2, multiCoins)}, + {"", NewInput(addrLong, someCoins)}, {"empty address string is not allowed", NewInput(addrEmpty, someCoins)}, - {"incorrect address length (expected: 20, actual: 33)", NewInput(addrTooLong, someCoins)}, {": invalid coins", NewInput(addr1, emptyCoins)}, // invalid coins {": invalid coins", NewInput(addr1, emptyCoins2)}, // invalid coins {"10eth,0atom: invalid coins", NewInput(addr1, someEmptyCoins)}, // invalid coins @@ -132,7 +132,7 @@ func TestOutputValidation(t *testing.T) { addr1 := sdk.AccAddress([]byte("_______alice________")) addr2 := sdk.AccAddress([]byte("________bob_________")) addrEmpty := sdk.AccAddress([]byte("")) - addrTooLong := sdk.AccAddress([]byte("Accidentally used 33 bytes pubkey")) + addrLong := sdk.AccAddress([]byte("Purposefully long address")) someCoins := sdk.NewCoins(sdk.NewInt64Coin("atom", 123)) multiCoins := sdk.NewCoins(sdk.NewInt64Coin("atom", 123), sdk.NewInt64Coin("eth", 20)) @@ -150,9 +150,9 @@ func TestOutputValidation(t *testing.T) { {"", NewOutput(addr1, someCoins)}, {"", NewOutput(addr2, someCoins)}, {"", NewOutput(addr2, multiCoins)}, + {"", NewOutput(addrLong, someCoins)}, {"Invalid output address (empty address string is not allowed): invalid address", NewOutput(addrEmpty, someCoins)}, - {"Invalid output address (incorrect address length (expected: 20, actual: 33)): invalid address", NewOutput(addrTooLong, someCoins)}, {": invalid coins", NewOutput(addr1, emptyCoins)}, // invalid coins {": invalid coins", NewOutput(addr1, emptyCoins2)}, // invalid coins {"10eth,0atom: invalid coins", NewOutput(addr1, someEmptyCoins)}, // invalid coins @@ -251,8 +251,6 @@ func TestMsgMultiSendGetSigners(t *testing.T) { require.Equal(t, "[696E707574313131313131313131313131313131 696E707574323232323232323232323232323232 696E707574333333333333333333333333333333]", fmt.Sprintf("%v", res)) } -/* -// what to do w/ this test? func TestMsgSendSigners(t *testing.T) { signers := []sdk.AccAddress{ {1, 2, 3}, @@ -265,8 +263,7 @@ func TestMsgSendSigners(t *testing.T) { for i, signer := range signers { inputs[i] = NewInput(signer, someCoins) } - tx := NewMsgSend(inputs, nil) + tx := NewMsgMultiSend(inputs, nil) - require.Equal(t, signers, tx.Signers()) + require.Equal(t, signers, tx.GetSigners()) } -*/ diff --git a/x/distribution/types/keys.go b/x/distribution/types/keys.go index 12fe9b17b9..4f0f37f823 100644 --- a/x/distribution/types/keys.go +++ b/x/distribution/types/keys.go @@ -4,6 +4,7 @@ import ( "encoding/binary" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -27,19 +28,19 @@ const ( // // - 0x01: sdk.ConsAddress // -// - 0x02: ValidatorOutstandingRewards +// - 0x02: ValidatorOutstandingRewards // -// - 0x03: sdk.AccAddress +// - 0x03: sdk.AccAddress // -// - 0x04: DelegatorStartingInfo +// - 0x04: DelegatorStartingInfo // -// - 0x05: ValidatorHistoricalRewards +// - 0x05: ValidatorHistoricalRewards // -// - 0x06: ValidatorCurrentRewards +// - 0x06: ValidatorCurrentRewards // -// - 0x07: ValidatorCurrentRewards +// - 0x07: ValidatorCurrentRewards // -// - 0x08: ValidatorSlashEvent +// - 0x08: ValidatorSlashEvent var ( FeePoolKey = []byte{0x00} // key for global distribution state ProposerKey = []byte{0x01} // key for the proposer operator address @@ -53,47 +54,56 @@ var ( ValidatorSlashEventPrefix = []byte{0x08} // key for validator slash fraction ) -// gets an address from a validator's outstanding rewards key +// GetValidatorOutstandingRewardsAddress creates an address from a validator's outstanding rewards key. func GetValidatorOutstandingRewardsAddress(key []byte) (valAddr sdk.ValAddress) { - addr := key[1:] - if len(addr) != sdk.AddrLen { + // key is in the format: + // 0x02 + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { panic("unexpected key length") } + return sdk.ValAddress(addr) } -// gets an address from a delegator's withdraw info key +// GetDelegatorWithdrawInfoAddress creates an address from a delegator's withdraw info key. func GetDelegatorWithdrawInfoAddress(key []byte) (delAddr sdk.AccAddress) { - addr := key[1:] - if len(addr) != sdk.AddrLen { + // key is in the format: + // 0x03 + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { panic("unexpected key length") } + return sdk.AccAddress(addr) } -// gets the addresses from a delegator starting info key +// GetDelegatorStartingInfoAddresses creates the addresses from a delegator starting info key. func GetDelegatorStartingInfoAddresses(key []byte) (valAddr sdk.ValAddress, delAddr sdk.AccAddress) { - addr := key[1 : 1+sdk.AddrLen] - if len(addr) != sdk.AddrLen { + // key is in the format: + // 0x04 + valAddrLen := int(key[1]) + valAddr = sdk.ValAddress(key[2 : 2+valAddrLen]) + delAddrLen := int(key[2+valAddrLen]) + delAddr = sdk.AccAddress(key[3+valAddrLen:]) + if len(delAddr.Bytes()) != delAddrLen { panic("unexpected key length") } - valAddr = sdk.ValAddress(addr) - addr = key[1+sdk.AddrLen:] - if len(addr) != sdk.AddrLen { - panic("unexpected key length") - } - delAddr = sdk.AccAddress(addr) + return } -// gets the address & period from a validator's historical rewards key +// GetValidatorHistoricalRewardsAddressPeriod creates the address & period from a validator's historical rewards key. func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddress, period uint64) { - addr := key[1 : 1+sdk.AddrLen] - if len(addr) != sdk.AddrLen { - panic("unexpected key length") - } - valAddr = sdk.ValAddress(addr) - b := key[1+sdk.AddrLen:] + // key is in the format: + // 0x05 + valAddrLen := int(key[1]) + valAddr = sdk.ValAddress(key[2 : 2+valAddrLen]) + b := key[2+valAddrLen:] if len(b) != 8 { panic("unexpected key length") } @@ -101,93 +111,104 @@ func GetValidatorHistoricalRewardsAddressPeriod(key []byte) (valAddr sdk.ValAddr return } -// gets the address from a validator's current rewards key +// GetValidatorCurrentRewardsAddress creates the address from a validator's current rewards key. func GetValidatorCurrentRewardsAddress(key []byte) (valAddr sdk.ValAddress) { - addr := key[1:] - if len(addr) != sdk.AddrLen { + // key is in the format: + // 0x06: ValidatorCurrentRewards + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { panic("unexpected key length") } + return sdk.ValAddress(addr) } -// gets the address from a validator's accumulated commission key +// GetValidatorAccumulatedCommissionAddress creates the address from a validator's accumulated commission key. func GetValidatorAccumulatedCommissionAddress(key []byte) (valAddr sdk.ValAddress) { - addr := key[1:] - if len(addr) != sdk.AddrLen { + // key is in the format: + // 0x07: ValidatorCurrentRewards + + // Remove prefix and address length. + addr := key[2:] + if len(addr) != int(key[1]) { panic("unexpected key length") } + return sdk.ValAddress(addr) } -// gets the height from a validator's slash event key +// GetValidatorSlashEventAddressHeight creates the height from a validator's slash event key. func GetValidatorSlashEventAddressHeight(key []byte) (valAddr sdk.ValAddress, height uint64) { - addr := key[1 : 1+sdk.AddrLen] - if len(addr) != sdk.AddrLen { - panic("unexpected key length") - } - valAddr = sdk.ValAddress(addr) - startB := 1 + sdk.AddrLen + // key is in the format: + // 0x08: ValidatorSlashEvent + valAddrLen := int(key[1]) + valAddr = key[2 : 2+valAddrLen] + startB := 2 + valAddrLen b := key[startB : startB+8] // the next 8 bytes represent the height height = binary.BigEndian.Uint64(b) return } -// gets the outstanding rewards key for a validator +// GetValidatorOutstandingRewardsKey creates the outstanding rewards key for a validator. func GetValidatorOutstandingRewardsKey(valAddr sdk.ValAddress) []byte { - return append(ValidatorOutstandingRewardsPrefix, valAddr.Bytes()...) + return append(ValidatorOutstandingRewardsPrefix, address.MustLengthPrefix(valAddr.Bytes())...) } -// gets the key for a delegator's withdraw addr +// GetDelegatorWithdrawAddrKey creates the key for a delegator's withdraw addr. func GetDelegatorWithdrawAddrKey(delAddr sdk.AccAddress) []byte { - return append(DelegatorWithdrawAddrPrefix, delAddr.Bytes()...) + return append(DelegatorWithdrawAddrPrefix, address.MustLengthPrefix(delAddr.Bytes())...) } -// gets the key for a delegator's starting info +// GetDelegatorStartingInfoKey creates the key for a delegator's starting info. func GetDelegatorStartingInfoKey(v sdk.ValAddress, d sdk.AccAddress) []byte { - return append(append(DelegatorStartingInfoPrefix, v.Bytes()...), d.Bytes()...) + return append(append(DelegatorStartingInfoPrefix, address.MustLengthPrefix(v.Bytes())...), address.MustLengthPrefix(d.Bytes())...) } -// gets the prefix key for a validator's historical rewards +// GetValidatorHistoricalRewardsPrefix creates the prefix key for a validator's historical rewards. func GetValidatorHistoricalRewardsPrefix(v sdk.ValAddress) []byte { - return append(ValidatorHistoricalRewardsPrefix, v.Bytes()...) + return append(ValidatorHistoricalRewardsPrefix, address.MustLengthPrefix(v.Bytes())...) } -// gets the key for a validator's historical rewards +// GetValidatorHistoricalRewardsKey creates the key for a validator's historical rewards. func GetValidatorHistoricalRewardsKey(v sdk.ValAddress, k uint64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, k) - return append(append(ValidatorHistoricalRewardsPrefix, v.Bytes()...), b...) + return append(append(ValidatorHistoricalRewardsPrefix, address.MustLengthPrefix(v.Bytes())...), b...) } -// gets the key for a validator's current rewards +// GetValidatorCurrentRewardsKey creates the key for a validator's current rewards. func GetValidatorCurrentRewardsKey(v sdk.ValAddress) []byte { - return append(ValidatorCurrentRewardsPrefix, v.Bytes()...) + return append(ValidatorCurrentRewardsPrefix, address.MustLengthPrefix(v.Bytes())...) } -// gets the key for a validator's current commission +// GetValidatorAccumulatedCommissionKey creates the key for a validator's current commission. func GetValidatorAccumulatedCommissionKey(v sdk.ValAddress) []byte { - return append(ValidatorAccumulatedCommissionPrefix, v.Bytes()...) + return append(ValidatorAccumulatedCommissionPrefix, address.MustLengthPrefix(v.Bytes())...) } -// gets the prefix key for a validator's slash fractions +// GetValidatorSlashEventPrefix creates the prefix key for a validator's slash fractions. func GetValidatorSlashEventPrefix(v sdk.ValAddress) []byte { - return append(ValidatorSlashEventPrefix, v.Bytes()...) + return append(ValidatorSlashEventPrefix, address.MustLengthPrefix(v.Bytes())...) } -// gets the prefix key for a validator's slash fraction (ValidatorSlashEventPrefix + height) +// GetValidatorSlashEventKeyPrefix creates the prefix key for a validator's slash fraction (ValidatorSlashEventPrefix + height). func GetValidatorSlashEventKeyPrefix(v sdk.ValAddress, height uint64) []byte { heightBz := make([]byte, 8) binary.BigEndian.PutUint64(heightBz, height) + return append( ValidatorSlashEventPrefix, - append(v.Bytes(), heightBz...)..., + append(address.MustLengthPrefix(v.Bytes()), heightBz...)..., ) } -// gets the key for a validator's slash fraction +// GetValidatorSlashEventKey creates the key for a validator's slash fraction. func GetValidatorSlashEventKey(v sdk.ValAddress, height, period uint64) []byte { periodBz := make([]byte, 8) binary.BigEndian.PutUint64(periodBz, period) prefix := GetValidatorSlashEventKeyPrefix(v, height) + return append(prefix, periodBz...) } diff --git a/x/feegrant/types/key.go b/x/feegrant/types/key.go index e30427b136..7cd1ce4f8c 100644 --- a/x/feegrant/types/key.go +++ b/x/feegrant/types/key.go @@ -2,6 +2,7 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -26,10 +27,10 @@ var ( // FeeAllowanceKey is the canonical key to store a grant from granter to grantee // We store by grantee first to allow searching by everyone who granted to you func FeeAllowanceKey(granter sdk.AccAddress, grantee sdk.AccAddress) []byte { - return append(append(FeeAllowanceKeyPrefix, grantee.Bytes()...), granter.Bytes()...) + return append(FeeAllowancePrefixByGrantee(grantee), address.MustLengthPrefix(granter.Bytes())...) } // FeeAllowancePrefixByGrantee returns a prefix to scan for all grants to this given address. func FeeAllowancePrefixByGrantee(grantee sdk.AccAddress) []byte { - return append(FeeAllowanceKeyPrefix, grantee.Bytes()...) + return append(FeeAllowanceKeyPrefix, address.MustLengthPrefix(grantee.Bytes())...) } diff --git a/x/gov/types/keys.go b/x/gov/types/keys.go index 7681116fc4..fe98bcbf81 100644 --- a/x/gov/types/keys.go +++ b/x/gov/types/keys.go @@ -6,6 +6,7 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -33,9 +34,9 @@ const ( // // - 0x03: nextProposalID // -// - 0x10: Deposit +// - 0x10: Deposit // -// - 0x20: Voter +// - 0x20: Voter var ( ProposalsKeyPrefix = []byte{0x00} ActiveProposalQueuePrefix = []byte{0x01} @@ -93,7 +94,7 @@ func DepositsKey(proposalID uint64) []byte { // DepositKey key of a specific deposit from the store func DepositKey(proposalID uint64, depositorAddr sdk.AccAddress) []byte { - return append(DepositsKey(proposalID), depositorAddr.Bytes()...) + return append(DepositsKey(proposalID), address.MustLengthPrefix(depositorAddr.Bytes())...) } // VotesKey gets the first part of the votes key based on the proposalID @@ -103,7 +104,7 @@ func VotesKey(proposalID uint64) []byte { // VoteKey key of a specific vote from the store func VoteKey(proposalID uint64, voterAddr sdk.AccAddress) []byte { - return append(VotesKey(proposalID), voterAddr.Bytes()...) + return append(VotesKey(proposalID), address.MustLengthPrefix(voterAddr.Bytes())...) } // Split keys function; used for iterators @@ -154,11 +155,9 @@ func splitKeyWithTime(key []byte) (proposalID uint64, endTime time.Time) { } func splitKeyWithAddress(key []byte) (proposalID uint64, addr sdk.AccAddress) { - if len(key[1:]) != 8+sdk.AddrLen { - panic(fmt.Sprintf("unexpected key length (%d ≠ %d)", len(key), 8+sdk.AddrLen)) - } - + // Both Vote and Deposit store keys are of format: + // proposalID = GetProposalIDFromBytes(key[1:9]) - addr = sdk.AccAddress(key[9:]) + addr = sdk.AccAddress(key[10:]) return } diff --git a/x/gov/types/keys_test.go b/x/gov/types/keys_test.go index 80dfa7d207..30266f8f4d 100644 --- a/x/gov/types/keys_test.go +++ b/x/gov/types/keys_test.go @@ -46,11 +46,6 @@ func TestDepositKeys(t *testing.T) { proposalID, depositorAddr := SplitKeyDeposit(key) require.Equal(t, int(proposalID), 2) require.Equal(t, addr, depositorAddr) - - // invalid key - addr2 := sdk.AccAddress("test1") - key = DepositKey(5, addr2) - require.Panics(t, func() { SplitKeyDeposit(key) }) } func TestVoteKeys(t *testing.T) { @@ -63,9 +58,4 @@ func TestVoteKeys(t *testing.T) { proposalID, voterAddr := SplitKeyDeposit(key) require.Equal(t, int(proposalID), 2) require.Equal(t, addr, voterAddr) - - // invalid key - addr2 := sdk.AccAddress("test1") - key = VoteKey(5, addr2) - require.Panics(t, func() { SplitKeyVote(key) }) } diff --git a/x/slashing/types/keys.go b/x/slashing/types/keys.go index c9792d2208..f0049760f0 100644 --- a/x/slashing/types/keys.go +++ b/x/slashing/types/keys.go @@ -4,6 +4,7 @@ import ( "encoding/binary" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -23,11 +24,11 @@ const ( // Keys for slashing store // Items are stored with the following key: values // -// - 0x01: ValidatorSigningInfo +// - 0x01: ValidatorSigningInfo // -// - 0x02: bool +// - 0x02: bool // -// - 0x03: crypto.PubKey +// - 0x03: cryptotypes.PubKey var ( ValidatorSigningInfoKeyPrefix = []byte{0x01} // Prefix for signing info ValidatorMissedBlockBitArrayKeyPrefix = []byte{0x02} // Prefix for missed block bit array @@ -36,31 +37,31 @@ var ( // ValidatorSigningInfoKey - stored by *Consensus* address (not operator address) func ValidatorSigningInfoKey(v sdk.ConsAddress) []byte { - return append(ValidatorSigningInfoKeyPrefix, v.Bytes()...) + return append(ValidatorSigningInfoKeyPrefix, address.MustLengthPrefix(v.Bytes())...) } // ValidatorSigningInfoAddress - extract the address from a validator signing info key func ValidatorSigningInfoAddress(key []byte) (v sdk.ConsAddress) { - addr := key[1:] - if len(addr) != sdk.AddrLen { - panic("unexpected key length") - } + // Remove prefix and address length. + addr := key[2:] + return sdk.ConsAddress(addr) } // ValidatorMissedBlockBitArrayPrefixKey - stored by *Consensus* address (not operator address) func ValidatorMissedBlockBitArrayPrefixKey(v sdk.ConsAddress) []byte { - return append(ValidatorMissedBlockBitArrayKeyPrefix, v.Bytes()...) + return append(ValidatorMissedBlockBitArrayKeyPrefix, address.MustLengthPrefix(v.Bytes())...) } // ValidatorMissedBlockBitArrayKey - stored by *Consensus* address (not operator address) func ValidatorMissedBlockBitArrayKey(v sdk.ConsAddress, i int64) []byte { b := make([]byte, 8) binary.LittleEndian.PutUint64(b, uint64(i)) + return append(ValidatorMissedBlockBitArrayPrefixKey(v), b...) } // AddrPubkeyRelationKey gets pubkey relation key used to get the pubkey from the address -func AddrPubkeyRelationKey(address []byte) []byte { - return append(AddrPubkeyRelationKeyPrefix, address...) +func AddrPubkeyRelationKey(addr []byte) []byte { + return append(AddrPubkeyRelationKeyPrefix, address.MustLengthPrefix(addr)...) } diff --git a/x/staking/keeper/val_state_change.go b/x/staking/keeper/val_state_change.go index f06994f44f..52b7392300 100644 --- a/x/staking/keeper/val_state_change.go +++ b/x/staking/keeper/val_state_change.go @@ -12,7 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking/types" ) -// Calculate the ValidatorUpdates for the current block +// BlockValidatorUpdates calculates the ValidatorUpdates for the current block // Called in each EndBlock func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate { // Calculate validator set changes. @@ -97,7 +97,7 @@ func (k Keeper) BlockValidatorUpdates(ctx sdk.Context) []abci.ValidatorUpdate { return validatorUpdates } -// Apply and return accumulated updates to the bonded validator set. Also, +// ApplyAndReturnValidatorSetUpdates applies and return accumulated updates to the bonded validator set. Also, // * Updates the active valset as keyed by LastValidatorPowerKey. // * Updates the total power as keyed by LastTotalPowerKey. // * Updates validator status' according to updated powers. @@ -117,7 +117,10 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab // Retrieve the last validator set. // The persistent set is updated later in this function. // (see LastValidatorPowerKey). - last := k.getLastValidatorsByAddr(ctx) + last, err := k.getLastValidatorsByAddr(ctx) + if err != nil { + return nil, err + } // Iterate over validators, highest power to lowest. iterator := k.ValidatorsPowerStoreIterator(ctx) @@ -160,10 +163,11 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab } // fetch the old power bytes - var valAddrBytes [sdk.AddrLen]byte - - copy(valAddrBytes[:], valAddr[:]) - oldPowerBytes, found := last[valAddrBytes] + valAddrStr, err := sdk.Bech32ifyAddressBytes(sdk.Bech32PrefixValAddr, valAddr) + if err != nil { + return nil, err + } + oldPowerBytes, found := last[valAddrStr] newPower := validator.ConsensusPower() newPowerBytes := k.cdc.MustMarshalBinaryBare(&gogotypes.Int64Value{Value: newPower}) @@ -174,13 +178,17 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab k.SetLastValidatorPower(ctx, valAddr, newPower) } - delete(last, valAddrBytes) + delete(last, valAddrStr) count++ totalPower = totalPower.Add(sdk.NewInt(newPower)) } - noLongerBonded := sortNoLongerBonded(last) + noLongerBonded, err := sortNoLongerBonded(last) + if err != nil { + return nil, err + } + for _, valAddrBytes := range noLongerBonded { validator := k.mustGetValidator(ctx, sdk.ValAddress(valAddrBytes)) validator, err = k.bondedToUnbonding(ctx, validator) @@ -339,39 +347,46 @@ func (k Keeper) completeUnbondingValidator(ctx sdk.Context, validator types.Vali return validator } -// map of operator addresses to serialized power -type validatorsByAddr map[[sdk.AddrLen]byte][]byte +// map of operator bech32-addresses to serialized power +// We use bech32 strings here, because we can't have slices as keys: map[[]byte][]byte +type validatorsByAddr map[string][]byte // get the last validator set -func (k Keeper) getLastValidatorsByAddr(ctx sdk.Context) validatorsByAddr { +func (k Keeper) getLastValidatorsByAddr(ctx sdk.Context) (validatorsByAddr, error) { last := make(validatorsByAddr) iterator := k.LastValidatorsIterator(ctx) defer iterator.Close() for ; iterator.Valid(); iterator.Next() { - var valAddr [sdk.AddrLen]byte - // extract the validator address from the key (prefix is 1-byte) - copy(valAddr[:], iterator.Key()[1:]) + // extract the validator address from the key (prefix is 1-byte, addrLen is 1-byte) + valAddr := types.AddressFromLastValidatorPowerKey(iterator.Key()) + valAddrStr, err := sdk.Bech32ifyAddressBytes(sdk.Bech32PrefixValAddr, valAddr) + if err != nil { + return nil, err + } + powerBytes := iterator.Value() - last[valAddr] = make([]byte, len(powerBytes)) - copy(last[valAddr], powerBytes) + last[valAddrStr] = make([]byte, len(powerBytes)) + copy(last[valAddrStr], powerBytes) } - return last + return last, nil } // given a map of remaining validators to previous bonded power // returns the list of validators to be unbonded, sorted by operator address -func sortNoLongerBonded(last validatorsByAddr) [][]byte { +func sortNoLongerBonded(last validatorsByAddr) ([][]byte, error) { // sort the map keys for determinism noLongerBonded := make([][]byte, len(last)) index := 0 - for valAddrBytes := range last { - valAddr := make([]byte, sdk.AddrLen) - copy(valAddr, valAddrBytes[:]) - noLongerBonded[index] = valAddr + for valAddrStr := range last { + valAddrBytes, err := sdk.ValAddressFromBech32(valAddrStr) + if err != nil { + return nil, err + } + noLongerBonded[index] = valAddrBytes index++ } // sorted by address - order doesn't matter @@ -380,5 +395,5 @@ func sortNoLongerBonded(last validatorsByAddr) [][]byte { return bytes.Compare(noLongerBonded[i], noLongerBonded[j]) == -1 }) - return noLongerBonded + return noLongerBonded, nil } diff --git a/x/staking/keeper/validator.go b/x/staking/keeper/validator.go index edb00ddba5..9fa6a0ca0a 100644 --- a/x/staking/keeper/validator.go +++ b/x/staking/keeper/validator.go @@ -327,7 +327,7 @@ func (k Keeper) IterateLastValidatorPowers(ctx sdk.Context, handler func(operato defer iter.Close() for ; iter.Valid(); iter.Next() { - addr := sdk.ValAddress(iter.Key()[len(types.LastValidatorPowerKey):]) + addr := sdk.ValAddress(types.AddressFromLastValidatorPowerKey(iter.Key())) intV := &gogotypes.Int64Value{} k.cdc.MustUnmarshalBinaryBare(iter.Value(), intV) diff --git a/x/staking/types/keys.go b/x/staking/types/keys.go index 40d62244a0..1854ddac61 100644 --- a/x/staking/types/keys.go +++ b/x/staking/types/keys.go @@ -8,6 +8,7 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" ) const ( @@ -48,24 +49,29 @@ var ( HistoricalInfoKey = []byte{0x50} // prefix for the historical info ) -// gets the key for the validator with address +// GetValidatorKey creates the key for the validator with address // VALUE: staking/Validator func GetValidatorKey(operatorAddr sdk.ValAddress) []byte { - return append(ValidatorsKey, operatorAddr.Bytes()...) + return append(ValidatorsKey, address.MustLengthPrefix(operatorAddr)...) } -// gets the key for the validator with pubkey +// GetValidatorByConsAddrKey creates the key for the validator with pubkey // VALUE: validator operator address ([]byte) func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte { - return append(ValidatorsByConsAddrKey, addr.Bytes()...) + return append(ValidatorsByConsAddrKey, address.MustLengthPrefix(addr)...) } -// Get the validator operator address from LastValidatorPowerKey +// AddressFromValidatorsKey creates the validator operator address from ValidatorsKey +func AddressFromValidatorsKey(key []byte) []byte { + return key[2:] // remove prefix bytes and address length +} + +// AddressFromLastValidatorPowerKey creates the validator operator address from LastValidatorPowerKey func AddressFromLastValidatorPowerKey(key []byte) []byte { - return key[1:] // remove prefix bytes + return key[2:] // remove prefix bytes and address length } -// get the validator by power index. +// GetValidatorsByPowerIndexKey creates the validator by power index. // Power index is the key used in the power-store, and represents the relative // power ranking of the validator. // VALUE: validator operator address ([]byte) @@ -80,39 +86,39 @@ func GetValidatorsByPowerIndexKey(validator Validator) []byte { powerBytes := consensusPowerBytes powerBytesLen := len(powerBytes) // 8 - // key is of format prefix || powerbytes || addrBytes - key := make([]byte, 1+powerBytesLen+sdk.AddrLen) - - key[0] = ValidatorsByPowerIndexKey[0] - copy(key[1:powerBytesLen+1], powerBytes) addr, err := sdk.ValAddressFromBech32(validator.OperatorAddress) if err != nil { panic(err) } operAddrInvr := sdk.CopyBytes(addr) + addrLen := len(operAddrInvr) for i, b := range operAddrInvr { operAddrInvr[i] = ^b } - copy(key[powerBytesLen+1:], operAddrInvr) + // key is of format prefix || powerbytes || addrLen (1byte) || addrBytes + key := make([]byte, 1+powerBytesLen+1+addrLen) + + key[0] = ValidatorsByPowerIndexKey[0] + copy(key[1:powerBytesLen+1], powerBytes) + key[powerBytesLen+1] = byte(addrLen) + copy(key[powerBytesLen+2:], operAddrInvr) return key } -// get the bonded validator index key for an operator address +// GetLastValidatorPowerKey creates the bonded validator index key for an operator address func GetLastValidatorPowerKey(operator sdk.ValAddress) []byte { - return append(LastValidatorPowerKey, operator...) + return append(LastValidatorPowerKey, address.MustLengthPrefix(operator)...) } -// parse the validators operator address from power rank key +// ParseValidatorPowerRankKey parses the validators operator address from power rank key func ParseValidatorPowerRankKey(key []byte) (operAddr []byte) { powerBytesLen := 8 - if len(key) != 1+powerBytesLen+sdk.AddrLen { - panic("Invalid validator power rank key length") - } - operAddr = sdk.CopyBytes(key[powerBytesLen+1:]) + // key is of format prefix (1 byte) || powerbytes || addrLen (1byte) || addrBytes + operAddr = sdk.CopyBytes(key[powerBytesLen+2:]) for i, b := range operAddr { operAddr[i] = ^b @@ -165,55 +171,51 @@ func ParseValidatorQueueKey(bz []byte) (time.Time, int64, error) { return ts, int64(height), nil } -// gets the key for delegator bond with validator +// GetDelegationKey creates the key for delegator bond with validator // VALUE: staking/Delegation func GetDelegationKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { - return append(GetDelegationsKey(delAddr), valAddr.Bytes()...) + return append(GetDelegationsKey(delAddr), address.MustLengthPrefix(valAddr)...) } -// gets the prefix for a delegator for all validators +// GetDelegationsKey creates the prefix for a delegator for all validators func GetDelegationsKey(delAddr sdk.AccAddress) []byte { - return append(DelegationKey, delAddr.Bytes()...) + return append(DelegationKey, address.MustLengthPrefix(delAddr)...) } -// gets the key for an unbonding delegation by delegator and validator addr +// GetUBDKey creates the key for an unbonding delegation by delegator and validator addr // VALUE: staking/UnbondingDelegation func GetUBDKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { - return append( - GetUBDsKey(delAddr.Bytes()), - valAddr.Bytes()...) + return append(GetUBDsKey(delAddr.Bytes()), address.MustLengthPrefix(valAddr)...) } -// gets the index-key for an unbonding delegation, stored by validator-index +// GetUBDByValIndexKey creates the index-key for an unbonding delegation, stored by validator-index // VALUE: none (key rearrangement used) func GetUBDByValIndexKey(delAddr sdk.AccAddress, valAddr sdk.ValAddress) []byte { - return append(GetUBDsByValIndexKey(valAddr), delAddr.Bytes()...) + return append(GetUBDsByValIndexKey(valAddr), address.MustLengthPrefix(delAddr)...) } -// rearranges the ValIndexKey to get the UBDKey +// GetUBDKeyFromValIndexKey rearranges the ValIndexKey to get the UBDKey func GetUBDKeyFromValIndexKey(indexKey []byte) []byte { addrs := indexKey[1:] // remove prefix bytes - if len(addrs) != 2*sdk.AddrLen { - panic("unexpected key length") - } - valAddr := addrs[:sdk.AddrLen] - delAddr := addrs[sdk.AddrLen:] + valAddrLen := addrs[0] + valAddr := addrs[1 : 1+valAddrLen] + delAddr := addrs[valAddrLen+2:] return GetUBDKey(delAddr, valAddr) } -// gets the prefix for all unbonding delegations from a delegator +// GetUBDsKey creates the prefix for all unbonding delegations from a delegator func GetUBDsKey(delAddr sdk.AccAddress) []byte { - return append(UnbondingDelegationKey, delAddr.Bytes()...) + return append(UnbondingDelegationKey, address.MustLengthPrefix(delAddr)...) } -// gets the prefix keyspace for the indexes of unbonding delegations for a validator +// GetUBDsByValIndexKey creates the prefix keyspace for the indexes of unbonding delegations for a validator func GetUBDsByValIndexKey(valAddr sdk.ValAddress) []byte { - return append(UnbondingDelegationByValIndexKey, valAddr.Bytes()...) + return append(UnbondingDelegationByValIndexKey, address.MustLengthPrefix(valAddr)...) } -// gets the prefix for all unbonding delegations from a delegator +// GetUnbondingDelegationTimeKey creates the prefix for all unbonding delegations from a delegator func GetUnbondingDelegationTimeKey(timestamp time.Time) []byte { bz := sdk.FormatTimeBytes(timestamp) return append(UnbondingQueueKey, bz...) @@ -222,69 +224,76 @@ func GetUnbondingDelegationTimeKey(timestamp time.Time) []byte { // GetREDKey returns a key prefix for indexing a redelegation from a delegator // and source validator to a destination validator. func GetREDKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { - key := make([]byte, 1+sdk.AddrLen*3) + // key is of the form GetREDsKey || valSrcAddrLen (1 byte) || valSrcAddr || valDstAddrLen (1 byte) || valDstAddr + key := make([]byte, 1+3+len(delAddr)+len(valSrcAddr)+len(valDstAddr)) - copy(key[0:sdk.AddrLen+1], GetREDsKey(delAddr.Bytes())) - copy(key[sdk.AddrLen+1:2*sdk.AddrLen+1], valSrcAddr.Bytes()) - copy(key[2*sdk.AddrLen+1:3*sdk.AddrLen+1], valDstAddr.Bytes()) + copy(key[0:2+len(delAddr)], GetREDsKey(delAddr.Bytes())) + key[2+len(delAddr)] = byte(len(valSrcAddr)) + copy(key[3+len(delAddr):3+len(delAddr)+len(valSrcAddr)], valSrcAddr.Bytes()) + key[3+len(delAddr)+len(valSrcAddr)] = byte(len(valDstAddr)) + copy(key[4+len(delAddr)+len(valSrcAddr):], valDstAddr.Bytes()) return key } -// gets the index-key for a redelegation, stored by source-validator-index +// GetREDByValSrcIndexKey creates the index-key for a redelegation, stored by source-validator-index // VALUE: none (key rearrangement used) func GetREDByValSrcIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { REDSFromValsSrcKey := GetREDsFromValSrcIndexKey(valSrcAddr) offset := len(REDSFromValsSrcKey) - // key is of the form REDSFromValsSrcKey || delAddr || valDstAddr - key := make([]byte, len(REDSFromValsSrcKey)+2*sdk.AddrLen) + // key is of the form REDSFromValsSrcKey || delAddrLen (1 byte) || delAddr || valDstAddrLen (1 byte) || valDstAddr + key := make([]byte, offset+2+len(delAddr)+len(valDstAddr)) copy(key[0:offset], REDSFromValsSrcKey) - copy(key[offset:offset+sdk.AddrLen], delAddr.Bytes()) - copy(key[offset+sdk.AddrLen:offset+2*sdk.AddrLen], valDstAddr.Bytes()) + key[offset] = byte(len(delAddr)) + copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes()) + key[offset+1+len(delAddr)] = byte(len(valDstAddr)) + copy(key[offset+2+len(delAddr):], valDstAddr.Bytes()) return key } -// gets the index-key for a redelegation, stored by destination-validator-index +// GetREDByValDstIndexKey creates the index-key for a redelegation, stored by destination-validator-index // VALUE: none (key rearrangement used) func GetREDByValDstIndexKey(delAddr sdk.AccAddress, valSrcAddr, valDstAddr sdk.ValAddress) []byte { REDSToValsDstKey := GetREDsToValDstIndexKey(valDstAddr) offset := len(REDSToValsDstKey) - // key is of the form REDSToValsDstKey || delAddr || valSrcAddr - key := make([]byte, len(REDSToValsDstKey)+2*sdk.AddrLen) + // key is of the form REDSToValsDstKey || delAddrLen (1 byte) || delAddr || valSrcAddrLen (1 byte) || valSrcAddr + key := make([]byte, offset+2+len(delAddr)+len(valSrcAddr)) copy(key[0:offset], REDSToValsDstKey) - copy(key[offset:offset+sdk.AddrLen], delAddr.Bytes()) - copy(key[offset+sdk.AddrLen:offset+2*sdk.AddrLen], valSrcAddr.Bytes()) + key[offset] = byte(len(delAddr)) + copy(key[offset+1:offset+1+len(delAddr)], delAddr.Bytes()) + key[offset+1+len(delAddr)] = byte(len(valSrcAddr)) + copy(key[offset+2+len(delAddr):], valSrcAddr.Bytes()) return key } // GetREDKeyFromValSrcIndexKey rearranges the ValSrcIndexKey to get the REDKey func GetREDKeyFromValSrcIndexKey(indexKey []byte) []byte { - // note that first byte is prefix byte - if len(indexKey) != 3*sdk.AddrLen+1 { - panic("unexpected key length") - } + // note that first byte is prefix byte, which we remove + addrs := indexKey[1:] - valSrcAddr := indexKey[1 : sdk.AddrLen+1] - delAddr := indexKey[sdk.AddrLen+1 : 2*sdk.AddrLen+1] - valDstAddr := indexKey[2*sdk.AddrLen+1 : 3*sdk.AddrLen+1] + valSrcAddrLen := addrs[0] + valSrcAddr := addrs[1 : valSrcAddrLen+1] + delAddrLen := addrs[valSrcAddrLen+1] + delAddr := addrs[valSrcAddrLen+2 : valSrcAddrLen+2+delAddrLen] + valDstAddr := addrs[valSrcAddrLen+delAddrLen+3:] return GetREDKey(delAddr, valSrcAddr, valDstAddr) } // GetREDKeyFromValDstIndexKey rearranges the ValDstIndexKey to get the REDKey func GetREDKeyFromValDstIndexKey(indexKey []byte) []byte { - // note that first byte is prefix byte - if len(indexKey) != 3*sdk.AddrLen+1 { - panic("unexpected key length") - } + // note that first byte is prefix byte, which we remove + addrs := indexKey[1:] - valDstAddr := indexKey[1 : sdk.AddrLen+1] - delAddr := indexKey[sdk.AddrLen+1 : 2*sdk.AddrLen+1] - valSrcAddr := indexKey[2*sdk.AddrLen+1 : 3*sdk.AddrLen+1] + valDstAddrLen := addrs[0] + valDstAddr := addrs[1 : valDstAddrLen+1] + delAddrLen := addrs[valDstAddrLen+1] + delAddr := addrs[valDstAddrLen+2 : valDstAddrLen+2+delAddrLen] + valSrcAddr := addrs[valDstAddrLen+delAddrLen+3:] return GetREDKey(delAddr, valSrcAddr, valDstAddr) } @@ -299,25 +308,25 @@ func GetRedelegationTimeKey(timestamp time.Time) []byte { // GetREDsKey returns a key prefix for indexing a redelegation from a delegator // address. func GetREDsKey(delAddr sdk.AccAddress) []byte { - return append(RedelegationKey, delAddr.Bytes()...) + return append(RedelegationKey, address.MustLengthPrefix(delAddr)...) } // GetREDsFromValSrcIndexKey returns a key prefix for indexing a redelegation to // a source validator. func GetREDsFromValSrcIndexKey(valSrcAddr sdk.ValAddress) []byte { - return append(RedelegationByValSrcIndexKey, valSrcAddr.Bytes()...) + return append(RedelegationByValSrcIndexKey, address.MustLengthPrefix(valSrcAddr)...) } // GetREDsToValDstIndexKey returns a key prefix for indexing a redelegation to a // destination (target) validator. func GetREDsToValDstIndexKey(valDstAddr sdk.ValAddress) []byte { - return append(RedelegationByValDstIndexKey, valDstAddr.Bytes()...) + return append(RedelegationByValDstIndexKey, address.MustLengthPrefix(valDstAddr)...) } // GetREDsByDelToValDstIndexKey returns a key prefix for indexing a redelegation // from an address to a source validator. func GetREDsByDelToValDstIndexKey(delAddr sdk.AccAddress, valDstAddr sdk.ValAddress) []byte { - return append(GetREDsToValDstIndexKey(valDstAddr), delAddr.Bytes()...) + return append(GetREDsToValDstIndexKey(valDstAddr), address.MustLengthPrefix(delAddr)...) } // GetHistoricalInfoKey returns a key prefix for indexing HistoricalInfo objects. diff --git a/x/staking/types/keys_test.go b/x/staking/types/keys_test.go index 0f63617f26..949c7caedb 100644 --- a/x/staking/types/keys_test.go +++ b/x/staking/types/keys_test.go @@ -37,10 +37,10 @@ func TestGetValidatorPowerRank(t *testing.T) { validator types.Validator wantHex string }{ - {val1, "2300000000000000009c288ede7df62742fc3b7d0962045a8cef0f79f6"}, - {val2, "2300000000000000019c288ede7df62742fc3b7d0962045a8cef0f79f6"}, - {val3, "23000000000000000a9c288ede7df62742fc3b7d0962045a8cef0f79f6"}, - {val4, "2300000100000000009c288ede7df62742fc3b7d0962045a8cef0f79f6"}, + {val1, "230000000000000000149c288ede7df62742fc3b7d0962045a8cef0f79f6"}, + {val2, "230000000000000001149c288ede7df62742fc3b7d0962045a8cef0f79f6"}, + {val3, "23000000000000000a149c288ede7df62742fc3b7d0962045a8cef0f79f6"}, + {val4, "230000010000000000149c288ede7df62742fc3b7d0962045a8cef0f79f6"}, } for i, tt := range tests { got := hex.EncodeToString(types.GetValidatorsByPowerIndexKey(tt.validator)) @@ -57,11 +57,11 @@ func TestGetREDByValDstIndexKey(t *testing.T) { wantHex string }{ {sdk.AccAddress(keysAddr1), sdk.ValAddress(keysAddr1), sdk.ValAddress(keysAddr1), - "3663d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f08609"}, + "361463d771218209d8bd03c482f69dfba57310f086091463d771218209d8bd03c482f69dfba57310f086091463d771218209d8bd03c482f69dfba57310f08609"}, {sdk.AccAddress(keysAddr1), sdk.ValAddress(keysAddr2), sdk.ValAddress(keysAddr3), - "363ab62f0d93849be495e21e3e9013a517038f45bd63d771218209d8bd03c482f69dfba57310f086095ef3b5f25c54946d4a89fc0d09d2f126614540f2"}, + "36143ab62f0d93849be495e21e3e9013a517038f45bd1463d771218209d8bd03c482f69dfba57310f08609145ef3b5f25c54946d4a89fc0d09d2f126614540f2"}, {sdk.AccAddress(keysAddr2), sdk.ValAddress(keysAddr1), sdk.ValAddress(keysAddr3), - "363ab62f0d93849be495e21e3e9013a517038f45bd5ef3b5f25c54946d4a89fc0d09d2f126614540f263d771218209d8bd03c482f69dfba57310f08609"}, + "36143ab62f0d93849be495e21e3e9013a517038f45bd145ef3b5f25c54946d4a89fc0d09d2f126614540f21463d771218209d8bd03c482f69dfba57310f08609"}, } for i, tt := range tests { got := hex.EncodeToString(types.GetREDByValDstIndexKey(tt.delAddr, tt.valSrcAddr, tt.valDstAddr)) @@ -78,11 +78,11 @@ func TestGetREDByValSrcIndexKey(t *testing.T) { wantHex string }{ {sdk.AccAddress(keysAddr1), sdk.ValAddress(keysAddr1), sdk.ValAddress(keysAddr1), - "3563d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f0860963d771218209d8bd03c482f69dfba57310f08609"}, + "351463d771218209d8bd03c482f69dfba57310f086091463d771218209d8bd03c482f69dfba57310f086091463d771218209d8bd03c482f69dfba57310f08609"}, {sdk.AccAddress(keysAddr1), sdk.ValAddress(keysAddr2), sdk.ValAddress(keysAddr3), - "355ef3b5f25c54946d4a89fc0d09d2f126614540f263d771218209d8bd03c482f69dfba57310f086093ab62f0d93849be495e21e3e9013a517038f45bd"}, + "35145ef3b5f25c54946d4a89fc0d09d2f126614540f21463d771218209d8bd03c482f69dfba57310f08609143ab62f0d93849be495e21e3e9013a517038f45bd"}, {sdk.AccAddress(keysAddr2), sdk.ValAddress(keysAddr1), sdk.ValAddress(keysAddr3), - "3563d771218209d8bd03c482f69dfba57310f086095ef3b5f25c54946d4a89fc0d09d2f126614540f23ab62f0d93849be495e21e3e9013a517038f45bd"}, + "351463d771218209d8bd03c482f69dfba57310f08609145ef3b5f25c54946d4a89fc0d09d2f126614540f2143ab62f0d93849be495e21e3e9013a517038f45bd"}, } for i, tt := range tests { got := hex.EncodeToString(types.GetREDByValSrcIndexKey(tt.delAddr, tt.valSrcAddr, tt.valDstAddr)) From f9da95ad0952b6800e707aeb8ba008427798781b Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Tue, 2 Feb 2021 10:59:25 +0100 Subject: [PATCH 29/40] Fix keyring import from older versions. (#8436) Co-authored-by: Alessio Treglia Co-authored-by: sahith-narahari --- client/keys/migrate.go | 26 ++++++---- client/keys/testdata/keys/keys.db/000002.ldb | Bin 391 -> 0 bytes client/keys/testdata/keys/keys.db/CURRENT | 2 +- client/keys/testdata/keys/keys.db/CURRENT.bak | 2 +- client/keys/testdata/keys/keys.db/LOG | 48 +++++++++++------- .../testdata/keys/keys.db/MANIFEST-000004 | Bin 237 -> 0 bytes .../testdata/keys/keys.db/MANIFEST-000005 | Bin 0 -> 41 bytes crypto/keyring/keyring.go | 1 + 8 files changed, 49 insertions(+), 30 deletions(-) delete mode 100644 client/keys/testdata/keys/keys.db/000002.ldb delete mode 100644 client/keys/testdata/keys/keys.db/MANIFEST-000004 create mode 100644 client/keys/testdata/keys/keys.db/MANIFEST-000005 diff --git a/client/keys/migrate.go b/client/keys/migrate.go index d80bbe1630..836a2655b0 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -62,7 +62,7 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { var ( tmpDir string - migrator keyring.InfoImporter + migrator keyring.Importer ) if dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun); dryRun { @@ -73,10 +73,10 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { defer os.RemoveAll(tmpDir) - migrator, err = keyring.NewInfoImporter(keyringServiceName, "test", tmpDir, buf) + migrator, err = keyring.New(keyringServiceName, keyring.BackendTest, tmpDir, buf) } else { backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend) - migrator, err = keyring.NewInfoImporter(keyringServiceName, backend, rootDir, buf) + migrator, err = keyring.New(keyringServiceName, backend, rootDir, buf) } if err != nil { @@ -86,12 +86,12 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { )) } - for _, key := range oldKeys { - legKeyInfo, err := legacyKb.Export(key.GetName()) - if err != nil { - return err - } + if len(oldKeys) == 0 { + cmd.Print("Migration Aborted: no keys to migrate") + return nil + } + for _, key := range oldKeys { keyName := key.GetName() keyType := key.GetType() @@ -107,7 +107,12 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { } if keyType != keyring.TypeLocal { - if err := migrator.Import(keyName, legKeyInfo); err != nil { + pubkeyArmor, err := legacyKb.ExportPubKey(keyName) + if err != nil { + return err + } + + if err := migrator.ImportPubKey(keyName, pubkeyArmor); err != nil { return err } @@ -127,10 +132,11 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { return err } - if err := migrator.Import(keyName, armoredPriv); err != nil { + if err := migrator.ImportPrivKey(keyName, armoredPriv, migratePassphrase); err != nil { return err } } + cmd.Print("Migration Complete") return err } diff --git a/client/keys/testdata/keys/keys.db/000002.ldb b/client/keys/testdata/keys/keys.db/000002.ldb deleted file mode 100644 index b36586df3626e4a01631c987005dd5b167ff1da2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 391 zcmey$^r4Z#RxCNcI5)r8Fr~Dl+#<2KsJx`KtSZ&C+#n^bq%tF`u)-ugH7~cY)V$I% zr?5&dF(suawYZp(g#iqTO7lVsQW8s2opV#-y;CcV^fL3(^4ZPAathMRi}EtE%8be? z%1q6&N-NC^O3Kqxat-nfiYqI#QcBBG%aVb{ar!ebvHCgrGpHDX^)kqL7g=R6a7wZ; zGIE+rc**mTQf0Uyr1m=MWxFC%+6+;l*L&_w+s))UMK~hzht#w>p1XUJc$A%Z zPwESPNR;9%PE9T_GBwLK6yWnVVl8E1WG;$fU@+p1Im5hYq0HxtQ@kC!+?#3MRPJ a`@iD$YnizAFo}VL@PqK*4c#iG?zaJJVsO>~ diff --git a/client/keys/testdata/keys/keys.db/CURRENT b/client/keys/testdata/keys/keys.db/CURRENT index cacca7574c..aa5bb8ea50 100644 --- a/client/keys/testdata/keys/keys.db/CURRENT +++ b/client/keys/testdata/keys/keys.db/CURRENT @@ -1 +1 @@ -MANIFEST-000004 +MANIFEST-000005 diff --git a/client/keys/testdata/keys/keys.db/CURRENT.bak b/client/keys/testdata/keys/keys.db/CURRENT.bak index feda7d6b24..4fb1dad19e 100644 --- a/client/keys/testdata/keys/keys.db/CURRENT.bak +++ b/client/keys/testdata/keys/keys.db/CURRENT.bak @@ -1 +1 @@ -MANIFEST-000000 +MANIFEST-000003 diff --git a/client/keys/testdata/keys/keys.db/LOG b/client/keys/testdata/keys/keys.db/LOG index 386101e4fb..e37648b855 100644 --- a/client/keys/testdata/keys/keys.db/LOG +++ b/client/keys/testdata/keys/keys.db/LOG @@ -1,18 +1,30 @@ -=============== Mar 30, 2020 (CEST) =============== -02:07:34.137606 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -02:07:34.144547 db@open opening -02:07:34.144770 version@stat F·[] S·0B[] Sc·[] -02:07:34.145843 db@janitor F·2 G·0 -02:07:34.145875 db@open done T·1.315251ms -02:07:34.335635 db@close closing -02:07:34.335736 db@close done T·98.95µs -=============== Mar 30, 2020 (CEST) =============== -02:08:33.239115 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -02:08:33.239264 version@stat F·[] S·0B[] Sc·[] -02:08:33.239281 db@open opening -02:08:33.239310 journal@recovery F·1 -02:08:33.239398 journal@recovery recovering @1 -02:08:33.322008 memdb@flush created L0@2 N·4 S·391B "cos..ess,v4":"run..nfo,v3" -02:08:33.323091 version@stat F·[1] S·391B[391B] Sc·[0.25] -02:08:33.421979 db@janitor F·3 G·0 -02:08:33.422153 db@open done T·182.707962ms +=============== Feb 2, 2021 (IST) =============== +00:03:25.348369 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +00:03:25.350695 db@open opening +00:03:25.350888 version@stat F·[] S·0B[] Sc·[] +00:03:25.351864 db@janitor F·2 G·0 +00:03:25.351881 db@open done T·1.169825ms +00:03:25.351895 db@close closing +00:03:25.351929 db@close done T·33.042µs +=============== Feb 2, 2021 (IST) =============== +00:03:34.450638 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +00:03:34.450722 version@stat F·[] S·0B[] Sc·[] +00:03:34.450737 db@open opening +00:03:34.450765 journal@recovery F·1 +00:03:34.450851 journal@recovery recovering @1 +00:03:34.451173 version@stat F·[] S·0B[] Sc·[] +00:03:34.454278 db@janitor F·2 G·0 +00:03:34.454298 db@open done T·3.548046ms +00:03:34.454307 db@close closing +00:03:34.454327 db@close done T·19.017µs +=============== Feb 2, 2021 (IST) =============== +00:03:42.025705 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +00:03:42.025892 version@stat F·[] S·0B[] Sc·[] +00:03:42.025907 db@open opening +00:03:42.025943 journal@recovery F·1 +00:03:42.026790 journal@recovery recovering @2 +00:03:42.026946 version@stat F·[] S·0B[] Sc·[] +00:03:42.031645 db@janitor F·2 G·0 +00:03:42.031661 db@open done T·5.750008ms +00:03:42.283102 db@close closing +00:03:42.283162 db@close done T·58.775µs diff --git a/client/keys/testdata/keys/keys.db/MANIFEST-000004 b/client/keys/testdata/keys/keys.db/MANIFEST-000004 deleted file mode 100644 index 557b4bdbbc93fd41441cfe30d1ca16f08f47f344..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 237 zcmeykNagJ_21Z7yoYb<^oRlOzr^=Gl^338?=ltA)#G=HK{30f1W>ywfb_S+)X4~Za z;@tdV!<5pJa*M>`qVkf`vZ_?ma)Xq#lFE#%!U~i0)V$onQu9j7oWd%-#FUhx)Z$`B l76veoD=N(kEl5c$Np;RmiT6&eG}6n=OUq|uhDg)i1^~DrOBnzF diff --git a/client/keys/testdata/keys/keys.db/MANIFEST-000005 b/client/keys/testdata/keys/keys.db/MANIFEST-000005 new file mode 100644 index 0000000000000000000000000000000000000000..a9e8a261c7882e802f65360dc49782db7df6fb77 GIT binary patch literal 41 wcmYcef4W17fss)vC$%g!CnZVGsj?)sJhM2}IX|}`u_&=5zle#2nT>@304?eb82|tP literal 0 HcmV?d00001 diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index f88ffdc370..164e6bfc19 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -108,6 +108,7 @@ type Signer interface { type Importer interface { // ImportPrivKey imports ASCII armored passphrase-encrypted private keys. ImportPrivKey(uid, armor, passphrase string) error + // ImportPubKey imports ASCII armored public keys. ImportPubKey(uid string, armor string) error } From 15d83f5dac95f4afeb9e266d14f044258e4d5744 Mon Sep 17 00:00:00 2001 From: SaReN Date: Tue, 2 Feb 2021 17:04:23 +0530 Subject: [PATCH 30/40] Add changelog (#8490) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a5fa83652..6c02349468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account * (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value +* (client/keys) [\#8436](https://github.com/cosmos/cosmos-sdk/pull/8436) Fix key migration issue ## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 From ce161c4f0c52689f199e3d0376b41f581394861e Mon Sep 17 00:00:00 2001 From: Michael FIG Date: Tue, 2 Feb 2021 10:57:58 -0600 Subject: [PATCH 31/40] fix: tendermint subcommands should not create missing files (#8481) If the user specifies an incorrect `--home`, then the old behaviour would automatically populate it with fresh values, but we should fail instead. --- CHANGELOG.md | 2 ++ server/tm_cmds.go | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c02349468..73b4ff3ecd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,8 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (x/bank) [\#8417](https://github.com/cosmos/cosmos-sdk/pull/8417) Validate balances and coin denom metadata on genesis * (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value * (client/keys) [\#8436](https://github.com/cosmos/cosmos-sdk/pull/8436) Fix key migration issue +* (server) [\#8481](https://github.com/cosmos/cosmos-sdk/pull/8481) Don't create + files when running `{appd} tendermint show-*` subcommands ## [v0.40.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.1) - 2021-01-19 diff --git a/server/tm_cmds.go b/server/tm_cmds.go index b05a88f797..854d4597fe 100644 --- a/server/tm_cmds.go +++ b/server/tm_cmds.go @@ -28,7 +28,7 @@ func ShowNodeIDCmd() *cobra.Command { serverCtx := GetServerContextFromCmd(cmd) cfg := serverCtx.Config - nodeKey, err := p2p.LoadOrGenNodeKey(cfg.NodeKeyFile()) + nodeKey, err := p2p.LoadNodeKey(cfg.NodeKeyFile()) if err != nil { return err } @@ -48,7 +48,7 @@ func ShowValidatorCmd() *cobra.Command { serverCtx := GetServerContextFromCmd(cmd) cfg := serverCtx.Config - privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) + privValidator := pvm.LoadFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) valPubKey, err := privValidator.GetPubKey() if err != nil { return err @@ -86,7 +86,7 @@ func ShowAddressCmd() *cobra.Command { serverCtx := GetServerContextFromCmd(cmd) cfg := serverCtx.Config - privValidator := pvm.LoadOrGenFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) + privValidator := pvm.LoadFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile()) valConsAddr := (sdk.ConsAddress)(privValidator.GetAddress()) output, _ := cmd.Flags().GetString(cli.OutputFlag) From d37c590e90cff8e04592bf8b2c63f31f4191a3b3 Mon Sep 17 00:00:00 2001 From: Andrei Ivasko Date: Wed, 3 Feb 2021 01:47:25 -0800 Subject: [PATCH 32/40] Limit context background (#8093) * limit context background * update * fixed minor issues * fixed TestStatusCommand * Fix keyring import from older versions. (#8436) Co-authored-by: Alessio Treglia Co-authored-by: sahith-narahari * Add changelog (#8490) * fix: tendermint subcommands should not create missing files (#8481) If the user specifies an incorrect `--home`, then the old behaviour would automatically populate it with fresh values, but we should fail instead. * limit context background * update * fixed minor issues * fixed TestStatusCommand * statik.go * replaced static.go Co-authored-by: Jonathan Gimeno Co-authored-by: Alessio Treglia Co-authored-by: sahith-narahari Co-authored-by: Michael FIG --- client/cmd_test.go | 3 +- client/grpc/tmservice/block.go | 4 +- client/grpc/tmservice/service.go | 18 ++++----- client/grpc/tmservice/status.go | 4 +- client/keys/parse.go | 3 +- client/rpc/validators.go | 10 ++--- x/auth/client/cli/query.go | 5 +-- x/bank/client/cli/query.go | 13 +++---- x/bank/client/testutil/cli_helpers.go | 3 +- x/distribution/client/cli/query.go | 16 ++++---- x/distribution/client/cli/tx.go | 3 +- x/gov/client/cli/query.go | 39 +++++++++++-------- .../applications/transfer/client/cli/query.go | 7 ++-- x/ibc/core/02-client/client/cli/query.go | 7 ++-- x/ibc/core/03-connection/client/cli/query.go | 3 +- x/ibc/core/04-channel/client/cli/query.go | 11 +++--- x/mint/client/cli/query.go | 7 ++-- x/params/client/cli/query.go | 4 +- x/slashing/client/cli/query.go | 7 ++-- x/staking/client/cli/query.go | 27 +++++++------ x/upgrade/client/cli/query.go | 9 ++--- 21 files changed, 96 insertions(+), 107 deletions(-) diff --git a/client/cmd_test.go b/client/cmd_test.go index 02e2c414f6..65161fe475 100644 --- a/client/cmd_test.go +++ b/client/cmd_test.go @@ -97,8 +97,7 @@ func TestSetCmdClientContextHandler(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { - ctx := context.Background() - ctx = context.WithValue(ctx, client.ClientContextKey, &client.Context{}) + ctx := context.WithValue(context.Background(), client.ClientContextKey, &client.Context{}) cmd := newCmd() _ = testutil.ApplyMockIODiscardOutErr(cmd) diff --git a/client/grpc/tmservice/block.go b/client/grpc/tmservice/block.go index e92fbec72b..554156982d 100644 --- a/client/grpc/tmservice/block.go +++ b/client/grpc/tmservice/block.go @@ -8,12 +8,12 @@ import ( "github.com/cosmos/cosmos-sdk/client" ) -func getBlock(clientCtx client.Context, height *int64) (*ctypes.ResultBlock, error) { +func getBlock(ctx context.Context, clientCtx client.Context, height *int64) (*ctypes.ResultBlock, error) { // get the node node, err := clientCtx.GetNode() if err != nil { return nil, err } - return node.Block(context.Background(), height) + return node.Block(ctx, height) } diff --git a/client/grpc/tmservice/service.go b/client/grpc/tmservice/service.go index 58d44af579..b621dff570 100644 --- a/client/grpc/tmservice/service.go +++ b/client/grpc/tmservice/service.go @@ -34,8 +34,8 @@ func NewQueryServer(clientCtx client.Context, interfaceRegistry codectypes.Inter } // GetSyncing implements ServiceServer.GetSyncing -func (s queryServer) GetSyncing(_ context.Context, _ *GetSyncingRequest) (*GetSyncingResponse, error) { - status, err := getNodeStatus(s.clientCtx) +func (s queryServer) GetSyncing(ctx context.Context, _ *GetSyncingRequest) (*GetSyncingResponse, error) { + status, err := getNodeStatus(ctx, s.clientCtx) if err != nil { return nil, err } @@ -45,8 +45,8 @@ func (s queryServer) GetSyncing(_ context.Context, _ *GetSyncingRequest) (*GetSy } // GetLatestBlock implements ServiceServer.GetLatestBlock -func (s queryServer) GetLatestBlock(context.Context, *GetLatestBlockRequest) (*GetLatestBlockResponse, error) { - status, err := getBlock(s.clientCtx, nil) +func (s queryServer) GetLatestBlock(ctx context.Context, _ *GetLatestBlockRequest) (*GetLatestBlockResponse, error) { + status, err := getBlock(ctx, s.clientCtx, nil) if err != nil { return nil, err } @@ -64,7 +64,7 @@ func (s queryServer) GetLatestBlock(context.Context, *GetLatestBlockRequest) (*G } // GetBlockByHeight implements ServiceServer.GetBlockByHeight -func (s queryServer) GetBlockByHeight(_ context.Context, req *GetBlockByHeightRequest) (*GetBlockByHeightResponse, error) { +func (s queryServer) GetBlockByHeight(ctx context.Context, req *GetBlockByHeightRequest) (*GetBlockByHeightResponse, error) { chainHeight, err := rpc.GetChainHeight(s.clientCtx) if err != nil { return nil, err @@ -74,7 +74,7 @@ func (s queryServer) GetBlockByHeight(_ context.Context, req *GetBlockByHeightRe return nil, status.Error(codes.InvalidArgument, "requested block height is bigger then the chain length") } - res, err := getBlock(s.clientCtx, &req.Height) + res, err := getBlock(ctx, s.clientCtx, &req.Height) if err != nil { return nil, err } @@ -96,7 +96,7 @@ func (s queryServer) GetLatestValidatorSet(ctx context.Context, req *GetLatestVa return nil, err } - validatorsRes, err := rpc.GetValidators(s.clientCtx, nil, &page, &limit) + validatorsRes, err := rpc.GetValidators(ctx, s.clientCtx, nil, &page, &limit) if err != nil { return nil, err } @@ -147,7 +147,7 @@ func (s queryServer) GetValidatorSetByHeight(ctx context.Context, req *GetValida return nil, status.Error(codes.InvalidArgument, "requested block height is bigger then the chain length") } - validatorsRes, err := rpc.GetValidators(s.clientCtx, &req.Height, &page, &limit) + validatorsRes, err := rpc.GetValidators(ctx, s.clientCtx, &req.Height, &page, &limit) if err != nil { return nil, err @@ -175,7 +175,7 @@ func (s queryServer) GetValidatorSetByHeight(ctx context.Context, req *GetValida // GetNodeInfo implements ServiceServer.GetNodeInfo func (s queryServer) GetNodeInfo(ctx context.Context, req *GetNodeInfoRequest) (*GetNodeInfoResponse, error) { - status, err := getNodeStatus(s.clientCtx) + status, err := getNodeStatus(ctx, s.clientCtx) if err != nil { return nil, err } diff --git a/client/grpc/tmservice/status.go b/client/grpc/tmservice/status.go index f1a8da8e83..9e9c3d2009 100644 --- a/client/grpc/tmservice/status.go +++ b/client/grpc/tmservice/status.go @@ -8,10 +8,10 @@ import ( "github.com/cosmos/cosmos-sdk/client" ) -func getNodeStatus(clientCtx client.Context) (*ctypes.ResultStatus, error) { +func getNodeStatus(ctx context.Context, clientCtx client.Context) (*ctypes.ResultStatus, error) { node, err := clientCtx.GetNode() if err != nil { return &ctypes.ResultStatus{}, err } - return node.Status(context.Background()) + return node.Status(ctx) } diff --git a/client/keys/parse.go b/client/keys/parse.go index 2af792c03c..b1169d68cc 100644 --- a/client/keys/parse.go +++ b/client/keys/parse.go @@ -1,7 +1,6 @@ package keys import ( - "context" "encoding/hex" "errors" "fmt" @@ -86,7 +85,7 @@ hexadecimal into bech32 cosmos prefixed format and vice versa. } func parseKey(cmd *cobra.Command, args []string) error { - config, _ := sdk.GetSealedConfig(context.Background()) + config, _ := sdk.GetSealedConfig(cmd.Context()) return doParseKey(cmd, config, args) } diff --git a/client/rpc/validators.go b/client/rpc/validators.go index 66c594966e..175e7ff91e 100644 --- a/client/rpc/validators.go +++ b/client/rpc/validators.go @@ -50,7 +50,7 @@ func ValidatorCommand() *cobra.Command { page, _ := cmd.Flags().GetInt(flags.FlagPage) limit, _ := cmd.Flags().GetInt(flags.FlagLimit) - result, err := GetValidators(clientCtx, height, &page, &limit) + result, err := GetValidators(cmd.Context(), clientCtx, height, &page, &limit) if err != nil { return err } @@ -117,14 +117,14 @@ func validatorOutput(validator *tmtypes.Validator) (ValidatorOutput, error) { } // GetValidators from client -func GetValidators(clientCtx client.Context, height *int64, page, limit *int) (ResultValidatorsOutput, error) { +func GetValidators(ctx context.Context, clientCtx client.Context, height *int64, page, limit *int) (ResultValidatorsOutput, error) { // get the node node, err := clientCtx.GetNode() if err != nil { return ResultValidatorsOutput{}, err } - validatorsRes, err := node.Validators(context.Background(), height, page, limit) + validatorsRes, err := node.Validators(ctx, height, page, limit) if err != nil { return ResultValidatorsOutput{}, err } @@ -172,7 +172,7 @@ func ValidatorSetRequestHandlerFn(clientCtx client.Context) http.HandlerFunc { return } - output, err := GetValidators(clientCtx, &height, &page, &limit) + output, err := GetValidators(r.Context(), clientCtx, &height, &page, &limit) if rest.CheckInternalServerError(w, err) { return } @@ -189,7 +189,7 @@ func LatestValidatorSetRequestHandlerFn(clientCtx client.Context) http.HandlerFu return } - output, err := GetValidators(clientCtx, nil, &page, &limit) + output, err := GetValidators(r.Context(), clientCtx, nil, &page, &limit) if rest.CheckInternalServerError(w, err) { return } diff --git a/x/auth/client/cli/query.go b/x/auth/client/cli/query.go index 2590858b4c..a236e900fb 100644 --- a/x/auth/client/cli/query.go +++ b/x/auth/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strings" @@ -58,7 +57,7 @@ $ query auth params } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) if err != nil { return err } @@ -90,7 +89,7 @@ func GetAccountCmd() *cobra.Command { } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Account(context.Background(), &types.QueryAccountRequest{Address: key.String()}) + res, err := queryClient.Account(cmd.Context(), &types.QueryAccountRequest{Address: key.String()}) if err != nil { return err } diff --git a/x/bank/client/cli/query.go b/x/bank/client/cli/query.go index fbb9ba4382..a192c8deba 100644 --- a/x/bank/client/cli/query.go +++ b/x/bank/client/cli/query.go @@ -74,11 +74,10 @@ Example: if err != nil { return err } - + ctx := cmd.Context() if denom == "" { params := types.NewQueryAllBalancesRequest(addr, pageReq) - - res, err := queryClient.AllBalances(cmd.Context(), params) + res, err := queryClient.AllBalances(ctx, params) if err != nil { return err } @@ -86,7 +85,7 @@ Example: } params := types.NewQueryBalanceRequest(addr, denom) - res, err := queryClient.Balance(cmd.Context(), params) + res, err := queryClient.Balance(ctx, params) if err != nil { return err } @@ -183,9 +182,9 @@ To query for the total supply of a specific coin denomination use: } queryClient := types.NewQueryClient(clientCtx) - + ctx := cmd.Context() if denom == "" { - res, err := queryClient.TotalSupply(cmd.Context(), &types.QueryTotalSupplyRequest{}) + res, err := queryClient.TotalSupply(ctx, &types.QueryTotalSupplyRequest{}) if err != nil { return err } @@ -193,7 +192,7 @@ To query for the total supply of a specific coin denomination use: return clientCtx.PrintProto(res) } - res, err := queryClient.SupplyOf(cmd.Context(), &types.QuerySupplyOfRequest{Denom: denom}) + res, err := queryClient.SupplyOf(ctx, &types.QuerySupplyOfRequest{Denom: denom}) if err != nil { return err } diff --git a/x/bank/client/testutil/cli_helpers.go b/x/bank/client/testutil/cli_helpers.go index 0f1b848cb7..e36f3744a6 100644 --- a/x/bank/client/testutil/cli_helpers.go +++ b/x/bank/client/testutil/cli_helpers.go @@ -1,7 +1,6 @@ package testutil import ( - "context" "fmt" "github.com/spf13/cobra" @@ -59,7 +58,7 @@ ignored as it is implied from [from_key_or_address].`, msg := types.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) svcMsgClientConn := &msgservice.ServiceMsgClientConn{} bankMsgClient := types.NewMsgClient(svcMsgClientConn) - _, err = bankMsgClient.Send(context.Background(), msg) + _, err = bankMsgClient.Send(cmd.Context(), msg) if err != nil { return err } diff --git a/x/distribution/client/cli/query.go b/x/distribution/client/cli/query.go index 3b6032ce7b..aa087f5f8b 100644 --- a/x/distribution/client/cli/query.go +++ b/x/distribution/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strconv" "strings" @@ -50,7 +49,7 @@ func GetCmdQueryParams() *cobra.Command { } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) if err != nil { return err } @@ -94,7 +93,7 @@ $ %s query distribution validator-outstanding-rewards %s1lwjmdnks33xwnmfayc64ycp } res, err := queryClient.ValidatorOutstandingRewards( - context.Background(), + cmd.Context(), &types.QueryValidatorOutstandingRewardsRequest{ValidatorAddress: validatorAddr.String()}, ) if err != nil { @@ -139,7 +138,7 @@ $ %s query distribution commission %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj } res, err := queryClient.ValidatorCommission( - context.Background(), + cmd.Context(), &types.QueryValidatorCommissionRequest{ValidatorAddress: validatorAddr.String()}, ) if err != nil { @@ -199,7 +198,7 @@ $ %s query distribution slashes %svaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj } res, err := queryClient.ValidatorSlashes( - context.Background(), + cmd.Context(), &types.QueryValidatorSlashesRequest{ ValidatorAddress: validatorAddr.String(), StartingHeight: startHeight, @@ -252,6 +251,7 @@ $ %s query distribution rewards %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1ggh } // query for rewards from a particular delegation + ctx := cmd.Context() if len(args) == 2 { validatorAddr, err := sdk.ValAddressFromBech32(args[1]) if err != nil { @@ -259,7 +259,7 @@ $ %s query distribution rewards %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1ggh } res, err := queryClient.DelegationRewards( - context.Background(), + ctx, &types.QueryDelegationRewardsRequest{DelegatorAddress: delegatorAddr.String(), ValidatorAddress: validatorAddr.String()}, ) if err != nil { @@ -270,7 +270,7 @@ $ %s query distribution rewards %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1ggh } res, err := queryClient.DelegationTotalRewards( - context.Background(), + ctx, &types.QueryDelegationTotalRewardsRequest{DelegatorAddress: delegatorAddr.String()}, ) if err != nil { @@ -307,7 +307,7 @@ $ %s query distribution community-pool } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.CommunityPool(context.Background(), &types.QueryCommunityPoolRequest{}) + res, err := queryClient.CommunityPool(cmd.Context(), &types.QueryCommunityPoolRequest{}) if err != nil { return err } diff --git a/x/distribution/client/cli/tx.go b/x/distribution/client/cli/tx.go index d62bcd21fa..dcf5a3b057 100644 --- a/x/distribution/client/cli/tx.go +++ b/x/distribution/client/cli/tx.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strings" @@ -155,7 +154,7 @@ $ %s tx distribution withdraw-all-rewards --from mykey } queryClient := types.NewQueryClient(clientCtx) - delValsRes, err := queryClient.DelegatorValidators(context.Background(), &types.QueryDelegatorValidatorsRequest{DelegatorAddress: delAddr.String()}) + delValsRes, err := queryClient.DelegatorValidators(cmd.Context(), &types.QueryDelegatorValidatorsRequest{DelegatorAddress: delAddr.String()}) if err != nil { return err } diff --git a/x/gov/client/cli/query.go b/x/gov/client/cli/query.go index 8c67cd96e5..b382f540e2 100644 --- a/x/gov/client/cli/query.go +++ b/x/gov/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strconv" "strings" @@ -74,7 +73,7 @@ $ %s query gov proposal 1 // Query the proposal res, err := queryClient.Proposal( - context.Background(), + cmd.Context(), &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -149,7 +148,7 @@ $ %s query gov proposals --page=2 --limit=100 } res, err := queryClient.Proposals( - context.Background(), + cmd.Context(), &types.QueryProposalsRequest{ ProposalStatus: proposalStatus, Voter: bechVoterAddr, @@ -208,8 +207,9 @@ $ %s query gov vote 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk } // check to see if the proposal is in the store + ctx := cmd.Context() _, err = queryClient.Proposal( - context.Background(), + ctx, &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -222,7 +222,7 @@ $ %s query gov vote 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk } res, err := queryClient.Vote( - context.Background(), + ctx, &types.QueryVoteRequest{ProposalId: proposalID, Voter: args[1]}, ) if err != nil { @@ -282,8 +282,9 @@ $ %[1]s query gov votes 1 --page=2 --limit=100 } // check to see if the proposal is in the store + ctx := cmd.Context() proposalRes, err := queryClient.Proposal( - context.Background(), + ctx, &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -315,7 +316,7 @@ $ %[1]s query gov votes 1 --page=2 --limit=100 } res, err := queryClient.Votes( - context.Background(), + ctx, &types.QueryVotesRequest{ProposalId: proposalID, Pagination: pageReq}, ) @@ -364,8 +365,9 @@ $ %s query gov deposit 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk } // check to see if the proposal is in the store + ctx := cmd.Context() _, err = queryClient.Proposal( - context.Background(), + ctx, &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -378,7 +380,7 @@ $ %s query gov deposit 1 cosmos1skjwj5whet0lpe65qaq4rpq03hjxlwd9nf39lk } res, err := queryClient.Deposit( - context.Background(), + ctx, &types.QueryDepositRequest{ProposalId: proposalID, Depositor: args[1]}, ) if err != nil { @@ -434,8 +436,9 @@ $ %s query gov deposits 1 } // check to see if the proposal is in the store + ctx := cmd.Context() proposalRes, err := queryClient.Proposal( - context.Background(), + ctx, &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -464,7 +467,7 @@ $ %s query gov deposits 1 } res, err := queryClient.Deposits( - context.Background(), + ctx, &types.QueryDepositsRequest{ProposalId: proposalID, Pagination: pageReq}, ) @@ -512,8 +515,9 @@ $ %s query gov tally 1 } // check to see if the proposal is in the store + ctx := cmd.Context() _, err = queryClient.Proposal( - context.Background(), + ctx, &types.QueryProposalRequest{ProposalId: proposalID}, ) if err != nil { @@ -522,7 +526,7 @@ $ %s query gov tally 1 // Query store res, err := queryClient.TallyResult( - context.Background(), + ctx, &types.QueryTallyResultRequest{ProposalId: proposalID}, ) if err != nil { @@ -561,8 +565,9 @@ $ %s query gov params queryClient := types.NewQueryClient(clientCtx) // Query store for all 3 params + ctx := cmd.Context() votingRes, err := queryClient.Params( - context.Background(), + ctx, &types.QueryParamsRequest{ParamsType: "voting"}, ) if err != nil { @@ -570,7 +575,7 @@ $ %s query gov params } tallyRes, err := queryClient.Params( - context.Background(), + ctx, &types.QueryParamsRequest{ParamsType: "tallying"}, ) if err != nil { @@ -578,7 +583,7 @@ $ %s query gov params } depositRes, err := queryClient.Params( - context.Background(), + ctx, &types.QueryParamsRequest{ParamsType: "deposit"}, ) if err != nil { @@ -626,7 +631,7 @@ $ %s query gov param deposit // Query store res, err := queryClient.Params( - context.Background(), + cmd.Context(), &types.QueryParamsRequest{ParamsType: args[0]}, ) if err != nil { diff --git a/x/ibc/applications/transfer/client/cli/query.go b/x/ibc/applications/transfer/client/cli/query.go index 7d281bb415..b9658e05ae 100644 --- a/x/ibc/applications/transfer/client/cli/query.go +++ b/x/ibc/applications/transfer/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "github.com/spf13/cobra" @@ -31,7 +30,7 @@ func GetCmdQueryDenomTrace() *cobra.Command { Hash: args[0], } - res, err := queryClient.DenomTrace(context.Background(), req) + res, err := queryClient.DenomTrace(cmd.Context(), req) if err != nil { return err } @@ -69,7 +68,7 @@ func GetCmdQueryDenomTraces() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.DenomTraces(context.Background(), req) + res, err := queryClient.DenomTraces(cmd.Context(), req) if err != nil { return err } @@ -98,7 +97,7 @@ func GetCmdParams() *cobra.Command { } queryClient := types.NewQueryClient(clientCtx) - res, _ := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + res, _ := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) return clientCtx.PrintProto(res.Params) }, } diff --git a/x/ibc/core/02-client/client/cli/query.go b/x/ibc/core/02-client/client/cli/query.go index 7c49b12e02..c1b5e51a05 100644 --- a/x/ibc/core/02-client/client/cli/query.go +++ b/x/ibc/core/02-client/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "errors" "fmt" @@ -44,7 +43,7 @@ func GetCmdQueryClientStates() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.ClientStates(context.Background(), req) + res, err := queryClient.ClientStates(cmd.Context(), req) if err != nil { return err } @@ -118,7 +117,7 @@ func GetCmdQueryConsensusStates() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.ConsensusStates(context.Background(), req) + res, err := queryClient.ConsensusStates(cmd.Context(), req) if err != nil { return err } @@ -250,7 +249,7 @@ func GetCmdParams() *cobra.Command { } queryClient := types.NewQueryClient(clientCtx) - res, _ := queryClient.ClientParams(context.Background(), &types.QueryClientParamsRequest{}) + res, _ := queryClient.ClientParams(cmd.Context(), &types.QueryClientParamsRequest{}) return clientCtx.PrintProto(res.Params) }, } diff --git a/x/ibc/core/03-connection/client/cli/query.go b/x/ibc/core/03-connection/client/cli/query.go index 071410398d..21c4bd8f57 100644 --- a/x/ibc/core/03-connection/client/cli/query.go +++ b/x/ibc/core/03-connection/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "github.com/spf13/cobra" @@ -39,7 +38,7 @@ func GetCmdQueryConnections() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.Connections(context.Background(), req) + res, err := queryClient.Connections(cmd.Context(), req) if err != nil { return err } diff --git a/x/ibc/core/04-channel/client/cli/query.go b/x/ibc/core/04-channel/client/cli/query.go index 5d059c08cf..03df474f1e 100644 --- a/x/ibc/core/04-channel/client/cli/query.go +++ b/x/ibc/core/04-channel/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strconv" @@ -44,7 +43,7 @@ func GetCmdQueryChannels() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.Channels(context.Background(), req) + res, err := queryClient.Channels(cmd.Context(), req) if err != nil { return err } @@ -118,7 +117,7 @@ func GetCmdQueryConnectionChannels() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.ConnectionChannels(context.Background(), req) + res, err := queryClient.ConnectionChannels(cmd.Context(), req) if err != nil { return err } @@ -189,7 +188,7 @@ func GetCmdQueryPacketCommitments() *cobra.Command { Pagination: pageReq, } - res, err := queryClient.PacketCommitments(context.Background(), req) + res, err := queryClient.PacketCommitments(cmd.Context(), req) if err != nil { return err } @@ -357,7 +356,7 @@ The return value represents: PacketCommitmentSequences: seqs, } - res, err := queryClient.UnreceivedPackets(context.Background(), req) + res, err := queryClient.UnreceivedPackets(cmd.Context(), req) if err != nil { return err } @@ -407,7 +406,7 @@ The return value represents: PacketAckSequences: seqs, } - res, err := queryClient.UnreceivedAcks(context.Background(), req) + res, err := queryClient.UnreceivedAcks(cmd.Context(), req) if err != nil { return err } diff --git a/x/mint/client/cli/query.go b/x/mint/client/cli/query.go index cce0d7c12b..792fa8a679 100644 --- a/x/mint/client/cli/query.go +++ b/x/mint/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "github.com/spf13/cobra" @@ -45,7 +44,7 @@ func GetCmdQueryParams() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) params := &types.QueryParamsRequest{} - res, err := queryClient.Params(context.Background(), params) + res, err := queryClient.Params(cmd.Context(), params) if err != nil { return err @@ -75,7 +74,7 @@ func GetCmdQueryInflation() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) params := &types.QueryInflationRequest{} - res, err := queryClient.Inflation(context.Background(), params) + res, err := queryClient.Inflation(cmd.Context(), params) if err != nil { return err @@ -105,7 +104,7 @@ func GetCmdQueryAnnualProvisions() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) params := &types.QueryAnnualProvisionsRequest{} - res, err := queryClient.AnnualProvisions(context.Background(), params) + res, err := queryClient.AnnualProvisions(cmd.Context(), params) if err != nil { return err diff --git a/x/params/client/cli/query.go b/x/params/client/cli/query.go index 516ff3b6b4..ce7b45d060 100644 --- a/x/params/client/cli/query.go +++ b/x/params/client/cli/query.go @@ -1,8 +1,6 @@ package cli import ( - "context" - "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" @@ -41,7 +39,7 @@ func NewQuerySubspaceParamsCmd() *cobra.Command { queryClient := proposal.NewQueryClient(clientCtx) params := proposal.QueryParamsRequest{Subspace: args[0], Key: args[1]} - res, err := queryClient.Params(context.Background(), ¶ms) + res, err := queryClient.Params(cmd.Context(), ¶ms) if err != nil { return err } diff --git a/x/slashing/client/cli/query.go b/x/slashing/client/cli/query.go index d55b33201b..6cb2f803d0 100644 --- a/x/slashing/client/cli/query.go +++ b/x/slashing/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "strings" "github.com/spf13/cobra" @@ -58,7 +57,7 @@ $ query slashing signing-info cosmosvalconspub1zcjduepqfhvwcmt7p06fvdgexx consAddr := sdk.ConsAddress(pk.Address()) params := &types.QuerySigningInfoRequest{ConsAddress: consAddr.String()} - res, err := queryClient.SigningInfo(context.Background(), params) + res, err := queryClient.SigningInfo(cmd.Context(), params) if err != nil { return err } @@ -95,7 +94,7 @@ $ query slashing signing-infos } params := &types.QuerySigningInfosRequest{Pagination: pageReq} - res, err := queryClient.SigningInfos(context.Background(), params) + res, err := queryClient.SigningInfos(cmd.Context(), params) if err != nil { return err } @@ -128,7 +127,7 @@ $ query slashing params queryClient := types.NewQueryClient(clientCtx) params := &types.QueryParamsRequest{} - res, err := queryClient.Params(context.Background(), params) + res, err := queryClient.Params(cmd.Context(), params) if err != nil { return err } diff --git a/x/staking/client/cli/query.go b/x/staking/client/cli/query.go index 1e8b0a5c53..7bf3ae41cc 100644 --- a/x/staking/client/cli/query.go +++ b/x/staking/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "strconv" "strings" @@ -115,7 +114,7 @@ $ %s query staking validators return err } - result, err := queryClient.Validators(context.Background(), &types.QueryValidatorsRequest{ + result, err := queryClient.Validators(cmd.Context(), &types.QueryValidatorsRequest{ // Leaving status empty on purpose to query all validators. Pagination: pageReq, }) @@ -172,7 +171,7 @@ $ %s query staking unbonding-delegations-from %s1gghjut3ccd8ay0zduzj64hwre2fxs9l Pagination: pageReq, } - res, err := queryClient.ValidatorUnbondingDelegations(context.Background(), params) + res, err := queryClient.ValidatorUnbondingDelegations(cmd.Context(), params) if err != nil { return err } @@ -227,7 +226,7 @@ $ %s query staking redelegations-from %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj Pagination: pageReq, } - res, err := queryClient.Redelegations(context.Background(), params) + res, err := queryClient.Redelegations(cmd.Context(), params) if err != nil { return err } @@ -282,7 +281,7 @@ $ %s query staking delegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1gghju ValidatorAddr: valAddr.String(), } - res, err := queryClient.Delegation(context.Background(), params) + res, err := queryClient.Delegation(cmd.Context(), params) if err != nil { return err } @@ -336,7 +335,7 @@ $ %s query staking delegations %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p Pagination: pageReq, } - res, err := queryClient.DelegatorDelegations(context.Background(), params) + res, err := queryClient.DelegatorDelegations(cmd.Context(), params) if err != nil { return err } @@ -391,7 +390,7 @@ $ %s query staking delegations-to %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj Pagination: pageReq, } - res, err := queryClient.ValidatorDelegations(context.Background(), params) + res, err := queryClient.ValidatorDelegations(cmd.Context(), params) if err != nil { return err } @@ -447,7 +446,7 @@ $ %s query staking unbonding-delegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9 ValidatorAddr: valAddr.String(), } - res, err := queryClient.UnbondingDelegation(context.Background(), params) + res, err := queryClient.UnbondingDelegation(cmd.Context(), params) if err != nil { return err } @@ -501,7 +500,7 @@ $ %s query staking unbonding-delegations %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru Pagination: pageReq, } - res, err := queryClient.DelegatorUnbondingDelegations(context.Background(), params) + res, err := queryClient.DelegatorUnbondingDelegations(cmd.Context(), params) if err != nil { return err } @@ -563,7 +562,7 @@ $ %s query staking redelegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1l2r SrcValidatorAddr: valSrcAddr.String(), } - res, err := queryClient.Redelegations(context.Background(), params) + res, err := queryClient.Redelegations(cmd.Context(), params) if err != nil { return err } @@ -617,7 +616,7 @@ $ %s query staking redelegation %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p Pagination: pageReq, } - res, err := queryClient.Redelegations(context.Background(), params) + res, err := queryClient.Redelegations(cmd.Context(), params) if err != nil { return err } @@ -660,7 +659,7 @@ $ %s query staking historical-info 5 } params := &types.QueryHistoricalInfoRequest{Height: height} - res, err := queryClient.HistoricalInfo(context.Background(), params) + res, err := queryClient.HistoricalInfo(cmd.Context(), params) if err != nil { return err @@ -697,7 +696,7 @@ $ %s query staking pool } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Pool(context.Background(), &types.QueryPoolRequest{}) + res, err := queryClient.Pool(cmd.Context(), &types.QueryPoolRequest{}) if err != nil { return err } @@ -733,7 +732,7 @@ $ %s query staking params } queryClient := types.NewQueryClient(clientCtx) - res, err := queryClient.Params(context.Background(), &types.QueryParamsRequest{}) + res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) if err != nil { return err } diff --git a/x/upgrade/client/cli/query.go b/x/upgrade/client/cli/query.go index 675dba3a9e..39674cbc73 100644 --- a/x/upgrade/client/cli/query.go +++ b/x/upgrade/client/cli/query.go @@ -1,7 +1,6 @@ package cli import ( - "context" "fmt" "github.com/spf13/cobra" @@ -41,7 +40,7 @@ func GetCurrentPlanCmd() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) params := types.QueryCurrentPlanRequest{} - res, err := queryClient.CurrentPlan(context.Background(), ¶ms) + res, err := queryClient.CurrentPlan(cmd.Context(), ¶ms) if err != nil { return err } @@ -74,9 +73,9 @@ func GetAppliedPlanCmd() *cobra.Command { return err } queryClient := types.NewQueryClient(clientCtx) - + ctx := cmd.Context() params := types.QueryAppliedPlanRequest{Name: args[0]} - res, err := queryClient.AppliedPlan(context.Background(), ¶ms) + res, err := queryClient.AppliedPlan(ctx, ¶ms) if err != nil { return err } @@ -90,7 +89,7 @@ func GetAppliedPlanCmd() *cobra.Command { if err != nil { return err } - headers, err := node.BlockchainInfo(context.Background(), res.Height, res.Height) + headers, err := node.BlockchainInfo(ctx, res.Height, res.Height) if err != nil { return err } From 2e9fd0402063a0d606dd266f9d72d275e69e95c0 Mon Sep 17 00:00:00 2001 From: SaReN Date: Wed, 3 Feb 2021 18:41:42 +0530 Subject: [PATCH 33/40] Remove Info Importer from legacy keybase (#8500) --- CHANGELOG.md | 4 ++++ crypto/keyring/legacy.go | 44 ----------------------------------- crypto/keyring/legacy_test.go | 12 ---------- 3 files changed, 4 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73b4ff3ecd..12a2d94b31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Addresses no longer have a fixed 20-byte length. From the SDK modules' point of view, any 1-255 bytes-long byte array is a valid address. +### API Breaking Changes + +* (client/keys) [\#8500](https://github.com/cosmos/cosmos-sdk/pull/8500) `InfoImporter` interface is removed from legacy keybase. + ### State Machine Breaking * (x/{bank,distrib,gov,slashing,staking}) [\#8363](https://github.com/cosmos/cosmos-sdk/issues/8363) Store keys have been modified to allow for variable-length addresses. diff --git a/crypto/keyring/legacy.go b/crypto/keyring/legacy.go index 59bdc3fc5d..d6653e9561 100644 --- a/crypto/keyring/legacy.go +++ b/crypto/keyring/legacy.go @@ -2,7 +2,6 @@ package keyring import ( "fmt" - "io" "strings" "github.com/pkg/errors" @@ -185,49 +184,6 @@ func (kb dbKeybase) Close() error { return kb.db.Close() } func infoKey(name string) []byte { return []byte(fmt.Sprintf("%s.%s", name, infoSuffix)) } -// InfoImporter is implemented by those types that want to provide functions necessary -// to migrate keys from LegacyKeybase types to Keyring types. -type InfoImporter interface { - // Import imports ASCII-armored private keys. - Import(uid string, armor string) error -} - -type keyringMigrator struct { - kr keystore -} - -func NewInfoImporter( - appName, backend, rootDir string, userInput io.Reader, opts ...Option, -) (InfoImporter, error) { - keyring, err := New(appName, backend, rootDir, userInput, opts...) - if err != nil { - return keyringMigrator{}, err - } - - kr := keyring.(keystore) - - return keyringMigrator{kr}, nil -} - -func (m keyringMigrator) Import(uid string, armor string) error { - _, err := m.kr.Key(uid) - if err == nil { - return fmt.Errorf("cannot overwrite key %q", uid) - } - - infoBytes, err := crypto.UnarmorInfoBytes(armor) - if err != nil { - return err - } - - info, err := unmarshalInfo(infoBytes) - if err != nil { - return err - } - - return m.kr.writeInfo(info) -} - // KeybaseOption overrides options for the db. type KeybaseOption func(*kbOptions) diff --git a/crypto/keyring/legacy_test.go b/crypto/keyring/legacy_test.go index 27503bdea0..d1b0dbf3e6 100644 --- a/crypto/keyring/legacy_test.go +++ b/crypto/keyring/legacy_test.go @@ -1,7 +1,6 @@ package keyring_test import ( - "io" "path/filepath" "testing" @@ -43,15 +42,4 @@ func TestLegacyKeybase(t *testing.T) { armoredInfo, err := kb.Export(keys[0].GetName()) require.NoError(t, err) require.NotEmpty(t, armoredInfo) - - importer, err := keyring.NewInfoImporter("cosmos", "memory", "", nil) - require.NoError(t, err) - err = importer.Import("test", "") - require.Error(t, err) - require.Equal(t, io.EOF, err) - require.NoError(t, importer.Import("test", armoredInfo)) - - err = importer.Import("test", armoredInfo) - require.Error(t, err) - require.Equal(t, `public key already exist in keybase`, err.Error()) } From d84942c1c030a415216f8d95e7d8037abf089d5f Mon Sep 17 00:00:00 2001 From: Amaury Date: Wed, 3 Feb 2021 21:38:23 +0100 Subject: [PATCH 34/40] Remove useless package-lock.json (#8506) --- package-lock.json | 137 ---------------------------------------------- 1 file changed, 137 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index a0da4739d2..0000000000 --- a/package-lock.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "@types/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", - "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", - "requires": { - "@types/node": "*" - } - }, - "@types/express": { - "version": "4.17.6", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz", - "integrity": "sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.8.tgz", - "integrity": "sha512-1SJZ+R3Q/7mLkOD9ewCBDYD2k0WyZQtWYqF/2VvoNN2/uhI49J9CDN4OAm+wGMA0DbArA4ef27xl4+JwMtGggw==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/mime": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", - "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==" - }, - "@types/node": { - "version": "14.0.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz", - "integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ==" - }, - "@types/passport": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.3.tgz", - "integrity": "sha512-nyztuxtDPQv9utCzU0qW7Gl8BY2Dn8BKlYAFFyxKipFxjaVd96celbkLCV/tRqqBUZ+JB8If3UfgV8347DTo3Q==", - "requires": { - "@types/express": "*" - } - }, - "@types/passport-twitter": { - "version": "1.0.35", - "resolved": "https://registry.npmjs.org/@types/passport-twitter/-/passport-twitter-1.0.35.tgz", - "integrity": "sha512-7ceE/w7bvIqDPdOkPuXSDHTwwCnBW/wpn4vB98AlXieJ31nuCzjWZKWjxtyNpie8/StigN1tzF/YCRGgEh2Seg==", - "requires": { - "@types/express": "*", - "@types/passport": "*" - } - }, - "@types/qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==" - }, - "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" - }, - "@types/serve-static": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", - "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==", - "requires": { - "@types/express-serve-static-core": "*", - "@types/mime": "*" - } - }, - "oauth": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", - "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" - }, - "passport-oauth1": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/passport-oauth1/-/passport-oauth1-1.1.0.tgz", - "integrity": "sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg=", - "requires": { - "oauth": "0.9.x", - "passport-strategy": "1.x.x", - "utils-merge": "1.x.x" - } - }, - "passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" - }, - "passport-twitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/passport-twitter/-/passport-twitter-1.0.4.tgz", - "integrity": "sha1-AaeZ4fdgvy3knyul+6MigvGJMtc=", - "requires": { - "passport-oauth1": "1.x.x", - "xtraverse": "0.1.x" - } - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "xmldom": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", - "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==" - }, - "xtraverse": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/xtraverse/-/xtraverse-0.1.0.tgz", - "integrity": "sha1-t0G60BjveNip0ug63gB7P3lZxzI=", - "requires": { - "xmldom": "0.1.x" - } - } - } -} From 931af4350b4967e91e0cdf2de3491901e47bfefc Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 4 Feb 2021 04:08:11 +0100 Subject: [PATCH 35/40] Finalize ADR-028 (#8398) Finalize ADR-028 * added note about Named Accounts * Update docs/architecture/adr-028-public-key-addresses.md * remove blake2b * move some paragraphs to 'Further Discussion' * move composing module accounts to a new subsectoin * adding appendix from meeting with Alan * composed addresses: use LengthPrefix before sorting --- .../adr-028-public-key-addresses.md | 340 +++++++++++++----- 1 file changed, 250 insertions(+), 90 deletions(-) diff --git a/docs/architecture/adr-028-public-key-addresses.md b/docs/architecture/adr-028-public-key-addresses.md index 00c6dddc0b..bacaec79cb 100644 --- a/docs/architecture/adr-028-public-key-addresses.md +++ b/docs/architecture/adr-028-public-key-addresses.md @@ -3,6 +3,7 @@ ## Changelog - 2020/08/18: Initial version +- 2021/01/15: Analysis and algorithm update ## Status @@ -10,42 +11,81 @@ Proposed ## Abstract -This ADR defines a canonical 20-byte address format for new public key algorithms, multisig public keys, and module -accounts using string prefixes. +This ADR defines an address format for all addressable SDK accounts. That includes: new public key algorithms, multisig public keys, and module accounts. ## Context Issue [\#3685](https://github.com/cosmos/cosmos-sdk/issues/3685) identified that public key -address spaces are currently overlapping. One initial proposal was extending the address length and -adding prefixes for different types of addresses. +address spaces are currently overlapping. We confirmed that it significantly decreases security of Cosmos SDK. + + +### Problem + +An attacker can control an input for an address generation function. This leads to a birthday attack, which significantly decreases the security space. +To overcome this, we need to separate the inputs for different kind of account types: +a security break of one account type shouldn't impact the security of other account types. + + +### Initial proposals + +One initial proposal was extending the address length and +adding prefixes for different types of addresses. @ethanfrey explained an alternate approach originally used in https://github.com/iov-one/weave: > I spent quite a bit of time thinking about this issue while building weave... The other cosmos Sdk. - > Basically I define a condition to be a type and format as human readable string with some binary data appended. This condition is hashed into an Address (again at 20 bytes). The use of this prefix makes it impossible to find a preimage for a given address with a different condition (eg ed25519 vs secp256k1). - > This is explained in depth here https://weave.readthedocs.io/en/latest/design/permissions.html - > And the code is here, look mainly at the top where we process conditions. https://github.com/iov-one/weave/blob/master/conditions.go And explained how this approach should be sufficiently collision resistant: + > Yeah, AFAIK, 20 bytes should be collision resistance when the preimages are unique and not malleable. A space of 2^160 would expect some collision to be likely around 2^80 elements (birthday paradox). And if you want to find a collision for some existing element in the database, it is still 2^160. 2^80 only is if all these elements are written to state. - > The good example you brought up was eg. a public key bytes being a valid public key on two algorithms supported by the codec. Meaning if either was broken, you would break accounts even if they were secured with the safer variant. This is only as the issue when no differentiating type info is present in the preimage (before hashing into an address). - > I would like to hear an argument if the 20 bytes space is an actual issue for security, as I would be happy to increase my address sizes in weave. I just figured cosmos and ethereum and bitcoin all use 20 bytes, it should be good enough. And the arguments above which made me feel it was secure. But I have not done a deeper analysis. -In discussions in [\#5694](https://github.com/cosmos/cosmos-sdk/issues/5694), we agreed to go with an -approach similar to this where essentially we take the first 20 bytes of the `sha256` hash of -the key type concatenated with the key bytes, summarized as `Sha256(KeyTypePrefix || Keybytes)[:20]`. +This led to the first proposal (which we proved to be not good enough): +we concatenate a key type with a public key, hash it and take the first 20 bytes of that hash, summarized as `sha256(keyTypePrefix || keybytes)[:20]`. + + +### Review and Discussions + +In [\#5694](https://github.com/cosmos/cosmos-sdk/issues/5694) we discussed various solutions. +We agreed that 20 bytes it's not future proof, and extending the address length is the only way to allow addresses of different types, various signature types, etc. +This disqualifies the initial proposal. + +In the issue we discussed various modifications: ++ Choice of the hash function. ++ Move the prefix out of the hash function: `keyTypePrefix + sha256(keybytes)[:20]` [post-hash-prefix-proposal]. ++ Use double hashing: `sha256(keyTypePrefix + sha256(keybytes)[:20])`. ++ Increase to keybytes hash slice from 20 byte to 32 or 40 bytes. We concluded that 32 bytes, produced by a good hash functions is future secure. + +### Requirements + ++ Support currently used tools - we don't want to break an ecosystem, or add a long adaptation period. Ref: https://github.com/cosmos/cosmos-sdk/issues/8041 ++ Try to keep the address length small - addresses are widely used in state, both as part of a key and object value. + + +### Scope + +This ADR only defines a process for the generation of address bytes. For end-user interactions with addresses (through the API, or CLI, etc.), we still use bech32 to format these addresses as strings. This ADR doesn't change that. +Using bech32 for string encoding gives us support for checksum error codes and handling of user typos. + ## Decision +We define the following account types, for which we define the address function: + +1. simple accounts: represented by a regular public key (ie: secp256k1, sr25519) +2. naive multisig: accounts composed by other addressable objects (ie: naive multisig) +3. composed accounts with a native address key (ie: bls, group module accounts) +4. module accounts: basically any accounts which cannot sign transactions and which are managed internally by modules + + ### Legacy Public Key Addresses Don't Change -`secp256k1` and multisig public keys are currently in use in existing Cosmos SDK zones. They use the following -address formats: +Currently (Jan 2021), the only officially supported SDK user accounts are `secp256k1` basic accounts and legacy amino multisig. +They are used in existing Cosmos SDK zones. They use the following address formats: - secp256k1: `ripemd160(sha256(pk_bytes))[:20]` - legacy amino multisig: `sha256(aminoCdc.Marshal(pk))[:20]` @@ -56,42 +96,142 @@ The current multisig public keys use amino serialization to generate the address those public keys and their address formatting, and call them "legacy amino" multisig public keys in protobuf. We will also create multisig public keys without amino addresses to be described below. +### Hash Function Choice -### Canonical Address Format +As in other parts of the Cosmos SDK, we will use `sha256`. -We have three types of accounts we would like to create addresses for in the future: -- regular public key addresses for new signature algorithms (ex. `sr25519`). -- public key addresses for multisig public keys that don't use amino encoding -- module accounts: basically any accounts which cannot sign transactions and -which are managed internally by modules +### Basic Address -To address all of these use cases we propose the following basic `AddressHash` function, -based on the discussions in [\#5694](https://github.com/cosmos/cosmos-sdk/issues/5694): +We start with defining a base hash algorithm for generating addresses. Notably, it's used for accounts represented by a single key pair. For each public key schema we have to have an associated `typ` string, which we discuss in a section below. `hash` is the cryptographic hash function defined in the previous section. ```go -func AddressHash(prefix string, contents []byte) []byte { - preImage := []byte(prefix) - if len(contents) != 0 { - preImage = append(preImage, 0) - preImage = append(preImage, contents...) - } - return sha256.Sum256(preImage)[:20] +const A_LEN = 32 + +func Hash(typ string, key []byte) []byte { + return hash(hash(typ) + key)[:A_LEN] } ``` -`AddressHash` always take a string `prefix` as a starting point which should represent the -type of public key (ex. `sr25519`) or module account being used (ex. `staking` or `group`). -For public keys, the `contents` parameter is used to specify the binary contents of the public -key. For module accounts, `contents` can be left empty (for modules which don't manage "sub-accounts"), -or can be some module-specific content to specify different pools (ex. `bonded` or `not-bonded` for `staking`) -or managed accounts (ex. different accounts managed by the `group` module). +The `+` is bytes concatenation, which doesn't use any separator. -In the `preImage`, the byte value `0` is used as the separator between `prefix` and `contents`. This is a logical -choice given that `0` is an invalid value for a string character and is commonly used as a null terminator. +This algorithm is the outcome of a consultation session with a professional cryptographer. +Motivation: this algorithm keeps the address relatively small (length of the `typ` doesn't impact the length of the final address) +and it's more secure than [post-hash-prefix-proposal] (which uses the first 20 bytes of a pubkey hash, significantly reducing the address space). +Moreover the cryptographer motivated the choice of adding `typ` in the hash to protect against a switch table attack. -### Canonical Public Key Address Prefixes +We use the `address.Hash` function for generating addresses for all accounts represented by a single key: +* simple public keys: `address.Hash(keyType, pubkey)` ++ aggregated keys (eg: BLS): `address.Hash(keyType, aggregatedPubKey)` ++ modules: `address.Hash("module", moduleName)` -All public key types will have a unique protobuf message type such as: + +### Composed Addresses + +For simple composed accounts (like new naive multisig), we generalize the `address.Hash`. The address is constructed by recursively creating addresses for the sub accounts, sorting the addresses and composing them into a single address. It ensures that the ordering of keys doesn't impact the resulting address. + +```go +// We don't need a PubKey interface - we need anything which is addressable. +type Addressable interface { + Address() []byte +} + +func NewComposed(typ string, subaccounts []Addressable) []byte { + addresses = map(subaccounts, \a -> LengthPrefix(a.Address())) + addresses = sort(addresses) + return address.Hash(typ, addresses[0] + ... + addresses[n]) +} +``` + +The `typ` parameter should be a schema descriptor, containing all significant attributes with deterministic serialization (eg: utf8 string). +`LengthPrefix` is a function which prepends 1 byte to the address. The value of that byte is the length of the address bits before prepending. The address must be at most 255 bits long. +We are using `LengthPrefix` to eliminate conflicts - it assures, that for 2 lists of addresses: `as = {a1, a2, ..., an}` and `bs = {b1, b2, ..., bm}` such that every `bi` and `ai` is at most 255 long, `concatenate(map(as, \a -> LengthPrefix(a))) = map(bs, \b -> LengthPrefix(b))` iff `as = bs`. + +Implementation Tip: account implementations should cache addresses. + +#### Multisig Addresses + +For new multisig public keys, we define the `typ` parameter not based on any encoding scheme (amino or protobuf). This avoids issues with non-determinism in the encoding scheme. + +Example: + +```proto +package cosmos.crypto.multisig; + +message PubKey { + uint32 threshold = 1; + repeated google.protobuf.Any pubkeys = 2; +} +``` + +```go +func (multisig PubKey) Address() { + // first gather all nested pub keys + var keys []address.Addressable // cryptotypes.PubKey implements Addressable + for _, _key := range multisig.Pubkeys { + keys = append(keys, key.GetCachedValue().(cryptotypes.PubKey)) + } + + // form the type from the message name (cosmos.crypto.multisig.PubKey) and the threshold joined together + prefix := fmt.Sprintf("%s/%d", proto.MessageName(multisig), multisig.Threshold) + + // use the Composed function defined above + return address.NewComposed(prefix, keys) +} +``` + +#### Module Account Addresses + +NOTE: this section is not finalize and it's in active discussion. + +In Basic Address section we defined a module account address as: + +``` +address.Hash("module", moduleName) +``` + +We use `"module"` as a schema type for all module derived addresses. Module accounts can have sub accounts. The derivation process has a defined order: module name, submodule key, subsubmodule key. +Module account addresses are heavily used in the SDK so it makes sense to optimize the derivation process: instead of using of using `LengthPrefix` for the module name, we use a null byte (`'\x00'`) as a separator. This works, because null byte is not a part of a valid module name. + +``` +func Module(moduleName string, key []byte) []byte{ + return Hash("module", []byte(moduleName) + 0 + key) +} +``` + +**Example** A lending BTC pool address would be: +``` +btcPool := address.Module("lending", btc.Addrress()}) +``` + +If we want to create an address for a module account depending on more than one key, we can concatenate them: +``` +btcAtomAMM := address.Module("amm", btc.Addrress() + atom.Address()}) +``` + +We can continue the derivation process and can create an address for a submodule account. + +``` +func Submodule(address []byte, derivationKey []byte) { + return Hash("module", address + derivationKey) +} +``` + +NOTE: if `address` is not a hash based address (with `LEN` length) then we should use `LengthPrefix`. An alternative would be to use one `Module` function, which takes a slice of keys and mapped with `LengthPrefix`. For final version we need to validate what's the most common use. + + +**Example** For a cosmwasm smart-contract address we could use the following construction: +``` +smartContractAddr := Submodule(Module("cosmwasm", smartContractsNamespace), smartContractKey) +``` + + + +### Schema Types + +A `typ` parameter used in `Hash` function SHOULD be unique for each account type. +Since all SDK account types are serialized in the state, we propose to use the protobuf message name string. + +Example: all public key types have a unique protobuf message type similar to: ```proto package cosmos.crypto.sr25519; @@ -100,69 +240,89 @@ message PubKey { bytes key = 1; } ``` - + All protobuf messages have unique fully qualified names, in this example `cosmos.crypto.sr25519.PubKey`. These names are derived directly from .proto files in a standardized way and used -in other places such as the type URL in `Any`s. Since there is an easy and obvious -way to get this name for every protobuf type, we can use this message name as the -key type `prefix` when creating addresses. For all basic public keys, `contents` -should just be the raw unencoded public key bytes. +in other places such as the type URL in `Any`s. We can easily obtain the name using +`proto.MessageName(msg)`. -Thus the canonical address for new public key types would be `AddressHash(proto.MessageName(pk), pk.Bytes)`. -### Multisig Addresses - -For new multisig public keys, we define a custom address format not based on any encoding scheme -(amino or protobuf). This avoids issues with non-determinism in the encoding scheme. It also -ensures that multisig public keys which differ simply in the ordering of keys have the same -address by sorting child public keys first. - -First we define a proto message for multisig public keys: -```proto -package cosmos.crypto.multisig; - -message PubKey { - uint32 threshold = 1; - repeated google.protobuf.Any public_keys = 2; -} -``` - -We define the following `Address()` function for this public key: - -``` -func (multisig PubKey) Address() { - // first gather all the addresses of each nested public key - var addresses [][]byte - for key := range multisig.Keys { - addresses = append(joinedAddresses, key.Address()) - } - - // then sort them in ascending order - addresses = Sort(addresses) - - // then concatenate them together - var joinedAddresses []byte - for addr := range addresses { - joinedAddresses := append(joinedAddresses, addr...) - } - - // form the string prefix from the message name (cosmos.crypto.multisig.PubKey) and the threshold joined together - prefix := fmt.Sprintf("%s/%d", proto.MessageName(multisig), multisig.Threshold) - - // use the standard AddressHash function - return AddressHash(prefix, joinedAddresses) -} -``` ## Consequences +### Backwards Compatibility + +This ADR is compatible with what was committed and directly supported in the SDK repository. + ### Positive -- a simple algorithm for generating addresses for new public keys and module accounts + +- a simple algorithm for generating addresses for new public keys, complex accounts and modules +- the algorithm generalizes _native composed keys_ +- increased security and collision resistance of addresses +- the approach is extensible for future use-cases - one can use other address types, as long as they don't conflict with the address length specified here (20 or 32 bytes). +- support new account types. ### Negative + - addresses do not communicate key type, a prefixed approach would have done this +- addresses are 60% longer and will consume more storage space +- requires a refactor of KVStore store keys to handle variable length addresses ### Neutral + - protobuf message names are used as key type prefixes -## References + +## Further Discussions + +Some accounts can have a fixed name or may be constructed in other way (eg: modules). We were discussing an idea of an account with a predefined name (eg: `me.regen`), which could be used by institutions. +Without going into details, these kinds of addresses are compatible with the hash based addresses described here as long as they don't have the same length. +More specifically, any special account address must not have a length equal to 20 or 32 bytes. + + +## Appendix: Consulting session + +End of Dec 2020 we had a session with [Alan Szepieniec](https://scholar.google.be/citations?user=4LyZn8oAAAAJ&hl=en) to consult the approach presented above. + +Alan general observations: ++ we don’t need 2-preimage resistance ++ we need 32bytes address space for collision resistance ++ when an attacker can control an input for object with an address then we have a problem with birthday attack ++ there is an issue with smart-contracts for hashing ++ sha2 mining can be use to breaking address pre-image + +Hashing algorithm ++ any attack breaking blake3 will break blake2 ++ Alan is pretty confident about the current security analysis of the blake hash algorithm. It was a finalist, and the author is well known in security analysis. + + +Algorithm: ++ Alan recommends to hash the prefix: `address(pub_key) = hash(hash(key_type) + pub_key)[:32]`, main benefits: + + we are free to user arbitrary long prefix names + + we still don’t risk collisions + + switch tables ++ discussion about penalization -> about adding prefix post hash ++ Aaron asked about post hash prefixes (`address(pub_key) = key_type + hash(pub_key)`) and differences. Alan noted that this approach has longer address space and it’s stronger. + +Algorithm for complex / composed keys: ++ merging tree like addresses with same algorithm are fine + +Module addresses: Should module addresses have different size to differentiate it? ++ we will need to set a pre-image prefix for module addresse to keept them in 32-byte space: `hash(hash('module') + module_key)` ++ Aaron observation: we already need to deal with variable length (to not break secp256k1 keys). + +Discssion about arithmetic hash function for ZKP ++ Posseidon / Rescue ++ Problem: much bigger risk because we don’t know much techniques and history of crypto-analysis of arithmetic constructions. It’s still a new ground and area of active research. + +Post quantum signature size ++ Alan suggestion: Falcon: speed / size ration - very good. ++ Aaron - should we think about it? + Alan: based on early extrapolation this thing will get able to break EC cryptography in 2050 . But that’s a lot of uncertainty. But there is magic happening with recurions / linking / simulation and that can speedup the progress. + +Other ideas ++ Let’s say we use same key and two different address algorithms for 2 different use cases. Is it still safe to use it? Alan: if we want to hide the public key (which is not our use case), then it’s less secure but there are fixes. + + +### References ++ [Notes](https://hackmd.io/_NGWI4xZSbKzj1BkCqyZMw) From 2e04f2778f2aa2445f4a917ed4a6535b7ce6e3fb Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 4 Feb 2021 09:54:01 +0000 Subject: [PATCH 36/40] snapshots: document use of ioutil.TempDir() (#8508) Document with inline comments the changes introduced in https://github.com/cosmos/cosmos-sdk/pull/8475. Run make format. --- server/grpc/grpc_web.go | 3 ++- snapshots/helpers_test.go | 3 +++ snapshots/store_test.go | 3 +++ x/authz/client/cli/cli_test.go | 3 ++- x/authz/keeper/keeper_test.go | 5 ++--- x/feegrant/ante/fee_test.go | 7 ++++--- x/feegrant/client/cli/cli_test.go | 7 ++++--- x/feegrant/client/cli/query.go | 3 ++- x/feegrant/client/rest/grpc_query_test.go | 3 ++- x/feegrant/genesis_test.go | 5 +++-- x/feegrant/simulation/decoder_test.go | 3 ++- x/feegrant/simulation/genesis_test.go | 3 ++- x/feegrant/types/basic_fee_test.go | 5 +++-- x/feegrant/types/expiration_test.go | 3 ++- x/feegrant/types/grant.go | 3 ++- x/feegrant/types/grant_test.go | 5 +++-- x/feegrant/types/msgs.go | 3 ++- x/feegrant/types/periodic_fee_test.go | 5 +++-- 18 files changed, 46 insertions(+), 26 deletions(-) diff --git a/server/grpc/grpc_web.go b/server/grpc/grpc_web.go index 30c71808e4..67dc4364a8 100644 --- a/server/grpc/grpc_web.go +++ b/server/grpc/grpc_web.go @@ -3,9 +3,10 @@ package grpc import ( "net/http" - "github.com/cosmos/cosmos-sdk/server/config" "github.com/improbable-eng/grpc-web/go/grpcweb" "google.golang.org/grpc" + + "github.com/cosmos/cosmos-sdk/server/config" ) // StartGRPCWeb starts a gRPC-Web server on the given address. diff --git a/snapshots/helpers_test.go b/snapshots/helpers_test.go index 751ac212d3..7056679191 100644 --- a/snapshots/helpers_test.go +++ b/snapshots/helpers_test.go @@ -101,6 +101,9 @@ func (m *mockSnapshotter) Snapshot(height uint64, format uint32) (<-chan io.Read // setupBusyManager creates a manager with an empty store that is busy creating a snapshot at height 1. // The snapshot will complete when the returned closer is called. func setupBusyManager(t *testing.T) *snapshots.Manager { + // ioutil.TempDir() is used instead of testing.T.TempDir() + // see https://github.com/cosmos/cosmos-sdk/pull/8475 for + // this change's rationale. tempdir, err := ioutil.TempDir("", "") require.NoError(t, err) t.Cleanup(func() { _ = os.RemoveAll(tempdir) }) diff --git a/snapshots/store_test.go b/snapshots/store_test.go index 325fd3410b..333031bc44 100644 --- a/snapshots/store_test.go +++ b/snapshots/store_test.go @@ -20,6 +20,9 @@ import ( ) func setupStore(t *testing.T) *snapshots.Store { + // ioutil.TempDir() is used instead of testing.T.TempDir() + // see https://github.com/cosmos/cosmos-sdk/pull/8475 for + // this change's rationale. tempdir, err := ioutil.TempDir("", "") require.NoError(t, err) t.Cleanup(func() { _ = os.RemoveAll(tempdir) }) diff --git a/x/authz/client/cli/cli_test.go b/x/authz/client/cli/cli_test.go index fb6fb1a177..96f5da08bb 100644 --- a/x/authz/client/cli/cli_test.go +++ b/x/authz/client/cli/cli_test.go @@ -12,9 +12,10 @@ import ( "github.com/stretchr/testify/suite" + tmcli "github.com/tendermint/tendermint/libs/cli" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" - tmcli "github.com/tendermint/tendermint/libs/cli" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/testutil" diff --git a/x/authz/keeper/keeper_test.go b/x/authz/keeper/keeper_test.go index 5a544a04af..43dbc3b94b 100644 --- a/x/authz/keeper/keeper_test.go +++ b/x/authz/keeper/keeper_test.go @@ -4,17 +4,16 @@ import ( "testing" "time" - "github.com/cosmos/cosmos-sdk/baseapp" proto "github.com/gogo/protobuf/proto" - + "github.com/stretchr/testify/suite" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtime "github.com/tendermint/tendermint/types/time" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/authz/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/stretchr/testify/suite" ) type TestSuite struct { diff --git a/x/feegrant/ante/fee_test.go b/x/feegrant/ante/fee_test.go index 293f448d73..fe7bc4208a 100644 --- a/x/feegrant/ante/fee_test.go +++ b/x/feegrant/ante/fee_test.go @@ -5,13 +5,14 @@ import ( "testing" "time" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/stretchr/testify/suite" "github.com/tendermint/tendermint/crypto" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/simapp/helpers" "github.com/cosmos/cosmos-sdk/testutil/testdata" diff --git a/x/feegrant/client/cli/cli_test.go b/x/feegrant/client/cli/cli_test.go index 224e7282a8..df4ac286f7 100644 --- a/x/feegrant/client/cli/cli_test.go +++ b/x/feegrant/client/cli/cli_test.go @@ -6,6 +6,10 @@ import ( "fmt" "testing" + "github.com/gogo/protobuf/proto" + "github.com/stretchr/testify/suite" + tmcli "github.com/tendermint/tendermint/libs/cli" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -16,9 +20,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/feegrant/types" govtestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - "github.com/gogo/protobuf/proto" - "github.com/stretchr/testify/suite" - tmcli "github.com/tendermint/tendermint/libs/cli" ) type IntegrationTestSuite struct { diff --git a/x/feegrant/client/cli/query.go b/x/feegrant/client/cli/query.go index c3a488ab55..5fd10cd1be 100644 --- a/x/feegrant/client/cli/query.go +++ b/x/feegrant/client/cli/query.go @@ -4,12 +4,13 @@ import ( "fmt" "strings" + "github.com/spf13/cobra" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/spf13/cobra" ) // GetQueryCmd returns the cli query commands for this module diff --git a/x/feegrant/client/rest/grpc_query_test.go b/x/feegrant/client/rest/grpc_query_test.go index 10d77a1e4c..7b665ee915 100644 --- a/x/feegrant/client/rest/grpc_query_test.go +++ b/x/feegrant/client/rest/grpc_query_test.go @@ -4,6 +4,8 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/suite" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -14,7 +16,6 @@ import ( banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" "github.com/cosmos/cosmos-sdk/x/feegrant/client/cli" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/stretchr/testify/suite" ) type IntegrationTestSuite struct { diff --git a/x/feegrant/genesis_test.go b/x/feegrant/genesis_test.go index d086daac07..3ea58441a8 100644 --- a/x/feegrant/genesis_test.go +++ b/x/feegrant/genesis_test.go @@ -3,14 +3,15 @@ package feegrant_test import ( "testing" + "github.com/stretchr/testify/suite" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" feegrant "github.com/cosmos/cosmos-sdk/x/feegrant" "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/stretchr/testify/suite" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) type GenesisTestSuite struct { diff --git a/x/feegrant/simulation/decoder_test.go b/x/feegrant/simulation/decoder_test.go index 0087e5eba1..8871118456 100644 --- a/x/feegrant/simulation/decoder_test.go +++ b/x/feegrant/simulation/decoder_test.go @@ -4,13 +4,14 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/kv" "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/stretchr/testify/require" ) var ( diff --git a/x/feegrant/simulation/genesis_test.go b/x/feegrant/simulation/genesis_test.go index 4f3ae74b56..3d00ba3ece 100644 --- a/x/feegrant/simulation/genesis_test.go +++ b/x/feegrant/simulation/genesis_test.go @@ -5,13 +5,14 @@ import ( "math/rand" "testing" + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types/module" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/feegrant/simulation" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/stretchr/testify/require" ) func TestRandomizedGenState(t *testing.T) { diff --git a/x/feegrant/types/basic_fee_test.go b/x/feegrant/types/basic_fee_test.go index a5669e99ad..dd3f09590f 100644 --- a/x/feegrant/types/basic_fee_test.go +++ b/x/feegrant/types/basic_fee_test.go @@ -4,10 +4,11 @@ import ( "testing" "time" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/feegrant/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" ) func TestBasicFeeValidAllow(t *testing.T) { diff --git a/x/feegrant/types/expiration_test.go b/x/feegrant/types/expiration_test.go index 60b1753bcb..5f390c328a 100644 --- a/x/feegrant/types/expiration_test.go +++ b/x/feegrant/types/expiration_test.go @@ -4,9 +4,10 @@ import ( "testing" "time" - "github.com/cosmos/cosmos-sdk/x/feegrant/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/feegrant/types" ) func TestExpiresAt(t *testing.T) { diff --git a/x/feegrant/types/grant.go b/x/feegrant/types/grant.go index ca2c93d9ef..97a18de529 100644 --- a/x/feegrant/types/grant.go +++ b/x/feegrant/types/grant.go @@ -3,10 +3,11 @@ package types import ( "time" + proto "github.com/gogo/protobuf/proto" + "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - proto "github.com/gogo/protobuf/proto" ) var ( diff --git a/x/feegrant/types/grant_test.go b/x/feegrant/types/grant_test.go index a4819b102c..8b29d47ee0 100644 --- a/x/feegrant/types/grant_test.go +++ b/x/feegrant/types/grant_test.go @@ -3,11 +3,12 @@ package types_test import ( "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/feegrant/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestGrant(t *testing.T) { diff --git a/x/feegrant/types/msgs.go b/x/feegrant/types/msgs.go index 5a25016f87..04f09c8f3f 100644 --- a/x/feegrant/types/msgs.go +++ b/x/feegrant/types/msgs.go @@ -1,10 +1,11 @@ package types import ( + "github.com/gogo/protobuf/proto" + "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/gogo/protobuf/proto" ) var ( diff --git a/x/feegrant/types/periodic_fee_test.go b/x/feegrant/types/periodic_fee_test.go index cc54f40808..229fd99cea 100644 --- a/x/feegrant/types/periodic_fee_test.go +++ b/x/feegrant/types/periodic_fee_test.go @@ -4,10 +4,11 @@ import ( "testing" "time" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/feegrant/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/feegrant/types" ) func TestPeriodicFeeValidAllow(t *testing.T) { From 0ddb7041a8df1c61a4972174194309f8dc459bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Victor=20Fran=C3=A7a=20Ferreira?= Date: Thu, 4 Feb 2021 06:58:27 -0300 Subject: [PATCH 37/40] fixing typo at 'os' backend session (#8477) Co-authored-by: SaReN Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- docs/run-node/keyring.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/run-node/keyring.md b/docs/run-node/keyring.md index e84a4d0718..61636f27fd 100644 --- a/docs/run-node/keyring.md +++ b/docs/run-node/keyring.md @@ -31,7 +31,7 @@ is a list of the most popular operating systems and their respective passwords m GNU/Linux distributions that use GNOME as default desktop environment typically come with [Seahorse](https://wiki.gnome.org/Apps/Seahorse). Users of KDE based distributions are commonly provided with [KDE Wallet Manager](https://userbase.kde.org/KDE_Wallet_Manager). -Whilst the former is in fact a `libsecret` convenient frontend, the former is a `kwallet` +Whilst the former is in fact a `libsecret` convenient frontend, the latter is a `kwallet` client. `os` is the default option since operating system's default credentials managers are From 0af248b95b3de060d23ffb2f3ca760fd10120abc Mon Sep 17 00:00:00 2001 From: atheeshp <59333759+atheeshp@users.noreply.github.com> Date: Thu, 4 Feb 2021 19:08:16 +0530 Subject: [PATCH 38/40] Add specs for feegrant (#8496) * add specs * address review comments * Address review changes Co-authored-by: Amaury * review changes * address review changes Co-authored-by: Marie Gauthier Co-authored-by: Amaury Co-authored-by: Marie Gauthier --- x/feegrant/spec/01_concepts.md | 70 ++++++++++++++++++++++++++++++++++ x/feegrant/spec/02_state.md | 15 ++++++++ x/feegrant/spec/03_messages.md | 17 +++++++++ x/feegrant/spec/04_events.md | 33 ++++++++++++++++ x/feegrant/spec/README.md | 32 ++++++++++++++++ 5 files changed, 167 insertions(+) create mode 100644 x/feegrant/spec/01_concepts.md create mode 100644 x/feegrant/spec/02_state.md create mode 100644 x/feegrant/spec/03_messages.md create mode 100644 x/feegrant/spec/04_events.md create mode 100644 x/feegrant/spec/README.md diff --git a/x/feegrant/spec/01_concepts.md b/x/feegrant/spec/01_concepts.md new file mode 100644 index 0000000000..92200f2d47 --- /dev/null +++ b/x/feegrant/spec/01_concepts.md @@ -0,0 +1,70 @@ + + +# Concepts + +## FeeAllowanceGrant + +`FeeAllowanceGrant` is stored in the KVStore to record a grant with full context. Every grant will contain `granter`, `grantee` and what kind of `allowance` is granted. `granter` is an account address who is giving permission to `grantee` (the beneficiary account address) to pay for some or all of `grantee`'s transaction fees. `allowance` defines what kind of fee allowance (`BasicFeeAllowance` or `PeriodicFeeAllowance`, see below) is granted to `grantee`. `allowance` accepts an interface which implements `FeeAllowanceI`, encoded as `Any` type. There can be only one existing fee grant allowed for a `grantee` and `granter`, self grants are not allowed. + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/feegrant/v1beta1/feegrant.proto#L75-L81 + +`FeeAllowanceI` looks like: + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/x/feegrant/types/fees.go#L9-L32 + +## Fee Allowance types +There are two types of fee allowances present at the moment: +- `BasicFeeAllowance` +- `PeriodicFeeAllowance` + +## BasicFeeAllowance + +`BasicFeeAllowance` is permission for `grantee` to use fee from a `granter`'s account. If any of the `spend_limit` or `expiration` reaches its limit, the grant will be removed from the state. + + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/feegrant/v1beta1/feegrant.proto#L13-L26 + +- `spend_limit` is the limit of coins that are allowed to be used from the `granter` account. If it is empty, it assumes there's no spend limit, `grantee` can use any number of available tokens from `granter` account address before the expiration. + +- `expiration` specifies an optional time when this allowance expires. If the value is left empty, there is no expiry for the grant. + +- When a grant is created with empty values for `spend_limit` and `expiration`, it is still a valid grant. It won't restrict the `grantee` to use any number of tokens from `granter` and it won't have any expiration. The only way to restrict the `grantee` is by revoking the grant. + +## PeriodicFeeAllowance + +`PeriodicFeeAllowance` is a repeating fee allowance for the mentioned period, we can mention when the grant can expire as well as when a period can reset. We can also define the maximum number of coins that can be used in a mentioned period of time. + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/feegrant/v1beta1/feegrant.proto#L28-L73 + +- `basic` is the instance of `BasicFeeAllowance` which is optional for periodic fee allowance. If empty, the grant will have no `expiration` and no `spend_limit`. + +- `period` is the specific period of time or blocks, after each period passes, `period_spend_limit` will be reset. + +- `period_spend_limit` specifies the maximum number of coins that can be spent in the period. + +- `period_can_spend` is the number of coins left to be spent before the period_reset time. + +- `period_reset` keeps track of when a next period reset should happen. + +## FeeAccount flag + +`feegrant` module introduces a `FeeAccount` flag for CLI for the sake of executing transactions with fee granter. When this flag is set, `clientCtx` will append the granter account address for transactions generated through CLI. + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/client/cmd.go#L224-L235 + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/client/tx/tx.go#L120 + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/x/auth/tx/builder.go#L268-L277 + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/tx/v1beta1/tx.proto#L160-L181 + +Example cmd: +```go +./simd tx gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --from validator-key --fee-account=cosmos1xh44hxt7spr67hqaa7nyx5gnutrz5fraw6grxn --chain-id=testnet --fees="10stake" +``` + +## DeductGrantedFeeDecorator + +`feegrant` module also adds a `DeductGrantedFeeDecorator` ante handler. Whenever a transaction is being executed with `granter` field set, then this ante handler will check whether `payer` and `granter` have proper fee allowance grant in state. If it exists the fees will be deducted from the `granter`'s account address. If the `granter` field isn't set then this ante handler works as normal fee deductor. diff --git a/x/feegrant/spec/02_state.md b/x/feegrant/spec/02_state.md new file mode 100644 index 0000000000..463ea70d06 --- /dev/null +++ b/x/feegrant/spec/02_state.md @@ -0,0 +1,15 @@ + + +# State + +## FeeAllowance + +Fee Allowances are identified by combining `Grantee` (the account address of fee allowance grantee) with the `Granter` (the account address of fee allowance granter). + +Fee allowances are stored in the state as follows: + +- FeeAllowance: `0x00 | grantee_addr_len (1 byte) | grantee_addr_bytes | granter_addr_len (1 byte) | granter_addr_bytes -> ProtocolBuffer(FeeAllowance)` + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/x/feegrant/types/feegrant.pb.go#L358-L363 diff --git a/x/feegrant/spec/03_messages.md b/x/feegrant/spec/03_messages.md new file mode 100644 index 0000000000..3ca65e25cd --- /dev/null +++ b/x/feegrant/spec/03_messages.md @@ -0,0 +1,17 @@ + + +# Messages + +## Msg/GrantFeeAllowance + +A fee allowance grant will be created with the `MsgGrantFeeAllowance` message. + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/feegrant/v1beta1/tx.proto#L22-L28 + +## Msg/RevokeFeeAllowance + +An allowed grant fee allowance can be removed with the `MsgRevokeFeeAllowance` message. + ++++ https://github.com/cosmos/cosmos-sdk/blob/d97e7907f176777ed8a464006d360bb3e1a223e4/proto/cosmos/feegrant/v1beta1/tx.proto#L33-L37 diff --git a/x/feegrant/spec/04_events.md b/x/feegrant/spec/04_events.md new file mode 100644 index 0000000000..021142d390 --- /dev/null +++ b/x/feegrant/spec/04_events.md @@ -0,0 +1,33 @@ + + +# Events + +The feegrant module emits the following events: + +# Handlers + +### MsgGrantFeeAllowance + +| Type | Attribute Key | Attribute Value | +| -------- | ------------- | ------------------ | +| message | action | set_feegrant | +| message | granter | {granterAddress} | +| message | grantee | {granteeAddress} | + +### MsgRevokeFeeAllowance + +| Type | Attribute Key | Attribute Value | +| -------- | ------------- | ------------------ | +| message | action | revoke_feegrant | +| message | granter | {granterAddress} | +| message | grantee | {granteeAddress} | + +### Exec fee allowance + +| Type | Attribute Key | Attribute Value | +| -------- | ------------- | ------------------ | +| message | action | use_feegrant | +| message | granter | {granterAddress} | +| message | grantee | {granteeAddress} | \ No newline at end of file diff --git a/x/feegrant/spec/README.md b/x/feegrant/spec/README.md new file mode 100644 index 0000000000..1abdcf464b --- /dev/null +++ b/x/feegrant/spec/README.md @@ -0,0 +1,32 @@ + + +## Abstract + +This document specifies the feegrant module. For the full ADR, please see [Fee Grant ADR-029](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/docs/architecture/adr-029-fee-grant-module.md). + +This module allows accounts to grant fee allowances and to use fees from their accounts. Grantees can execute any transaction without the need to maintain sufficient fees. + +## Contents + +1. **[Concepts](01_concepts.md)** + - [FeeAllowanceGrant](01_concepts.md#feeallowancegrant) + - [Fee Allowance types](01_concepts.md#fee-allowance-types) + - [BasicFeeAllowance](01_concepts.md#basicfeeallowance) + - [PeriodicFeeAllowance](01_concepts.md#periodicfeeallowance) + - [FeeAccount flag](01_concepts.md#feeaccount-flag) + - [DeductGrantedFeeDecorator](01_concepts.md#deductgrantedfeedecorator) +2. **[State](02_state.md)** + - [FeeAllowance](02_state.md#feeallowance) +3. **[Messages](03_messages.md)** + - [Msg/GrantFeeAllowance](03_messages.md#msggrantfeeallowance) + - [Msg/RevokeFeeAllowance](03_messages.md#msgrevokefeeallowance) +3. **[Events](04_events.md)** + - [MsgGrantFeeAllowance](04_events.md#msggrantfeeallowance) + - [MsgrevokeFeeAllowance](04_events.md#msgrevokefeeallowance) + - [Exec fee allowance](04_events.md#exec-fee-allowance) + From a3757e14a8f71d28975d270128b47209112fe8fa Mon Sep 17 00:00:00 2001 From: Ian Norden Date: Thu, 4 Feb 2021 20:09:28 -0600 Subject: [PATCH 39/40] ADR 038: State Listening (#8012) * ADR-038 state listening * updates/fixes * review fixes/adjustments * review fixes/adjustments part 2 * review updates part 3: refactor after review to coordinate store changes with block and tx messages and enable file pruning * review updates part 4: additional details and fixes; addressing recent feedback; use binary protobuf encoding for kv pairs in files * review updates part 5: formatting fixes; updated StreamingService/Hook interface * auxiliary streaming/queue service * review updates part 6: update StoreKVPair to differentiate between Set and Deletes on nil byte values; some minor adjustments * typo fix --- docs/architecture/README.md | 3 +- docs/architecture/adr-038-state-listening.md | 612 +++++++++++++++++++ 2 files changed, 614 insertions(+), 1 deletion(-) create mode 100644 docs/architecture/adr-038-state-listening.md diff --git a/docs/architecture/README.md b/docs/architecture/README.md index a979f30e41..19e6d6e2db 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -73,4 +73,5 @@ Read about the [PROCESS](./PROCESS.md). - [ADR 028: Public Key Addresses](./adr-028-public-key-addresses.md) - [ADR 032: Typed Events](./adr-032-typed-events.md) - [ADR 035: Rosetta API Support](./adr-035-rosetta-api-support.md) -- [ADR 037: Governance Split Votes](./adr-037-gov-split-vote.md) \ No newline at end of file +- [ADR 037: Governance Split Votes](./adr-037-gov-split-vote.md) +- [ADR 038: State Listening](./adr-038-state-listening.md) \ No newline at end of file diff --git a/docs/architecture/adr-038-state-listening.md b/docs/architecture/adr-038-state-listening.md new file mode 100644 index 0000000000..cd78e72e2c --- /dev/null +++ b/docs/architecture/adr-038-state-listening.md @@ -0,0 +1,612 @@ +# ADR 038: KVStore state listening + +## Changelog + +- 11/23/2020: Initial draft + +## Status + +Proposed + +## Abstract + +This ADR defines a set of changes to enable listening to state changes of individual KVStores and exposing these data to consumers. + +## Context + +Currently, KVStore data can be remotely accessed through [Queries](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/messages-and-queries.md#queries) +which proceed either through Tendermint and the ABCI, or through the gRPC server. +In addition to these request/response queries, it would be beneficial to have a means of listening to state changes as they occur in real time. + +## Decision + +We will modify the `MultiStore` interface and its concrete (`rootmulti` and `cachemulti`) implementations and introduce a new `listenkv.Store` to allow listening to state changes in underlying KVStores. +We will also introduce the tooling for writing these state changes out to files and configuring this service. + +### Listening interface + +In a new file, `store/types/listening.go`, we will create a `WriteListener` interface for streaming out state changes from a KVStore. + +```go +// WriteListener interface for streaming data out from a listenkv.Store +type WriteListener interface { + // if value is nil then it was deleted + // storeKey indicates the source KVStore, to facilitate using the the same WriteListener across separate KVStores + // set bool indicates if it was a set; true: set, false: delete + OnWrite(storeKey types.StoreKey, set bool, key []byte, value []byte) +} +``` + +### Listener type + +We will create a concrete implementation of the `WriteListener` interface in `store/types/listening.go`, that writes out protobuf +encoded KV pairs to an underlying `io.Writer`. + +This will include defining a simple protobuf type for the KV pairs. In addition to the key and value fields this message +will include the StoreKey for the originating KVStore so that we can write out from separate KVStores to the same stream/file +and determine the source of each KV pair. + +```protobuf +message StoreKVPair { + optional string store_key = 1; // the store key for the KVStore this pair originates from + required bool set = 2; // true indicates a set operation, false indicates a delete operation + required bytes key = 3; + required bytes value = 4; +} +``` + +```go +// StoreKVPairWriteListener is used to configure listening to a KVStore by writing out length-prefixed +// protobuf encoded StoreKVPairs to an underlying io.Writer +type StoreKVPairWriteListener struct { + writer io.Writer + marshaller codec.BinaryMarshaler +} + +// NewStoreKVPairWriteListener wraps creates a StoreKVPairWriteListener with a provdied io.Writer and codec.BinaryMarshaler +func NewStoreKVPairWriteListener(w io.Writer, m codec.BinaryMarshaler) *StoreKVPairWriteListener { + return &StoreKVPairWriteListener{ + writer: w, + marshaller: m, + } +} + +// OnWrite satisfies the WriteListener interface by writing length-prefixed protobuf encoded StoreKVPairs +func (wl *StoreKVPairWriteListener) OnWrite(storeKey types.StoreKey, set bool, key []byte, value []byte) { + kvPair := new(types.StoreKVPair) + kvPair.StoreKey = storeKey.Name() + kvPair.Set = set + kvPair.Key = key + kvPair.Value = value + if by, err := wl.marshaller.MarshalBinaryLengthPrefixed(kvPair); err == nil { + wl.writer.Write(by) + } +} +``` + +### ListenKVStore + +We will create a new `Store` type `listenkv.Store` that the `MultiStore` wraps around a `KVStore` to enable state listening. +We can configure the `Store` with a set of `WriteListener`s which stream the output to specific destinations. + +```go +// Store implements the KVStore interface with listening enabled. +// Operations are traced on each core KVStore call and written to any of the +// underlying listeners with the proper key and operation permissions +type Store struct { + parent types.KVStore + listeners []types.WriteListener + parentStoreKey types.StoreKey +} + +// NewStore returns a reference to a new traceKVStore given a parent +// KVStore implementation and a buffered writer. +func NewStore(parent types.KVStore, psk types.StoreKey, listeners []types.WriteListener) *Store { + return &Store{parent: parent, listeners: listeners, parentStoreKey: psk} +} + +// Set implements the KVStore interface. It traces a write operation and +// delegates the Set call to the parent KVStore. +func (s *Store) Set(key []byte, value []byte) { + types.AssertValidKey(key) + s.parent.Set(key, value) + s.onWrite(true, key, value) +} + +// Delete implements the KVStore interface. It traces a write operation and +// delegates the Delete call to the parent KVStore. +func (s *Store) Delete(key []byte) { + s.parent.Delete(key) + s.onWrite(false, key, nil) +} + +// onWrite writes a KVStore operation to all of the WriteListeners +func (s *Store) onWrite(set bool, key, value []byte) { + for _, l := range s.listeners { + l.OnWrite(s.parentStoreKey, set, key, value) + } +} +``` + +### MultiStore interface updates + +We will update the `MultiStore` interface to allow us to wrap a set of listeners around a specific `KVStore`. +Additionally, we will update the `CacheWrap` and `CacheWrapper` interfaces to enable listening in the caching layer. + +```go +type MultiStore interface { + ... + + // ListeningEnabled returns if listening is enabled for the KVStore belonging the provided StoreKey + ListeningEnabled(key StoreKey) bool + + // SetListeners sets the WriteListeners for the KVStore belonging to the provided StoreKey + // It appends the listeners to a current set, if one already exists + SetListeners(key StoreKey, listeners []WriteListener) +} +``` + +```go +type CacheWrap interface { + ... + + // CacheWrapWithListeners recursively wraps again with listening enabled + CacheWrapWithListeners(storeKey types.StoreKey, listeners []WriteListener) CacheWrap +} + +type CacheWrapper interface { + ... + + // CacheWrapWithListeners recursively wraps again with listening enabled + CacheWrapWithListeners(storeKey types.StoreKey, listeners []WriteListener) CacheWrap +} +``` + +### MultiStore implementation updates + +We will modify all of the `Store` and `MultiStore` implementations to satisfy these new interfaces, and adjust the `rootmulti` `GetKVStore` method +to wrap the returned `KVStore` with a `listenkv.Store` if listening is turned on for that `Store`. + +```go +func (rs *Store) GetKVStore(key types.StoreKey) types.KVStore { + store := rs.stores[key].(types.KVStore) + + if rs.TracingEnabled() { + store = tracekv.NewStore(store, rs.traceWriter, rs.traceContext) + } + if rs.ListeningEnabled(key) { + store = listenkv.NewStore(key, store, rs.listeners[key]) + } + + return store +} +``` + +We will also adjust the `cachemulti` constructor methods and the `rootmulti` `CacheMultiStore` method to forward the listeners +to and enable listening in the cache layer. + +```go +func (rs *Store) CacheMultiStore() types.CacheMultiStore { + stores := make(map[types.StoreKey]types.CacheWrapper) + for k, v := range rs.stores { + stores[k] = v + } + return cachemulti.NewStore(rs.db, stores, rs.keysByName, rs.traceWriter, rs.traceContext, rs.listeners) +} +``` + +### Exposing the data + +We will introduce a new `StreamingService` interface for exposing `WriteListener` data streams to external consumers. + +```go +// Hook interface used to hook into the ABCI message processing of the BaseApp +type Hook interface { + ListenBeginBlock(ctx sdk.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) // update the streaming service with the latest BeginBlock messages + ListenEndBlock(ctx sdk.Context, req abci.RequestEndBlock, res abci.ResponseEndBlock) // update the steaming service with the latest EndBlock messages + ListenDeliverTx(ctx sdk.Context, req abci.RequestDeliverTx, res abci.ResponseDeliverTx) // update the steaming service with the latest DeliverTx messages +} + +// StreamingService interface for registering WriteListeners with the BaseApp and updating the service with the ABCI messages using the hooks +type StreamingService interface { + Stream(wg *sync.WaitGroup, quitChan <-chan struct{}) // streaming service loop, awaits kv pairs and writes them to some destination stream or file + Listeners() map[sdk.StoreKey][]storeTypes.WriteListener // returns the streaming service's listeners for the BaseApp to register + Hook +} +``` + +#### Writing state changes to files + +We will introduce an implementation of `StreamingService` which writes state changes out to files as length-prefixed protobuf encoded `StoreKVPair`s. +This service uses the same `StoreKVPairWriteListener` for every KVStore, writing all the KV pairs from every KVStore +out to the same files, relying on the `StoreKey` field in the `StoreKVPair` protobuf message to later distinguish the source for each pair. + +The file naming schema is as such: +* After every `BeginBlock` request a new file is created with the name `block-{N}-begin`, where N is the block number. All +subsequent state changes are written out to this file until the first `DeliverTx` request is received. At the head of these files, + the length-prefixed protobuf encoded `BeginBlock` request is written, and the response is written at the tail. +* After every `DeliverTx` request a new file is created with the name `block-{N}-tx-{M}` where N is the block number and M +is the tx number in the block (i.e. 0, 1, 2...). All subsequent state changes are written out to this file until the next +`DeliverTx` request is received or an `EndBlock` request is received. At the head of these files, the length-prefixed protobuf + encoded `DeliverTx` request is written, and the response is written at the tail. +* After every `EndBlock` request a new file is created with the name `block-{N}-end`, where N is the block number. All +subsequent state changes are written out to this file until the next `BeginBlock` request is received. At the head of these files, + the length-prefixed protobuf encoded `EndBlock` request is written, and the response is written at the tail. + +```go +// FileStreamingService is a concrete implementation of StreamingService that writes state changes out to a file +type FileStreamingService struct { + listeners map[sdk.StoreKey][]storeTypes.WriteListener // the listeners that will be initialized with BaseApp + srcChan <-chan []byte // the channel that all of the WriteListeners write their data out to + filePrefix string // optional prefix for each of the generated files + writeDir string // directory to write files into + dstFile *os.File // the current write output file + marshaller codec.BinaryMarshaler // marshaller used for re-marshalling the ABCI messages to write them out to the destination files + stateCache [][]byte // cache the protobuf binary encoded StoreKVPairs in the order they are received +} +``` + +This streaming service uses a single instance of a simple intermediate `io.Writer` as the underlying `io.Writer` for its single `StoreKVPairWriteListener`, +It collects KV pairs from every KVStore synchronously off of the same channel, caching them in the order they are received, and then writing +them out to a file generated in response to an ABCI message hook. Files are named as outlined above, with optional prefixes to avoid potential naming collisions +across separate instances. + +```go +// intermediateWriter is used so that we do not need to update the underlying io.Writer inside the StoreKVPairWriteListener +// everytime we begin writing to a new file +type intermediateWriter struct { + outChan chan <-[]byte +} + +// NewIntermediateWriter create an instance of an intermediateWriter that sends to the provided channel +func NewIntermediateWriter(outChan chan <-[]byte) *intermediateWriter { + return &intermediateWriter{ + outChan: outChan, + } +} + +// Write satisfies io.Writer +func (iw *intermediateWriter) Write(b []byte) (int, error) { + iw.outChan <- b + return len(b), nil +} + +// NewFileStreamingService creates a new FileStreamingService for the provided writeDir, (optional) filePrefix, and storeKeys +func NewFileStreamingService(writeDir, filePrefix string, storeKeys []sdk.StoreKey, m codec.BinaryMarshaler) (*FileStreamingService, error) { + listenChan := make(chan []byte, 0) + iw := NewIntermediateWriter(listenChan) + listener := listen.NewStoreKVPairWriteListener(iw, m) + listners := make(map[sdk.StoreKey][]storeTypes.WriteListener, len(storeKeys)) + // in this case, we are using the same listener for each Store + for _, key := range storeKeys { + listeners[key] = listener + } + // check that the writeDir exists and is writeable so that we can catch the error here at initialization if it is not + // we don't open a dstFile until we receive our first ABCI message + if err := fileutil.IsDirWriteable(writeDir); err != nil { + return nil, err + } + return &FileStreamingService{ + listeners: listeners, + srcChan: listenChan, + filePrefix: filePrefix, + writeDir: writeDir, + marshaller: m, + stateCache: make([][]byte, 0), + }, nil +} + +// Listeners returns the StreamingService's underlying WriteListeners, use for registering them with the BaseApp +func (fss *FileStreamingService) Listeners() map[sdk.StoreKey][]storeTypes.WriteListener { + return fss.listeners +} + +func (fss *FileStreamingService) ListenBeginBlock(ctx sdk.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) { + // NOTE: this could either be done synchronously or asynchronously + // create a new file with the req info according to naming schema + // write req to file + // write all state changes cached for this stage to file + // reset cache + // write res to file + // close file +} + +func (fss *FileStreamingService) ListenEndBlock(ctx sdk.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) { + // NOTE: this could either be done synchronously or asynchronously + // create a new file with the req info according to naming schema + // write req to file + // write all state changes cached for this stage to file + // reset cache + // write res to file + // close file +} + +func (fss *FileStreamingService) ListenDeliverTx(ctx sdk.Context, req abci.RequestDeliverTx, res abci.ResponseDeliverTx) { + // NOTE: this could either be done synchronously or asynchronously + // create a new file with the req info according to naming schema + // NOTE: if the tx failed, handle accordingly + // write req to file + // write all state changes cached for this stage to file + // reset cache + // write res to file + // close file +} + +// Stream spins up a goroutine select loop which awaits length-prefixed binary encoded KV pairs and caches them in the order they were received +func (fss *FileStreamingService) Stream(wg *sync.WaitGroup, quitChan <-chan struct{}) { + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + case <-quitChan: + return + case by := <-fss.srcChan: + append(fss.stateCache, by) + } + } + }() +} +``` + +Writing to a file is the simplest approach for streaming the data out to consumers. +This approach also provides the advantages of being persistent and durable, and the files can be read directly, +or an auxiliary streaming services can read from the files and serve the data over a remote interface. + +#### Auxiliary streaming service + +We will create a separate standalone process that reads and internally queues the state as it is written out to these files +and serves the data over a gRPC API. This API will allow filtering of requested data, e.g. by block number, block/tx hash, ABCI message type, +whether a DeliverTx message failed or succeeded, etc. In addition to unary RPC endpoints this service will expose `stream` RPC endpoints for realtime subscriptions. + +#### File pruning + +Without pruning the number of files can grow indefinitely, this may need to be managed by +the developer in an application or even module-specific manner (e.g. log rotation). +The file naming schema facilitates pruning by block number and/or ABCI message. +The gRPC auxiliary streaming service introduced above will include an option to remove the files as it consumes their data. + +### Configuration + +We will provide detailed documentation on how to configure a `FileStreamingService` from within an app's `AppCreator`, +using the provided `AppOptions` and TOML configuration fields. + +#### BaseApp registration + +We will add a new method to the `BaseApp` to enable the registration of `StreamingService`s: + +```go +// RegisterStreamingService is used to register a streaming service with the BaseApp +func (app *BaseApp) RegisterHooks(s StreamingService) { + // set the listeners for each StoreKey + for key, lis := range s.Listeners() { + app.cms.SetListeners(key, lis) + } + // register the streaming service hooks within the BaseApp + // BaseApp will pass BeginBlock, DeliverTx, and EndBlock requests and responses to the streaming services to update their ABCI context using these hooks + app.hooks = append(app.hooks, s) +} +``` + +We will also modify the `BeginBlock`, `EndBlock`, and `DeliverTx` methods to pass ABCI requests and responses to any streaming service hooks registered +with the `BaseApp`. + + +```go +func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeginBlock) { + + ... + + // Call the streaming service hooks with the BeginBlock messages + for _ hook := range app.hooks { + hook.ListenBeginBlock(app.deliverState.ctx, req, res) + } + + return res +} +``` + +```go +func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBlock) { + + ... + + // Call the streaming service hooks with the EndBlock messages + for _, hook := range app.hooks { + hook.ListenEndBlock(app.deliverState.ctx, req, res) + } + + return res +} +``` + +```go +func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx { + + ... + + gInfo, result, err := app.runTx(runTxModeDeliver, req.Tx) + if err != nil { + resultStr = "failed" + res := sdkerrors.ResponseDeliverTx(err, gInfo.GasWanted, gInfo.GasUsed, app.trace) + // If we throw and error, be sure to still call the streaming service's hook + for _, hook := range app.hooks { + hook.ListenDeliverTx(app.deliverState.ctx, req, res) + } + return res + } + + res := abci.ResponseDeliverTx{ + GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints? + GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints? + Log: result.Log, + Data: result.Data, + Events: sdk.MarkEventsToIndex(result.Events, app.indexEvents), + } + + // Call the streaming service hooks with the DeliverTx messages + for _, hook := range app.hook { + hook.ListenDeliverTx(app.deliverState.ctx, req, res) + } + + return res +} +``` + +#### TOML Configuration + +We will provide standard TOML configuration options for configuring a `FileStreamingService` for specific `Store`s. +Note: the actual namespace is TBD. + +```toml +[store] + streamers = [ # if len(streamers) > 0 we are streaming + "file", + ] + +[streamers] + [streamers.file] + keys = ["list", "of", "store", "keys", "we", "want", "to", "expose", "for", "this", "streaming", "service"] + writeDir = "path to the write directory" + prefix = "optional prefix to prepend to the generated file names" +``` + +We will also provide a mapping of the TOML `store.streamers` "file" configuration option to a helper functions for constructing the specified +streaming service. In the future, as other streaming services are added, their constructors will be added here as well. + +```go +// StreamingServiceConstructor is used to construct a streaming service +type StreamingServiceConstructor func(opts servertypes.AppOptions, keys []sdk.StoreKey) (StreamingService, error) + +// StreamingServiceType enum for specifying the type of StreamingService +type StreamingServiceType int + +const ( + Unknown StreamingServiceType = iota + File + // add more in the future +) + +// NewStreamingServiceType returns the StreamingServiceType corresponding to the provided name +func NewStreamingServiceType(name string) StreamingServiceType { + switch strings.ToLower(name) { + case "file", "f": + return File + default: + return Unknown + } +} + +// String returns the string name of a StreamingServiceType +func (sst StreamingServiceType) String() string { + switch sst { + case File: + return "file" + default: + return "" + } +} + +// StreamingServiceConstructorLookupTable is a mapping of StreamingServiceTypes to StreamingServiceConstructors +var StreamingServiceConstructorLookupTable = map[StreamingServiceType]StreamingServiceConstructor{ + File: FileStreamingConstructor, +} + +// NewStreamingServiceConstructor returns the StreamingServiceConstructor corresponding to the provided name +func NewStreamingServiceConstructor(name string) (StreamingServiceConstructor, error) { + ssType := NewStreamingServiceType(name) + if ssType == Unknown { + return nil, fmt.Errorf("unrecognized streaming service name %s", name) + } + if constructor, ok := StreamingServiceConstructorLookupTable[ssType]; ok { + return constructor, nil + } + return nil, fmt.Errorf("streaming service constructor of type %s not found", ssType.String()) +} + +// FileStreamingConstructor is the StreamingServiceConstructor function for creating a FileStreamingService +func FileStreamingConstructor(opts servertypes.AppOptions, keys []sdk.StoreKey) (StreamingService, error) { + filePrefix := cast.ToString(opts.Get("streamers.file.prefix")) + fileDir := cast.ToString(opts.Get("streamers.file.writeDir")) + return streaming.NewFileStreamingService(fileDir, filePrefix, keys), nil +} +``` + +#### Example configuration + +As a demonstration, we will implement the state watching features as part of SimApp. +For example, the below is a very rudimentary integration of the state listening features into the SimApp `AppCreator` function: + + +```go +func NewSimApp( + logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, skipUpgradeHeights map[int64]bool, + homePath string, invCheckPeriod uint, encodingConfig simappparams.EncodingConfig, + appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), +) *SimApp { + + ... + + keys := sdk.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, + minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, + govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, + evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, + ) + + // configure state listening capabilities using AppOptions + listeners := cast.ToStringSlice(appOpts.Get("store.streamers")) + for _, listenerName := range listeners { + // get the store keys allowed to be exposed for this streaming service/state listeners + exposeKeyStrs := cast.ToStringSlice(appOpts.Get(fmt.Sprintf("streamers.%s.keys", listenerName)) + exposeStoreKeys = make([]storeTypes.StoreKey, 0, len(exposeKeyStrs)) + for _, keyStr := range exposeKeyStrs { + if storeKey, ok := keys[keyStr]; ok { + exposeStoreKeys = append(exposeStoreKeys, storeKey) + } + } + // get the constructor for this listener name + constructor, err := baseapp.NewStreamingServiceConstructor(listenerName) + if err != nil { + tmos.Exit(err.Error()) // or continue? + } + // generate the streaming service using the constructor, appOptions, and the StoreKeys we want to expose + streamingService, err := constructor(appOpts, exposeStoreKeys) + if err != nil { + tmos.Exit(err.Error()) + } + // register the streaming service with the BaseApp + bApp.RegisterStreamingService(streamingService) + // waitgroup and quit channel for optional shutdown coordination of the streaming service + wg := new(sync.WaitGroup) + quitChan := new(chan struct{})) + // kick off the background streaming service loop + streamingService.Stream(wg, quitChan) // maybe this should be done from inside BaseApp instead? + } + + ... + + return app +} +``` + +## Consequences + +These changes will provide a means of subscribing to KVStore state changes in real time. + +### Backwards Compatibility + +- This ADR changes the `MultiStore`, `CacheWrap`, and `CacheWrapper` interfaces, implementations supporting the previous version of these interfaces will not support the new ones + +### Positive + +- Ability to listen to KVStore state changes in real time and expose these events to external consumers + +### Negative + +- Changes `MultiStore`, `CacheWrap`, and `CacheWrapper` interfaces + +### Neutral + +- Introduces additional- but optional- complexity to configuring and running a cosmos application +- If an application developer opts to use these features to expose data, they need to be aware of the ramifications/risks of that data exposure as it pertains to the specifics of their application From c0c0665d4e9c76f6fc613a5496bbc6c1b4c47c33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Feb 2021 13:45:56 +0000 Subject: [PATCH 40/40] build(deps): bump actions/cache from v2.1.3 to v2.1.4 (#8521) Bumps [actions/cache](https://github.com/actions/cache) from v2.1.3 to v2.1.4. - [Release notes](https://github.com/actions/cache/releases) - [Commits](https://github.com/actions/cache/compare/v2.1.3...26968a09c0ea4f3e233fdddbafd1166051a095f6) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release-sims.yml | 4 ++-- .github/workflows/sims.yml | 10 +++++----- .github/workflows/test.yml | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release-sims.yml b/.github/workflows/release-sims.yml index 68ca310511..82e68ff41b 100644 --- a/.github/workflows/release-sims.yml +++ b/.github/workflows/release-sims.yml @@ -30,7 +30,7 @@ jobs: - name: install runsim run: | export GO111MODULE="on" && go get github.com/cosmos/tools/cmd/runsim@v1.0.0 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary @@ -40,7 +40,7 @@ jobs: needs: [build, install-runsim] steps: - uses: actions/checkout@v2 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary diff --git a/.github/workflows/sims.yml b/.github/workflows/sims.yml index d50ddb63a2..a84570b807 100644 --- a/.github/workflows/sims.yml +++ b/.github/workflows/sims.yml @@ -39,7 +39,7 @@ jobs: run: go version - name: Install runsim run: export GO111MODULE="on" && go get github.com/cosmos/tools/cmd/runsim@v1.0.0 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary @@ -60,7 +60,7 @@ jobs: **/**.go go.mod go.sum - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary @@ -88,7 +88,7 @@ jobs: go.sum SET_ENV_NAME_INSERTIONS: 1 SET_ENV_NAME_LINES: 1 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary @@ -116,7 +116,7 @@ jobs: go.sum SET_ENV_NAME_INSERTIONS: 1 SET_ENV_NAME_LINES: 1 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary @@ -144,7 +144,7 @@ jobs: go.sum SET_ENV_NAME_INSERTIONS: 1 SET_ENV_NAME_LINES: 1 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-runsim-binary diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dd09041862..b499f28228 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: - name: install tparse run: | export GO111MODULE="on" && go get github.com/mfridman/tparse@v0.8.3 - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-tparse-binary @@ -254,7 +254,7 @@ jobs: with: name: "${{ github.sha }}-03-race-output" if: env.GIT_DIFF - - uses: actions/cache@v2.1.3 + - uses: actions/cache@v2.1.4 with: path: ~/go/bin key: ${{ runner.os }}-go-tparse-binary