chore: collapse module spec and readme (#13143)

* updates

* add auth and separate vesting

* authz

* capability

* crisis

* epoching

* nft

* mint

* params

* upgrade

* fix website build

* finish other modules

* fix `pre.sh` and update modules title

* add docs

* display vesting in docs

* add page splitting for missing modules

* updates

* improve `pre.sh`

Co-authored-by: marbar3778 <marbar3778@yahoo.com>
Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
Aleksandr Bezobchuk 2022-09-05 08:26:40 -04:00 committed by GitHub
parent ca86ec5e93
commit a0682b14f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
137 changed files with 12526 additions and 12741 deletions

View File

@ -4,11 +4,30 @@ mkdir -p modules
for D in ../x/*; do
if [ -d "${D}" ]; then
rm -rf "modules/$(echo $D | awk -F/ '{print $NF}')"
mkdir -p "modules/$(echo $D | awk -F/ '{print $NF}')" && cp -r $D/spec/* "$_"
MODDOC=modules/$(echo $D | awk -F/ '{print $NF}')
rm -rf $MODDOC
mkdir -p $MODDOC && cp -r $D/README.md "$_"
if [ -f "$MODDOC/README.md" ]; then
cd $MODDOC
# This ensures that we have multiples pages for the modules documantation
# This is easier to read for the user
# In order to split pages, we need to add a <!-- order: X --> in the module README.md, for each pages that we want.
csplit -k -q README.md '/<!-- order:/' '{*}' --prefix='section_' --suffix-format='%02d.md'
mv section_00.md README.md
cd ../..
fi
fi
done
cat ../x/README.md | sed 's/\.\/x/\/modules/g' | sed 's/spec\/README.md//g' | sed 's/\.\.\/docs\/building-modules\/README\.md/\/building-modules\/intro\.html/g' > ./modules/README.md
## Vesting is a submodule of auth, but we still want to display it in docs
## TODO to be removed in https://github.com/cosmos/cosmos-sdk/issues/9958
mkdir -p modules/vesting
cp -r ../x/auth/vesting/README.md modules/vesting
cd modules/vesting
csplit -k -q README.md '/<!-- order:/' '{*}' --prefix='section_' --suffix-format='%02d.md'
mv section_00.md README.md
cd ../..
cat ../x/README.md | sed 's/\.\/x/\/modules/g' | sed 's/\.\.\/docs\/building-modules\/README\.md/\/building-modules\/intro\.html/g' > ./modules/README.md
cp ../cosmovisor/README.md ./run-node/cosmovisor.md

View File

@ -6,22 +6,22 @@ order: 0
Here are some production-grade modules that can be used in Cosmos SDK applications, along with their respective documentation:
* [Auth](auth/spec/README.md) - Authentication of accounts and transactions for Cosmos SDK applications.
* [Authz](authz/spec/README.md) - Authorization for accounts to perform actions on behalf of other accounts.
* [Bank](bank/spec/README.md) - Token transfer functionalities.
* [Capability](capability/spec/README.md) - Object capability implementation.
* [Crisis](crisis/spec/README.md) - Halting the blockchain under certain circumstances (e.g. if an invariant is broken).
* [Distribution](distribution/spec/README.md) - Fee distribution, and staking token provision distribution.
* [Epoching](epoching/spec/README.md) - Allows modules to queue messages for execution at a certain block height.
* [Evidence](evidence/spec/README.md) - Evidence handling for double signing, misbehaviour, etc.
* [Feegrant](feegrant/spec/README.md) - Grant fee allowances for executing transactions.
* [Governance](gov/spec/README.md) - On-chain proposals and voting.
* [Mint](mint/spec/README.md) - Creation of new units of staking token.
* [Params](params/spec/README.md) - Globally available parameter store.
* [Slashing](slashing/spec/README.md) - Validator punishment mechanisms.
* [Staking](staking/spec/README.md) - Proof-of-Stake layer for public blockchains.
* [Upgrade](upgrade/spec/README.md) - Software upgrades handling and coordination.
* [Nft](nft/spec/README.md) - NFT module implemented based on [ADR43](https://docs.cosmos.network/master/architecture/adr-043-nft-module.html).
* [Auth](auth/README.md) - Authentication of accounts and transactions for Cosmos SDK applications.
* [Authz](authz/README.md) - Authorization for accounts to perform actions on behalf of other accounts.
* [Bank](bank/README.md) - Token transfer functionalities.
* [Capability](capability/README.md) - Object capability implementation.
* [Crisis](crisis/README.md) - Halting the blockchain under certain circumstances (e.g. if an invariant is broken).
* [Distribution](distribution/README.md) - Fee distribution, and staking token provision distribution.
* [Epoching](epoching/README.md) - Allows modules to queue messages for execution at a certain block height.
* [Evidence](evidence/README.md) - Evidence handling for double signing, misbehaviour, etc.
* [Feegrant](feegrant/README.md) - Grant fee allowances for executing transactions.
* [Governance](gov/README.md) - On-chain proposals and voting.
* [Mint](mint/README.md) - Creation of new units of staking token.
* [Params](params/README.md) - Globally available parameter store.
* [Slashing](slashing/README.md) - Validator punishment mechanisms.
* [Staking](staking/README.md) - Proof-of-Stake layer for public blockchains.
* [Upgrade](upgrade/README.md) - Software upgrades handling and coordination.
* [NFT](nft/README.md) - NFT module implemented based on [ADR43](https://docs.cosmos.network/main/architecture/adr-043-nft-module.html).
To learn more about the process of building modules, visit the [building modules reference documentation](../docs/building-modules/README.md).

View File

@ -1,7 +1,623 @@
<!--
order: 0
title: "Auth Overview"
parent:
title: "auth"
-->
# Auth
# `x/auth`
* [Auth](spec/README.md) - Authentication of accounts and transactions for Cosmos SDK applications.
## Abstract
This document specifies the auth module of the Cosmos SDK.
The auth module is responsible for specifying the base transaction and account types
for an application, since the SDK itself is agnostic to these particulars. It contains
the middlewares, where all basic transaction validity checks (signatures, nonces, auxiliary fields)
are performed, and exposes the account keeper, which allows other modules to read, write, and modify accounts.
This module is used in the Cosmos Hub.
## Contents
* [Concepts](#concepts)
* [Gas & Fees](#gas--fees)
* [State](#state)
* [Accounts](#accounts)
* [AnteHandlers](#antehandlers)
* [Keepers](#keepers)
* [Account Keeper](#account-keeper)
* [Parameters](#parameters)
* [Client](#client)
* [CLI](#cli)
* [gRPC](#grpc)
* [REST](#rest)
<!-- order: 1 -->
# Concepts
**Note:** The auth module is different from the [authz module](../modules/authz/).
The differences are:
* `auth` - authentication of accounts and transactions for Cosmos SDK applications and is responsible for specifying the base transaction and account types.
* `authz` - authorization for accounts to perform actions on behalf of other accounts and enables a granter to grant authorizations to a grantee that allows the grantee to execute messages on behalf of the granter.
## Gas & Fees
Fees serve two purposes for an operator of the network.
Fees limit the growth of the state stored by every full node and allow for
general purpose censorship of transactions of little economic value. Fees
are best suited as an anti-spam mechanism where validators are disinterested in
the use of the network and identities of users.
Fees are determined by the gas limits and gas prices transactions provide, where
`fees = ceil(gasLimit * gasPrices)`. Txs incur gas costs for all state reads/writes,
signature verification, as well as costs proportional to the tx size. Operators
should set minimum gas prices when starting their nodes. They must set the unit
costs of gas in each token denomination they wish to support:
`simd start ... --minimum-gas-prices=0.00001stake;0.05photinos`
When adding transactions to mempool or gossipping transactions, validators check
if the transaction's gas prices, which are determined by the provided fees, meet
any of the validator's minimum gas prices. In other words, a transaction must
provide a fee of at least one denomination that matches a validator's minimum
gas price.
Tendermint does not currently provide fee based mempool prioritization, and fee
based mempool filtering is local to node and not part of consensus. But with
minimum gas prices set, such a mechanism could be implemented by node operators.
Because the market value for tokens will fluctuate, validators are expected to
dynamically adjust their minimum gas prices to a level that would encourage the
use of the network.
<!-- order: 2 -->
# State
## Accounts
Accounts contain authentication information for a uniquely identified external user of an SDK blockchain,
including public key, address, and account number / sequence number for replay protection. For efficiency,
since account balances must also be fetched to pay fees, account structs also store the balance of a user
as `sdk.Coins`.
Accounts are exposed externally as an interface, and stored internally as
either a base account or vesting account. Module clients wishing to add more
account types may do so.
* `0x01 | Address -> ProtocolBuffer(account)`
### Account Interface
The account interface exposes methods to read and write standard account information.
Note that all of these methods operate on an account struct confirming to the
interface - in order to write the account to the store, the account keeper will
need to be used.
```go
// AccountI is an interface used to store coins at a given address within state.
// It presumes a notion of sequence numbers for replay protection,
// a notion of account numbers for replay protection for previously pruned accounts,
// and a pubkey for authentication purposes.
//
// Many complex conditions can be used in the concrete struct which implements AccountI.
type AccountI interface {
proto.Message
GetAddress() sdk.AccAddress
SetAddress(sdk.AccAddress) error // errors if already set.
GetPubKey() crypto.PubKey // can return nil.
SetPubKey(crypto.PubKey) error
GetAccountNumber() uint64
SetAccountNumber(uint64) error
GetSequence() uint64
SetSequence(uint64) error
// Ensure that account implements stringer
String() string
}
```
#### Base Account
A base account is the simplest and most common account type, which just stores all requisite
fields directly in a struct.
```protobuf
// 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).
message BaseAccount {
string address = 1;
google.protobuf.Any pub_key = 2;
uint64 account_number = 3;
uint64 sequence = 4;
}
```
### Vesting Account
See [Vesting](https://docs.cosmos.network/main/modules/vesting/).
<!-- order: 3 -->
# AnteHandlers
The `x/auth` module presently has no transaction handlers of its own, but does expose the special `AnteHandler`, used for performing basic validity checks on a transaction, such that it could be thrown out of the mempool.
The `AnteHandler` can be seen as a set of decorators that check transactions within the current context, per [ADR 010](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-010-modular-antehandler.md).
Note that the `AnteHandler` is called on both `CheckTx` and `DeliverTx`, as Tendermint proposers presently have the ability to include in their proposed block transactions which fail `CheckTx`.
## Decorators
The auth module provides `AnteDecorator`s that are recursively chained together into a single `AnteHandler` in the following order:
* `SetUpContextDecorator`: Sets the `GasMeter` in the `Context` and wraps the next `AnteHandler` with a defer clause to recover from any downstream `OutOfGas` panics in the `AnteHandler` chain to return an error with information on gas provided and gas used.
* `RejectExtensionOptionsDecorator`: Rejects all extension options which can optionally be included in protobuf transactions.
* `MempoolFeeDecorator`: Checks if the `tx` fee is above local mempool `minFee` parameter during `CheckTx`.
* `ValidateBasicDecorator`: Calls `tx.ValidateBasic` and returns any non-nil error.
* `TxTimeoutHeightDecorator`: Check for a `tx` height timeout.
* `ValidateMemoDecorator`: Validates `tx` memo with application parameters and returns any non-nil error.
* `ConsumeGasTxSizeDecorator`: Consumes gas proportional to the `tx` size based on application parameters.
* `DeductFeeDecorator`: Deducts the `FeeAmount` from first signer of the `tx`. If the `x/feegrant` module is enabled and a fee granter is set, it deducts fees from the fee granter account.
* `SetPubKeyDecorator`: Sets the pubkey from a `tx`'s signers that does not already have its corresponding pubkey saved in the state machine and in the current context.
* `ValidateSigCountDecorator`: Validates the number of signatures in `tx` based on app-parameters.
* `SigGasConsumeDecorator`: Consumes parameter-defined amount of gas for each signature. This requires pubkeys to be set in context for all signers as part of `SetPubKeyDecorator`.
* `SigVerificationDecorator`: Verifies all signatures are valid. This requires pubkeys to be set in context for all signers as part of `SetPubKeyDecorator`.
* `IncrementSequenceDecorator`: Increments the account sequence for each signer to prevent replay attacks.
<!-- order: 4 -->
# Keepers
The auth module only exposes one keeper, the account keeper, which can be used to read and write accounts.
## Account Keeper
Presently only one fully-permissioned account keeper is exposed, which has the ability to both read and write
all fields of all accounts, and to iterate over all stored accounts.
```go
// AccountKeeperI is the interface contract that x/auth's keeper implements.
type AccountKeeperI interface {
// Return a new account with the next account number and the specified address. Does not save the new account to the store.
NewAccountWithAddress(sdk.Context, sdk.AccAddress) types.AccountI
// Return a new account with the next account number. Does not save the new account to the store.
NewAccount(sdk.Context, types.AccountI) types.AccountI
// Check if an account exists in the store.
HasAccount(sdk.Context, sdk.AccAddress) bool
// Retrieve an account from the store.
GetAccount(sdk.Context, sdk.AccAddress) types.AccountI
// Set an account in the store.
SetAccount(sdk.Context, types.AccountI)
// Remove an account from the store.
RemoveAccount(sdk.Context, types.AccountI)
// Iterate over all accounts, calling the provided function. Stop iteration when it returns true.
IterateAccounts(sdk.Context, func(types.AccountI) bool)
// Fetch the public key of an account at a specified address
GetPubKey(sdk.Context, sdk.AccAddress) (crypto.PubKey, error)
// Fetch the sequence of an account at a specified address.
GetSequence(sdk.Context, sdk.AccAddress) (uint64, error)
// Fetch the next account number, and increment the internal counter.
GetNextAccountNumber(sdk.Context) uint64
}
```
<!-- order: 5 -->
# Parameters
The auth module contains the following parameters:
| Key | Type | Example |
| ---------------------- | --------------- | ------- |
| MaxMemoCharacters | uint64 | 256 |
| TxSigLimit | uint64 | 7 |
| TxSizeCostPerByte | uint64 | 10 |
| SigVerifyCostED25519 | uint64 | 590 |
| SigVerifyCostSecp256k1 | uint64 | 1000 |
<!-- order: 6 -->
# Client
## CLI
A user can query and interact with the `auth` module using the CLI.
### Query
The `query` commands allow users to query `auth` state.
```bash
simd query auth --help
```
#### account
The `account` command allow users to query for an account by it's address.
```bash
simd query auth account [address] [flags]
```
Example:
```bash
simd query auth account cosmos1...
```
Example Output:
```bash
'@type': /cosmos.auth.v1beta1.BaseAccount
account_number: "0"
address: cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2
pub_key:
'@type': /cosmos.crypto.secp256k1.PubKey
key: ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD
sequence: "1"
```
#### accounts
The `accounts` command allow users to query all the available accounts.
```bash
simd query auth accounts [flags]
```
Example:
```bash
simd query auth accounts
```
Example Output:
```bash
accounts:
- '@type': /cosmos.auth.v1beta1.BaseAccount
account_number: "0"
address: cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2
pub_key:
'@type': /cosmos.crypto.secp256k1.PubKey
key: ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD
sequence: "1"
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "8"
address: cosmos1yl6hdjhmkf37639730gffanpzndzdpmhwlkfhr
pub_key: null
sequence: "0"
name: transfer
permissions:
- minter
- burner
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "4"
address: cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh
pub_key: null
sequence: "0"
name: bonded_tokens_pool
permissions:
- burner
- staking
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "5"
address: cosmos1tygms3xhhs3yv487phx3dw4a95jn7t7lpm470r
pub_key: null
sequence: "0"
name: not_bonded_tokens_pool
permissions:
- burner
- staking
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "6"
address: cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn
pub_key: null
sequence: "0"
name: gov
permissions:
- burner
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "3"
address: cosmos1jv65s3grqf6v6jl3dp4t6c9t9rk99cd88lyufl
pub_key: null
sequence: "0"
name: distribution
permissions: []
- '@type': /cosmos.auth.v1beta1.BaseAccount
account_number: "1"
address: cosmos147k3r7v2tvwqhcmaxcfql7j8rmkrlsemxshd3j
pub_key: null
sequence: "0"
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "7"
address: cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q
pub_key: null
sequence: "0"
name: mint
permissions:
- minter
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "2"
address: cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta
pub_key: null
sequence: "0"
name: fee_collector
permissions: []
pagination:
next_key: null
total: "0"
```
#### params
The `params` command allow users to query the current auth parameters.
```bash
simd query auth params [flags]
```
Example:
```bash
simd query auth params
```
Example Output:
```bash
max_memo_characters: "256"
sig_verify_cost_ed25519: "590"
sig_verify_cost_secp256k1: "1000"
tx_sig_limit: "7"
tx_size_cost_per_byte: "10"
```
## gRPC
A user can query the `auth` module using gRPC endpoints.
### Account
The `account` endpoint allow users to query for an account by it's address.
```bash
cosmos.auth.v1beta1.Query/Account
```
Example:
```bash
grpcurl -plaintext \
-d '{"address":"cosmos1.."}' \
localhost:9090 \
cosmos.auth.v1beta1.Query/Account
```
Example Output:
```bash
{
"account":{
"@type":"/cosmos.auth.v1beta1.BaseAccount",
"address":"cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2",
"pubKey":{
"@type":"/cosmos.crypto.secp256k1.PubKey",
"key":"ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD"
},
"sequence":"1"
}
}
```
### Accounts
The `accounts` endpoint allow users to query all the available accounts.
```bash
cosmos.auth.v1beta1.Query/Accounts
```
Example:
```bash
grpcurl -plaintext \
localhost:9090 \
cosmos.auth.v1beta1.Query/Accounts
```
Example Output:
```bash
{
"accounts":[
{
"@type":"/cosmos.auth.v1beta1.BaseAccount",
"address":"cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2",
"pubKey":{
"@type":"/cosmos.crypto.secp256k1.PubKey",
"key":"ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD"
},
"sequence":"1"
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos1yl6hdjhmkf37639730gffanpzndzdpmhwlkfhr",
"accountNumber":"8"
},
"name":"transfer",
"permissions":[
"minter",
"burner"
]
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh",
"accountNumber":"4"
},
"name":"bonded_tokens_pool",
"permissions":[
"burner",
"staking"
]
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos1tygms3xhhs3yv487phx3dw4a95jn7t7lpm470r",
"accountNumber":"5"
},
"name":"not_bonded_tokens_pool",
"permissions":[
"burner",
"staking"
]
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn",
"accountNumber":"6"
},
"name":"gov",
"permissions":[
"burner"
]
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos1jv65s3grqf6v6jl3dp4t6c9t9rk99cd88lyufl",
"accountNumber":"3"
},
"name":"distribution"
},
{
"@type":"/cosmos.auth.v1beta1.BaseAccount",
"accountNumber":"1",
"address":"cosmos147k3r7v2tvwqhcmaxcfql7j8rmkrlsemxshd3j"
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q",
"accountNumber":"7"
},
"name":"mint",
"permissions":[
"minter"
]
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta",
"accountNumber":"2"
},
"name":"fee_collector"
}
],
"pagination":{
"total":"9"
}
}
```
### Params
The `params` endpoint allow users to query the current auth parameters.
```bash
cosmos.auth.v1beta1.Query/Params
```
Example:
```bash
grpcurl -plaintext \
localhost:9090 \
cosmos.auth.v1beta1.Query/Params
```
Example Output:
```bash
{
"params": {
"maxMemoCharacters": "256",
"txSigLimit": "7",
"txSizeCostPerByte": "10",
"sigVerifyCostEd25519": "590",
"sigVerifyCostSecp256k1": "1000"
}
}
```
## REST
A user can query the `auth` module using REST endpoints.
### Account
The `account` endpoint allow users to query for an account by it's address.
```bash
/cosmos/auth/v1beta1/account?address={address}
```
### Accounts
The `accounts` endpoint allow users to query all the available accounts.
```bash
/cosmos/auth/v1beta1/accounts
```
### Params
The `params` endpoint allow users to query the current auth parameters.
```bash
/cosmos/auth/v1beta1/params
```

View File

@ -1,43 +0,0 @@
<!--
order: 1
-->
# Concepts
**Note:** The auth module is different from the [authz module](../modules/authz/).
The differences are:
* `auth` - authentication of accounts and transactions for Cosmos SDK applications and is responsible for specifying the base transaction and account types.
* `authz` - authorization for accounts to perform actions on behalf of other accounts and enables a granter to grant authorizations to a grantee that allows the grantee to execute messages on behalf of the granter.
## Gas & Fees
Fees serve two purposes for an operator of the network.
Fees limit the growth of the state stored by every full node and allow for
general purpose censorship of transactions of little economic value. Fees
are best suited as an anti-spam mechanism where validators are disinterested in
the use of the network and identities of users.
Fees are determined by the gas limits and gas prices transactions provide, where
`fees = ceil(gasLimit * gasPrices)`. Txs incur gas costs for all state reads/writes,
signature verification, as well as costs proportional to the tx size. Operators
should set minimum gas prices when starting their nodes. They must set the unit
costs of gas in each token denomination they wish to support:
`simd start ... --minimum-gas-prices=0.00001stake;0.05photinos`
When adding transactions to mempool or gossipping transactions, validators check
if the transaction's gas prices, which are determined by the provided fees, meet
any of the validator's minimum gas prices. In other words, a transaction must
provide a fee of at least one denomination that matches a validator's minimum
gas price.
Tendermint does not currently provide fee based mempool prioritization, and fee
based mempool filtering is local to node and not part of consensus. But with
minimum gas prices set, such a mechanism could be implemented by node operators.
Because the market value for tokens will fluctuate, validators are expected to
dynamically adjust their minimum gas prices to a level that would encourage the
use of the network.

View File

@ -1,73 +0,0 @@
<!--
order: 2
-->
# State
## Accounts
Accounts contain authentication information for a uniquely identified external user of an SDK blockchain,
including public key, address, and account number / sequence number for replay protection. For efficiency,
since account balances must also be fetched to pay fees, account structs also store the balance of a user
as `sdk.Coins`.
Accounts are exposed externally as an interface, and stored internally as
either a base account or vesting account. Module clients wishing to add more
account types may do so.
* `0x01 | Address -> ProtocolBuffer(account)`
### Account Interface
The account interface exposes methods to read and write standard account information.
Note that all of these methods operate on an account struct confirming to the
interface - in order to write the account to the store, the account keeper will
need to be used.
```go
// AccountI is an interface used to store coins at a given address within state.
// It presumes a notion of sequence numbers for replay protection,
// a notion of account numbers for replay protection for previously pruned accounts,
// and a pubkey for authentication purposes.
//
// Many complex conditions can be used in the concrete struct which implements AccountI.
type AccountI interface {
proto.Message
GetAddress() sdk.AccAddress
SetAddress(sdk.AccAddress) error // errors if already set.
GetPubKey() crypto.PubKey // can return nil.
SetPubKey(crypto.PubKey) error
GetAccountNumber() uint64
SetAccountNumber(uint64) error
GetSequence() uint64
SetSequence(uint64) error
// Ensure that account implements stringer
String() string
}
```
#### Base Account
A base account is the simplest and most common account type, which just stores all requisite
fields directly in a struct.
```protobuf
// 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).
message BaseAccount {
string address = 1;
google.protobuf.Any pub_key = 2;
uint64 account_number = 3;
uint64 sequence = 4;
}
```
### Vesting Account
See [Vesting](05_vesting.md).

View File

@ -1,40 +0,0 @@
<!--
order: 3
-->
# AnteHandlers
The `x/auth` module presently has no transaction handlers of its own, but does expose the special `AnteHandler`, used for performing basic validity checks on a transaction, such that it could be thrown out of the mempool.
The `AnteHandler` can be seen as a set of decorators that check transactions within the current context, per [ADR 010](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-010-modular-antehandler.md).
Note that the `AnteHandler` is called on both `CheckTx` and `DeliverTx`, as Tendermint proposers presently have the ability to include in their proposed block transactions which fail `CheckTx`.
## Decorators
The auth module provides `AnteDecorator`s that are recursively chained together into a single `AnteHandler` in the following order:
* `SetUpContextDecorator`: Sets the `GasMeter` in the `Context` and wraps the next `AnteHandler` with a defer clause to recover from any downstream `OutOfGas` panics in the `AnteHandler` chain to return an error with information on gas provided and gas used.
* `RejectExtensionOptionsDecorator`: Rejects all extension options which can optionally be included in protobuf transactions.
* `MempoolFeeDecorator`: Checks if the `tx` fee is above local mempool `minFee` parameter during `CheckTx`.
* `ValidateBasicDecorator`: Calls `tx.ValidateBasic` and returns any non-nil error.
* `TxTimeoutHeightDecorator`: Check for a `tx` height timeout.
* `ValidateMemoDecorator`: Validates `tx` memo with application parameters and returns any non-nil error.
* `ConsumeGasTxSizeDecorator`: Consumes gas proportional to the `tx` size based on application parameters.
* `DeductFeeDecorator`: Deducts the `FeeAmount` from first signer of the `tx`. If the `x/feegrant` module is enabled and a fee granter is set, it deducts fees from the fee granter account.
* `SetPubKeyDecorator`: Sets the pubkey from a `tx`'s signers that does not already have its corresponding pubkey saved in the state machine and in the current context.
* `ValidateSigCountDecorator`: Validates the number of signatures in `tx` based on app-parameters.
* `SigGasConsumeDecorator`: Consumes parameter-defined amount of gas for each signature. This requires pubkeys to be set in context for all signers as part of `SetPubKeyDecorator`.
* `SigVerificationDecorator`: Verifies all signatures are valid. This requires pubkeys to be set in context for all signers as part of `SetPubKeyDecorator`.
* `IncrementSequenceDecorator`: Increments the account sequence for each signer to prevent replay attacks.

View File

@ -1,47 +0,0 @@
<!--
order: 4
-->
# Keepers
The auth module only exposes one keeper, the account keeper, which can be used to read and write accounts.
## Account Keeper
Presently only one fully-permissioned account keeper is exposed, which has the ability to both read and write
all fields of all accounts, and to iterate over all stored accounts.
```go
// AccountKeeperI is the interface contract that x/auth's keeper implements.
type AccountKeeperI interface {
// Return a new account with the next account number and the specified address. Does not save the new account to the store.
NewAccountWithAddress(sdk.Context, sdk.AccAddress) types.AccountI
// Return a new account with the next account number. Does not save the new account to the store.
NewAccount(sdk.Context, types.AccountI) types.AccountI
// Check if an account exists in the store.
HasAccount(sdk.Context, sdk.AccAddress) bool
// Retrieve an account from the store.
GetAccount(sdk.Context, sdk.AccAddress) types.AccountI
// Set an account in the store.
SetAccount(sdk.Context, types.AccountI)
// Remove an account from the store.
RemoveAccount(sdk.Context, types.AccountI)
// Iterate over all accounts, calling the provided function. Stop iteration when it returns true.
IterateAccounts(sdk.Context, func(types.AccountI) bool)
// Fetch the public key of an account at a specified address
GetPubKey(sdk.Context, sdk.AccAddress) (crypto.PubKey, error)
// Fetch the sequence of an account at a specified address.
GetSequence(sdk.Context, sdk.AccAddress) (uint64, error)
// Fetch the next account number, and increment the internal counter.
GetNextAccountNumber(sdk.Context) uint64
}
```

View File

@ -1,15 +0,0 @@
<!--
order: 6
-->
# Parameters
The auth module contains the following parameters:
| Key | Type | Example |
| ---------------------- | --------------- | ------- |
| MaxMemoCharacters | uint64 | 256 |
| TxSigLimit | uint64 | 7 |
| TxSizeCostPerByte | uint64 | 10 |
| SigVerifyCostED25519 | uint64 | 590 |
| SigVerifyCostSecp256k1 | uint64 | 1000 |

View File

@ -1,421 +0,0 @@
<!--
order: 7
-->
# Client
# Auth
## CLI
A user can query and interact with the `auth` module using the CLI.
### Query
The `query` commands allow users to query `auth` state.
```bash
simd query auth --help
```
#### account
The `account` command allow users to query for an account by it's address.
```bash
simd query auth account [address] [flags]
```
Example:
```bash
simd query auth account cosmos1...
```
Example Output:
```bash
'@type': /cosmos.auth.v1beta1.BaseAccount
account_number: "0"
address: cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2
pub_key:
'@type': /cosmos.crypto.secp256k1.PubKey
key: ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD
sequence: "1"
```
#### accounts
The `accounts` command allow users to query all the available accounts.
```bash
simd query auth accounts [flags]
```
Example:
```bash
simd query auth accounts
```
Example Output:
```bash
accounts:
- '@type': /cosmos.auth.v1beta1.BaseAccount
account_number: "0"
address: cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2
pub_key:
'@type': /cosmos.crypto.secp256k1.PubKey
key: ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD
sequence: "1"
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "8"
address: cosmos1yl6hdjhmkf37639730gffanpzndzdpmhwlkfhr
pub_key: null
sequence: "0"
name: transfer
permissions:
- minter
- burner
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "4"
address: cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh
pub_key: null
sequence: "0"
name: bonded_tokens_pool
permissions:
- burner
- staking
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "5"
address: cosmos1tygms3xhhs3yv487phx3dw4a95jn7t7lpm470r
pub_key: null
sequence: "0"
name: not_bonded_tokens_pool
permissions:
- burner
- staking
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "6"
address: cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn
pub_key: null
sequence: "0"
name: gov
permissions:
- burner
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "3"
address: cosmos1jv65s3grqf6v6jl3dp4t6c9t9rk99cd88lyufl
pub_key: null
sequence: "0"
name: distribution
permissions: []
- '@type': /cosmos.auth.v1beta1.BaseAccount
account_number: "1"
address: cosmos147k3r7v2tvwqhcmaxcfql7j8rmkrlsemxshd3j
pub_key: null
sequence: "0"
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "7"
address: cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q
pub_key: null
sequence: "0"
name: mint
permissions:
- minter
- '@type': /cosmos.auth.v1beta1.ModuleAccount
base_account:
account_number: "2"
address: cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta
pub_key: null
sequence: "0"
name: fee_collector
permissions: []
pagination:
next_key: null
total: "0"
```
#### params
The `params` command allow users to query the current auth parameters.
```bash
simd query auth params [flags]
```
Example:
```bash
simd query auth params
```
Example Output:
```bash
max_memo_characters: "256"
sig_verify_cost_ed25519: "590"
sig_verify_cost_secp256k1: "1000"
tx_sig_limit: "7"
tx_size_cost_per_byte: "10"
```
## gRPC
A user can query the `auth` module using gRPC endpoints.
### Account
The `account` endpoint allow users to query for an account by it's address.
```bash
cosmos.auth.v1beta1.Query/Account
```
Example:
```bash
grpcurl -plaintext \
-d '{"address":"cosmos1.."}' \
localhost:9090 \
cosmos.auth.v1beta1.Query/Account
```
Example Output:
```bash
{
"account":{
"@type":"/cosmos.auth.v1beta1.BaseAccount",
"address":"cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2",
"pubKey":{
"@type":"/cosmos.crypto.secp256k1.PubKey",
"key":"ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD"
},
"sequence":"1"
}
}
```
### Accounts
The `accounts` endpoint allow users to query all the available accounts.
```bash
cosmos.auth.v1beta1.Query/Accounts
```
Example:
```bash
grpcurl -plaintext \
localhost:9090 \
cosmos.auth.v1beta1.Query/Accounts
```
Example Output:
```bash
{
"accounts":[
{
"@type":"/cosmos.auth.v1beta1.BaseAccount",
"address":"cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2",
"pubKey":{
"@type":"/cosmos.crypto.secp256k1.PubKey",
"key":"ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD"
},
"sequence":"1"
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos1yl6hdjhmkf37639730gffanpzndzdpmhwlkfhr",
"accountNumber":"8"
},
"name":"transfer",
"permissions":[
"minter",
"burner"
]
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh",
"accountNumber":"4"
},
"name":"bonded_tokens_pool",
"permissions":[
"burner",
"staking"
]
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos1tygms3xhhs3yv487phx3dw4a95jn7t7lpm470r",
"accountNumber":"5"
},
"name":"not_bonded_tokens_pool",
"permissions":[
"burner",
"staking"
]
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn",
"accountNumber":"6"
},
"name":"gov",
"permissions":[
"burner"
]
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos1jv65s3grqf6v6jl3dp4t6c9t9rk99cd88lyufl",
"accountNumber":"3"
},
"name":"distribution"
},
{
"@type":"/cosmos.auth.v1beta1.BaseAccount",
"accountNumber":"1",
"address":"cosmos147k3r7v2tvwqhcmaxcfql7j8rmkrlsemxshd3j"
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q",
"accountNumber":"7"
},
"name":"mint",
"permissions":[
"minter"
]
},
{
"@type":"/cosmos.auth.v1beta1.ModuleAccount",
"baseAccount":{
"address":"cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta",
"accountNumber":"2"
},
"name":"fee_collector"
}
],
"pagination":{
"total":"9"
}
}
```
### Params
The `params` endpoint allow users to query the current auth parameters.
```bash
cosmos.auth.v1beta1.Query/Params
```
Example:
```bash
grpcurl -plaintext \
localhost:9090 \
cosmos.auth.v1beta1.Query/Params
```
Example Output:
```bash
{
"params": {
"maxMemoCharacters": "256",
"txSigLimit": "7",
"txSizeCostPerByte": "10",
"sigVerifyCostEd25519": "590",
"sigVerifyCostSecp256k1": "1000"
}
}
```
## REST
A user can query the `auth` module using REST endpoints.
### Account
The `account` endpoint allow users to query for an account by it's address.
```bash
/cosmos/auth/v1beta1/account?address={address}
```
### Accounts
The `accounts` endpoint allow users to query all the available accounts.
```bash
/cosmos/auth/v1beta1/accounts
```
### Params
The `params` endpoint allow users to query the current auth parameters.
```bash
/cosmos/auth/v1beta1/params
```
# Vesting
## CLI
A user can query and interact with the `vesting` module using the CLI.
### Transactions
The `tx` commands allow users to interact with the `vesting` module.
```bash
simd tx vesting --help
```
#### create-periodic-vesting-account
The `create-periodic-vesting-account` command creates a new vesting account funded with an allocation of tokens, where a sequence of coins and period length in seconds. Periods are sequential, in that the duration of of a period only starts at the end of the previous period. The duration of the first period starts upon account creation.
```bash
simd tx vesting create-periodic-vesting-account [to_address] [periods_json_file] [flags]
```
Example:
```bash
simd tx vesting create-periodic-vesting-account cosmos1.. periods.json
```
#### create-vesting-account
The `create-vesting-account` command creates a new vesting account funded with an allocation of tokens. The account can either be a delayed or continuous vesting account, which is determined by the '--delayed' flag. All vesting accouts created will have their start time set by the committed block's time. The end_time must be provided as a UNIX epoch timestamp.
```bash
simd tx vesting create-vesting-account [to_address] [amount] [end_time] [flags]
```
Example:
```bash
simd tx vesting create-vesting-account cosmos1.. 100stake 2592000
```

View File

@ -1,45 +0,0 @@
<!--
order: 0
title: "Auth Overview"
parent:
title: "auth"
-->
# `auth`
## Abstract
This document specifies the auth module of the Cosmos SDK.
The auth module is responsible for specifying the base transaction and account types
for an application, since the SDK itself is agnostic to these particulars. It contains
the middlewares, where all basic transaction validity checks (signatures, nonces, auxiliary fields)
are performed, and exposes the account keeper, which allows other modules to read, write, and modify accounts.
This module is used in the Cosmos Hub.
## Contents
1. **[Concepts](01_concepts.md)**
* [Gas & Fees](01_concepts.md#gas-&-fees)
2. **[State](02_state.md)**
* [Accounts](02_state.md#accounts)
3. **[AnteHandlers](03_antehandlers.md)**
4. **[Keepers](04_keepers.md)**
* [Account Keeper](04_keepers.md#account-keeper)
5. **[Vesting](05_vesting.md)**
* [Intro and Requirements](05_vesting.md#intro-and-requirements)
* [Vesting Account Types](05_vesting.md#vesting-account-types)
* [Vesting Account Specification](05_vesting.md#vesting-account-specification)
* [Keepers & Handlers](05_vesting.md#keepers-&-handlers)
* [Genesis Initialization](05_vesting.md#genesis-initialization)
* [Examples](05_vesting.md#examples)
* [Glossary](05_vesting.md#glossary)
6. **[Parameters](06_params.md)**
7. **[Client](07_client.md)**
* **[Auth](07_client.md#auth)**
* [CLI](07_client.md#cli)
* [gRPC](07_client.md#grpc)
* [REST](07_client.md#rest)
* **[Vesting](07_client.md#vesting)**
* [CLI](07_client.md#vesting#cli)

View File

@ -1,5 +1,8 @@
<!--
order: 5
order: 0
title: "Vesting Overview"
parent:
title: "vesting"
-->
# Vesting
@ -32,6 +35,8 @@ order: 5
* [Slashing](#slashing)
* [Periodic Vesting](#periodic-vesting)
* [Glossary](#glossary)
* [Client](#client)
* [CLI](#vesting#cli)
## Intro and Requirements
@ -628,3 +633,44 @@ all coins at a given time.
according to a custom vesting schedule.
* PermanentLockedAccount: It does not ever release coins, locking them indefinitely.
Coins in this account can still be used for delegating and for governance votes even while locked.
## CLI
A user can query and interact with the `vesting` module using the CLI.
### Transactions
The `tx` commands allow users to interact with the `vesting` module.
```bash
simd tx vesting --help
```
#### create-periodic-vesting-account
The `create-periodic-vesting-account` command creates a new vesting account funded with an allocation of tokens, where a sequence of coins and period length in seconds. Periods are sequential, in that the duration of of a period only starts at the end of the previous period. The duration of the first period starts upon account creation.
```bash
simd tx vesting create-periodic-vesting-account [to_address] [periods_json_file] [flags]
```
Example:
```bash
simd tx vesting create-periodic-vesting-account cosmos1.. periods.json
```
#### create-vesting-account
The `create-vesting-account` command creates a new vesting account funded with an allocation of tokens. The account can either be a delayed or continuous vesting account, which is determined by the '--delayed' flag. All vesting accouts created will have their start time set by the committed block's time. The end_time must be provided as a UNIX epoch timestamp.
```bash
simd tx vesting create-vesting-account [to_address] [amount] [end_time] [flags]
```
Example:
```bash
simd tx vesting create-vesting-account cosmos1.. 100stake 2592000
```

View File

@ -1,7 +1,334 @@
<!--
order: 0
title: Authz Overview
parent:
title: "authz"
-->
# Authz
# `x/authz`
* [Authz](spec/README.md) - Authorization for accounts to perform actions on behalf of other accounts.
## Abstract
`x/authz` is an implementation of a Cosmos SDK module, per [ADR 30](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-030-authz-module.md), that allows
granting arbitrary privileges from one account (the granter) to another account (the grantee). Authorizations must be granted for a particular Msg service method one by one using an implementation of the `Authorization` interface.
## Contents
* [Concepts](#concepts)
* [Authorization and Grant](#authorization-and-grant)
* [Built-in Authorizations](#built-in-authorizations)
* [Gas](#gas)
* [State](#state)
* [Grant](#grant)
* [GrantQueue](#grantqueue)
* [Messages](#messages)
* [MsgGrant](#msggrant)
* [MsgRevoke](#msgrevoke)
* [MsgExec](#msgexec)
* [Events](#events)
* [Client](#client)
* [CLI](#cli)
* [gRPC](#grpc)
* [REST](#rest)
<!-- order: 1 -->
# Concepts
## Authorization and Grant
The `x/authz` module defines interfaces and messages grant authorizations to perform actions
on behalf of one account to other accounts. The design is defined in the [ADR 030](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-030-authz-module.md).
A *grant* is an allowance to execute a Msg by the grantee on behalf of the granter.
Authorization is an interface that must be implemented by a concrete authorization logic to validate and execute grants. Authorizations are extensible and can be defined for any Msg service method even outside of the module where the Msg method is defined. See the `SendAuthorization` example in the next section for more details.
**Note:** The authz module is different from the [auth (authentication)](../modules/auth/) module that is responsible for specifying the base transaction and account types.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/authz/authorizations.go#L11-L25
## Built-in Authorizations
The Cosmos SDK `x/authz` module comes with following authorization types:
### GenericAuthorization
`GenericAuthorization` implements the `Authorization` interface that gives unrestricted permission to execute the provided Msg on behalf of granter's account.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/authz/v1beta1/authz.proto#L13-L20
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/authz/generic_authorization.go#L16-L29
* `msg` stores Msg type URL.
### SendAuthorization
`SendAuthorization` implements the `Authorization` interface for the `cosmos.bank.v1beta1.MsgSend` Msg. It takes a (positive) `SpendLimit` that specifies the maximum amount of tokens the grantee can spend. The `SpendLimit` is updated as the tokens are spent.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/bank/v1beta1/authz.proto#L10-L19
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/bank/types/send_authorization.go#L23-L38
* `spend_limit` keeps track of how many coins are left in the authorization.
### StakeAuthorization
`StakeAuthorization` implements the `Authorization` interface for messages in the [staking module](https://docs.cosmos.network/v0.44/modules/staking/). It takes an `AuthorizationType` to specify whether you want to authorise delegating, undelegating or redelegating (i.e. these have to be authorised seperately). It also takes a required `MaxTokens` that keeps track of a limit to the amount of tokens that can be delegated/undelegated/redelegated. If left empty, the amount is unlimited. Additionally, this Msg takes an `AllowList` or a `DenyList`, which allows you to select which validators you allow or deny grantees to stake with.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/staking/v1beta1/authz.proto#L10-L33
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/staking/types/authz.go#L15-L35
## Gas
In order to prevent DoS attacks, granting `StakeAuthorization`s with `x/authz` incurs gas. `StakeAuthorization` allows you to authorize another account to delegate, undelegate, or redelegate to validators. The authorizer can define a list of validators they allow or deny delegations to. The Cosmos SDK iterates over these lists and charge 10 gas for each validator in both of the lists.
Since the state maintaining a list for granter, grantee pair with same expiration, we are iterating over the list to remove the grant (incase of any revoke of paritcular `msgType`) from the list and we are charging 20 gas per iteration.
<!-- order: 2 -->
# State
## Grant
Grants are identified by combining granter address (the address bytes of the granter), grantee address (the address bytes of the grantee) and Authorization type (its type URL). Hence we only allow one grant for the (granter, grantee, Authorization) triple.
* Grant: `0x01 | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes | msgType_bytes -> ProtocolBuffer(AuthorizationGrant)`
The grant object encapsulates an `Authorization` type and an expiration timestamp:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/authz/v1beta1/authz.proto#L22-L30
## GrantQueue
We are maintaining a queue for authz pruning. Whenever a grant is created, an item will be added to `GrantQueue` with a key of expiration, granter, grantee.
* GrantQueue: `0x02 | expiration_bytes | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes -> ProtocalBuffer(GrantQueueItem)`
The `expiration_bytes` are the expiration date in UTC with the format `"2006-01-02T15:04:05.000000000"`.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/authz/keeper/keys.go#L78-L93
The `GrantQueueItem` object contains the list of type urls between granter and grantee that expire at the time indicated in the key.
<!-- order: 3 -->
# Messages
In this section we describe the processing of messages for the authz module.
## MsgGrant
An authorization grant is created using the `MsgGrant` message.
If there is already a grant for the `(granter, grantee, Authorization)` triple, then the new grant overwrites the previous one. To update or extend an existing grant, a new grant with the same `(granter, grantee, Authorization)` triple should be created.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/authz/v1beta1/tx.proto#L32-L41
The message handling should fail if:
* both granter and grantee have the same address.
* provided `Expiration` time is less than current unix timestamp (but a grant will be created if no `expiration` time is provided since `expiration` is optional).
* provided `Grant.Authorization` is not implemented.
* `Authorization.MsgTypeURL()` is not defined in the router (there is no defined handler in the app router to handle that Msg types).
## MsgRevoke
A grant can be removed with the `MsgRevoke` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/authz/v1beta1/tx.proto#L66-L72
The message handling should fail if:
* both granter and grantee have the same address.
* provided `MsgTypeUrl` is empty.
NOTE: The `MsgExec` message removes a grant if the grant has expired.
## MsgExec
When a grantee wants to execute a transaction on behalf of a granter, they must send `MsgExec`.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/authz/v1beta1/tx.proto#L51-L59
The message handling should fail if:
* provided `Authorization` is not implemented.
* grantee doesn't have permission to run the transaction.
* if granted authorization is expired.
<!-- order: 4 -->
# Events
The authz module emits proto events defined in [the Protobuf reference](https://buf.build/cosmos/cosmos-sdk/docs/main/cosmos.authz.v1beta1#cosmos.authz.v1beta1.EventGrant).
<!-- order: 5 -->
# Client
## CLI
A user can query and interact with the `authz` module using the CLI.
### Query
The `query` commands allow users to query `authz` state.
```bash
simd query authz --help
```
#### grants
The `grants` command allows users to query grants for a granter-grantee pair. If the message type URL is set, it selects grants only for that message type.
```bash
simd query authz grants [granter-addr] [grantee-addr] [msg-type-url]? [flags]
```
Example:
```bash
simd query authz grants cosmos1.. cosmos1.. /cosmos.bank.v1beta1.MsgSend
```
Example Output:
```bash
grants:
- authorization:
'@type': /cosmos.bank.v1beta1.SendAuthorization
spend_limit:
- amount: "100"
denom: stake
expiration: "2022-01-01T00:00:00Z"
pagination: null
```
### Transactions
The `tx` commands allow users to interact with the `authz` module.
```bash
simd tx authz --help
```
#### exec
The `exec` command allows a grantee to execute a transaction on behalf of granter.
```bash
simd tx authz exec [tx-json-file] --from [grantee] [flags]
```
Example:
```bash
simd tx authz exec tx.json --from=cosmos1..
```
#### grant
The `grant` command allows a granter to grant an authorization to a grantee.
```bash
simd tx authz grant <grantee> <authorization_type="send"|"generic"|"delegate"|"unbond"|"redelegate"> --from <granter> [flags]
```
Example:
```bash
simd tx authz grant cosmos1.. send --spend-limit=100stake --from=cosmos1..
```
#### revoke
The `revoke` command allows a granter to revoke an authorization from a grantee.
```bash
simd tx authz revoke [grantee] [msg-type-url] --from=[granter] [flags]
```
Example:
```bash
simd tx authz revoke cosmos1.. /cosmos.bank.v1beta1.MsgSend --from=cosmos1..
```
## gRPC
A user can query the `authz` module using gRPC endpoints.
### Grants
The `Grants` endpoint allows users to query grants for a granter-grantee pair. If the message type URL is set, it selects grants only for that message type.
```bash
cosmos.authz.v1beta1.Query/Grants
```
Example:
```bash
grpcurl -plaintext \
-d '{"granter":"cosmos1..","grantee":"cosmos1..","msg_type_url":"/cosmos.bank.v1beta1.MsgSend"}' \
localhost:9090 \
cosmos.authz.v1beta1.Query/Grants
```
Example Output:
```bash
{
"grants": [
{
"authorization": {
"@type": "/cosmos.bank.v1beta1.SendAuthorization",
"spendLimit": [
{
"denom":"stake",
"amount":"100"
}
]
},
"expiration": "2022-01-01T00:00:00Z"
}
]
}
```
## REST
A user can query the `authz` module using REST endpoints.
```bash
/cosmos/authz/v1beta1/grants
```
Example:
```bash
curl "localhost:1317/cosmos/authz/v1beta1/grants?granter=cosmos1..&grantee=cosmos1..&msg_type_url=/cosmos.bank.v1beta1.MsgSend"
```
Example Output:
```bash
{
"grants": [
{
"authorization": {
"@type": "/cosmos.bank.v1beta1.SendAuthorization",
"spend_limit": [
{
"denom": "stake",
"amount": "100"
}
]
},
"expiration": "2022-01-01T00:00:00Z"
}
],
"pagination": null
}
```

View File

@ -1,55 +0,0 @@
<!--
order: 1
-->
# Concepts
## Authorization and Grant
The `x/authz` module defines interfaces and messages grant authorizations to perform actions
on behalf of one account to other accounts. The design is defined in the [ADR 030](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-030-authz-module.md).
A *grant* is an allowance to execute a Msg by the grantee on behalf of the granter.
Authorization is an interface that must be implemented by a concrete authorization logic to validate and execute grants. Authorizations are extensible and can be defined for any Msg service method even outside of the module where the Msg method is defined. See the `SendAuthorization` example in the next section for more details.
**Note:** The authz module is different from the [auth (authentication)](../modules/auth/) module that is responsible for specifying the base transaction and account types.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/authz/authorizations.go#L11-L25
## Built-in Authorizations
The Cosmos SDK `x/authz` module comes with following authorization types:
### GenericAuthorization
`GenericAuthorization` implements the `Authorization` interface that gives unrestricted permission to execute the provided Msg on behalf of granter's account.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/authz/v1beta1/authz.proto#L13-L20
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/authz/generic_authorization.go#L16-L29
* `msg` stores Msg type URL.
### SendAuthorization
`SendAuthorization` implements the `Authorization` interface for the `cosmos.bank.v1beta1.MsgSend` Msg. It takes a (positive) `SpendLimit` that specifies the maximum amount of tokens the grantee can spend. The `SpendLimit` is updated as the tokens are spent.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/bank/v1beta1/authz.proto#L10-L19
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/bank/types/send_authorization.go#L23-L38
* `spend_limit` keeps track of how many coins are left in the authorization.
### StakeAuthorization
`StakeAuthorization` implements the `Authorization` interface for messages in the [staking module](https://docs.cosmos.network/v0.44/modules/staking/). It takes an `AuthorizationType` to specify whether you want to authorise delegating, undelegating or redelegating (i.e. these have to be authorised seperately). It also takes a required `MaxTokens` that keeps track of a limit to the amount of tokens that can be delegated/undelegated/redelegated. If left empty, the amount is unlimited. Additionally, this Msg takes an `AllowList` or a `DenyList`, which allows you to select which validators you allow or deny grantees to stake with.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/staking/v1beta1/authz.proto#L10-L33
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/staking/types/authz.go#L15-L35
## Gas
In order to prevent DoS attacks, granting `StakeAuthorization`s with `x/authz` incurs gas. `StakeAuthorization` allows you to authorize another account to delegate, undelegate, or redelegate to validators. The authorizer can define a list of validators they allow or deny delegations to. The Cosmos SDK iterates over these lists and charge 10 gas for each validator in both of the lists.
Since the state maintaining a list for granter, grantee pair with same expiration, we are iterating over the list to remove the grant (incase of any revoke of paritcular `msgType`) from the list and we are charging 20 gas per iteration.

View File

@ -1,27 +0,0 @@
<!--
order: 2
-->
# State
## Grant
Grants are identified by combining granter address (the address bytes of the granter), grantee address (the address bytes of the grantee) and Authorization type (its type URL). Hence we only allow one grant for the (granter, grantee, Authorization) triple.
* Grant: `0x01 | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes | msgType_bytes -> ProtocolBuffer(AuthorizationGrant)`
The grant object encapsulates an `Authorization` type and an expiration timestamp:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/authz/v1beta1/authz.proto#L22-L30
## GrantQueue
We are maintaining a queue for authz pruning. Whenever a grant is created, an item will be added to `GrantQueue` with a key of expiration, granter, grantee.
* GrantQueue: `0x02 | expiration_bytes | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes -> ProtocalBuffer(GrantQueueItem)`
The `expiration_bytes` are the expiration date in UTC with the format `"2006-01-02T15:04:05.000000000"`.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/authz/keeper/keys.go#L78-L93
The `GrantQueueItem` object contains the list of type urls between granter and grantee that expire at the time indicated in the key.

View File

@ -1,46 +0,0 @@
<!--
order: 3
-->
# Messages
In this section we describe the processing of messages for the authz module.
## MsgGrant
An authorization grant is created using the `MsgGrant` message.
If there is already a grant for the `(granter, grantee, Authorization)` triple, then the new grant overwrites the previous one. To update or extend an existing grant, a new grant with the same `(granter, grantee, Authorization)` triple should be created.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/authz/v1beta1/tx.proto#L32-L41
The message handling should fail if:
* both granter and grantee have the same address.
* provided `Expiration` time is less than current unix timestamp (but a grant will be created if no `expiration` time is provided since `expiration` is optional).
* provided `Grant.Authorization` is not implemented.
* `Authorization.MsgTypeURL()` is not defined in the router (there is no defined handler in the app router to handle that Msg types).
## MsgRevoke
A grant can be removed with the `MsgRevoke` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/authz/v1beta1/tx.proto#L66-L72
The message handling should fail if:
* both granter and grantee have the same address.
* provided `MsgTypeUrl` is empty.
NOTE: The `MsgExec` message removes a grant if the grant has expired.
## MsgExec
When a grantee wants to execute a transaction on behalf of a granter, they must send `MsgExec`.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/authz/v1beta1/tx.proto#L51-L59
The message handling should fail if:
* provided `Authorization` is not implemented.
* grantee doesn't have permission to run the transaction.
* if granted authorization is expired.

View File

@ -1,7 +0,0 @@
<!--
order: 4
-->
# Events
The authz module emits proto events defined in [the Protobuf reference](https://buf.build/cosmos/cosmos-sdk/docs/main/cosmos.authz.v1beta1#cosmos.authz.v1beta1.EventGrant).

View File

@ -1,172 +0,0 @@
<!--
order: 5
-->
# Client
## CLI
A user can query and interact with the `authz` module using the CLI.
### Query
The `query` commands allow users to query `authz` state.
```bash
simd query authz --help
```
#### grants
The `grants` command allows users to query grants for a granter-grantee pair. If the message type URL is set, it selects grants only for that message type.
```bash
simd query authz grants [granter-addr] [grantee-addr] [msg-type-url]? [flags]
```
Example:
```bash
simd query authz grants cosmos1.. cosmos1.. /cosmos.bank.v1beta1.MsgSend
```
Example Output:
```bash
grants:
- authorization:
'@type': /cosmos.bank.v1beta1.SendAuthorization
spend_limit:
- amount: "100"
denom: stake
expiration: "2022-01-01T00:00:00Z"
pagination: null
```
### Transactions
The `tx` commands allow users to interact with the `authz` module.
```bash
simd tx authz --help
```
#### exec
The `exec` command allows a grantee to execute a transaction on behalf of granter.
```bash
simd tx authz exec [tx-json-file] --from [grantee] [flags]
```
Example:
```bash
simd tx authz exec tx.json --from=cosmos1..
```
#### grant
The `grant` command allows a granter to grant an authorization to a grantee.
```bash
simd tx authz grant <grantee> <authorization_type="send"|"generic"|"delegate"|"unbond"|"redelegate"> --from <granter> [flags]
```
Example:
```bash
simd tx authz grant cosmos1.. send --spend-limit=100stake --from=cosmos1..
```
#### revoke
The `revoke` command allows a granter to revoke an authorization from a grantee.
```bash
simd tx authz revoke [grantee] [msg-type-url] --from=[granter] [flags]
```
Example:
```bash
simd tx authz revoke cosmos1.. /cosmos.bank.v1beta1.MsgSend --from=cosmos1..
```
## gRPC
A user can query the `authz` module using gRPC endpoints.
### Grants
The `Grants` endpoint allows users to query grants for a granter-grantee pair. If the message type URL is set, it selects grants only for that message type.
```bash
cosmos.authz.v1beta1.Query/Grants
```
Example:
```bash
grpcurl -plaintext \
-d '{"granter":"cosmos1..","grantee":"cosmos1..","msg_type_url":"/cosmos.bank.v1beta1.MsgSend"}' \
localhost:9090 \
cosmos.authz.v1beta1.Query/Grants
```
Example Output:
```bash
{
"grants": [
{
"authorization": {
"@type": "/cosmos.bank.v1beta1.SendAuthorization",
"spendLimit": [
{
"denom":"stake",
"amount":"100"
}
]
},
"expiration": "2022-01-01T00:00:00Z"
}
]
}
```
## REST
A user can query the `authz` module using REST endpoints.
```bash
/cosmos/authz/v1beta1/grants
```
Example:
```bash
curl "localhost:1317/cosmos/authz/v1beta1/grants?granter=cosmos1..&grantee=cosmos1..&msg_type_url=/cosmos.bank.v1beta1.MsgSend"
```
Example Output:
```bash
{
"grants": [
{
"authorization": {
"@type": "/cosmos.bank.v1beta1.SendAuthorization",
"spend_limit": [
{
"denom": "stake",
"amount": "100"
}
]
},
"expiration": "2022-01-01T00:00:00Z"
}
],
"pagination": null
}
```

View File

@ -1,30 +0,0 @@
<!--
order: 0
title: Authz Overview
parent:
title: "authz"
-->
# `authz`
## Contents
## Abstract
`x/authz` is an implementation of a Cosmos SDK module, per [ADR 30](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-030-authz-module.md), that allows
granting arbitrary privileges from one account (the granter) to another account (the grantee). Authorizations must be granted for a particular Msg service method one by one using an implementation of the `Authorization` interface.
1. **[Concept](01_concepts.md)**
* [Authorization and Grant](01_concepts.md#Authorization-and-Grant)
* [Built-in Authorizations](01_concepts.md#Built-in-Authorizations)
* [Gas](01_concepts.md#gas)
2. **[State](02_state.md)**
3. **[Messages](03_messages.md)**
* [MsgGrant](03_messages.md#MsgGrant)
* [MsgRevoke](03_messages.md#MsgRevoke)
* [MsgExec](03_messages.md#MsgExec)
4. **[Events](04_events.md)**
5. **[Client](05_client.md)**
* [CLI](05_client.md#cli)
* [gRPC](05_client.md#grpc)
* [REST](05_client.md#rest)

View File

@ -1,7 +1,941 @@
<!--
order: 0
title: Bank Overview
parent:
title: "bank"
-->
# Bank
# `x/bank`
* [Bank](spec/README.md) - Token transfer functionalities.
## Abstract
This document specifies the bank module of the Cosmos SDK.
The bank module is responsible for handling multi-asset coin transfers between
accounts and tracking special-case pseudo-transfers which must work differently
with particular kinds of accounts (notably delegating/undelegating for vesting
accounts). It exposes several interfaces with varying capabilities for secure
interaction with other modules which must alter user balances.
In addition, the bank module tracks and provides query support for the total
supply of all assets used in the application.
This module is used in the Cosmos Hub.
## Contents
* [Supply](#supply)
* [Total Supply](#total-supply)
* [Module Accounts](#module-accounts)
* [Permissions](#permissions)
* [State](#state)
* [Params](#params)
* [Keepers](#keepers)
* [Messages](#messages)
* [Events](#events)
* [Message Events](#message-events)
* [Keeper Events](#keeper-events)
* [Parameters](#parameters)
* [SendEnabled](#sendenabled)
* [DefaultSendEnabled](#defaultsendenabled)
* [Client](#client)
* [CLI](#cli)
* [Query](#query)
* [Transactions](#transactions)
* [gRPC](#grpc)
## Supply
The `supply` functionality:
* passively tracks the total supply of coins within a chain,
* provides a pattern for modules to hold/interact with `Coins`, and
* introduces the invariant check to verify a chain's total supply.
### Total Supply
The total `Supply` of the network is equal to the sum of all coins from the
account. The total supply is updated every time a `Coin` is minted (eg: as part
of the inflation mechanism) or burned (eg: due to slashing or if a governance
proposal is vetoed).
## Module Accounts
The supply functionality introduces a new type of `auth.Account` which can be used by
modules to allocate tokens and in special cases mint or burn tokens. At a base
level these module accounts are capable of sending/receiving tokens to and from
`auth.Account`s and other module accounts. This design replaces previous
alternative designs where, to hold tokens, modules would burn the incoming
tokens from the sender account, and then track those tokens internally. Later,
in order to send tokens, the module would need to effectively mint tokens
within a destination account. The new design removes duplicate logic between
modules to perform this accounting.
The `ModuleAccount` interface is defined as follows:
```go
type ModuleAccount interface {
auth.Account // same methods as the Account interface
GetName() string // name of the module; used to obtain the address
GetPermissions() []string // permissions of module account
HasPermission(string) bool
}
```
> **WARNING!**
> Any module or message handler that allows either direct or indirect sending of funds must explicitly guarantee those funds cannot be sent to module accounts (unless allowed).
The supply `Keeper` also introduces new wrapper functions for the auth `Keeper`
and the bank `Keeper` that are related to `ModuleAccount`s in order to be able
to:
* Get and set `ModuleAccount`s by providing the `Name`.
* Send coins from and to other `ModuleAccount`s or standard `Account`s
(`BaseAccount` or `VestingAccount`) by passing only the `Name`.
* `Mint` or `Burn` coins for a `ModuleAccount` (restricted to its permissions).
### Permissions
Each `ModuleAccount` has a different set of permissions that provide different
object capabilities to perform certain actions. Permissions need to be
registered upon the creation of the supply `Keeper` so that every time a
`ModuleAccount` calls the allowed functions, the `Keeper` can lookup the
permissions to that specific account and perform or not perform the action.
The available permissions are:
* `Minter`: allows for a module to mint a specific amount of coins.
* `Burner`: allows for a module to burn a specific amount of coins.
* `Staking`: allows for a module to delegate and undelegate a specific amount of coins.
<!-- order: 1 -->
## State
The `x/bank` module keeps state of the following primary objects:
1. Account balances
2. Denomination metadata
3. The total supply of all balances
4. Information on which denominations are allowed to be sent.
In addition, the `x/bank` module keeps the following indexes to manage the
aforementioned state:
* Supply Index: `0x0 | byte(denom) -> byte(amount)`
* Denom Metadata Index: `0x1 | byte(denom) -> ProtocolBuffer(Metadata)`
* Balances Index: `0x2 | byte(address length) | []byte(address) | []byte(balance.Denom) -> ProtocolBuffer(balance)`
* Reverse Denomination to Address Index: `0x03 | byte(denom) | 0x00 | []byte(address) -> 0`
## Params
The bank module stores it's params in state with the prefix of `0x05`,
it can be updated with governance or the address with authority.
* Params: `0x05 | ProtocolBuffer(Params)`
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc3/proto/cosmos/bank/v1beta1/bank.proto#L11-L16
<!-- order: 2 -->
## Keepers
The bank module provides these exported keeper interfaces that can be
passed to other modules that read or update account balances. Modules
should use the least-permissive interface that provides the functionality they
require.
Best practices dictate careful review of `bank` module code to ensure that
permissions are limited in the way that you expect.
### Denied Addresses
The `x/bank` module accepts a map of addresses that are considered blocklisted
from directly and explicitly receiving funds through means such as `MsgSend` and
`MsgMultiSend` and direct API calls like `SendCoinsFromModuleToAccount`.
Typically, these addresses are module accounts. If these addresses receive funds
outside the expected rules of the state machine, invariants are likely to be
broken and could result in a halted network.
By providing the `x/bank` module with a blocklisted set of addresses, an error occurs for the operation if a user or client attempts to directly or indirectly send funds to a blocklisted account, for example, by using [IBC](https://ibc.cosmos.network).
### Common Types
#### Input
An input of a multiparty transfer
```protobuf
// Input models transaction input.
message Input {
string address = 1;
repeated cosmos.base.v1beta1.Coin coins = 2;
}
```
#### Output
An output of a multiparty transfer.
```protobuf
// Output models transaction outputs.
message Output {
string address = 1;
repeated cosmos.base.v1beta1.Coin coins = 2;
}
```
### BaseKeeper
The base keeper provides full-permission access: the ability to arbitrary modify any account's balance and mint or burn coins.
Restricted permission to mint per module could be achieved by using baseKeeper with `WithMintCoinsRestriction` to give specific restrictions to mint (e.g. only minting certain denom).
```go
// Keeper defines a module interface that facilitates the transfer of coins
// between accounts.
type Keeper interface {
SendKeeper
WithMintCoinsRestriction(MintingRestrictionFn) BaseKeeper
InitGenesis(sdk.Context, *types.GenesisState)
ExportGenesis(sdk.Context) *types.GenesisState
GetSupply(ctx sdk.Context, denom string) sdk.Coin
HasSupply(ctx sdk.Context, denom string) bool
GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error)
IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool)
GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool)
HasDenomMetaData(ctx sdk.Context, denom string) bool
SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata)
IterateAllDenomMetaData(ctx sdk.Context, cb func(types.Metadata) bool)
SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) error
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
DelegateCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error
UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error
// GetAuthority gets the address capable of executing governance proposal messages. Usually the gov module account.
GetAuthority() string
types.QueryServer
}
```
### SendKeeper
The send keeper provides access to account balances and the ability to transfer coins between
accounts. The send keeper does not alter the total supply (mint or burn coins).
```go
// SendKeeper defines a module interface that facilitates the transfer of coins
// between accounts without the possibility of creating coins.
type SendKeeper interface {
ViewKeeper
InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
GetParams(ctx sdk.Context) types.Params
SetParams(ctx sdk.Context, params types.Params) error
IsSendEnabledDenom(ctx sdk.Context, denom string) bool
SetSendEnabled(ctx sdk.Context, denom string, value bool)
SetAllSendEnabled(ctx sdk.Context, sendEnableds []*types.SendEnabled)
DeleteSendEnabled(ctx sdk.Context, denom string)
IterateSendEnabledEntries(ctx sdk.Context, cb func(denom string, sendEnabled bool) (stop bool))
GetAllSendEnabledEntries(ctx sdk.Context) []types.SendEnabled
IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
BlockedAddr(addr sdk.AccAddress) bool
}
```
### ViewKeeper
The view keeper provides read-only access to account balances. The view keeper does not have balance alteration functionality. All balance lookups are `O(1)`.
```go
// ViewKeeper defines a module interface that facilitates read only access to
// account balances.
type ViewKeeper interface {
ValidateBalance(ctx sdk.Context, addr sdk.AccAddress) error
HasBalance(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coin) bool
GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
GetAccountsBalances(ctx sdk.Context) []types.Balance
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
SpendableCoin(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
IterateAccountBalances(ctx sdk.Context, addr sdk.AccAddress, cb func(coin sdk.Coin) (stop bool))
IterateAllBalances(ctx sdk.Context, cb func(address sdk.AccAddress, coin sdk.Coin) (stop bool))
}
```
<!-- order: 3 -->
## Messages
### MsgSend
Send coins from one address to another.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/bank/v1beta1/tx.proto#L21-L32
The message will fail under the following conditions:
* The coins do not have sending enabled
* The `to` address is restricted
### MsgMultiSend
Send coins from and to a series of different address. If any of the receiving addresses do not correspond to an existing account, a new account is created.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/bank/v1beta1/tx.proto#L37-L45
The message will fail under the following conditions:
* Any of the coins do not have sending enabled
* Any of the `to` addresses are restricted
* Any of the coins are locked
* The inputs and outputs do not correctly correspond to one another
### MsgUpdateParams
The `bank` module params can be updated through `MsgUpdateParams`, which can be done using governance proposal. The signer will always be the `gov` module account address.
+++ https://github.com/cosmos/cosmos-sdk/blob/e167855c9b99c4e58c1455533c6f88af5ff78ae1/proto/cosmos/bank/v1beta1/tx.proto#L56-L69
The message handling can fail if:
* signer is not the gov module account address.
<!-- order: 4 -->
## Events
The bank module emits the following events:
### Message Events
#### MsgSend
| Type | Attribute Key | Attribute Value |
| -------- | ------------- | ------------------ |
| transfer | recipient | {recipientAddress} |
| transfer | amount | {amount} |
| message | module | bank |
| message | action | send |
| message | sender | {senderAddress} |
#### MsgMultiSend
| Type | Attribute Key | Attribute Value |
| -------- | ------------- | ------------------ |
| transfer | recipient | {recipientAddress} |
| transfer | amount | {amount} |
| message | module | bank |
| message | action | multisend |
| message | sender | {senderAddress} |
### Keeper Events
In addition to message events, the bank keeper will produce events when the following methods are called (or any method which ends up calling them)
#### MintCoins
```json
{
"type": "coinbase",
"attributes": [
{
"key": "minter",
"value": "{{sdk.AccAddress of the module minting coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being minted}}",
"index": true
}
]
}
```
```json
{
"type": "coin_received",
"attributes": [
{
"key": "receiver",
"value": "{{sdk.AccAddress of the module minting coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being received}}",
"index": true
}
]
}
```
#### BurnCoins
```json
{
"type": "burn",
"attributes": [
{
"key": "burner",
"value": "{{sdk.AccAddress of the module burning coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being burned}}",
"index": true
}
]
}
```
```json
{
"type": "coin_spent",
"attributes": [
{
"key": "spender",
"value": "{{sdk.AccAddress of the module burning coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being burned}}",
"index": true
}
]
}
```
#### addCoins
```json
{
"type": "coin_received",
"attributes": [
{
"key": "receiver",
"value": "{{sdk.AccAddress of the address beneficiary of the coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being received}}",
"index": true
}
]
}
```
#### subUnlockedCoins/DelegateCoins
```json
{
"type": "coin_spent",
"attributes": [
{
"key": "spender",
"value": "{{sdk.AccAddress of the address which is spending coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being spent}}",
"index": true
}
]
}
```
<!-- order: 5 -->
## Parameters
The bank module contains the following parameters
### SendEnabled
The SendEnabled parameter is now deprecated and not to be use. It is replaced
with state store records.
### DefaultSendEnabled
The default send enabled value controls send transfer capability for all
coin denominations unless specifically included in the array of `SendEnabled`
parameters.
<!-- order: 6 -->
## Client
### CLI
A user can query and interact with the `bank` module using the CLI.
### Query
The `query` commands allow users to query `bank` state.
```sh
simd query bank --help
```
#### balances
The `balances` command allows users to query account balances by address.
```sh
simd query bank balances [address] [flags]
```
Example:
```sh
simd query bank balances cosmos1..
```
Example Output:
```yml
balances:
- amount: "1000000000"
denom: stake
pagination:
next_key: null
total: "0"
```
#### denom-metadata
The `denom-metadata` command allows users to query metadata for coin denominations. A user can query metadata for a single denomination using the `--denom` flag or all denominations without it.
```sh
simd query bank denom-metadata [flags]
```
Example:
```sh
simd query bank denom-metadata --denom stake
```
Example Output:
```yml
metadata:
base: stake
denom_units:
- aliases:
- STAKE
denom: stake
description: native staking token of simulation app
display: stake
name: SimApp Token
symbol: STK
```
#### total
The `total` command allows users to query the total supply of coins. A user can query the total supply for a single coin using the `--denom` flag or all coins without it.
```sh
simd query bank total [flags]
```
Example:
```sh
simd query bank total --denom stake
```
Example Output:
```yml
amount: "10000000000"
denom: stake
```
#### send-enabled
The `send-enabled` command allows users to query for all or some SendEnabled entries.
```sh
simd query bank send-enabled [denom1 ...] [flags]
```
Example:
```sh
simd query bank send-enabled
```
Example output:
```yml
send_enabled:
- denom: foocoin
enabled: true
- denom: barcoin
pagination:
next-key: null
total: 2
```
### Transactions
The `tx` commands allow users to interact with the `bank` module.
```sh
simd tx bank --help
```
#### send
The `send` command allows users to send funds from one account to another.
```sh
simd tx bank send [from_key_or_address] [to_address] [amount] [flags]
```
Example:
```sh
simd tx bank send cosmos1.. cosmos1.. 100stake
```
## gRPC
A user can query the `bank` module using gRPC endpoints.
### Balance
The `Balance` endpoint allows users to query account balance by address for a given denomination.
```sh
cosmos.bank.v1beta1.Query/Balance
```
Example:
```sh
grpcurl -plaintext \
-d '{"address":"cosmos1..","denom":"stake"}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/Balance
```
Example Output:
```json
{
"balance": {
"denom": "stake",
"amount": "1000000000"
}
}
```
### AllBalances
The `AllBalances` endpoint allows users to query account balance by address for all denominations.
```sh
cosmos.bank.v1beta1.Query/AllBalances
```
Example:
```sh
grpcurl -plaintext \
-d '{"address":"cosmos1.."}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/AllBalances
```
Example Output:
```json
{
"balances": [
{
"denom": "stake",
"amount": "1000000000"
}
],
"pagination": {
"total": "1"
}
}
```
### DenomMetadata
The `DenomMetadata` endpoint allows users to query metadata for a single coin denomination.
```sh
cosmos.bank.v1beta1.Query/DenomMetadata
```
Example:
```sh
grpcurl -plaintext \
-d '{"denom":"stake"}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/DenomMetadata
```
Example Output:
```json
{
"metadata": {
"description": "native staking token of simulation app",
"denomUnits": [
{
"denom": "stake",
"aliases": [
"STAKE"
]
}
],
"base": "stake",
"display": "stake",
"name": "SimApp Token",
"symbol": "STK"
}
}
```
### DenomsMetadata
The `DenomsMetadata` endpoint allows users to query metadata for all coin denominations.
```sh
cosmos.bank.v1beta1.Query/DenomsMetadata
```
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.bank.v1beta1.Query/DenomsMetadata
```
Example Output:
```json
{
"metadatas": [
{
"description": "native staking token of simulation app",
"denomUnits": [
{
"denom": "stake",
"aliases": [
"STAKE"
]
}
],
"base": "stake",
"display": "stake",
"name": "SimApp Token",
"symbol": "STK"
}
],
"pagination": {
"total": "1"
}
}
```
### DenomOwners
The `DenomOwners` endpoint allows users to query metadata for a single coin denomination.
```sh
cosmos.bank.v1beta1.Query/DenomOwners
```
Example:
```sh
grpcurl -plaintext \
-d '{"denom":"stake"}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/DenomOwners
```
Example Output:
```json
{
"denomOwners": [
{
"address": "cosmos1..",
"balance": {
"denom": "stake",
"amount": "5000000000"
}
},
{
"address": "cosmos1..",
"balance": {
"denom": "stake",
"amount": "5000000000"
}
},
],
"pagination": {
"total": "2"
}
}
```
### TotalSupply
The `TotalSupply` endpoint allows users to query the total supply of all coins.
```sh
cosmos.bank.v1beta1.Query/TotalSupply
```
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.bank.v1beta1.Query/TotalSupply
```
Example Output:
```json
{
"supply": [
{
"denom": "stake",
"amount": "10000000000"
}
],
"pagination": {
"total": "1"
}
}
```
### SupplyOf
The `SupplyOf` endpoint allows users to query the total supply of a single coin.
```sh
cosmos.bank.v1beta1.Query/SupplyOf
```
Example:
```sh
grpcurl -plaintext \
-d '{"denom":"stake"}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/SupplyOf
```
Example Output:
```json
{
"amount": {
"denom": "stake",
"amount": "10000000000"
}
}
```
### Params
The `Params` endpoint allows users to query the parameters of the `bank` module.
```sh
cosmos.bank.v1beta1.Query/Params
```
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.bank.v1beta1.Query/Params
```
Example Output:
```json
{
"params": {
"defaultSendEnabled": true
}
}
```
### SendEnabled
The `SendEnabled` enpoints allows users to query the SendEnabled entries of the `bank` module.
Any denominations NOT returned, use the `Params.DefaultSendEnabled` value.
```sh
cosmos.bank.v1beta1.Query/SendEnabled
```
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.bank.v1beta1.Query/SendEnabled
```
Example Output:
```json
{
"send_enabled": [
{
"denom": "foocoin",
"enabled": true
},
{
"denom": "barcoin"
}
],
"pagination": {
"next-key": null,
"total": 2
}
}
```

View File

@ -1,29 +0,0 @@
<!--
order: 1
-->
# State
The `x/bank` module keeps state of the following primary objects:
1. Account balances
2. Denomination metadata
3. The total supply of all balances
4. Information on which denominations are allowed to be sent.
In addition, the `x/bank` module keeps the following indexes to manage the
aforementioned state:
* Supply Index: `0x0 | byte(denom) -> byte(amount)`
* Denom Metadata Index: `0x1 | byte(denom) -> ProtocolBuffer(Metadata)`
* Balances Index: `0x2 | byte(address length) | []byte(address) | []byte(balance.Denom) -> ProtocolBuffer(balance)`
* Reverse Denomination to Address Index: `0x03 | byte(denom) | 0x00 | []byte(address) -> 0`
## Params
The bank module stores it's params in state with the prefix of `0x05`,
it can be updated with governance or the address with authority.
* Params: `0x05 | ProtocolBuffer(Params)`
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0-rc3/proto/cosmos/bank/v1beta1/bank.proto#L11-L16

View File

@ -1,148 +0,0 @@
<!--
order: 2
-->
# Keepers
The bank module provides these exported keeper interfaces that can be
passed to other modules that read or update account balances. Modules
should use the least-permissive interface that provides the functionality they
require.
Best practices dictate careful review of `bank` module code to ensure that
permissions are limited in the way that you expect.
## Blocklisting Addresses
The `x/bank` module accepts a map of addresses that are considered blocklisted
from directly and explicitly receiving funds through means such as `MsgSend` and
`MsgMultiSend` and direct API calls like `SendCoinsFromModuleToAccount`.
Typically, these addresses are module accounts. If these addresses receive funds
outside the expected rules of the state machine, invariants are likely to be
broken and could result in a halted network.
By providing the `x/bank` module with a blocklisted set of addresses, an error occurs for the operation if a user or client attempts to directly or indirectly send funds to a blocklisted account, for example, by using [IBC](https://ibc.cosmos.network).
## Common Types
### Input
An input of a multiparty transfer
```protobuf
// Input models transaction input.
message Input {
string address = 1;
repeated cosmos.base.v1beta1.Coin coins = 2;
}
```
### Output
An output of a multiparty transfer.
```protobuf
// Output models transaction outputs.
message Output {
string address = 1;
repeated cosmos.base.v1beta1.Coin coins = 2;
}
```
## BaseKeeper
The base keeper provides full-permission access: the ability to arbitrary modify any account's balance and mint or burn coins.
Restricted permission to mint per module could be achieved by using baseKeeper with `WithMintCoinsRestriction` to give specific restrictions to mint (e.g. only minting certain denom).
```go
// Keeper defines a module interface that facilitates the transfer of coins
// between accounts.
type Keeper interface {
SendKeeper
WithMintCoinsRestriction(MintingRestrictionFn) BaseKeeper
InitGenesis(sdk.Context, *types.GenesisState)
ExportGenesis(sdk.Context) *types.GenesisState
GetSupply(ctx sdk.Context, denom string) sdk.Coin
HasSupply(ctx sdk.Context, denom string) bool
GetPaginatedTotalSupply(ctx sdk.Context, pagination *query.PageRequest) (sdk.Coins, *query.PageResponse, error)
IterateTotalSupply(ctx sdk.Context, cb func(sdk.Coin) bool)
GetDenomMetaData(ctx sdk.Context, denom string) (types.Metadata, bool)
HasDenomMetaData(ctx sdk.Context, denom string) bool
SetDenomMetaData(ctx sdk.Context, denomMetaData types.Metadata)
IterateAllDenomMetaData(ctx sdk.Context, cb func(types.Metadata) bool)
SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) error
SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
DelegateCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
UndelegateCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error
DelegateCoins(ctx sdk.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error
UndelegateCoins(ctx sdk.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error
// GetAuthority gets the address capable of executing governance proposal messages. Usually the gov module account.
GetAuthority() string
types.QueryServer
}
```
## SendKeeper
The send keeper provides access to account balances and the ability to transfer coins between
accounts. The send keeper does not alter the total supply (mint or burn coins).
```go
// SendKeeper defines a module interface that facilitates the transfer of coins
// between accounts without the possibility of creating coins.
type SendKeeper interface {
ViewKeeper
InputOutputCoins(ctx sdk.Context, inputs []types.Input, outputs []types.Output) error
SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error
GetParams(ctx sdk.Context) types.Params
SetParams(ctx sdk.Context, params types.Params) error
IsSendEnabledDenom(ctx sdk.Context, denom string) bool
SetSendEnabled(ctx sdk.Context, denom string, value bool)
SetAllSendEnabled(ctx sdk.Context, sendEnableds []*types.SendEnabled)
DeleteSendEnabled(ctx sdk.Context, denom string)
IterateSendEnabledEntries(ctx sdk.Context, cb func(denom string, sendEnabled bool) (stop bool))
GetAllSendEnabledEntries(ctx sdk.Context) []types.SendEnabled
IsSendEnabledCoin(ctx sdk.Context, coin sdk.Coin) bool
IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
BlockedAddr(addr sdk.AccAddress) bool
}
```
## ViewKeeper
The view keeper provides read-only access to account balances. The view keeper does not have balance alteration functionality. All balance lookups are `O(1)`.
```go
// ViewKeeper defines a module interface that facilitates read only access to
// account balances.
type ViewKeeper interface {
ValidateBalance(ctx sdk.Context, addr sdk.AccAddress) error
HasBalance(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coin) bool
GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
GetAccountsBalances(ctx sdk.Context) []types.Balance
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
LockedCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
SpendableCoin(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
IterateAccountBalances(ctx sdk.Context, addr sdk.AccAddress, cb func(coin sdk.Coin) (stop bool))
IterateAllBalances(ctx sdk.Context, cb func(address sdk.AccAddress, coin sdk.Coin) (stop bool))
}
```

View File

@ -1,38 +0,0 @@
<!--
order: 3
-->
# Messages
## MsgSend
Send coins from one address to another.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/bank/v1beta1/tx.proto#L21-L32
The message will fail under the following conditions:
* The coins do not have sending enabled
* The `to` address is restricted
## MsgMultiSend
Send coins from and to a series of different address. If any of the receiving addresses do not correspond to an existing account, a new account is created.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/bank/v1beta1/tx.proto#L37-L45
The message will fail under the following conditions:
* Any of the coins do not have sending enabled
* Any of the `to` addresses are restricted
* Any of the coins are locked
* The inputs and outputs do not correctly correspond to one another
## MsgUpdateParams
The `bank` module params can be updated through `MsgUpdateParams`, which can be done using governance proposal. The signer will always be the `gov` module account address.
+++ https://github.com/cosmos/cosmos-sdk/blob/e167855c9b99c4e58c1455533c6f88af5ff78ae1/proto/cosmos/bank/v1beta1/tx.proto#L56-L69
The message handling can fail if:
* signer is not the gov module account address.

View File

@ -1,149 +0,0 @@
<!--
order: 4
-->
# Events
The bank module emits the following events:
## Handlers
### MsgSend
| Type | Attribute Key | Attribute Value |
| -------- | ------------- | ------------------ |
| transfer | recipient | {recipientAddress} |
| transfer | amount | {amount} |
| message | module | bank |
| message | action | send |
| message | sender | {senderAddress} |
### MsgMultiSend
| Type | Attribute Key | Attribute Value |
| -------- | ------------- | ------------------ |
| transfer | recipient | {recipientAddress} |
| transfer | amount | {amount} |
| message | module | bank |
| message | action | multisend |
| message | sender | {senderAddress} |
## Keeper events
In addition to handlers events, the bank keeper will produce events when the following methods are called (or any method which ends up calling them)
### MintCoins
```json
{
"type": "coinbase",
"attributes": [
{
"key": "minter",
"value": "{{sdk.AccAddress of the module minting coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being minted}}",
"index": true
}
]
}
```
```json
{
"type": "coin_received",
"attributes": [
{
"key": "receiver",
"value": "{{sdk.AccAddress of the module minting coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being received}}",
"index": true
}
]
}
```
### BurnCoins
```json
{
"type": "burn",
"attributes": [
{
"key": "burner",
"value": "{{sdk.AccAddress of the module burning coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being burned}}",
"index": true
}
]
}
```
```json
{
"type": "coin_spent",
"attributes": [
{
"key": "spender",
"value": "{{sdk.AccAddress of the module burning coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being burned}}",
"index": true
}
]
}
```
### addCoins
```json
{
"type": "coin_received",
"attributes": [
{
"key": "receiver",
"value": "{{sdk.AccAddress of the address beneficiary of the coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being received}}",
"index": true
}
]
}
```
### subUnlockedCoins/DelegateCoins
```json
{
"type": "coin_spent",
"attributes": [
{
"key": "spender",
"value": "{{sdk.AccAddress of the address which is spending coins}}",
"index": true
},
{
"key": "amount",
"value": "{{sdk.Coins being spent}}",
"index": true
}
]
}
```

View File

@ -1,24 +0,0 @@
<!--
order: 5
-->
# Parameters
The bank module contains the following parameters:
| Key | Type | Example |
| ------------------ | ------------- |--------------|
| SendEnabled | []SendEnabled | (deprecated) |
| DefaultSendEnabled | bool | true |
## SendEnabled
The SendEnabled parameter is now deprecated and not to be use. It is replaced
with state store records.
## DefaultSendEnabled
The default send enabled value controls send transfer capability for all
coin denominations unless specifically included in the array of `SendEnabled`
parameters.

View File

@ -1,454 +0,0 @@
<!--
order: 6
-->
# Client
## CLI
A user can query and interact with the `bank` module using the CLI.
### Query
The `query` commands allow users to query `bank` state.
```sh
simd query bank --help
```
#### balances
The `balances` command allows users to query account balances by address.
```sh
simd query bank balances [address] [flags]
```
Example:
```sh
simd query bank balances cosmos1..
```
Example Output:
```yml
balances:
- amount: "1000000000"
denom: stake
pagination:
next_key: null
total: "0"
```
#### denom-metadata
The `denom-metadata` command allows users to query metadata for coin denominations. A user can query metadata for a single denomination using the `--denom` flag or all denominations without it.
```sh
simd query bank denom-metadata [flags]
```
Example:
```sh
simd query bank denom-metadata --denom stake
```
Example Output:
```yml
metadata:
base: stake
denom_units:
- aliases:
- STAKE
denom: stake
description: native staking token of simulation app
display: stake
name: SimApp Token
symbol: STK
```
#### total
The `total` command allows users to query the total supply of coins. A user can query the total supply for a single coin using the `--denom` flag or all coins without it.
```sh
simd query bank total [flags]
```
Example:
```sh
simd query bank total --denom stake
```
Example Output:
```yml
amount: "10000000000"
denom: stake
```
#### send-enabled
The `send-enabled` command allows users to query for all or some SendEnabled entries.
```sh
simd query bank send-enabled [denom1 ...] [flags]
```
Example:
```sh
simd query bank send-enabled
```
Example output:
```yml
send_enabled:
- denom: foocoin
enabled: true
- denom: barcoin
pagination:
next-key: null
total: 2
```
### Transactions
The `tx` commands allow users to interact with the `bank` module.
```sh
simd tx bank --help
```
#### send
The `send` command allows users to send funds from one account to another.
```sh
simd tx bank send [from_key_or_address] [to_address] [amount] [flags]
```
Example:
```sh
simd tx bank send cosmos1.. cosmos1.. 100stake
```
## gRPC
A user can query the `bank` module using gRPC endpoints.
### Balance
The `Balance` endpoint allows users to query account balance by address for a given denomination.
```sh
cosmos.bank.v1beta1.Query/Balance
```
Example:
```sh
grpcurl -plaintext \
-d '{"address":"cosmos1..","denom":"stake"}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/Balance
```
Example Output:
```json
{
"balance": {
"denom": "stake",
"amount": "1000000000"
}
}
```
### AllBalances
The `AllBalances` endpoint allows users to query account balance by address for all denominations.
```sh
cosmos.bank.v1beta1.Query/AllBalances
```
Example:
```sh
grpcurl -plaintext \
-d '{"address":"cosmos1.."}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/AllBalances
```
Example Output:
```json
{
"balances": [
{
"denom": "stake",
"amount": "1000000000"
}
],
"pagination": {
"total": "1"
}
}
```
### DenomMetadata
The `DenomMetadata` endpoint allows users to query metadata for a single coin denomination.
```sh
cosmos.bank.v1beta1.Query/DenomMetadata
```
Example:
```sh
grpcurl -plaintext \
-d '{"denom":"stake"}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/DenomMetadata
```
Example Output:
```json
{
"metadata": {
"description": "native staking token of simulation app",
"denomUnits": [
{
"denom": "stake",
"aliases": [
"STAKE"
]
}
],
"base": "stake",
"display": "stake",
"name": "SimApp Token",
"symbol": "STK"
}
}
```
### DenomsMetadata
The `DenomsMetadata` endpoint allows users to query metadata for all coin denominations.
```sh
cosmos.bank.v1beta1.Query/DenomsMetadata
```
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.bank.v1beta1.Query/DenomsMetadata
```
Example Output:
```json
{
"metadatas": [
{
"description": "native staking token of simulation app",
"denomUnits": [
{
"denom": "stake",
"aliases": [
"STAKE"
]
}
],
"base": "stake",
"display": "stake",
"name": "SimApp Token",
"symbol": "STK"
}
],
"pagination": {
"total": "1"
}
}
```
### DenomOwners
The `DenomOwners` endpoint allows users to query metadata for a single coin denomination.
```sh
cosmos.bank.v1beta1.Query/DenomOwners
```
Example:
```sh
grpcurl -plaintext \
-d '{"denom":"stake"}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/DenomOwners
```
Example Output:
```json
{
"denomOwners": [
{
"address": "cosmos1..",
"balance": {
"denom": "stake",
"amount": "5000000000"
}
},
{
"address": "cosmos1..",
"balance": {
"denom": "stake",
"amount": "5000000000"
}
},
],
"pagination": {
"total": "2"
}
}
```
### TotalSupply
The `TotalSupply` endpoint allows users to query the total supply of all coins.
```sh
cosmos.bank.v1beta1.Query/TotalSupply
```
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.bank.v1beta1.Query/TotalSupply
```
Example Output:
```json
{
"supply": [
{
"denom": "stake",
"amount": "10000000000"
}
],
"pagination": {
"total": "1"
}
}
```
### SupplyOf
The `SupplyOf` endpoint allows users to query the total supply of a single coin.
```sh
cosmos.bank.v1beta1.Query/SupplyOf
```
Example:
```sh
grpcurl -plaintext \
-d '{"denom":"stake"}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/SupplyOf
```
Example Output:
```json
{
"amount": {
"denom": "stake",
"amount": "10000000000"
}
}
```
### Params
The `Params` endpoint allows users to query the parameters of the `bank` module.
```sh
cosmos.bank.v1beta1.Query/Params
```
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.bank.v1beta1.Query/Params
```
Example Output:
```json
{
"params": {
"defaultSendEnabled": true
}
}
```
### SendEnabled
The `SendEnabled` enpoints allows users to query the SendEnabled entries of the `bank` module.
Any denominations NOT returned, use the `Params.DefaultSendEnabled` value.
```sh
cosmos.bank.v1beta1.Query/SendEnabled
```
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.bank.v1beta1.Query/SendEnabled
```
Example Output:
```json
{
"send_enabled": [
{
"denom": "foocoin",
"enabled": true
},
{
"denom": "barcoin"
}
],
"pagination": {
"next-key": null,
"total": 2
}
}
```

View File

@ -1,106 +0,0 @@
<!--
order: 0
title: Bank Overview
parent:
title: "bank"
-->
# `x/bank`
## Abstract
This document specifies the bank module of the Cosmos SDK.
The bank module is responsible for handling multi-asset coin transfers between
accounts and tracking special-case pseudo-transfers which must work differently
with particular kinds of accounts (notably delegating/undelegating for vesting
accounts). It exposes several interfaces with varying capabilities for secure
interaction with other modules which must alter user balances.
In addition, the bank module tracks and provides query support for the total
supply of all assets used in the application.
This module will be used in the Cosmos Hub.
## Supply
The `supply` functionality:
* passively tracks the total supply of coins within a chain,
* provides a pattern for modules to hold/interact with `Coins`, and
* introduces the invariant check to verify a chain's total supply.
### Total Supply
The total `Supply` of the network is equal to the sum of all coins from the
account. The total supply is updated every time a `Coin` is minted (eg: as part
of the inflation mechanism) or burned (eg: due to slashing or if a governance
proposal is vetoed).
## Module Accounts
The supply functionality introduces a new type of `auth.Account` which can be used by
modules to allocate tokens and in special cases mint or burn tokens. At a base
level these module accounts are capable of sending/receiving tokens to and from
`auth.Account`s and other module accounts. This design replaces previous
alternative designs where, to hold tokens, modules would burn the incoming
tokens from the sender account, and then track those tokens internally. Later,
in order to send tokens, the module would need to effectively mint tokens
within a destination account. The new design removes duplicate logic between
modules to perform this accounting.
The `ModuleAccount` interface is defined as follows:
```go
type ModuleAccount interface {
auth.Account // same methods as the Account interface
GetName() string // name of the module; used to obtain the address
GetPermissions() []string // permissions of module account
HasPermission(string) bool
}
```
> **WARNING!**
> Any module or message handler that allows either direct or indirect sending of funds must explicitly guarantee those funds cannot be sent to module accounts (unless allowed).
The supply `Keeper` also introduces new wrapper functions for the auth `Keeper`
and the bank `Keeper` that are related to `ModuleAccount`s in order to be able
to:
* Get and set `ModuleAccount`s by providing the `Name`.
* Send coins from and to other `ModuleAccount`s or standard `Account`s
(`BaseAccount` or `VestingAccount`) by passing only the `Name`.
* `Mint` or `Burn` coins for a `ModuleAccount` (restricted to its permissions).
### Permissions
Each `ModuleAccount` has a different set of permissions that provide different
object capabilities to perform certain actions. Permissions need to be
registered upon the creation of the supply `Keeper` so that every time a
`ModuleAccount` calls the allowed functions, the `Keeper` can lookup the
permissions to that specific account and perform or not perform the action.
The available permissions are:
* `Minter`: allows for a module to mint a specific amount of coins.
* `Burner`: allows for a module to burn a specific amount of coins.
* `Staking`: allows for a module to delegate and undelegate a specific amount of coins.
## Contents
1. **[State](01_state.md)**
2. **[Keepers](02_keepers.md)**
* [Common Types](02_keepers.md#common-types)
* [BaseKeeper](02_keepers.md#basekeeper)
* [SendKeeper](02_keepers.md#sendkeeper)
* [ViewKeeper](02_keepers.md#viewkeeper)
3. **[Messages](03_messages.md)**
* [MsgSend](03_messages.md#msgsend)
* [MsgMultiSend](03_messages.md#msgmultisend)
4. **[Events](04_events.md)**
* [Handlers](04_events.md#handlers)
5. **[Parameters](05_params.md)**
6. **[Client](06_client.md)**
* [CLI](06_client.md#cli)
* [gRPC](06_client.md#grpc)

View File

@ -1,7 +1,141 @@
<!--
order: 0
title: Capability Overview
parent:
title: "capability"
-->
# Capability
# `x/capability`
* [Capability](spec/README.md) - Object capability implementation.
## Overview
`x/capability` is an implementation of a Cosmos SDK module, per [ADR 003](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-003-dynamic-capability-store.md),
that allows for provisioning, tracking, and authenticating multi-owner capabilities
at runtime.
The keeper maintains two states: persistent and ephemeral in-memory. The persistent
store maintains a globally unique auto-incrementing index and a mapping from
capability index to a set of capability owners that are defined as a module and
capability name tuple. The in-memory ephemeral state keeps track of the actual
capabilities, represented as addresses in local memory, with both forward and reverse indexes.
The forward index maps module name and capability tuples to the capability name. The
reverse index maps between the module and capability name and the capability itself.
The keeper allows the creation of "scoped" sub-keepers which are tied to a particular
module by name. Scoped keepers must be created at application initialization and
passed to modules, which can then use them to claim capabilities they receive and
retrieve capabilities which they own by name, in addition to creating new capabilities
& authenticating capabilities passed by other modules. A scoped keeper cannot escape its scope,
so a module cannot interfere with or inspect capabilities owned by other modules.
The keeper provides no other core functionality that can be found in other modules
like queriers, REST and CLI handlers, and genesis state.
## Initialization
During application initialization, the keeper must be instantiated with a persistent
store key and an in-memory store key.
```go
type App struct {
// ...
capabilityKeeper *capability.Keeper
}
func NewApp(...) *App {
// ...
app.capabilityKeeper = capability.NewKeeper(codec, persistentStoreKey, memStoreKey)
}
```
After the keeper is created, it can be used to create scoped sub-keepers which
are passed to other modules that can create, authenticate, and claim capabilities.
After all the necessary scoped keepers are created and the state is loaded, the
main capability keeper must be sealed to prevent further scoped keepers from
being created.
```go
func NewApp(...) *App {
// ...
// Creating a scoped keeper
scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName)
// Seal the capability keeper to prevent any further modules from creating scoped
// sub-keepers.
app.capabilityKeeper.Seal()
return app
}
```
## Contents
* [Concepts](#concepts)
* [Capabilities](#capabilities)
* [Stores](#stores)
* [State](#state)
* [In persisted KV store](#in-persisted-kv-store)
* [In-memory KV store](#in-memory-kv-store)
<!-- order: 1 -->
# Concepts
## Capabilities
Capabilities are multi-owner. A scoped keeper can create a capability via `NewCapability`
which creates a new unique, unforgeable object-capability reference. The newly
created capability is automatically persisted; the calling module need not call
`ClaimCapability`. Calling `NewCapability` will create the capability with the
calling module and name as a tuple to be treated the capabilities first owner.
Capabilities can be claimed by other modules which add them as owners. `ClaimCapability`
allows a module to claim a capability key which it has received from another
module so that future `GetCapability` calls will succeed. `ClaimCapability` MUST
be called if a module which receives a capability wishes to access it by name in
the future. Again, capabilities are multi-owner, so if multiple modules have a
single Capability reference, they will all own it. If a module receives a capability
from another module but does not call `ClaimCapability`, it may use it in the executing
transaction but will not be able to access it afterwards.
`AuthenticateCapability` can be called by any module to check that a capability
does in fact correspond to a particular name (the name can be un-trusted user input)
with which the calling module previously associated it.
`GetCapability` allows a module to fetch a capability which it has previously
claimed by name. The module is not allowed to retrieve capabilities which it does
not own.
## Stores
* MemStore
* KeyStore
<!-- order: 2 -->
# State
## In persisted KV store
1. Global unique capability index
2. Capability owners
Indexes:
* Unique index: `[]byte("index") -> []byte(currentGlobalIndex)`
* Capability Index: `[]byte("capability_index") | []byte(index) -> ProtocolBuffer(CapabilityOwners)`
## In-memory KV store
1. Initialized flag
2. Mapping between the module and capability tuple and the capability name
3. Mapping between the module and capability name and its index
Indexes:
* Initialized flag: `[]byte("mem_initialized")`
* RevCapabilityKey: `[]byte(moduleName + "/rev/" + capabilityName) -> []byte(index)`
* FwdCapabilityKey: `[]byte(moduleName + "/fwd/" + capabilityPointerAddress) -> []byte(capabilityName)`

View File

@ -1,35 +0,0 @@
<!--
order: 1
-->
# Concepts
## Capabilities
Capabilities are multi-owner. A scoped keeper can create a capability via `NewCapability`
which creates a new unique, unforgeable object-capability reference. The newly
created capability is automatically persisted; the calling module need not call
`ClaimCapability`. Calling `NewCapability` will create the capability with the
calling module and name as a tuple to be treated the capabilities first owner.
Capabilities can be claimed by other modules which add them as owners. `ClaimCapability`
allows a module to claim a capability key which it has received from another
module so that future `GetCapability` calls will succeed. `ClaimCapability` MUST
be called if a module which receives a capability wishes to access it by name in
the future. Again, capabilities are multi-owner, so if multiple modules have a
single Capability reference, they will all own it. If a module receives a capability
from another module but does not call `ClaimCapability`, it may use it in the executing
transaction but will not be able to access it afterwards.
`AuthenticateCapability` can be called by any module to check that a capability
does in fact correspond to a particular name (the name can be un-trusted user input)
with which the calling module previously associated it.
`GetCapability` allows a module to fetch a capability which it has previously
claimed by name. The module is not allowed to retrieve capabilities which it does
not own.
## Stores
* MemStore
* KeyStore

View File

@ -1,26 +0,0 @@
<!--
order: 2
-->
# State
## In persisted KV store
1. Global unique capability index
2. Capability owners
Indexes:
* Unique index: `[]byte("index") -> []byte(currentGlobalIndex)`
* Capability Index: `[]byte("capability_index") | []byte(index) -> ProtocolBuffer(CapabilityOwners)`
## In-memory KV store
1. Initialized flag
2. Mapping between the module and capability tuple and the capability name
3. Mapping between the module and capability name and its index
Indexes:
* Initialized flag: `[]byte("mem_initialized")`
* RevCapabilityKey: `[]byte(moduleName + "/rev/" + capabilityName) -> []byte(index)`
* FwdCapabilityKey: `[]byte(moduleName + "/fwd/" + capabilityPointerAddress) -> []byte(capabilityName)`

View File

@ -1,77 +0,0 @@
<!--
order: 0
title: Capability Overview
parent:
title: "capability"
-->
# `capability`
## Overview
`x/capability` is an implementation of a Cosmos SDK module, per [ADR 003](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-003-dynamic-capability-store.md),
that allows for provisioning, tracking, and authenticating multi-owner capabilities
at runtime.
The keeper maintains two states: persistent and ephemeral in-memory. The persistent
store maintains a globally unique auto-incrementing index and a mapping from
capability index to a set of capability owners that are defined as a module and
capability name tuple. The in-memory ephemeral state keeps track of the actual
capabilities, represented as addresses in local memory, with both forward and reverse indexes.
The forward index maps module name and capability tuples to the capability name. The
reverse index maps between the module and capability name and the capability itself.
The keeper allows the creation of "scoped" sub-keepers which are tied to a particular
module by name. Scoped keepers must be created at application initialization and
passed to modules, which can then use them to claim capabilities they receive and
retrieve capabilities which they own by name, in addition to creating new capabilities
& authenticating capabilities passed by other modules. A scoped keeper cannot escape its scope,
so a module cannot interfere with or inspect capabilities owned by other modules.
The keeper provides no other core functionality that can be found in other modules
like queriers, REST and CLI handlers, and genesis state.
## Initialization
During application initialization, the keeper must be instantiated with a persistent
store key and an in-memory store key.
```go
type App struct {
// ...
capabilityKeeper *capability.Keeper
}
func NewApp(...) *App {
// ...
app.capabilityKeeper = capability.NewKeeper(codec, persistentStoreKey, memStoreKey)
}
```
After the keeper is created, it can be used to create scoped sub-keepers which
are passed to other modules that can create, authenticate, and claim capabilities.
After all the necessary scoped keepers are created and the state is loaded, the
main capability keeper must be sealed to prevent further scoped keepers from
being created.
```go
func NewApp(...) *App {
// ...
// Creating a scoped keeper
scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName)
// Seal the capability keeper to prevent any further modules from creating scoped
// sub-keepers.
app.capabilityKeeper.Seal()
return app
}
```
## Contents
1. **[Concepts](01_concepts.md)**
1. **[State](02_state.md)**

View File

@ -1,7 +1,119 @@
<!--
order: 0
title: Crisis Overview
parent:
title: "crisis"
-->
# Crisis
# `x/crisis`
* [Crisis](spec/README.md) - Halting the blockchain under certain circumstances (e.g. if an invariant is broken).
## Overview
The crisis module halts the blockchain under the circumstance that a blockchain
invariant is broken. Invariants can be registered with the application during the
application initialization process.
## Contents
* [State](#state)
* [Messages](#messages)
* [Events](#events)
* [Parameters](#parameters)
* [Client](#client)
* [CLI](#cli)
<!-- order: 1 -->
# State
## ConstantFee
Due to the anticipated large gas cost requirement to verify an invariant (and
potential to exceed the maximum allowable block gas limit) a constant fee is
used instead of the standard gas consumption method. The constant fee is
intended to be larger than the anticipated gas cost of running the invariant
with the standard gas consumption method.
The ConstantFee param is stored in the module params state with the prefix of `0x01`,
it can be updated with governance or the address with authority.
* Params: `mint/params -> legacy_amino(sdk.Coin)`
<!-- order: 2 -->
# Messages
In this section we describe the processing of the crisis messages and the
corresponding updates to the state.
## MsgVerifyInvariant
Blockchain invariants can be checked using the `MsgVerifyInvariant` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/crisis/v1beta1/tx.proto#L16-L26
This message is expected to fail if:
* the sender does not have enough coins for the constant fee
* the invariant route is not registered
This message checks the invariant provided, and if the invariant is broken it
panics, halting the blockchain. If the invariant is broken, the constant fee is
never deducted as the transaction is never committed to a block (equivalent to
being refunded). However, if the invariant is not broken, the constant fee will
not be refunded.
<!-- order: 3 -->
# Events
The crisis module emits the following events:
## Handlers
### MsgVerifyInvariance
| Type | Attribute Key | Attribute Value |
|-----------|---------------|------------------|
| invariant | route | {invariantRoute} |
| message | module | crisis |
| message | action | verify_invariant |
| message | sender | {senderAddress} |
# Parameters
The crisis module contains the following parameters:
| Key | Type | Example |
|-------------|---------------|-----------------------------------|
| ConstantFee | object (coin) | {"denom":"uatom","amount":"1000"} |
<!-- order: 4 -->
# Client
## CLI
A user can query and interact with the `crisis` module using the CLI.
### Transactions
The `tx` commands allow users to interact with the `crisis` module.
```bash
simd tx crisis --help
```
#### invariant-broken
The `invariant-broken` command submits proof when an invariant was broken to halt the chain
```bash
simd tx crisis invariant-broken [module-name] [invariant-route] [flags]
```
Example:
```bash
simd tx crisis invariant-broken bank total-supply --from=[keyname or address]
```

View File

@ -1,18 +0,0 @@
<!--
order: 1
-->
# State
## ConstantFee
Due to the anticipated large gas cost requirement to verify an invariant (and
potential to exceed the maximum allowable block gas limit) a constant fee is
used instead of the standard gas consumption method. The constant fee is
intended to be larger than the anticipated gas cost of running the invariant
with the standard gas consumption method.
The ConstantFee param is stored in the module params state with the prefix of `0x01`,
it can be updated with governance or the address with authority.
* Params: `mint/params -> legacy_amino(sdk.Coin)`

View File

@ -1,25 +0,0 @@
<!--
order: 2
-->
# Messages
In this section we describe the processing of the crisis messages and the
corresponding updates to the state.
## MsgVerifyInvariant
Blockchain invariants can be checked using the `MsgVerifyInvariant` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/crisis/v1beta1/tx.proto#L16-L26
This message is expected to fail if:
* the sender does not have enough coins for the constant fee
* the invariant route is not registered
This message checks the invariant provided, and if the invariant is broken it
panics, halting the blockchain. If the invariant is broken, the constant fee is
never deducted as the transaction is never committed to a block (equivalent to
being refunded). However, if the invariant is not broken, the constant fee will
not be refunded.

View File

@ -1,18 +0,0 @@
<!--
order: 3
-->
# Events
The crisis module emits the following events:
## Handlers
### MsgVerifyInvariance
| Type | Attribute Key | Attribute Value |
|-----------|---------------|------------------|
| invariant | route | {invariantRoute} |
| message | module | crisis |
| message | action | verify_invariant |
| message | sender | {senderAddress} |

View File

@ -1,11 +0,0 @@
<!--
order: 4
-->
# Parameters
The crisis module contains the following parameters:
| Key | Type | Example |
|-------------|---------------|-----------------------------------|
| ConstantFee | object (coin) | {"denom":"uatom","amount":"1000"} |

View File

@ -1,31 +0,0 @@
<!--
order: 5
-->
# Client
## CLI
A user can query and interact with the `crisis` module using the CLI.
### Transactions
The `tx` commands allow users to interact with the `crisis` module.
```bash
simd tx crisis --help
```
#### invariant-broken
The `invariant-broken` command submits proof when an invariant was broken to halt the chain
```bash
simd tx crisis invariant-broken [module-name] [invariant-route] [flags]
```
Example:
```bash
simd tx crisis invariant-broken bank total-supply --from=[keyname or address]
```

View File

@ -1,26 +0,0 @@
<!--
order: 0
title: Crisis Overview
parent:
title: "crisis"
-->
# `crisis`
## Overview
The crisis module halts the blockchain under the circumstance that a blockchain
invariant is broken. Invariants can be registered with the application during the
application initialization process.
## Contents
1. **[State](01_state.md)**
* [ConstantFee](01_state.md#constantfee)
2. **[Messages](02_messages.md)**
* [MsgVerifyInvariant](02_messages.md#msgverifyinvariant)
3. **[Events](03_events.md)**
* [Handlers](03_events.md#handlers)
4. **[Parameters](04_params.md)**
5. **[Client](05_client.md)**
* [CLI](05_client.md#cli)

View File

@ -1,7 +1,997 @@
<!--
order: 0
title: Distribution Overview
parent:
title: "distribution"
-->
# Distribution
# `x/distribution`
* [Distribution](spec/README.md) - Fee distribution, and staking token provision distribution.
## Overview
This _simple_ distribution mechanism describes a functional way to passively
distribute rewards between validators and delegators. Note that this mechanism does
not distribute funds in as precisely as active reward distribution mechanisms and
will therefore be upgraded in the future.
The mechanism operates as follows. Collected rewards are pooled globally and
divided out passively to validators and delegators. Each validator has the
opportunity to charge commission to the delegators on the rewards collected on
behalf of the delegators. Fees are collected directly into a global reward pool
and validator proposer-reward pool. Due to the nature of passive accounting,
whenever changes to parameters which affect the rate of reward distribution
occurs, withdrawal of rewards must also occur.
* Whenever withdrawing, one must withdraw the maximum amount they are entitled
to, leaving nothing in the pool.
* Whenever bonding, unbonding, or re-delegating tokens to an existing account, a
full withdrawal of the rewards must occur (as the rules for lazy accounting
change).
* Whenever a validator chooses to change the commission on rewards, all accumulated
commission rewards must be simultaneously withdrawn.
The above scenarios are covered in `hooks.md`.
The distribution mechanism outlined herein is used to lazily distribute the
following rewards between validators and associated delegators:
* multi-token fees to be socially distributed
* inflated staked asset provisions
* validator commission on all rewards earned by their delegators stake
Fees are pooled within a global pool. The mechanisms used allow for validators
and delegators to independently and lazily withdraw their rewards.
## Shortcomings
As a part of the lazy computations, each delegator holds an accumulation term
specific to each validator which is used to estimate what their approximate
fair portion of tokens held in the global fee pool is owed to them.
```text
entitlement = delegator-accumulation / all-delegators-accumulation
```
Under the circumstance that there was constant and equal flow of incoming
reward tokens every block, this distribution mechanism would be equal to the
active distribution (distribute individually to all delegators each block).
However, this is unrealistic so deviations from the active distribution will
occur based on fluctuations of incoming reward tokens as well as timing of
reward withdrawal by other delegators.
If you happen to know that incoming rewards are about to significantly increase,
you are incentivized to not withdraw until after this event, increasing the
worth of your existing _accum_. See [#2764](https://github.com/cosmos/cosmos-sdk/issues/2764)
for further details.
## Effect on Staking
Charging commission on Atom provisions while also allowing for Atom-provisions
to be auto-bonded (distributed directly to the validators bonded stake) is
problematic within BPoS. Fundamentally, these two mechanisms are mutually
exclusive. If both commission and auto-bonding mechanisms are simultaneously
applied to the staking-token then the distribution of staking-tokens between
any validator and its delegators will change with each block. This then
necessitates a calculation for each delegation records for each block -
which is considered computationally expensive.
In conclusion, we can only have Atom commission and unbonded atoms
provisions or bonded atom provisions with no Atom commission, and we elect to
implement the former. Stakeholders wishing to rebond their provisions may elect
to set up a script to periodically withdraw and rebond rewards.
## Contents
* [Concepts](#concepts)
* [State](#state)
* [FeePool](#feepool)
* [Validator Distribution](#validator-distribution)
* [Delegation Distribution](#delegation-distribution)
* [Params](#params)
* [Begin Block](#begin-block)
* [Messages](#messages)
* [Hooks](#hooks)
* [Events](#events)
* [Parameters](#parameters)
* [Client](#client)
* [CLI](#cli)
* [gRPC](#grpc)
<!-- order: 1 -->
# Concepts
In Proof of Stake (PoS) blockchains, rewards gained from transaction fees are paid to validators. The fee distribution module fairly distributes the rewards to the validators' constituent delegators.
Rewards are calculated per period. The period is updated each time a validator's delegation changes, for example, when the validator receives a new delegation.
The rewards for a single validator can then be calculated by taking the total rewards for the period before the delegation started, minus the current total rewards.
To learn more, see the [F1 Fee Distribution paper](/docs/spec/fee_distribution/f1_fee_distr.pdf).
The commission to the validator is paid when the validator is removed or when the validator requests a withdrawal.
The commission is calculated and incremented at every `BeginBlock` operation to update accumulated fee amounts.
The rewards to a delegator are distributed when the delegation is changed or removed, or a withdrawal is requested.
Before rewards are distributed, all slashes to the validator that occurred during the current delegation are applied.
## Reference Counting in F1 Fee Distribution
In F1 fee distribution, the rewards a delegator receives are calculated when their delegation is withdrawn. This calculation must read the terms of the summation of rewards divided by the share of tokens from the period which they ended when they delegated, and the final period that was created for the withdrawal.
Additionally, as slashes change the amount of tokens a delegation will have (but we calculate this lazily,
only when a delegator un-delegates), we must calculate rewards in separate periods before / after any slashes
which occurred in between when a delegator delegated and when they withdrew their rewards. Thus slashes, like
delegations, reference the period which was ended by the slash event.
All stored historical rewards records for periods which are no longer referenced by any delegations
or any slashes can thus be safely removed, as they will never be read (future delegations and future
slashes will always reference future periods). This is implemented by tracking a `ReferenceCount`
along with each historical reward storage entry. Each time a new object (delegation or slash)
is created which might need to reference the historical record, the reference count is incremented.
Each time one object which previously needed to reference the historical record is deleted, the reference
count is decremented. If the reference count hits zero, the historical record is deleted.
<!-- order: 2 -->
# State
## FeePool
All globally tracked parameters for distribution are stored within
`FeePool`. Rewards are collected and added to the reward pool and
distributed to validators/delegators from here.
Note that the reward pool holds decimal coins (`DecCoins`) to allow
for fractions of coins to be received from operations like inflation.
When coins are distributed from the pool they are truncated back to
`sdk.Coins` which are non-decimal.
* FeePool: `0x00 -> ProtocolBuffer(FeePool)`
```go
// coins with decimal
type DecCoins []DecCoin
type DecCoin struct {
Amount sdk.Dec
Denom string
}
```
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/distribution/v1beta1/distribution.proto#L92-L96
## Validator Distribution
Validator distribution information for the relevant validator is updated each time:
1. delegation amount to a validator is updated,
2. any delegator withdraws from a validator, or
3. the validator withdraws its commission.
* ValidatorDistInfo: `0x02 | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)`
```go
type ValidatorDistInfo struct {
OperatorAddress sdk.AccAddress
SelfBondRewards sdk.DecCoins
ValidatorCommission types.ValidatorAccumulatedCommission
}
```
## Delegation Distribution
Each delegation distribution only needs to record the height at which it last
withdrew fees. Because a delegation must withdraw fees each time it's
properties change (aka bonded tokens etc.) its properties will remain constant
and the delegator's _accumulation_ factor can be calculated passively knowing
only the height of the last withdrawal and its current properties.
* DelegationDistInfo: `0x02 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(delegatorDist)`
```go
type DelegationDistInfo struct {
WithdrawalHeight int64 // last time this delegation withdrew rewards
}
```
## Params
The distribution module stores it's params in state with the prefix of `0x09`,
it can be updated with governance or the address with authority.
* Params: `0x09 | ProtocolBuffer(Params)`
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/distribution/v1beta1/distribution.proto#L11-L30
<!-- order: 3 -->
# Begin Block
At each `BeginBlock`, all fees received in the previous block are transferred to
the distribution `ModuleAccount` account. When a delegator or validator
withdraws their rewards, they are taken out of the `ModuleAccount`. During begin
block, the different claims on the fees collected are updated as follows:
* The reserve community tax is charged.
* The remainder is distributed proportionally by voting power to all bonded validators
## The Distribution Scheme
See [params](07_params.md) for description of parameters.
Let `fees` be the total fees collected in the previous block, including
inflationary rewards to the stake. All fees are collected in a specific module
account during the block. During `BeginBlock`, they are sent to the
`"distribution"` `ModuleAccount`. No other sending of tokens occurs. Instead, the
rewards each account is entitled to are stored, and withdrawals can be triggered
through the messages `FundCommunityPool`, `WithdrawValidatorCommission` and
`WithdrawDelegatorReward`.
### Reward to the Community Pool
The community pool gets `community_tax * fees`, plus any remaining dust after
validators get their rewards that are always rounded down to the nearest
integer value.
### Reward To the Validators
The proposer receives no extra rewards. All fees are distributed among all the
bonded validators, including the proposer, in proportion to their consensus power.
```text
powFrac = validator power / total bonded validator power
voteMul = 1 - community_tax
```
All validators receive `fees * voteMul * powFrac`.
### Rewards to Delegators
Each validator's rewards are distributed to its delegators. The validator also
has a self-delegation that is treated like a regular delegation in
distribution calculations.
The validator sets a commission rate. The commission rate is flexible, but each
validator sets a maximum rate and a maximum daily increase. These maximums cannot be exceeded and protect delegators from sudden increases of validator commission rates to prevent validators from taking all of the rewards.
The outstanding rewards that the operator is entitled to are stored in
`ValidatorAccumulatedCommission`, while the rewards the delegators are entitled
to are stored in `ValidatorCurrentRewards`. The [F1 fee distribution
scheme](01_concepts.md) is used to calculate the rewards per delegator as they
withdraw or update their delegation, and is thus not handled in `BeginBlock`.
### Example Distribution
For this example distribution, the underlying consensus engine selects block proposers in
proportion to their power relative to the entire bonded power.
All validators are equally performant at including pre-commits in their proposed
blocks. Then hold `(pre_commits included) / (total bonded validator power)`
constant so that the amortized block reward for the validator is `( validator power / total bonded power) * (1 - community tax rate)` of
the total rewards. Consequently, the reward for a single delegator is:
```text
(delegator proportion of the validator power / validator power) * (validator power / total bonded power)
* (1 - community tax rate) * (1 - validator commission rate)
= (delegator proportion of the validator power / total bonded power) * (1 -
community tax rate) * (1 - validator commission rate)
```
<!-- order: 4 -->
# Messages
## MsgSetWithdrawAddress
By default, the withdraw address is the delegator address. To change its withdraw address, a delegator must send a `MsgSetWithdrawAddress` message.
Changing the withdraw address is possible only if the parameter `WithdrawAddrEnabled` is set to `true`.
The withdraw address cannot be any of the module accounts. These accounts are blocked from being withdraw addresses by being added to the distribution keeper's `blockedAddrs` array at initialization.
Response:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/distribution/v1beta1/tx.proto#L31-L41
```go
func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, withdrawAddr sdk.AccAddress) error
if k.blockedAddrs[withdrawAddr.String()] {
fail with "`{withdrawAddr}` is not allowed to receive external funds"
}
if !k.GetWithdrawAddrEnabled(ctx) {
fail with `ErrSetWithdrawAddrDisabled`
}
k.SetDelegatorWithdrawAddr(ctx, delegatorAddr, withdrawAddr)
```
## MsgWithdrawDelegatorReward
A delegator can withdraw its rewards.
Internally in the distribution module, this transaction simultaneously removes the previous delegation with associated rewards, the same as if the delegator simply started a new delegation of the same value.
The rewards are sent immediately from the distribution `ModuleAccount` to the withdraw address.
Any remainder (truncated decimals) are sent to the community pool.
The starting height of the delegation is set to the current validator period, and the reference count for the previous period is decremented.
The amount withdrawn is deducted from the `ValidatorOutstandingRewards` variable for the validator.
In the F1 distribution, the total rewards are calculated per validator period, and a delegator receives a piece of those rewards in proportion to their stake in the validator.
In basic F1, the total rewards that all the delegators are entitled to between to periods is calculated the following way.
Let `R(X)` be the total accumulated rewards up to period `X` divided by the tokens staked at that time. The delegator allocation is `R(X) * delegator_stake`.
Then the rewards for all the delegators for staking between periods `A` and `B` are `(R(B) - R(A)) * total stake`.
However, these calculated rewards don't account for slashing.
Taking the slashes into account requires iteration.
Let `F(X)` be the fraction a validator is to be slashed for a slashing event that happened at period `X`.
If the validator was slashed at periods `P1, ..., PN`, where `A < P1`, `PN < B`, the distribution module calculates the individual delegator's rewards, `T(A, B)`, as follows:
```go
stake := initial stake
rewards := 0
previous := A
for P in P1, ..., PN`:
rewards = (R(P) - previous) * stake
stake = stake * F(P)
previous = P
rewards = rewards + (R(B) - R(PN)) * stake
```
The historical rewards are calculated retroactively by playing back all the slashes and then attenuating the delegator's stake at each step.
The final calculated stake is equivalent to the actual staked coins in the delegation with a margin of error due to rounding errors.
Response:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/distribution/v1beta1/tx.proto#L46-L56
## WithdrawValidatorCommission
The validator can send the WithdrawValidatorCommission message to withdraw their accumulated commission.
The commission is calculated in every block during `BeginBlock`, so no iteration is required to withdraw.
The amount withdrawn is deducted from the `ValidatorOutstandingRewards` variable for the validator.
Only integer amounts can be sent. If the accumulated awards have decimals, the amount is truncated before the withdrawal is sent, and the remainder is left to be withdrawn later.
## FundCommunityPool
This message sends coins directly from the sender to the community pool.
The transaction fails if the amount cannot be transferred from the sender to the distribution module account.
```go
func (k Keeper) FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error {
if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, amount); err != nil {
return err
}
feePool := k.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(sdk.NewDecCoinsFromCoins(amount...)...)
k.SetFeePool(ctx, feePool)
return nil
}
```
## Common distribution operations
These operations take place during many different messages.
### Initialize delegation
Each time a delegation is changed, the rewards are withdrawn and the delegation is reinitialized.
Initializing a delegation increments the validator period and keeps track of the starting period of the delegation.
```go
// initialize starting info for a new delegation
func (k Keeper) initializeDelegation(ctx sdk.Context, val sdk.ValAddress, del sdk.AccAddress) {
// period has already been incremented - we want to store the period ended by this delegation action
previousPeriod := k.GetValidatorCurrentRewards(ctx, val).Period - 1
// increment reference count for the period we're going to track
k.incrementReferenceCount(ctx, val, previousPeriod)
validator := k.stakingKeeper.Validator(ctx, val)
delegation := k.stakingKeeper.Delegation(ctx, del, val)
// calculate delegation stake in tokens
// we don't store directly, so multiply delegation shares * (tokens per share)
// note: necessary to truncate so we don't allow withdrawing more rewards than owed
stake := validator.TokensFromSharesTruncated(delegation.GetShares())
k.SetDelegatorStartingInfo(ctx, val, del, types.NewDelegatorStartingInfo(previousPeriod, stake, uint64(ctx.BlockHeight())))
}
```
## MsgUpdateParams
Distribution module params can be updated through `MsgUpdateParams`, which can be done using governance proposal and the signer will always be gov module account address.
+++ https://github.com/cosmos/cosmos-sdk/blob/8822ef2695a1eb8cb30b7432f58f631c73951f1d/proto/cosmos/distribution/v1beta1/tx.proto#L106-L119
The message handling can fail if:
* signer is not the gov module account address.
<!-- order: 5 -->
# Hooks
Available hooks that can be called by and from this module.
## Create or modify delegation distribution
* triggered-by: `staking.MsgDelegate`, `staking.MsgBeginRedelegate`, `staking.MsgUndelegate`
### Before
* The delegation rewards are withdrawn to the withdraw address of the delegator.
The rewards include the current period and exclude the starting period.
* The validator period is incremented.
The validator period is incremented because the validator's power and share distribution might have changed.
* The reference count for the delegator's starting period is decremented.
### After
The starting height of the delegation is set to the previous period.
Because of the `Before`-hook, this period is the last period for which the delegator was rewarded.
## Validator created
* triggered-by: `staking.MsgCreateValidator`
When a validator is created, the following validator variables are initialized:
* Historical rewards
* Current accumulated rewards
* Accumulated commission
* Total outstanding rewards
* Period
By default, all values are set to a `0`, except period, which is set to `1`.
## Validator removed
* triggered-by: `staking.RemoveValidator`
Outstanding commission is sent to the validator's self-delegation withdrawal address.
Remaining delegator rewards get sent to the community fee pool.
Note: The validator gets removed only when it has no remaining delegations.
At that time, all outstanding delegator rewards will have been withdrawn.
Any remaining rewards are dust amounts.
## Validator is slashed
* triggered-by: `staking.Slash`
* The current validator period reference count is incremented.
The reference count is incremented because the slash event has created a reference to it.
* The validator period is incremented.
* The slash event is stored for later use.
The slash event will be referenced when calculating delegator rewards.
<!-- order: 6 -->
# Events
The distribution module emits the following events:
## BeginBlocker
| Type | Attribute Key | Attribute Value |
|-----------------|---------------|--------------------|
| proposer_reward | validator | {validatorAddress} |
| proposer_reward | reward | {proposerReward} |
| commission | amount | {commissionAmount} |
| commission | validator | {validatorAddress} |
| rewards | amount | {rewardAmount} |
| rewards | validator | {validatorAddress} |
## Handlers
### MsgSetWithdrawAddress
| Type | Attribute Key | Attribute Value |
|----------------------|------------------|----------------------|
| set_withdraw_address | withdraw_address | {withdrawAddress} |
| message | module | distribution |
| message | action | set_withdraw_address |
| message | sender | {senderAddress} |
### MsgWithdrawDelegatorReward
| Type | Attribute Key | Attribute Value |
|---------|---------------|---------------------------|
| withdraw_rewards | amount | {rewardAmount} |
| withdraw_rewards | validator | {validatorAddress} |
| message | module | distribution |
| message | action | withdraw_delegator_reward |
| message | sender | {senderAddress} |
### MsgWithdrawValidatorCommission
| Type | Attribute Key | Attribute Value |
|------------|---------------|-------------------------------|
| withdraw_commission | amount | {commissionAmount} |
| message | module | distribution |
| message | action | withdraw_validator_commission |
| message | sender | {senderAddress} |
<!-- order: 7 -->
# Parameters
The distribution module contains the following parameters:
| Key | Type | Example |
| ------------------- | ------------ | -------------------------- |
| communitytax | string (dec) | "0.020000000000000000" [0] |
| baseproposerreward | string (dec) | "0.010000000000000000" [0] |
| bonusproposerreward | string (dec) | "0.040000000000000000" [0] |
| withdrawaddrenabled | bool | true |
* [0] `communitytax`, `baseproposerreward` and `bonusproposerreward` must be
positive and their sum cannot exceed 1.00.
<!-- order: 8 -->
# Client
## CLI
A user can query and interact with the `distribution` module using the CLI.
### Query
The `query` commands allow users to query `distribution` state.
```sh
simd query distribution --help
```
#### commission
The `commission` command allows users to query validator commission rewards by address.
```sh
simd query distribution commission [address] [flags]
```
Example:
```sh
simd query distribution commission cosmosvaloper1..
```
Example Output:
```yml
commission:
- amount: "1000000.000000000000000000"
denom: stake
```
#### community-pool
The `community-pool` command allows users to query all coin balances within the community pool.
```sh
simd query distribution community-pool [flags]
```
Example:
```sh
simd query distribution community-pool
```
Example Output:
```yml
pool:
- amount: "1000000.000000000000000000"
denom: stake
```
#### params
The `params` command allows users to query the parameters of the `distribution` module.
```sh
simd query distribution params [flags]
```
Example:
```sh
simd query distribution params
```
Example Output:
```yml
base_proposer_reward: "0.010000000000000000"
bonus_proposer_reward: "0.040000000000000000"
community_tax: "0.020000000000000000"
withdraw_addr_enabled: true
```
#### rewards
The `rewards` command allows users to query delegator rewards. Users can optionally include the validator address to query rewards earned from a specific validator.
```sh
simd query distribution rewards [delegator-addr] [validator-addr] [flags]
```
Example:
```sh
simd query distribution rewards cosmos1..
```
Example Output:
```yml
rewards:
- reward:
- amount: "1000000.000000000000000000"
denom: stake
validator_address: cosmosvaloper1..
total:
- amount: "1000000.000000000000000000"
denom: stake
```
#### slashes
The `slashes` command allows users to query all slashes for a given block range.
```sh
simd query distribution slashes [validator] [start-height] [end-height] [flags]
```
Example:
```sh
simd query distribution slashes cosmosvaloper1.. 1 1000
```
Example Output:
```yml
pagination:
next_key: null
total: "0"
slashes:
- validator_period: 20,
fraction: "0.009999999999999999"
```
#### validator-outstanding-rewards
The `validator-outstanding-rewards` command allows users to query all outstanding (un-withdrawn) rewards for a validator and all their delegations.
```sh
simd query distribution validator-outstanding-rewards [validator] [flags]
```
Example:
```sh
simd query distribution validator-outstanding-rewards cosmosvaloper1..
```
Example Output:
```yml
rewards:
- amount: "1000000.000000000000000000"
denom: stake
```
### Transactions
The `tx` commands allow users to interact with the `distribution` module.
```sh
simd tx distribution --help
```
#### fund-community-pool
The `fund-community-pool` command allows users to send funds to the community pool.
```sh
simd tx distribution fund-community-pool [amount] [flags]
```
Example:
```sh
simd tx distribution fund-community-pool 100stake --from cosmos1..
```
#### set-withdraw-addr
The `set-withdraw-addr` command allows users to set the withdraw address for rewards associated with a delegator address.
```sh
simd tx distribution set-withdraw-addr [withdraw-addr] [flags]
```
Example:
```sh
simd tx distribution set-withdraw-addr cosmos1.. --from cosmos1..
```
#### withdraw-all-rewards
The `withdraw-all-rewards` command allows users to withdraw all rewards for a delegator.
```sh
simd tx distribution withdraw-all-rewards [flags]
```
Example:
```sh
simd tx distribution withdraw-all-rewards --from cosmos1..
```
#### withdraw-rewards
The `withdraw-rewards` command allows users to withdraw all rewards from a given delegation address,
and optionally withdraw validator commission if the delegation address given is a validator operator and the user proves the `--commision` flag.
```sh
simd tx distribution withdraw-rewards [validator-addr] [flags]
```
Example:
```sh
simd tx distribution withdraw-rewards cosmosvaloper1.. --from cosmos1.. --commision
```
## gRPC
A user can query the `distribution` module using gRPC endpoints.
### Params
The `Params` endpoint allows users to query parameters of the `distribution` module.
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.distribution.v1beta1.Query/Params
```
Example Output:
```json
{
"params": {
"communityTax": "20000000000000000",
"baseProposerReward": "10000000000000000",
"bonusProposerReward": "40000000000000000",
"withdrawAddrEnabled": true
}
}
```
### ValidatorOutstandingRewards
The `ValidatorOutstandingRewards` endpoint allows users to query rewards of a validator address.
Example:
```sh
grpcurl -plaintext \
-d '{"validator_address":"cosmosvalop1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/ValidatorOutstandingRewards
```
Example Output:
```json
{
"rewards": {
"rewards": [
{
"denom": "stake",
"amount": "1000000000000000"
}
]
}
}
```
### ValidatorCommission
The `ValidatorCommission` endpoint allows users to query accumulated commission for a validator.
Example:
```sh
grpcurl -plaintext \
-d '{"validator_address":"cosmosvalop1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/ValidatorCommission
```
Example Output:
```json
{
"commission": {
"commission": [
{
"denom": "stake",
"amount": "1000000000000000"
}
]
}
}
```
### ValidatorSlashes
The `ValidatorSlashes` endpoint allows users to query slash events of a validator.
Example:
```sh
grpcurl -plaintext \
-d '{"validator_address":"cosmosvalop1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/ValidatorSlashes
```
Example Output:
```json
{
"slashes": [
{
"validator_period": "20",
"fraction": "0.009999999999999999"
}
],
"pagination": {
"total": "1"
}
}
```
### DelegationRewards
The `DelegationRewards` endpoint allows users to query the total rewards accrued by a delegation.
Example:
```sh
grpcurl -plaintext \
-d '{"delegator_address":"cosmos1..","validator_address":"cosmosvalop1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/DelegationRewards
```
Example Output:
```json
{
"rewards": [
{
"denom": "stake",
"amount": "1000000000000000"
}
]
}
```
### DelegationTotalRewards
The `DelegationTotalRewards` endpoint allows users to query the total rewards accrued by each validator.
Example:
```sh
grpcurl -plaintext \
-d '{"delegator_address":"cosmos1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/DelegationTotalRewards
```
Example Output:
```json
{
"rewards": [
{
"validatorAddress": "cosmosvaloper1..",
"reward": [
{
"denom": "stake",
"amount": "1000000000000000"
}
]
}
],
"total": [
{
"denom": "stake",
"amount": "1000000000000000"
}
]
}
```
### DelegatorValidators
The `DelegatorValidators` endpoint allows users to query all validators for given delegator.
Example:
```sh
grpcurl -plaintext \
-d '{"delegator_address":"cosmos1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/DelegatorValidators
```
Example Output:
```json
{
"validators": [
"cosmosvaloper1.."
]
}
```
### DelegatorWithdrawAddress
The `DelegatorWithdrawAddress` endpoint allows users to query the withdraw address of a delegator.
Example:
```sh
grpcurl -plaintext \
-d '{"delegator_address":"cosmos1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/DelegatorWithdrawAddress
```
Example Output:
```json
{
"withdrawAddress": "cosmos1.."
}
```
### CommunityPool
The `CommunityPool` endpoint allows users to query the community pool coins.
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.distribution.v1beta1.Query/CommunityPool
```
Example Output:
```json
{
"pool": [
{
"denom": "stake",
"amount": "1000000000000000000"
}
]
}
```

View File

@ -1,34 +0,0 @@
<!--
order: 1
-->
# Concepts
In Proof of Stake (PoS) blockchains, rewards gained from transaction fees are paid to validators. The fee distribution module fairly distributes the rewards to the validators' constituent delegators.
Rewards are calculated per period. The period is updated each time a validator's delegation changes, for example, when the validator receives a new delegation.
The rewards for a single validator can then be calculated by taking the total rewards for the period before the delegation started, minus the current total rewards.
To learn more, see the [F1 Fee Distribution paper](/docs/spec/fee_distribution/f1_fee_distr.pdf).
The commission to the validator is paid when the validator is removed or when the validator requests a withdrawal.
The commission is calculated and incremented at every `BeginBlock` operation to update accumulated fee amounts.
The rewards to a delegator are distributed when the delegation is changed or removed, or a withdrawal is requested.
Before rewards are distributed, all slashes to the validator that occurred during the current delegation are applied.
## Reference Counting in F1 Fee Distribution
In F1 fee distribution, the rewards a delegator receives are calculated when their delegation is withdrawn. This calculation must read the terms of the summation of rewards divided by the share of tokens from the period which they ended when they delegated, and the final period that was created for the withdrawal.
Additionally, as slashes change the amount of tokens a delegation will have (but we calculate this lazily,
only when a delegator un-delegates), we must calculate rewards in separate periods before / after any slashes
which occurred in between when a delegator delegated and when they withdrew their rewards. Thus slashes, like
delegations, reference the period which was ended by the slash event.
All stored historical rewards records for periods which are no longer referenced by any delegations
or any slashes can thus be safely removed, as they will never be read (future delegations and future
slashes will always reference future periods). This is implemented by tracking a `ReferenceCount`
along with each historical reward storage entry. Each time a new object (delegation or slash)
is created which might need to reference the historical record, the reference count is incremented.
Each time one object which previously needed to reference the historical record is deleted, the reference
count is decremented. If the reference count hits zero, the historical record is deleted.

View File

@ -1,73 +0,0 @@
<!--
order: 2
-->
# State
## FeePool
All globally tracked parameters for distribution are stored within
`FeePool`. Rewards are collected and added to the reward pool and
distributed to validators/delegators from here.
Note that the reward pool holds decimal coins (`DecCoins`) to allow
for fractions of coins to be received from operations like inflation.
When coins are distributed from the pool they are truncated back to
`sdk.Coins` which are non-decimal.
* FeePool: `0x00 -> ProtocolBuffer(FeePool)`
```go
// coins with decimal
type DecCoins []DecCoin
type DecCoin struct {
Amount sdk.Dec
Denom string
}
```
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/distribution/v1beta1/distribution.proto#L92-L96
## Validator Distribution
Validator distribution information for the relevant validator is updated each time:
1. delegation amount to a validator is updated,
2. any delegator withdraws from a validator, or
3. the validator withdraws its commission.
* ValidatorDistInfo: `0x02 | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(validatorDistribution)`
```go
type ValidatorDistInfo struct {
OperatorAddress sdk.AccAddress
SelfBondRewards sdk.DecCoins
ValidatorCommission types.ValidatorAccumulatedCommission
}
```
## Delegation Distribution
Each delegation distribution only needs to record the height at which it last
withdrew fees. Because a delegation must withdraw fees each time it's
properties change (aka bonded tokens etc.) its properties will remain constant
and the delegator's _accumulation_ factor can be calculated passively knowing
only the height of the last withdrawal and its current properties.
* DelegationDistInfo: `0x02 | DelegatorAddrLen (1 byte) | DelegatorAddr | ValOperatorAddrLen (1 byte) | ValOperatorAddr -> ProtocolBuffer(delegatorDist)`
```go
type DelegationDistInfo struct {
WithdrawalHeight int64 // last time this delegation withdrew rewards
}
```
## Params
The distribution module stores it's params in state with the prefix of `0x09`,
it can be updated with governance or the address with authority.
* Params: `0x09 | ProtocolBuffer(Params)`
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/distribution/v1beta1/distribution.proto#L11-L30

View File

@ -1,75 +0,0 @@
<!--
order: 3
-->
# Begin Block
At each `BeginBlock`, all fees received in the previous block are transferred to
the distribution `ModuleAccount` account. When a delegator or validator
withdraws their rewards, they are taken out of the `ModuleAccount`. During begin
block, the different claims on the fees collected are updated as follows:
* The reserve community tax is charged.
* The remainder is distributed proportionally by voting power to all bonded validators
## The Distribution Scheme
See [params](07_params.md) for description of parameters.
Let `fees` be the total fees collected in the previous block, including
inflationary rewards to the stake. All fees are collected in a specific module
account during the block. During `BeginBlock`, they are sent to the
`"distribution"` `ModuleAccount`. No other sending of tokens occurs. Instead, the
rewards each account is entitled to are stored, and withdrawals can be triggered
through the messages `FundCommunityPool`, `WithdrawValidatorCommission` and
`WithdrawDelegatorReward`.
### Reward to the Community Pool
The community pool gets `community_tax * fees`, plus any remaining dust after
validators get their rewards that are always rounded down to the nearest
integer value.
### Reward To the Validators
The proposer receives no extra rewards. All fees are distributed among all the
bonded validators, including the proposer, in proportion to their consensus power.
```text
powFrac = validator power / total bonded validator power
voteMul = 1 - community_tax
```
All validators receive `fees * voteMul * powFrac`.
### Rewards to Delegators
Each validator's rewards are distributed to its delegators. The validator also
has a self-delegation that is treated like a regular delegation in
distribution calculations.
The validator sets a commission rate. The commission rate is flexible, but each
validator sets a maximum rate and a maximum daily increase. These maximums cannot be exceeded and protect delegators from sudden increases of validator commission rates to prevent validators from taking all of the rewards.
The outstanding rewards that the operator is entitled to are stored in
`ValidatorAccumulatedCommission`, while the rewards the delegators are entitled
to are stored in `ValidatorCurrentRewards`. The [F1 fee distribution
scheme](01_concepts.md) is used to calculate the rewards per delegator as they
withdraw or update their delegation, and is thus not handled in `BeginBlock`.
### Example Distribution
For this example distribution, the underlying consensus engine selects block proposers in
proportion to their power relative to the entire bonded power.
All validators are equally performant at including pre-commits in their proposed
blocks. Then hold `(pre_commits included) / (total bonded validator power)`
constant so that the amortized block reward for the validator is `( validator power / total bonded power) * (1 - community tax rate)` of
the total rewards. Consequently, the reward for a single delegator is:
```text
(delegator proportion of the validator power / validator power) * (validator power / total bonded power)
* (1 - community tax rate) * (1 - validator commission rate)
= (delegator proportion of the validator power / total bonded power) * (1 -
community tax rate) * (1 - validator commission rate)
```

View File

@ -1,132 +0,0 @@
<!--
order: 4
-->
# Messages
## MsgSetWithdrawAddress
By default, the withdraw address is the delegator address. To change its withdraw address, a delegator must send a `MsgSetWithdrawAddress` message.
Changing the withdraw address is possible only if the parameter `WithdrawAddrEnabled` is set to `true`.
The withdraw address cannot be any of the module accounts. These accounts are blocked from being withdraw addresses by being added to the distribution keeper's `blockedAddrs` array at initialization.
Response:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/distribution/v1beta1/tx.proto#L31-L41
```go
func (k Keeper) SetWithdrawAddr(ctx sdk.Context, delegatorAddr sdk.AccAddress, withdrawAddr sdk.AccAddress) error
if k.blockedAddrs[withdrawAddr.String()] {
fail with "`{withdrawAddr}` is not allowed to receive external funds"
}
if !k.GetWithdrawAddrEnabled(ctx) {
fail with `ErrSetWithdrawAddrDisabled`
}
k.SetDelegatorWithdrawAddr(ctx, delegatorAddr, withdrawAddr)
```
## MsgWithdrawDelegatorReward
A delegator can withdraw its rewards.
Internally in the distribution module, this transaction simultaneously removes the previous delegation with associated rewards, the same as if the delegator simply started a new delegation of the same value.
The rewards are sent immediately from the distribution `ModuleAccount` to the withdraw address.
Any remainder (truncated decimals) are sent to the community pool.
The starting height of the delegation is set to the current validator period, and the reference count for the previous period is decremented.
The amount withdrawn is deducted from the `ValidatorOutstandingRewards` variable for the validator.
In the F1 distribution, the total rewards are calculated per validator period, and a delegator receives a piece of those rewards in proportion to their stake in the validator.
In basic F1, the total rewards that all the delegators are entitled to between to periods is calculated the following way.
Let `R(X)` be the total accumulated rewards up to period `X` divided by the tokens staked at that time. The delegator allocation is `R(X) * delegator_stake`.
Then the rewards for all the delegators for staking between periods `A` and `B` are `(R(B) - R(A)) * total stake`.
However, these calculated rewards don't account for slashing.
Taking the slashes into account requires iteration.
Let `F(X)` be the fraction a validator is to be slashed for a slashing event that happened at period `X`.
If the validator was slashed at periods `P1, ..., PN`, where `A < P1`, `PN < B`, the distribution module calculates the individual delegator's rewards, `T(A, B)`, as follows:
```go
stake := initial stake
rewards := 0
previous := A
for P in P1, ..., PN`:
rewards = (R(P) - previous) * stake
stake = stake * F(P)
previous = P
rewards = rewards + (R(B) - R(PN)) * stake
```
The historical rewards are calculated retroactively by playing back all the slashes and then attenuating the delegator's stake at each step.
The final calculated stake is equivalent to the actual staked coins in the delegation with a margin of error due to rounding errors.
Response:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/distribution/v1beta1/tx.proto#L46-L56
## WithdrawValidatorCommission
The validator can send the WithdrawValidatorCommission message to withdraw their accumulated commission.
The commission is calculated in every block during `BeginBlock`, so no iteration is required to withdraw.
The amount withdrawn is deducted from the `ValidatorOutstandingRewards` variable for the validator.
Only integer amounts can be sent. If the accumulated awards have decimals, the amount is truncated before the withdrawal is sent, and the remainder is left to be withdrawn later.
## FundCommunityPool
This message sends coins directly from the sender to the community pool.
The transaction fails if the amount cannot be transferred from the sender to the distribution module account.
```go
func (k Keeper) FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error {
if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, sender, types.ModuleName, amount); err != nil {
return err
}
feePool := k.GetFeePool(ctx)
feePool.CommunityPool = feePool.CommunityPool.Add(sdk.NewDecCoinsFromCoins(amount...)...)
k.SetFeePool(ctx, feePool)
return nil
}
```
## Common distribution operations
These operations take place during many different messages.
### Initialize delegation
Each time a delegation is changed, the rewards are withdrawn and the delegation is reinitialized.
Initializing a delegation increments the validator period and keeps track of the starting period of the delegation.
```go
// initialize starting info for a new delegation
func (k Keeper) initializeDelegation(ctx sdk.Context, val sdk.ValAddress, del sdk.AccAddress) {
// period has already been incremented - we want to store the period ended by this delegation action
previousPeriod := k.GetValidatorCurrentRewards(ctx, val).Period - 1
// increment reference count for the period we're going to track
k.incrementReferenceCount(ctx, val, previousPeriod)
validator := k.stakingKeeper.Validator(ctx, val)
delegation := k.stakingKeeper.Delegation(ctx, del, val)
// calculate delegation stake in tokens
// we don't store directly, so multiply delegation shares * (tokens per share)
// note: necessary to truncate so we don't allow withdrawing more rewards than owed
stake := validator.TokensFromSharesTruncated(delegation.GetShares())
k.SetDelegatorStartingInfo(ctx, val, del, types.NewDelegatorStartingInfo(previousPeriod, stake, uint64(ctx.BlockHeight())))
}
```
## MsgUpdateParams
Distribution module params can be updated through `MsgUpdateParams`, which can be done using governance proposal and the signer will always be gov module account address.
+++ https://github.com/cosmos/cosmos-sdk/blob/8822ef2695a1eb8cb30b7432f58f631c73951f1d/proto/cosmos/distribution/v1beta1/tx.proto#L106-L119
The message handling can fail if:
* signer is not the gov module account address.

View File

@ -1,59 +0,0 @@
<!--
order: 5
-->
# Hooks
Available hooks that can be called by and from this module.
## Create or modify delegation distribution
* triggered-by: `staking.MsgDelegate`, `staking.MsgBeginRedelegate`, `staking.MsgUndelegate`
### Before
* The delegation rewards are withdrawn to the withdraw address of the delegator.
The rewards include the current period and exclude the starting period.
* The validator period is incremented.
The validator period is incremented because the validator's power and share distribution might have changed.
* The reference count for the delegator's starting period is decremented.
### After
The starting height of the delegation is set to the previous period.
Because of the `Before`-hook, this period is the last period for which the delegator was rewarded.
## Validator created
* triggered-by: `staking.MsgCreateValidator`
When a validator is created, the following validator variables are initialized:
* Historical rewards
* Current accumulated rewards
* Accumulated commission
* Total outstanding rewards
* Period
By default, all values are set to a `0`, except period, which is set to `1`.
## Validator removed
* triggered-by: `staking.RemoveValidator`
Outstanding commission is sent to the validator's self-delegation withdrawal address.
Remaining delegator rewards get sent to the community fee pool.
Note: The validator gets removed only when it has no remaining delegations.
At that time, all outstanding delegator rewards will have been withdrawn.
Any remaining rewards are dust amounts.
## Validator is slashed
* triggered-by: `staking.Slash`
* The current validator period reference count is incremented.
The reference count is incremented because the slash event has created a reference to it.
* The validator period is incremented.
* The slash event is stored for later use.
The slash event will be referenced when calculating delegator rewards.

View File

@ -1,48 +0,0 @@
<!--
order: 6
-->
# Events
The distribution module emits the following events:
## BeginBlocker
| Type | Attribute Key | Attribute Value |
|-----------------|---------------|--------------------|
| proposer_reward | validator | {validatorAddress} |
| proposer_reward | reward | {proposerReward} |
| commission | amount | {commissionAmount} |
| commission | validator | {validatorAddress} |
| rewards | amount | {rewardAmount} |
| rewards | validator | {validatorAddress} |
## Handlers
### MsgSetWithdrawAddress
| Type | Attribute Key | Attribute Value |
|----------------------|------------------|----------------------|
| set_withdraw_address | withdraw_address | {withdrawAddress} |
| message | module | distribution |
| message | action | set_withdraw_address |
| message | sender | {senderAddress} |
### MsgWithdrawDelegatorReward
| Type | Attribute Key | Attribute Value |
|---------|---------------|---------------------------|
| withdraw_rewards | amount | {rewardAmount} |
| withdraw_rewards | validator | {validatorAddress} |
| message | module | distribution |
| message | action | withdraw_delegator_reward |
| message | sender | {senderAddress} |
### MsgWithdrawValidatorCommission
| Type | Attribute Key | Attribute Value |
|------------|---------------|-------------------------------|
| withdraw_commission | amount | {commissionAmount} |
| message | module | distribution |
| message | action | withdraw_validator_commission |
| message | sender | {senderAddress} |

View File

@ -1,17 +0,0 @@
<!--
order: 7
-->
# Parameters
The distribution module contains the following parameters:
| Key | Type | Example |
| ------------------- | ------------ | -------------------------- |
| communitytax | string (dec) | "0.020000000000000000" [0] |
| baseproposerreward | string (dec) | "0.010000000000000000" [0] |
| bonusproposerreward | string (dec) | "0.040000000000000000" [0] |
| withdrawaddrenabled | bool | true |
* [0] `communitytax`, `baseproposerreward` and `bonusproposerreward` must be
positive and their sum cannot exceed 1.00.

View File

@ -1,469 +0,0 @@
<!--
order: 8
-->
# Client
## CLI
A user can query and interact with the `distribution` module using the CLI.
### Query
The `query` commands allow users to query `distribution` state.
```sh
simd query distribution --help
```
#### commission
The `commission` command allows users to query validator commission rewards by address.
```sh
simd query distribution commission [address] [flags]
```
Example:
```sh
simd query distribution commission cosmosvaloper1..
```
Example Output:
```yml
commission:
- amount: "1000000.000000000000000000"
denom: stake
```
#### community-pool
The `community-pool` command allows users to query all coin balances within the community pool.
```sh
simd query distribution community-pool [flags]
```
Example:
```sh
simd query distribution community-pool
```
Example Output:
```yml
pool:
- amount: "1000000.000000000000000000"
denom: stake
```
#### params
The `params` command allows users to query the parameters of the `distribution` module.
```sh
simd query distribution params [flags]
```
Example:
```sh
simd query distribution params
```
Example Output:
```yml
base_proposer_reward: "0.010000000000000000"
bonus_proposer_reward: "0.040000000000000000"
community_tax: "0.020000000000000000"
withdraw_addr_enabled: true
```
#### rewards
The `rewards` command allows users to query delegator rewards. Users can optionally include the validator address to query rewards earned from a specific validator.
```sh
simd query distribution rewards [delegator-addr] [validator-addr] [flags]
```
Example:
```sh
simd query distribution rewards cosmos1..
```
Example Output:
```yml
rewards:
- reward:
- amount: "1000000.000000000000000000"
denom: stake
validator_address: cosmosvaloper1..
total:
- amount: "1000000.000000000000000000"
denom: stake
```
#### slashes
The `slashes` command allows users to query all slashes for a given block range.
```sh
simd query distribution slashes [validator] [start-height] [end-height] [flags]
```
Example:
```sh
simd query distribution slashes cosmosvaloper1.. 1 1000
```
Example Output:
```yml
pagination:
next_key: null
total: "0"
slashes:
- validator_period: 20,
fraction: "0.009999999999999999"
```
#### validator-outstanding-rewards
The `validator-outstanding-rewards` command allows users to query all outstanding (un-withdrawn) rewards for a validator and all their delegations.
```sh
simd query distribution validator-outstanding-rewards [validator] [flags]
```
Example:
```sh
simd query distribution validator-outstanding-rewards cosmosvaloper1..
```
Example Output:
```yml
rewards:
- amount: "1000000.000000000000000000"
denom: stake
```
### Transactions
The `tx` commands allow users to interact with the `distribution` module.
```sh
simd tx distribution --help
```
#### fund-community-pool
The `fund-community-pool` command allows users to send funds to the community pool.
```sh
simd tx distribution fund-community-pool [amount] [flags]
```
Example:
```sh
simd tx distribution fund-community-pool 100stake --from cosmos1..
```
#### set-withdraw-addr
The `set-withdraw-addr` command allows users to set the withdraw address for rewards associated with a delegator address.
```sh
simd tx distribution set-withdraw-addr [withdraw-addr] [flags]
```
Example:
```sh
simd tx distribution set-withdraw-addr cosmos1.. --from cosmos1..
```
#### withdraw-all-rewards
The `withdraw-all-rewards` command allows users to withdraw all rewards for a delegator.
```sh
simd tx distribution withdraw-all-rewards [flags]
```
Example:
```sh
simd tx distribution withdraw-all-rewards --from cosmos1..
```
#### withdraw-rewards
The `withdraw-rewards` command allows users to withdraw all rewards from a given delegation address,
and optionally withdraw validator commission if the delegation address given is a validator operator and the user proves the `--commision` flag.
```sh
simd tx distribution withdraw-rewards [validator-addr] [flags]
```
Example:
```sh
simd tx distribution withdraw-rewards cosmosvaloper1.. --from cosmos1.. --commision
```
## gRPC
A user can query the `distribution` module using gRPC endpoints.
### Params
The `Params` endpoint allows users to query parameters of the `distribution` module.
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.distribution.v1beta1.Query/Params
```
Example Output:
```json
{
"params": {
"communityTax": "20000000000000000",
"baseProposerReward": "10000000000000000",
"bonusProposerReward": "40000000000000000",
"withdrawAddrEnabled": true
}
}
```
### ValidatorOutstandingRewards
The `ValidatorOutstandingRewards` endpoint allows users to query rewards of a validator address.
Example:
```sh
grpcurl -plaintext \
-d '{"validator_address":"cosmosvalop1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/ValidatorOutstandingRewards
```
Example Output:
```json
{
"rewards": {
"rewards": [
{
"denom": "stake",
"amount": "1000000000000000"
}
]
}
}
```
### ValidatorCommission
The `ValidatorCommission` endpoint allows users to query accumulated commission for a validator.
Example:
```sh
grpcurl -plaintext \
-d '{"validator_address":"cosmosvalop1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/ValidatorCommission
```
Example Output:
```json
{
"commission": {
"commission": [
{
"denom": "stake",
"amount": "1000000000000000"
}
]
}
}
```
### ValidatorSlashes
The `ValidatorSlashes` endpoint allows users to query slash events of a validator.
Example:
```sh
grpcurl -plaintext \
-d '{"validator_address":"cosmosvalop1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/ValidatorSlashes
```
Example Output:
```json
{
"slashes": [
{
"validator_period": "20",
"fraction": "0.009999999999999999"
}
],
"pagination": {
"total": "1"
}
}
```
### DelegationRewards
The `DelegationRewards` endpoint allows users to query the total rewards accrued by a delegation.
Example:
```sh
grpcurl -plaintext \
-d '{"delegator_address":"cosmos1..","validator_address":"cosmosvalop1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/DelegationRewards
```
Example Output:
```json
{
"rewards": [
{
"denom": "stake",
"amount": "1000000000000000"
}
]
}
```
### DelegationTotalRewards
The `DelegationTotalRewards` endpoint allows users to query the total rewards accrued by each validator.
Example:
```sh
grpcurl -plaintext \
-d '{"delegator_address":"cosmos1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/DelegationTotalRewards
```
Example Output:
```json
{
"rewards": [
{
"validatorAddress": "cosmosvaloper1..",
"reward": [
{
"denom": "stake",
"amount": "1000000000000000"
}
]
}
],
"total": [
{
"denom": "stake",
"amount": "1000000000000000"
}
]
}
```
### DelegatorValidators
The `DelegatorValidators` endpoint allows users to query all validators for given delegator.
Example:
```sh
grpcurl -plaintext \
-d '{"delegator_address":"cosmos1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/DelegatorValidators
```
Example Output:
```json
{
"validators": [
"cosmosvaloper1.."
]
}
```
### DelegatorWithdrawAddress
The `DelegatorWithdrawAddress` endpoint allows users to query the withdraw address of a delegator.
Example:
```sh
grpcurl -plaintext \
-d '{"delegator_address":"cosmos1.."}' \
localhost:9090 \
cosmos.distribution.v1beta1.Query/DelegatorWithdrawAddress
```
Example Output:
```json
{
"withdrawAddress": "cosmos1.."
}
```
### CommunityPool
The `CommunityPool` endpoint allows users to query the community pool coins.
Example:
```sh
grpcurl -plaintext \
localhost:9090 \
cosmos.distribution.v1beta1.Query/CommunityPool
```
Example Output:
```json
{
"pool": [
{
"denom": "stake",
"amount": "1000000000000000000"
}
]
}
```

View File

@ -1,104 +0,0 @@
<!--
order: 0
title: Distribution Overview
parent:
title: "distribution"
-->
# `distribution`
## Overview
This _simple_ distribution mechanism describes a functional way to passively
distribute rewards between validators and delegators. Note that this mechanism does
not distribute funds in as precisely as active reward distribution mechanisms and
will therefore be upgraded in the future.
The mechanism operates as follows. Collected rewards are pooled globally and
divided out passively to validators and delegators. Each validator has the
opportunity to charge commission to the delegators on the rewards collected on
behalf of the delegators. Fees are collected directly into a global reward pool
and validator proposer-reward pool. Due to the nature of passive accounting,
whenever changes to parameters which affect the rate of reward distribution
occurs, withdrawal of rewards must also occur.
* Whenever withdrawing, one must withdraw the maximum amount they are entitled
to, leaving nothing in the pool.
* Whenever bonding, unbonding, or re-delegating tokens to an existing account, a
full withdrawal of the rewards must occur (as the rules for lazy accounting
change).
* Whenever a validator chooses to change the commission on rewards, all accumulated
commission rewards must be simultaneously withdrawn.
The above scenarios are covered in `hooks.md`.
The distribution mechanism outlined herein is used to lazily distribute the
following rewards between validators and associated delegators:
* multi-token fees to be socially distributed
* inflated staked asset provisions
* validator commission on all rewards earned by their delegators stake
Fees are pooled within a global pool. The mechanisms used allow for validators
and delegators to independently and lazily withdraw their rewards.
## Shortcomings
As a part of the lazy computations, each delegator holds an accumulation term
specific to each validator which is used to estimate what their approximate
fair portion of tokens held in the global fee pool is owed to them.
```text
entitlement = delegator-accumulation / all-delegators-accumulation
```
Under the circumstance that there was constant and equal flow of incoming
reward tokens every block, this distribution mechanism would be equal to the
active distribution (distribute individually to all delegators each block).
However, this is unrealistic so deviations from the active distribution will
occur based on fluctuations of incoming reward tokens as well as timing of
reward withdrawal by other delegators.
If you happen to know that incoming rewards are about to significantly increase,
you are incentivized to not withdraw until after this event, increasing the
worth of your existing _accum_. See [#2764](https://github.com/cosmos/cosmos-sdk/issues/2764)
for further details.
## Effect on Staking
Charging commission on Atom provisions while also allowing for Atom-provisions
to be auto-bonded (distributed directly to the validators bonded stake) is
problematic within BPoS. Fundamentally, these two mechanisms are mutually
exclusive. If both commission and auto-bonding mechanisms are simultaneously
applied to the staking-token then the distribution of staking-tokens between
any validator and its delegators will change with each block. This then
necessitates a calculation for each delegation records for each block -
which is considered computationally expensive.
In conclusion, we can only have Atom commission and unbonded atoms
provisions or bonded atom provisions with no Atom commission, and we elect to
implement the former. Stakeholders wishing to rebond their provisions may elect
to set up a script to periodically withdraw and rebond rewards.
## Contents
1. **[Concepts](01_concepts.md)**
* [Reference Counting in F1 Fee Distribution](01_concepts.md#reference-counting-in-f1-fee-distribution)
2. **[State](02_state.md)**
3. **[Begin Block](03_begin_block.md)**
4. **[Messages](04_messages.md)**
* [MsgSetWithdrawAddress](04_messages.md#msgsetwithdrawaddress)
* [MsgWithdrawDelegatorReward](04_messages.md#msgwithdrawdelegatorreward)
* [Withdraw Validator Rewards All](04_messages.md#withdraw-validator-rewards-all)
* [Common calculations](04_messages.md#common-calculations-)
5. **[Hooks](05_hooks.md)**
* [Create or modify delegation distribution](05_hooks.md#create-or-modify-delegation-distribution)
* [Commission rate change](05_hooks.md#commission-rate-change)
* [Change in Validator State](05_hooks.md#change-in-validator-state)
6. **[Events](06_events.md)**
* [BeginBlocker](06_events.md#beginblocker)
* [Handlers](06_events.md#handlers)
7. **[Parameters](07_params.md)**
8. **[Client](08_client.md)**
* [CLI](08_client.md#cli)
* [gRPC](08_client.md#grpc)

View File

@ -1,7 +1,94 @@
<!--
order: 0
title: Epoching Overview
parent:
title: "epoching"
-->
# Epoching
# `x/epoching`
* [Epoching](epoching/spec/README.md) - Allows modules to queue messages for execution at a certain block height.
## Abstract
The epoching module allows modules to queue messages for execution at a certain block height. Each module will have its own instance of the epoching module, this allows each module to have its own message queue and own duration for epochs.
## Example
In this example, we are creating an epochkeeper for a module that will be used by the module to queue messages to be executed at a later point in time.
```go
type Keeper struct {
storeKey sdk.StoreKey
cdc codec.BinaryMarshaler
epochKeeper epochkeeper.Keeper
}
// NewKeeper creates a new staking Keeper instance
func NewKeeper(cdc codec.BinaryMarshaler, key sdk.StoreKey) Keeper {
return Keeper{
storeKey: key,
cdc: cdc,
epochKeeper: epochkeeper.NewKeeper(cdc, key),
}
}
```
### Contents
* [State](#state)
<!-- order: 1 -->
# State
## Messages queue
Messages are queued to run at the end of each epoch. Queued messages have an epoch number and for each epoch number, the queues are iterated over and each message is executed.
### Message queues
Each module has one unique message queue that is specific to that module.
## Actions
A module will add a message that implements the `sdk.Msg` interface. These message will be executed at a later time (end of the next epoch).
```go
type Msg interface {
proto.Message
// Return the message type.
// Must be alphanumeric or empty.
Route() string
// Returns a human-readable string for the message, intended for utilization
// within tags
Type() string
// ValidateBasic does a simple validation check that
// doesn't require access to any other information.
ValidateBasic() error
// Get the canonical byte representation of the Msg.
GetSignBytes() []byte
// Signers returns the addrs of signers that must sign.
// CONTRACT: All signatures must be present to be valid.
// CONTRACT: Returns addrs in some deterministic order.
GetSigners() []AccAddress
}
```
## Buffered Messages Export / Import
For now, the `x/epoching` module is implemented to export all buffered messages without epoch numbers. When state is imported, buffered messages are stored on current epoch to run at the end of current epoch.
## Genesis Transactions
We execute epoch after execution of genesis transactions to see the changes instantly before node start.
## Execution on epochs
* Try executing the message for the epoch
* If success, make changes as it is
* If failure, try making revert extra actions done on handlers (e.g. EpochDelegationPool deposit)
* If revert fail, panic

View File

@ -1,58 +0,0 @@
<!--
order: 1
-->
# State
## Messages queue
Messages are queued to run at the end of each epoch. Queued messages have an epoch number and for each epoch number, the queues are iterated over and each message is executed.
### Message queues
Each module has one unique message queue that is specific to that module.
## Actions
A module will add a message that implements the `sdk.Msg` interface. These message will be executed at a later time (end of the next epoch).
```go
type Msg interface {
proto.Message
// Return the message type.
// Must be alphanumeric or empty.
Route() string
// Returns a human-readable string for the message, intended for utilization
// within tags
Type() string
// ValidateBasic does a simple validation check that
// doesn't require access to any other information.
ValidateBasic() error
// Get the canonical byte representation of the Msg.
GetSignBytes() []byte
// Signers returns the addrs of signers that must sign.
// CONTRACT: All signatures must be present to be valid.
// CONTRACT: Returns addrs in some deterministic order.
GetSigners() []AccAddress
}
```
## Buffered Messages Export / Import
For now, the `x/epoching` module is implemented to export all buffered messages without epoch numbers. When state is imported, buffered messages are stored on current epoch to run at the end of current epoch.
## Genesis Transactions
We execute epoch after execution of genesis transactions to see the changes instantly before node start.
## Execution on epochs
* Try executing the message for the epoch
* If success, make changes as it is
* If failure, try making revert extra actions done on handlers (e.g. EpochDelegationPool deposit)
* If revert fail, panic

View File

@ -1,44 +0,0 @@
<!--
order: 3
-->
# Changes to make
## Validator self-unbonding (which exceed minimum self delegation) could be required to start instantly
Cases that trigger unbonding process
* Validator undelegate can unbond more tokens than his minimum_self_delegation and it will automatically turn the validator into unbonding
In this case, unbonding should start instantly.
* Validator miss blocks and get slashed
* Validator get slashed for double sign
**Note:** When a validator begins the unbonding process, it could be required to turn the validator into unbonding state instantly.
This is different than a specific delegator beginning to unbond. A validator beginning to unbond means that it's not in the set any more.
A delegator unbonding from a validator removes their delegation from the validator.
## Pending development
```go
// Changes to make
// — Implement correct next epoch time calculation
// — For validator self undelegation, it could be required to do start on end blocker
// — Implement TODOs on the PR #46
// Implement CLI commands for querying
// — BufferedValidators
// — BufferedMsgCreateValidatorQueue, BufferedMsgEditValidatorQueue
// — BufferedMsgUnjailQueue, BufferedMsgDelegateQueue, BufferedMsgRedelegationQueue, BufferedMsgUndelegateQueue
// Write epoch related tests with new scenarios
// — Simulation test is important for finding bugs [Ask Dev for questions)
// — Can easily add a simulator check to make sure all delegation amounts in queue add up to the same amount thats in the EpochUnbondedPool
// — Id like it added as an invariant test for the simulator
// — the simulator should check that the sum of all the queued delegations always equals the amount kept track in the data
// — Staking/Slashing/Distribution module params are being modified by governance based on vote result instantly. We should test the effect.
// — — Should test to see what would happen if max_validators is changed though, in the middle of an epoch
// — we should define some new invariants that help check that everything is working smoothly with these new changes for 3 modules e.g. https://github.com/cosmos/cosmos-sdk/blob/main/x/staking/keeper/invariants.go
// — — Within Epoch, ValidationPower = ValidationPower - SlashAmount
// — — When epoch actions queue is empty, EpochDelegationPool balance should be zero
// — we should count all the delegation changes that happen during the epoch, and then make sure that the resulting change at the end of the epoch is actually correct
// — If the validator that I delegated to double signs at block 16, I should still get slashed instantly because even though I asked to unbond at 14, they still used my power at block 16, I should only be not liable for slashes once my power is stopped being used
// — On the converse of this, I should still be getting rewards while my power is being used. I shouldnt stop receiving rewards until block 20
```

View File

@ -1,37 +0,0 @@
<!--
order: 20
title: Epoching Overview
parent:
title: "epoching"
-->
# `x/epoching`
## Abstract
The epoching module allows modules to queue messages for execution at a certain block height. Each module will have its own instance of the epoching module, this allows each module to have its own message queue and own duration for epochs.
## Example
In this example, we are creating an epochkeeper for a module that will be used by the module to queue messages to be executed at a later point in time.
```go
type Keeper struct {
storeKey sdk.StoreKey
cdc codec.BinaryMarshaler
epochKeeper epochkeeper.Keeper
}
// NewKeeper creates a new staking Keeper instance
func NewKeeper(cdc codec.BinaryMarshaler, key sdk.StoreKey) Keeper {
return Keeper{
storeKey: key,
cdc: cdc,
epochKeeper: epochkeeper.NewKeeper(cdc, key),
}
}
```
### Contents
1. **[State](01_state.md)**

View File

@ -1,7 +1,554 @@
<!--
order: 0
title: Evidence Overview
parent:
title: "evidence"
-->
# Evidence
# `x/evidence`
* [Evidence](spec/README.md) - Evidence handling for double signing, misbehaviour, etc.
* [Concepts](#concepts)
* [State](#state)
* [Messages](#messages)
* [Events](#events)
* [Parameters](#parameters)
* [BeginBlock](#beginblock)
* [Client](#client)
* [CLI](#cli)
* [REST](#rest)
* [gRPC](#grpc)
## Abstract
`x/evidence` is an implementation of a Cosmos SDK module, per [ADR 009](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-009-evidence-module.md),
that allows for the submission and handling of arbitrary evidence of misbehavior such
as equivocation and counterfactual signing.
The evidence module differs from standard evidence handling which typically expects the
underlying consensus engine, e.g. Tendermint, to automatically submit evidence when
it is discovered by allowing clients and foreign chains to submit more complex evidence
directly.
All concrete evidence types must implement the `Evidence` interface contract. Submitted
`Evidence` is first routed through the evidence module's `Router` in which it attempts
to find a corresponding registered `Handler` for that specific `Evidence` type.
Each `Evidence` type must have a `Handler` registered with the evidence module's
keeper in order for it to be successfully routed and executed.
Each corresponding handler must also fulfill the `Handler` interface contract. The
`Handler` for a given `Evidence` type can perform any arbitrary state transitions
such as slashing, jailing, and tombstoning.
<!-- order: 1 -->
# Concepts
## Evidence
Any concrete type of evidence submitted to the `x/evidence` module must fulfill the
`Evidence` contract outlined below. Not all concrete types of evidence will fulfill
this contract in the same way and some data may be entirely irrelevant to certain
types of evidence. An additional `ValidatorEvidence`, which extends `Evidence`,
has also been created to define a contract for evidence against malicious validators.
```go
// Evidence defines the contract which concrete evidence types of misbehavior
// must implement.
type Evidence interface {
proto.Message
Route() string
Type() string
String() string
Hash() tmbytes.HexBytes
ValidateBasic() error
// Height at which the infraction occurred
GetHeight() int64
}
// ValidatorEvidence extends Evidence interface to define contract
// for evidence against malicious validators
type ValidatorEvidence interface {
Evidence
// The consensus address of the malicious validator at time of infraction
GetConsensusAddress() sdk.ConsAddress
// The total power of the malicious validator at time of infraction
GetValidatorPower() int64
// The total validator set power at time of infraction
GetTotalPower() int64
}
```
## Registration & Handling
The `x/evidence` module must first know about all types of evidence it is expected
to handle. This is accomplished by registering the `Route` method in the `Evidence`
contract with what is known as a `Router` (defined below). The `Router` accepts
`Evidence` and attempts to find the corresponding `Handler` for the `Evidence`
via the `Route` method.
```go
type Router interface {
AddRoute(r string, h Handler) Router
HasRoute(r string) bool
GetRoute(path string) Handler
Seal()
Sealed() bool
}
```
The `Handler` (defined below) is responsible for executing the entirety of the
business logic for handling `Evidence`. This typically includes validating the
evidence, both stateless checks via `ValidateBasic` and stateful checks via any
keepers provided to the `Handler`. In addition, the `Handler` may also perform
capabilities such as slashing and jailing a validator. All `Evidence` handled
by the `Handler` should be persisted.
```go
// Handler defines an agnostic Evidence handler. The handler is responsible
// for executing all corresponding business logic necessary for verifying the
// evidence as valid. In addition, the Handler may execute any necessary
// slashing and potential jailing.
type Handler func(sdk.Context, Evidence) error
```
<!-- order: 2 -->
# State
Currently the `x/evidence` module only stores valid submitted `Evidence` in state.
The evidence state is also stored and exported in the `x/evidence` module's `GenesisState`.
```protobuf
// GenesisState defines the evidence module's genesis state.
message GenesisState {
// evidence defines all the evidence at genesis.
repeated google.protobuf.Any evidence = 1;
}
```
All `Evidence` is retrieved and stored via a prefix `KVStore` using prefix `0x00` (`KeyPrefixEvidence`).
<!-- order: 3 -->
# Messages
## MsgSubmitEvidence
Evidence is submitted through a `MsgSubmitEvidence` message:
```protobuf
// MsgSubmitEvidence represents a message that supports submitting arbitrary
// Evidence of misbehavior such as equivocation or counterfactual signing.
message MsgSubmitEvidence {
string submitter = 1;
google.protobuf.Any evidence = 2;
}
```
Note, the `Evidence` of a `MsgSubmitEvidence` message must have a corresponding
`Handler` registered with the `x/evidence` module's `Router` in order to be processed
and routed correctly.
Given the `Evidence` is registered with a corresponding `Handler`, it is processed
as follows:
```go
func SubmitEvidence(ctx Context, evidence Evidence) error {
if _, ok := GetEvidence(ctx, evidence.Hash()); ok {
return sdkerrors.Wrap(types.ErrEvidenceExists, evidence.Hash().String())
}
if !router.HasRoute(evidence.Route()) {
return sdkerrors.Wrap(types.ErrNoEvidenceHandlerExists, evidence.Route())
}
handler := router.GetRoute(evidence.Route())
if err := handler(ctx, evidence); err != nil {
return sdkerrors.Wrap(types.ErrInvalidEvidence, err.Error())
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSubmitEvidence,
sdk.NewAttribute(types.AttributeKeyEvidenceHash, evidence.Hash().String()),
),
)
SetEvidence(ctx, evidence)
return nil
}
```
First, there must not already exist valid submitted `Evidence` of the exact same
type. Secondly, the `Evidence` is routed to the `Handler` and executed. Finally,
if there is no error in handling the `Evidence`, an event is emitted and it is persisted to state.
<!-- order: 4 -->
# Events
The `x/evidence` module emits the following events:
## Handlers
### MsgSubmitEvidence
| Type | Attribute Key | Attribute Value |
| --------------- | ------------- | --------------- |
| submit_evidence | evidence_hash | {evidenceHash} |
| message | module | evidence |
| message | sender | {senderAddress} |
| message | action | submit_evidence |
<!-- order: 5 -->
# Parameters
The evidence module does not contain any parameters.
<!-- order: 6 -->
# BeginBlock
## Evidence Handling
Tendermint blocks can include
[Evidence](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/blockchain.md#evidence) that indicates if a validator committed malicious behavior. The relevant information is forwarded to the application as ABCI Evidence in `abci.RequestBeginBlock` so that the validator can be punished accordingly.
### Equivocation
The Cosmos SDK handles two types of evidence inside the ABCI `BeginBlock`:
* `DuplicateVoteEvidence`,
* `LightClientAttackEvidence`.
The evidence module handles these two evidence types the same way. First, the Cosmos SDK converts the Tendermint concrete evidence type to an SDK `Evidence` interface using `Equivocation` as the concrete type.
```proto
// Equivocation implements the Evidence interface.
message Equivocation {
int64 height = 1;
google.protobuf.Timestamp time = 2;
int64 power = 3;
string consensus_address = 4;
}
```
For some `Equivocation` submitted in `block` to be valid, it must satisfy:
`Evidence.Timestamp >= block.Timestamp - MaxEvidenceAge`
Where:
* `Evidence.Timestamp` is the timestamp in the block at height `Evidence.Height`
* `block.Timestamp` is the current block timestamp.
If valid `Equivocation` evidence is included in a block, the validator's stake is
reduced (slashed) by `SlashFractionDoubleSign` as defined by the `x/slashing` module
of what their stake was when the infraction occurred, rather than when the evidence was discovered.
We want to "follow the stake", i.e., the stake that contributed to the infraction
should be slashed, even if it has since been redelegated or started unbonding.
In addition, the validator is permanently jailed and tombstoned to make it impossible for that
validator to ever re-enter the validator set.
The `Equivocation` evidence is handled as follows:
```go
func (k Keeper) HandleEquivocationEvidence(ctx sdk.Context, evidence *types.Equivocation) {
logger := k.Logger(ctx)
consAddr := evidence.GetConsensusAddress()
if _, err := k.slashingKeeper.GetPubkey(ctx, consAddr.Bytes()); err != nil {
// Ignore evidence that cannot be handled.
//
// NOTE: We used to panic with:
// `panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr))`,
// but this couples the expectations of the app to both Tendermint and
// the simulator. Both are expected to provide the full range of
// allowable but none of the disallowed evidence types. Instead of
// getting this coordination right, it is easier to relax the
// constraints and ignore evidence that cannot be handled.
return
}
// calculate the age of the evidence
infractionHeight := evidence.GetHeight()
infractionTime := evidence.GetTime()
ageDuration := ctx.BlockHeader().Time.Sub(infractionTime)
ageBlocks := ctx.BlockHeader().Height - infractionHeight
// Reject evidence if the double-sign is too old. Evidence is considered stale
// if the difference in time and number of blocks is greater than the allowed
// parameters defined.
cp := ctx.ConsensusParams()
if cp != nil && cp.Evidence != nil {
if ageDuration > cp.Evidence.MaxAgeDuration && ageBlocks > cp.Evidence.MaxAgeNumBlocks {
logger.Info(
"ignored equivocation; evidence too old",
"validator", consAddr,
"infraction_height", infractionHeight,
"max_age_num_blocks", cp.Evidence.MaxAgeNumBlocks,
"infraction_time", infractionTime,
"max_age_duration", cp.Evidence.MaxAgeDuration,
)
return
}
}
validator := k.stakingKeeper.ValidatorByConsAddr(ctx, consAddr)
if validator == nil || validator.IsUnbonded() {
// Defensive: Simulation doesn't take unbonding periods into account, and
// Tendermint might break this assumption at some point.
return
}
if ok := k.slashingKeeper.HasValidatorSigningInfo(ctx, consAddr); !ok {
panic(fmt.Sprintf("expected signing info for validator %s but not found", consAddr))
}
// ignore if the validator is already tombstoned
if k.slashingKeeper.IsTombstoned(ctx, consAddr) {
logger.Info(
"ignored equivocation; validator already tombstoned",
"validator", consAddr,
"infraction_height", infractionHeight,
"infraction_time", infractionTime,
)
return
}
logger.Info(
"confirmed equivocation",
"validator", consAddr,
"infraction_height", infractionHeight,
"infraction_time", infractionTime,
)
// We need to retrieve the stake distribution which signed the block, so we
// subtract ValidatorUpdateDelay from the evidence height.
// Note, that this *can* result in a negative "distributionHeight", up to
// -ValidatorUpdateDelay, i.e. at the end of the
// pre-genesis block (none) = at the beginning of the genesis block.
// That's fine since this is just used to filter unbonding delegations & redelegations.
distributionHeight := infractionHeight - sdk.ValidatorUpdateDelay
// Slash validator. The `power` is the int64 power of the validator as provided
// to/by Tendermint. This value is validator.Tokens as sent to Tendermint via
// ABCI, and now received as evidence. The fraction is passed in to separately
// to slash unbonding and rebonding delegations.
k.slashingKeeper.Slash(
ctx,
consAddr,
k.slashingKeeper.SlashFractionDoubleSign(ctx),
evidence.GetValidatorPower(), distributionHeight,
)
// Jail the validator if not already jailed. This will begin unbonding the
// validator if not already unbonding (tombstoned).
if !validator.IsJailed() {
k.slashingKeeper.Jail(ctx, consAddr)
}
k.slashingKeeper.JailUntil(ctx, consAddr, types.DoubleSignJailEndTime)
k.slashingKeeper.Tombstone(ctx, consAddr)
}
```
**Note:** The slashing, jailing, and tombstoning calls are delegated through the `x/slashing` module
that emits informative events and finally delegates calls to the `x/staking` module. See documentation
on slashing and jailing in [State Transitions](/.././cosmos-sdk/x/staking/spec/02_state_transitions.md).
# Client
## CLI
A user can query and interact with the `evidence` module using the CLI.
### Query
The `query` commands allows users to query `evidence` state.
```bash
simd query evidence --help
```
### evidence
The `evidence` command allows users to list all evidence or evidence by hash.
Usage:
```bash
simd query evidence [flags]
```
To query evidence by hash
Example:
```bash
simd query evidence "DF0C23E8634E480F84B9D5674A7CDC9816466DEC28A3358F73260F68D28D7660"
```
Example Output:
```bash
evidence:
consensus_address: cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h
height: 11
power: 100
time: "2021-10-20T16:08:38.194017624Z"
```
To get all evidence
Example:
```bash
simd query evidence
```
Example Output:
```bash
evidence:
consensus_address: cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h
height: 11
power: 100
time: "2021-10-20T16:08:38.194017624Z"
pagination:
next_key: null
total: "1"
```
## REST
A user can query the `evidence` module using REST endpoints.
### Evidence
Get evidence by hash
```bash
/cosmos/evidence/v1beta1/evidence/{evidence_hash}
```
Example:
```bash
curl -X GET "http://localhost:1317/cosmos/evidence/v1beta1/evidence/DF0C23E8634E480F84B9D5674A7CDC9816466DEC28A3358F73260F68D28D7660"
```
Example Output:
```bash
{
"evidence": {
"consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h",
"height": "11",
"power": "100",
"time": "2021-10-20T16:08:38.194017624Z"
}
}
```
### All evidence
Get all evidence
```bash
/cosmos/evidence/v1beta1/evidence
```
Example:
```bash
curl -X GET "http://localhost:1317/cosmos/evidence/v1beta1/evidence"
```
Example Output:
```bash
{
"evidence": [
{
"consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h",
"height": "11",
"power": "100",
"time": "2021-10-20T16:08:38.194017624Z"
}
],
"pagination": {
"total": "1"
}
}
```
## gRPC
A user can query the `evidence` module using gRPC endpoints.
### Evidence
Get evidence by hash
```bash
cosmos.evidence.v1beta1.Query/Evidence
```
Example:
```bash
grpcurl -plaintext -d '{"evidence_hash":"DF0C23E8634E480F84B9D5674A7CDC9816466DEC28A3358F73260F68D28D7660"}' localhost:9090 cosmos.evidence.v1beta1.Query/Evidence
```
Example Output:
```bash
{
"evidence": {
"consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h",
"height": "11",
"power": "100",
"time": "2021-10-20T16:08:38.194017624Z"
}
}
```
### All evidence
Get all evidence
```bash
cosmos.evidence.v1beta1.Query/AllEvidence
```
Example:
```bash
grpcurl -plaintext localhost:9090 cosmos.evidence.v1beta1.Query/AllEvidence
```
Example Output:
```bash
{
"evidence": [
{
"consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h",
"height": "11",
"power": "100",
"time": "2021-10-20T16:08:38.194017624Z"
}
],
"pagination": {
"total": "1"
}
}
```

View File

@ -1,78 +0,0 @@
<!--
order: 1
-->
# Concepts
## Evidence
Any concrete type of evidence submitted to the `x/evidence` module must fulfill the
`Evidence` contract outlined below. Not all concrete types of evidence will fulfill
this contract in the same way and some data may be entirely irrelevant to certain
types of evidence. An additional `ValidatorEvidence`, which extends `Evidence`,
has also been created to define a contract for evidence against malicious validators.
```go
// Evidence defines the contract which concrete evidence types of misbehavior
// must implement.
type Evidence interface {
proto.Message
Route() string
Type() string
String() string
Hash() tmbytes.HexBytes
ValidateBasic() error
// Height at which the infraction occurred
GetHeight() int64
}
// ValidatorEvidence extends Evidence interface to define contract
// for evidence against malicious validators
type ValidatorEvidence interface {
Evidence
// The consensus address of the malicious validator at time of infraction
GetConsensusAddress() sdk.ConsAddress
// The total power of the malicious validator at time of infraction
GetValidatorPower() int64
// The total validator set power at time of infraction
GetTotalPower() int64
}
```
## Registration & Handling
The `x/evidence` module must first know about all types of evidence it is expected
to handle. This is accomplished by registering the `Route` method in the `Evidence`
contract with what is known as a `Router` (defined below). The `Router` accepts
`Evidence` and attempts to find the corresponding `Handler` for the `Evidence`
via the `Route` method.
```go
type Router interface {
AddRoute(r string, h Handler) Router
HasRoute(r string) bool
GetRoute(path string) Handler
Seal()
Sealed() bool
}
```
The `Handler` (defined below) is responsible for executing the entirety of the
business logic for handling `Evidence`. This typically includes validating the
evidence, both stateless checks via `ValidateBasic` and stateful checks via any
keepers provided to the `Handler`. In addition, the `Handler` may also perform
capabilities such as slashing and jailing a validator. All `Evidence` handled
by the `Handler` should be persisted.
```go
// Handler defines an agnostic Evidence handler. The handler is responsible
// for executing all corresponding business logic necessary for verifying the
// evidence as valid. In addition, the Handler may execute any necessary
// slashing and potential jailing.
type Handler func(sdk.Context, Evidence) error
```

View File

@ -1,19 +0,0 @@
<!--
order: 2
-->
# State
Currently the `x/evidence` module only stores valid submitted `Evidence` in state.
The evidence state is also stored and exported in the `x/evidence` module's `GenesisState`.
```protobuf
// GenesisState defines the evidence module's genesis state.
message GenesisState {
// evidence defines all the evidence at genesis.
repeated google.protobuf.Any evidence = 1;
}
```
All `Evidence` is retrieved and stored via a prefix `KVStore` using prefix `0x00` (`KeyPrefixEvidence`).

View File

@ -1,55 +0,0 @@
<!--
order: 3
-->
# Messages
## MsgSubmitEvidence
Evidence is submitted through a `MsgSubmitEvidence` message:
```protobuf
// MsgSubmitEvidence represents a message that supports submitting arbitrary
// Evidence of misbehavior such as equivocation or counterfactual signing.
message MsgSubmitEvidence {
string submitter = 1;
google.protobuf.Any evidence = 2;
}
```
Note, the `Evidence` of a `MsgSubmitEvidence` message must have a corresponding
`Handler` registered with the `x/evidence` module's `Router` in order to be processed
and routed correctly.
Given the `Evidence` is registered with a corresponding `Handler`, it is processed
as follows:
```go
func SubmitEvidence(ctx Context, evidence Evidence) error {
if _, ok := GetEvidence(ctx, evidence.Hash()); ok {
return sdkerrors.Wrap(types.ErrEvidenceExists, evidence.Hash().String())
}
if !router.HasRoute(evidence.Route()) {
return sdkerrors.Wrap(types.ErrNoEvidenceHandlerExists, evidence.Route())
}
handler := router.GetRoute(evidence.Route())
if err := handler(ctx, evidence); err != nil {
return sdkerrors.Wrap(types.ErrInvalidEvidence, err.Error())
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSubmitEvidence,
sdk.NewAttribute(types.AttributeKeyEvidenceHash, evidence.Hash().String()),
),
)
SetEvidence(ctx, evidence)
return nil
}
```
First, there must not already exist valid submitted `Evidence` of the exact same
type. Secondly, the `Evidence` is routed to the `Handler` and executed. Finally,
if there is no error in handling the `Evidence`, an event is emitted and it is persisted to state.

View File

@ -1,18 +0,0 @@
<!--
order: 4
-->
# Events
The `x/evidence` module emits the following events:
## Handlers
### MsgSubmitEvidence
| Type | Attribute Key | Attribute Value |
| --------------- | ------------- | --------------- |
| submit_evidence | evidence_hash | {evidenceHash} |
| message | module | evidence |
| message | sender | {senderAddress} |
| message | action | submit_evidence |

View File

@ -1,7 +0,0 @@
<!--
order: 5
-->
# Parameters
The evidence module does not contain any parameters.

View File

@ -1,154 +0,0 @@
<!--
order: 6
-->
# BeginBlock
## Evidence Handling
Tendermint blocks can include
[Evidence](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/blockchain.md#evidence) that indicates if a validator committed malicious behavior. The relevant information is forwarded to the application as ABCI Evidence in `abci.RequestBeginBlock` so that the validator can be punished accordingly.
### Equivocation
The Cosmos SDK handles two types of evidence inside the ABCI `BeginBlock`:
* `DuplicateVoteEvidence`,
* `LightClientAttackEvidence`.
The evidence module handles these two evidence types the same way. First, the Cosmos SDK converts the Tendermint concrete evidence type to an SDK `Evidence` interface using `Equivocation` as the concrete type.
```proto
// Equivocation implements the Evidence interface.
message Equivocation {
int64 height = 1;
google.protobuf.Timestamp time = 2;
int64 power = 3;
string consensus_address = 4;
}
```
For some `Equivocation` submitted in `block` to be valid, it must satisfy:
`Evidence.Timestamp >= block.Timestamp - MaxEvidenceAge`
Where:
* `Evidence.Timestamp` is the timestamp in the block at height `Evidence.Height`
* `block.Timestamp` is the current block timestamp.
If valid `Equivocation` evidence is included in a block, the validator's stake is
reduced (slashed) by `SlashFractionDoubleSign` as defined by the `x/slashing` module
of what their stake was when the infraction occurred, rather than when the evidence was discovered.
We want to "follow the stake", i.e., the stake that contributed to the infraction
should be slashed, even if it has since been redelegated or started unbonding.
In addition, the validator is permanently jailed and tombstoned to make it impossible for that
validator to ever re-enter the validator set.
The `Equivocation` evidence is handled as follows:
```go
func (k Keeper) HandleEquivocationEvidence(ctx sdk.Context, evidence *types.Equivocation) {
logger := k.Logger(ctx)
consAddr := evidence.GetConsensusAddress()
if _, err := k.slashingKeeper.GetPubkey(ctx, consAddr.Bytes()); err != nil {
// Ignore evidence that cannot be handled.
//
// NOTE: We used to panic with:
// `panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr))`,
// but this couples the expectations of the app to both Tendermint and
// the simulator. Both are expected to provide the full range of
// allowable but none of the disallowed evidence types. Instead of
// getting this coordination right, it is easier to relax the
// constraints and ignore evidence that cannot be handled.
return
}
// calculate the age of the evidence
infractionHeight := evidence.GetHeight()
infractionTime := evidence.GetTime()
ageDuration := ctx.BlockHeader().Time.Sub(infractionTime)
ageBlocks := ctx.BlockHeader().Height - infractionHeight
// Reject evidence if the double-sign is too old. Evidence is considered stale
// if the difference in time and number of blocks is greater than the allowed
// parameters defined.
cp := ctx.ConsensusParams()
if cp != nil && cp.Evidence != nil {
if ageDuration > cp.Evidence.MaxAgeDuration && ageBlocks > cp.Evidence.MaxAgeNumBlocks {
logger.Info(
"ignored equivocation; evidence too old",
"validator", consAddr,
"infraction_height", infractionHeight,
"max_age_num_blocks", cp.Evidence.MaxAgeNumBlocks,
"infraction_time", infractionTime,
"max_age_duration", cp.Evidence.MaxAgeDuration,
)
return
}
}
validator := k.stakingKeeper.ValidatorByConsAddr(ctx, consAddr)
if validator == nil || validator.IsUnbonded() {
// Defensive: Simulation doesn't take unbonding periods into account, and
// Tendermint might break this assumption at some point.
return
}
if ok := k.slashingKeeper.HasValidatorSigningInfo(ctx, consAddr); !ok {
panic(fmt.Sprintf("expected signing info for validator %s but not found", consAddr))
}
// ignore if the validator is already tombstoned
if k.slashingKeeper.IsTombstoned(ctx, consAddr) {
logger.Info(
"ignored equivocation; validator already tombstoned",
"validator", consAddr,
"infraction_height", infractionHeight,
"infraction_time", infractionTime,
)
return
}
logger.Info(
"confirmed equivocation",
"validator", consAddr,
"infraction_height", infractionHeight,
"infraction_time", infractionTime,
)
// We need to retrieve the stake distribution which signed the block, so we
// subtract ValidatorUpdateDelay from the evidence height.
// Note, that this *can* result in a negative "distributionHeight", up to
// -ValidatorUpdateDelay, i.e. at the end of the
// pre-genesis block (none) = at the beginning of the genesis block.
// That's fine since this is just used to filter unbonding delegations & redelegations.
distributionHeight := infractionHeight - sdk.ValidatorUpdateDelay
// Slash validator. The `power` is the int64 power of the validator as provided
// to/by Tendermint. This value is validator.Tokens as sent to Tendermint via
// ABCI, and now received as evidence. The fraction is passed in to separately
// to slash unbonding and rebonding delegations.
k.slashingKeeper.Slash(
ctx,
consAddr,
k.slashingKeeper.SlashFractionDoubleSign(ctx),
evidence.GetValidatorPower(), distributionHeight,
)
// Jail the validator if not already jailed. This will begin unbonding the
// validator if not already unbonding (tombstoned).
if !validator.IsJailed() {
k.slashingKeeper.Jail(ctx, consAddr)
}
k.slashingKeeper.JailUntil(ctx, consAddr, types.DoubleSignJailEndTime)
k.slashingKeeper.Tombstone(ctx, consAddr)
}
```
**Note:** The slashing, jailing, and tombstoning calls are delegated through the `x/slashing` module
that emits informative events and finally delegates calls to the `x/staking` module. See documentation
on slashing and jailing in [State Transitions](/.././cosmos-sdk/x/staking/spec/02_state_transitions.md).

View File

@ -1,188 +0,0 @@
# Client
## CLI
A user can query and interact with the `evidence` module using the CLI.
### Query
The `query` commands allows users to query `evidence` state.
```bash
simd query evidence --help
```
### evidence
The `evidence` command allows users to list all evidence or evidence by hash.
Usage:
```bash
simd query evidence [flags]
```
To query evidence by hash
Example:
```bash
simd query evidence "DF0C23E8634E480F84B9D5674A7CDC9816466DEC28A3358F73260F68D28D7660"
```
Example Output:
```bash
evidence:
consensus_address: cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h
height: 11
power: 100
time: "2021-10-20T16:08:38.194017624Z"
```
To get all evidence
Example:
```bash
simd query evidence
```
Example Output:
```bash
evidence:
consensus_address: cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h
height: 11
power: 100
time: "2021-10-20T16:08:38.194017624Z"
pagination:
next_key: null
total: "1"
```
## REST
A user can query the `evidence` module using REST endpoints.
### Evidence
Get evidence by hash
```bash
/cosmos/evidence/v1beta1/evidence/{evidence_hash}
```
Example:
```bash
curl -X GET "http://localhost:1317/cosmos/evidence/v1beta1/evidence/DF0C23E8634E480F84B9D5674A7CDC9816466DEC28A3358F73260F68D28D7660"
```
Example Output:
```bash
{
"evidence": {
"consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h",
"height": "11",
"power": "100",
"time": "2021-10-20T16:08:38.194017624Z"
}
}
```
### All evidence
Get all evidence
```bash
/cosmos/evidence/v1beta1/evidence
```
Example:
```bash
curl -X GET "http://localhost:1317/cosmos/evidence/v1beta1/evidence"
```
Example Output:
```bash
{
"evidence": [
{
"consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h",
"height": "11",
"power": "100",
"time": "2021-10-20T16:08:38.194017624Z"
}
],
"pagination": {
"total": "1"
}
}
```
## gRPC
A user can query the `evidence` module using gRPC endpoints.
### Evidence
Get evidence by hash
```bash
cosmos.evidence.v1beta1.Query/Evidence
```
Example:
```bash
grpcurl -plaintext -d '{"evidence_hash":"DF0C23E8634E480F84B9D5674A7CDC9816466DEC28A3358F73260F68D28D7660"}' localhost:9090 cosmos.evidence.v1beta1.Query/Evidence
```
Example Output:
```bash
{
"evidence": {
"consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h",
"height": "11",
"power": "100",
"time": "2021-10-20T16:08:38.194017624Z"
}
}
```
### All evidence
Get all evidence
```bash
cosmos.evidence.v1beta1.Query/AllEvidence
```
Example:
```bash
grpcurl -plaintext localhost:9090 cosmos.evidence.v1beta1.Query/AllEvidence
```
Example Output:
```bash
{
"evidence": [
{
"consensus_address": "cosmosvalcons1ntk8eualewuprz0gamh8hnvcem2nrcdsgz563h",
"height": "11",
"power": "100",
"time": "2021-10-20T16:08:38.194017624Z"
}
],
"pagination": {
"total": "1"
}
}
```

View File

@ -1,40 +0,0 @@
<!--
order: 0
title: Evidence Overview
parent:
title: "evidence"
-->
# `x/evidence`
## Table of Contents
<!-- TOC -->
1. **[Concepts](01_concepts.md)**
2. **[State](02_state.md)**
3. **[Messages](03_messages.md)**
4. **[Events](04_events.md)**
5. **[Params](05_params.md)**
6. **[BeginBlock](06_begin_block.md)**
## Abstract
`x/evidence` is an implementation of a Cosmos SDK module, per [ADR 009](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-009-evidence-module.md),
that allows for the submission and handling of arbitrary evidence of misbehavior such
as equivocation and counterfactual signing.
The evidence module differs from standard evidence handling which typically expects the
underlying consensus engine, e.g. Tendermint, to automatically submit evidence when
it is discovered by allowing clients and foreign chains to submit more complex evidence
directly.
All concrete evidence types must implement the `Evidence` interface contract. Submitted
`Evidence` is first routed through the evidence module's `Router` in which it attempts
to find a corresponding registered `Handler` for that specific `Evidence` type.
Each `Evidence` type must have a `Handler` registered with the evidence module's
keeper in order for it to be successfully routed and executed.
Each corresponding handler must also fulfill the `Handler` interface contract. The
`Handler` for a given `Evidence` type can perform any arbitrary state transitions
such as slashing, jailing, and tombstoning.

View File

@ -1,7 +1,377 @@
<!--
order: 0
title: Fee grant Overview
parent:
title: "feegrant"
-->
# Fee Grant
# `x/feegrant`
* [Fee Grant](spec/README.md) - Grant fee allowances for executing transactions.
## Abstract
This document specifies the fee grant module. For the full ADR, please see [Fee Grant ADR-029](https://github.com/cosmos/cosmos-sdk/blob/main/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
* [Concepts](#concepts)
* [State](#state)
* [FeeAllowance](#feeallowance)
* [FeeAllowanceQueue](#feeallowancequeue)
* [Messages](#messages)
* [Msg/GrantAllowance](#msggrantallowance)
* [Msg/RevokeAllowance](#msgrevokeallowance)
* [Events](#events)
* [Msg Server](#msg-server)
* [MsgGrantAllowance](#msggrantallowance-1)
* [MsgRevokeAllowance](#msgrevokeallowance-1)
* [Exec fee allowance](#exec-fee-allowance)
* [Client](#client)
* [CLI](#cli)
* [gRPC](#grpc)
<!-- order: 1 -->
# Concepts
## Grant
`Grant` 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 (`BasicAllowance` or `PeriodicAllowance`, 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/v0.46.0/proto/cosmos/feegrant/v1beta1/feegrant.proto#L76-L77
`FeeAllowanceI` looks like:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/feegrant/fees.go#L9-L32
## Fee Allowance types
There are two types of fee allowances present at the moment:
* `BasicAllowance`
* `PeriodicAllowance`
* `AllowedMsgAllowance`
## BasicAllowance
`BasicAllowance` 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/v0.46.0/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 coins 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 coins from `granter` and it won't have any expiration. The only way to restrict the `grantee` is by revoking the grant.
## PeriodicAllowance
`PeriodicAllowance` 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/v0.46.0/proto/cosmos/feegrant/v1beta1/feegrant.proto#L29-L54
* `basic` is the instance of `BasicAllowance` 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, after each period passes, `period_can_spend` 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.
## AllowedMsgAllowance
`AllowedMsgAllowance` is a fee allowance, it can be any of `BasicFeeAllowance`, `PeriodicAllowance` but restricted only to the allowed messages mentioned by the granter.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/feegrant/v1beta1/feegrant.proto#L56-L66
* `allowance` is either `BasicAllowance` or `PeriodicAllowance`.
* `allowed_messages` is array of messages allowed to execute the given allowance.
## FeeGranter flag
`feegrant` module introduces a `FeeGranter` 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/v0.46.0/client/cmd.go#L236-L246
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/client/tx/tx.go#L109-L109
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/auth/tx/builder.go#L270-L279
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/tx/v1beta1/tx.proto#L196-L217
Example cmd:
```go
./simd tx gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --from validator-key --fee-granter=cosmos1xh44hxt7spr67hqaa7nyx5gnutrz5fraw6grxn --chain-id=testnet --fees="10stake"
```
## Granted Fee Deductions
Fees are deducted from grants in the `x/auth` ante handler. To learn more about how ante handlers work, read the [Auth Module AnteHandlers Guide](../../auth/spec/03_antehandlers.md).
## Gas
In order to prevent DoS attacks, using a filtered `x/feegrant` incurs gas. The SDK must assure that the `grantee`'s transactions all conform to the filter set by the `granter`. The SDK does this by iterating over the allowed messages in the filter and charging 10 gas per filtered message. The SDK will then iterate over the messages being sent by the `grantee` to ensure the messages adhere to the filter, also charging 10 gas per message. The SDK will stop iterating and fail the transaction if it finds a message that does not conform to the filter.
**WARNING**: The gas is charged against the granted allowance. Ensure your messages conform to the filter, if any, before sending transactions using your allowance.
## Pruning
A queue in the state maintained with the prefix of expiration of the grants and checks them on EndBlock with the current block time for every block to prune.
<!-- order: 2 -->
# 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 allowance grants are stored in the state as follows:
* Grant: `0x00 | grantee_addr_len (1 byte) | grantee_addr_bytes | granter_addr_len (1 byte) | granter_addr_bytes -> ProtocolBuffer(Grant)`
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/feegrant/feegrant.pb.go#L221-L229
## FeeAllowanceQueue
Fee Allowances queue items are identified by combining the `FeeAllowancePrefixQueue` (i.e., 0x01), `expiration`, `grantee` (the account address of fee allowance grantee), `granter` (the account address of fee allowance granter). Endblocker checks `FeeAllowanceQueue` state for the expired grants and prunes them from `FeeAllowance` if there are any found.
Fee allowance queue keys are stored in the state as follows:
* Grant: `0x01 | expiration_bytes | grantee_addr_len (1 byte) | grantee_addr_bytes | granter_addr_len (1 byte) | granter_addr_bytes -> EmptyBytes`
<!-- order: 3 -->
# Messages
## Msg/GrantAllowance
A fee allowance grant will be created with the `MsgGrantAllowance` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/feegrant/v1beta1/tx.proto#L23-L36
## Msg/RevokeAllowance
An allowed grant fee allowance can be removed with the `MsgRevokeAllowance` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/feegrant/v1beta1/tx.proto#L41-L50
<!-- order: 4 -->
# Events
The feegrant module emits the following events:
# Msg Server
## MsgGrantAllowance
| Type | Attribute Key | Attribute Value |
| ------- | ------------- | ---------------- |
| message | action | set_feegrant |
| message | granter | {granterAddress} |
| message | grantee | {granteeAddress} |
## MsgRevokeAllowance
| 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} |
<!-- order: 6 -->
# Client
## CLI
A user can query and interact with the `feegrant` module using the CLI.
### Query
The `query` commands allow users to query `feegrant` state.
```sh
simd query feegrant --help
```
#### grant
The `grant` command allows users to query a grant for a given granter-grantee pair.
```sh
simd query feegrant grant [granter] [grantee] [flags]
```
Example:
```sh
simd query feegrant grant cosmos1.. cosmos1..
```
Example Output:
```yml
allowance:
'@type': /cosmos.feegrant.v1beta1.BasicAllowance
expiration: null
spend_limit:
- amount: "100"
denom: stake
grantee: cosmos1..
granter: cosmos1..
```
#### grants
The `grants` command allows users to query all grants for a given grantee.
```sh
simd query feegrant grants [grantee] [flags]
```
Example:
```sh
simd query feegrant grants cosmos1..
```
Example Output:
```yml
allowances:
- allowance:
'@type': /cosmos.feegrant.v1beta1.BasicAllowance
expiration: null
spend_limit:
- amount: "100"
denom: stake
grantee: cosmos1..
granter: cosmos1..
pagination:
next_key: null
total: "0"
```
### Transactions
The `tx` commands allow users to interact with the `feegrant` module.
```sh
simd tx feegrant --help
```
#### grant
The `grant` command allows users to grant fee allowances to another account. The fee allowance can have an expiration date, a total spend limit, and/or a periodic spend limit.
```sh
simd tx feegrant grant [granter] [grantee] [flags]
```
Example (one-time spend limit):
```sh
simd tx feegrant grant cosmos1.. cosmos1.. --spend-limit 100stake
```
Example (periodic spend limit):
```sh
simd tx feegrant grant cosmos1.. cosmos1.. --period 3600 --period-limit 10stake
```
#### revoke
The `revoke` command allows users to revoke a granted fee allowance.
```sh
simd tx feegrant revoke [granter] [grantee] [flags]
```
Example:
```sh
simd tx feegrant revoke cosmos1.. cosmos1..
```
## gRPC
A user can query the `feegrant` module using gRPC endpoints.
### Allowance
The `Allowance` endpoint allows users to query a granted fee allowance.
```sh
cosmos.feegrant.v1beta1.Query/Allowance
```
Example:
```sh
grpcurl -plaintext \
-d '{"grantee":"cosmos1..","granter":"cosmos1.."}' \
localhost:9090 \
cosmos.feegrant.v1beta1.Query/Allowance
```
Example Output:
```json
{
"allowance": {
"granter": "cosmos1..",
"grantee": "cosmos1..",
"allowance": {"@type":"/cosmos.feegrant.v1beta1.BasicAllowance","spendLimit":[{"denom":"stake","amount":"100"}]}
}
}
```
### Allowances
The `Allowances` endpoint allows users to query all granted fee allowances for a given grantee.
```sh
cosmos.feegrant.v1beta1.Query/Allowances
```
Example:
```sh
grpcurl -plaintext \
-d '{"address":"cosmos1.."}' \
localhost:9090 \
cosmos.feegrant.v1beta1.Query/Allowances
```
Example Output:
```json
{
"allowances": [
{
"granter": "cosmos1..",
"grantee": "cosmos1..",
"allowance": {"@type":"/cosmos.feegrant.v1beta1.BasicAllowance","spendLimit":[{"denom":"stake","amount":"100"}]}
}
],
"pagination": {
"total": "1"
}
}
```

View File

@ -1,93 +0,0 @@
<!--
order: 1
-->
# Concepts
## Grant
`Grant` 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 (`BasicAllowance` or `PeriodicAllowance`, 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/v0.46.0/proto/cosmos/feegrant/v1beta1/feegrant.proto#L76-L77
`FeeAllowanceI` looks like:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/feegrant/fees.go#L9-L32
## Fee Allowance types
There are two types of fee allowances present at the moment:
* `BasicAllowance`
* `PeriodicAllowance`
* `AllowedMsgAllowance`
## BasicAllowance
`BasicAllowance` 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/v0.46.0/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 coins 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 coins from `granter` and it won't have any expiration. The only way to restrict the `grantee` is by revoking the grant.
## PeriodicAllowance
`PeriodicAllowance` 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/v0.46.0/proto/cosmos/feegrant/v1beta1/feegrant.proto#L29-L54
* `basic` is the instance of `BasicAllowance` 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, after each period passes, `period_can_spend` 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.
## AllowedMsgAllowance
`AllowedMsgAllowance` is a fee allowance, it can be any of `BasicFeeAllowance`, `PeriodicAllowance` but restricted only to the allowed messages mentioned by the granter.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/feegrant/v1beta1/feegrant.proto#L56-L66
* `allowance` is either `BasicAllowance` or `PeriodicAllowance`.
* `allowed_messages` is array of messages allowed to execute the given allowance.
## FeeGranter flag
`feegrant` module introduces a `FeeGranter` 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/v0.46.0/client/cmd.go#L236-L246
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/client/tx/tx.go#L109-L109
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/auth/tx/builder.go#L270-L279
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/tx/v1beta1/tx.proto#L196-L217
Example cmd:
```go
./simd tx gov submit-proposal --title="Test Proposal" --description="My awesome proposal" --type="Text" --from validator-key --fee-granter=cosmos1xh44hxt7spr67hqaa7nyx5gnutrz5fraw6grxn --chain-id=testnet --fees="10stake"
```
## Granted Fee Deductions
Fees are deducted from grants in the `x/auth` ante handler. To learn more about how ante handlers work, read the [Auth Module AnteHandlers Guide](../../auth/spec/03_antehandlers.md).
## Gas
In order to prevent DoS attacks, using a filtered `x/feegrant` incurs gas. The SDK must assure that the `grantee`'s transactions all conform to the filter set by the `granter`. The SDK does this by iterating over the allowed messages in the filter and charging 10 gas per filtered message. The SDK will then iterate over the messages being sent by the `grantee` to ensure the messages adhere to the filter, also charging 10 gas per message. The SDK will stop iterating and fail the transaction if it finds a message that does not conform to the filter.
**WARNING**: The gas is charged against the granted allowance. Ensure your messages conform to the filter, if any, before sending transactions using your allowance.
## Pruning
A queue in the state maintained with the prefix of expiration of the grants and checks them on EndBlock with the current block time for every block to prune.

View File

@ -1,23 +0,0 @@
<!--
order: 2
-->
# 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 allowance grants are stored in the state as follows:
* Grant: `0x00 | grantee_addr_len (1 byte) | grantee_addr_bytes | granter_addr_len (1 byte) | granter_addr_bytes -> ProtocolBuffer(Grant)`
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/feegrant/feegrant.pb.go#L221-L229
## FeeAllowanceQueue
Fee Allowances queue items are identified by combining the `FeeAllowancePrefixQueue` (i.e., 0x01), `expiration`, `grantee` (the account address of fee allowance grantee), `granter` (the account address of fee allowance granter). Endblocker checks `FeeAllowanceQueue` state for the expired grants and prunes them from `FeeAllowance` if there are any found.
Fee allowance queue keys are stored in the state as follows:
* Grant: `0x01 | expiration_bytes | grantee_addr_len (1 byte) | grantee_addr_bytes | granter_addr_len (1 byte) | granter_addr_bytes -> EmptyBytes`

View File

@ -1,17 +0,0 @@
<!--
order: 3
-->
# Messages
## Msg/GrantAllowance
A fee allowance grant will be created with the `MsgGrantAllowance` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/feegrant/v1beta1/tx.proto#L23-L36
## Msg/RevokeAllowance
An allowed grant fee allowance can be removed with the `MsgRevokeAllowance` message.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/feegrant/v1beta1/tx.proto#L41-L50

View File

@ -1,33 +0,0 @@
<!--
order: 4
-->
# Events
The feegrant module emits the following events:
# Msg Server
## MsgGrantAllowance
| Type | Attribute Key | Attribute Value |
| ------- | ------------- | ---------------- |
| message | action | set_feegrant |
| message | granter | {granterAddress} |
| message | grantee | {granteeAddress} |
## MsgRevokeAllowance
| 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} |

View File

@ -1,184 +0,0 @@
<!--
order: 6
-->
# Client
## CLI
A user can query and interact with the `feegrant` module using the CLI.
### Query
The `query` commands allow users to query `feegrant` state.
```sh
simd query feegrant --help
```
#### grant
The `grant` command allows users to query a grant for a given granter-grantee pair.
```sh
simd query feegrant grant [granter] [grantee] [flags]
```
Example:
```sh
simd query feegrant grant cosmos1.. cosmos1..
```
Example Output:
```yml
allowance:
'@type': /cosmos.feegrant.v1beta1.BasicAllowance
expiration: null
spend_limit:
- amount: "100"
denom: stake
grantee: cosmos1..
granter: cosmos1..
```
#### grants
The `grants` command allows users to query all grants for a given grantee.
```sh
simd query feegrant grants [grantee] [flags]
```
Example:
```sh
simd query feegrant grants cosmos1..
```
Example Output:
```yml
allowances:
- allowance:
'@type': /cosmos.feegrant.v1beta1.BasicAllowance
expiration: null
spend_limit:
- amount: "100"
denom: stake
grantee: cosmos1..
granter: cosmos1..
pagination:
next_key: null
total: "0"
```
### Transactions
The `tx` commands allow users to interact with the `feegrant` module.
```sh
simd tx feegrant --help
```
#### grant
The `grant` command allows users to grant fee allowances to another account. The fee allowance can have an expiration date, a total spend limit, and/or a periodic spend limit.
```sh
simd tx feegrant grant [granter] [grantee] [flags]
```
Example (one-time spend limit):
```sh
simd tx feegrant grant cosmos1.. cosmos1.. --spend-limit 100stake
```
Example (periodic spend limit):
```sh
simd tx feegrant grant cosmos1.. cosmos1.. --period 3600 --period-limit 10stake
```
#### revoke
The `revoke` command allows users to revoke a granted fee allowance.
```sh
simd tx feegrant revoke [granter] [grantee] [flags]
```
Example:
```sh
simd tx feegrant revoke cosmos1.. cosmos1..
```
## gRPC
A user can query the `feegrant` module using gRPC endpoints.
### Allowance
The `Allowance` endpoint allows users to query a granted fee allowance.
```sh
cosmos.feegrant.v1beta1.Query/Allowance
```
Example:
```sh
grpcurl -plaintext \
-d '{"grantee":"cosmos1..","granter":"cosmos1.."}' \
localhost:9090 \
cosmos.feegrant.v1beta1.Query/Allowance
```
Example Output:
```json
{
"allowance": {
"granter": "cosmos1..",
"grantee": "cosmos1..",
"allowance": {"@type":"/cosmos.feegrant.v1beta1.BasicAllowance","spendLimit":[{"denom":"stake","amount":"100"}]}
}
}
```
### Allowances
The `Allowances` endpoint allows users to query all granted fee allowances for a given grantee.
```sh
cosmos.feegrant.v1beta1.Query/Allowances
```
Example:
```sh
grpcurl -plaintext \
-d '{"address":"cosmos1.."}' \
localhost:9090 \
cosmos.feegrant.v1beta1.Query/Allowances
```
Example Output:
```json
{
"allowances": [
{
"granter": "cosmos1..",
"grantee": "cosmos1..",
"allowance": {"@type":"/cosmos.feegrant.v1beta1.BasicAllowance","spendLimit":[{"denom":"stake","amount":"100"}]}
}
],
"pagination": {
"total": "1"
}
}
```

View File

@ -1,37 +0,0 @@
<!--
order: 0
title: Fee grant
parent:
title: "feegrant"
-->
# Fee grant
## Abstract
This document specifies the fee grant module. For the full ADR, please see [Fee Grant ADR-029](https://github.com/cosmos/cosmos-sdk/blob/main/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)**
* [Grant](01_concepts.md#grant)
* [Fee Allowance types](01_concepts.md#fee-allowance-types)
* [BasicAllowance](01_concepts.md#basicallowance)
* [PeriodicAllowance](01_concepts.md#periodicallowance)
* [FeeAccount flag](01_concepts.md#feeaccount-flag)
* [Granted Fee Deductions](01_concepts.md#granted-fee-deductions)
* [Gas](01_concepts.md#gas)
2. **[State](02_state.md)**
* [FeeAllowance](02_state.md#feeallowance)
3. **[Messages](03_messages.md)**
* [Msg/GrantAllowance](03_messages.md#msggrantallowance)
* [Msg/RevokeAllowance](03_messages.md#msgrevokeallowance)
4. **[Events](04_events.md)**
* [MsgGrantAllowance](04_events.md#msggrantallowance)
* [MsgRevokeAllowance](04_events.md#msgrevokeallowance)
* [Exec fee allowance](04_events.md#exec-fee-allowance)
5. **[Client](05_client.md)**
* [CLI](05_client.md#cli)
* [gRPC](05_client.md#grpc)

File diff suppressed because it is too large Load Diff

View File

@ -1,203 +0,0 @@
<!--
order: 1
-->
# Concepts
_Disclaimer: This is work in progress. Mechanisms are susceptible to change._
The governance process is divided in a few steps that are outlined below:
* **Proposal submission:** Proposal is submitted to the blockchain with a
deposit.
* **Vote:** Once deposit reaches a certain value (`MinDeposit`), proposal is
confirmed and vote opens. Bonded Atom holders can then send `TxGovVote`
transactions to vote on the proposal.
* **Execution** After a period of time, the votes are tallied and depending
on the result, the messages in the proposal will be executed.
## Proposal submission
### Right to submit a proposal
Every account can submit proposals by sending a `MsgSubmitProposal` transaction.
Once a proposal is submitted, it is identified by its unique `proposalID`.
### Proposal Messages
A proposal includes an array of `sdk.Msg`s which are executed automatically if the
proposal passes. The messages are executed by the governance `ModuleAccount` itself. Modules
such as `x/upgrade`, that want to allow certain messages to be executed by governance
only should add a whitelist within the respective msg server, granting the governance
module the right to execute the message once a quorum has been reached. The governance
module uses the `MsgServiceRouter` to check that these messages are correctly constructed
and have a respective path to execute on but do not perform a full validity check.
## Deposit
To prevent spam, proposals must be submitted with a deposit in the coins defined by
the `MinDeposit` param.
When a proposal is submitted, it has to be accompanied with a deposit that must be
strictly positive, but can be inferior to `MinDeposit`. The submitter doesn't need
to pay for the entire deposit on their own. The newly created proposal is stored in
an _inactive proposal queue_ and stays there until its deposit passes the `MinDeposit`.
Other token holders can increase the proposal's deposit by sending a `Deposit`
transaction. If a proposal doesn't pass the `MinDeposit` before the deposit end time
(the time when deposits are no longer accepted), the proposal will be destroyed: the
proposal will be removed from state and the deposit will be burned (see x/gov `EndBlocker`).
When a proposal deposit passes the `MinDeposit` threshold (even during the proposal
submission) before the deposit end time, the proposal will be moved into the
_active proposal queue_ and the voting period will begin.
The deposit is kept in escrow and held by the governance `ModuleAccount` until the
proposal is finalized (passed or rejected).
### Deposit refund and burn
When a proposal is finalized, the coins from the deposit are either refunded or burned
according to the final tally of the proposal:
* If the proposal is approved or rejected but _not_ vetoed, each deposit will be
automatically refunded to its respective depositor (transferred from the governance
`ModuleAccount`).
* When the proposal is vetoed with greater than 1/3, deposits will be burned from the
governance `ModuleAccount` and the proposal information along with its deposit
information will be removed from state.
* All refunded or burned deposits are removed from the state. Events are issued when
burning or refunding a deposit.
## Vote
### Participants
_Participants_ are users that have the right to vote on proposals. On the
Cosmos Hub, participants are bonded Atom holders. Unbonded Atom holders and
other users do not get the right to participate in governance. However, they
can submit and deposit on proposals.
Note that some _participants_ can be forbidden to vote on a proposal under a
certain validator if:
* _participant_ bonded or unbonded Atoms to said validator after proposal
entered voting period.
* _participant_ became validator after proposal entered voting period.
This does not prevent _participant_ to vote with Atoms bonded to other
validators. For example, if a _participant_ bonded some Atoms to validator A
before a proposal entered voting period and other Atoms to validator B after
proposal entered voting period, only the vote under validator B will be
forbidden.
### Voting period
Once a proposal reaches `MinDeposit`, it immediately enters `Voting period`. We
define `Voting period` as the interval between the moment the vote opens and
the moment the vote closes. `Voting period` should always be shorter than
`Unbonding period` to prevent double voting. The initial value of
`Voting period` is 2 weeks.
### Option set
The option set of a proposal refers to the set of choices a participant can
choose from when casting its vote.
The initial option set includes the following options:
* `Yes`
* `No`
* `NoWithVeto`
* `Abstain`
`NoWithVeto` counts as `No` but also adds a `Veto` vote. `Abstain` option
allows voters to signal that they do not intend to vote in favor or against the
proposal but accept the result of the vote.
_Note: from the UI, for urgent proposals we should maybe add a Not Urgent
option that casts a `NoWithVeto` vote._
### Weighted Votes
[ADR-037](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-037-gov-split-vote.md) introduces the weighted vote feature which allows a staker to split their votes into several voting options. For example, it could use 70% of its voting power to vote Yes and 30% of its voting power to vote No.
Often times the entity owning that address might not be a single individual. For example, a company might have different stakeholders who want to vote differently, and so it makes sense to allow them to split their voting power. Currently, it is not possible for them to do "passthrough voting" and giving their users voting rights over their tokens. However, with this system, exchanges can poll their users for voting preferences, and then vote on-chain proportionally to the results of the poll.
To represent weighted vote on chain, we use the following Protobuf message.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/gov/v1beta1/gov.proto#L33-L43
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/gov/v1beta1/gov.proto#L136-L150
For a weighted vote to be valid, the `options` field must not contain duplicate vote options, and the sum of weights of all options must be equal to 1.
### Quorum
Quorum is defined as the minimum percentage of voting power that needs to be
cast on a proposal for the result to be valid.
### Threshold
Threshold is defined as the minimum proportion of `Yes` votes (excluding
`Abstain` votes) for the proposal to be accepted.
Initially, the threshold is set at 50% of `Yes` votes, excluding `Abstain`
votes. A possibility to veto exists if more than 1/3rd of all votes are
`NoWithVeto` votes. Note, both of these values are derived from the `TallyParams`
on-chain parameter, which is modifiable by governance.
This means that proposals are accepted iff:
* There exist bonded tokens.
* Quorum has been achieved.
* The proportion of `Abstain` votes is inferior to 1/1.
* The proportion of `NoWithVeto` votes is inferior to 1/3, including
`Abstain` votes.
* The proportion of `Yes` votes, excluding `Abstain` votes, at the end of
the voting period is superior to 1/2.
### Inheritance
If a delegator does not vote, it will inherit its validator vote.
* If the delegator votes before its validator, it will not inherit from the
validator's vote.
* If the delegator votes after its validator, it will override its validator
vote with its own. If the proposal is urgent, it is possible
that the vote will close before delegators have a chance to react and
override their validator's vote. This is not a problem, as proposals require more than 2/3rd of the total voting power to pass before the end of the voting period. Because as little as 1/3 + 1 validation power could collude to censor transactions, non-collusion is already assumed for ranges exceeding this threshold.
### Validators punishment for non-voting
At present, validators are not punished for failing to vote.
### Governance address
Later, we may add permissioned keys that could only sign txs from certain modules. For the MVP, the `Governance address` will be the main validator address generated at account creation. This address corresponds to a different PrivKey than the Tendermint PrivKey which is responsible for signing consensus messages. Validators thus do not have to sign governance transactions with the sensitive Tendermint PrivKey.
## Software Upgrade
If proposals are of type `SoftwareUpgradeProposal`, then nodes need to upgrade
their software to the new version that was voted. This process is divided into
two steps:
### Signal
After a `SoftwareUpgradeProposal` is accepted, validators are expected to
download and install the new version of the software while continuing to run
the previous version. Once a validator has downloaded and installed the
upgrade, it will start signaling to the network that it is ready to switch by
including the proposal's `proposalID` in its _precommits_.(_Note: Confirmation
that we want it in the precommit?_)
Note: There is only one signal slot per _precommit_. If several
`SoftwareUpgradeProposals` are accepted in a short timeframe, a pipeline will
form and they will be implemented one after the other in the order that they
were accepted.
### Switch
Once a block contains more than 2/3rd _precommits_ where a common
`SoftwareUpgradeProposal` is signaled, all the nodes (including validator
nodes, non-validating full nodes and light-nodes) are expected to switch to the
new version of the software.
Validators and full nodes can use an automation tool, such as [Cosmovisor](https://github.com/cosmos/cosmos-sdk/blob/main/cosmovisor/README.md), for automatically switching version of the chain.

View File

@ -1,219 +0,0 @@
<!--
order: 2
-->
# State
## Proposals
`Proposal` objects are used to tally votes and generally track the proposal's state.
They contain an array of arbitrary `sdk.Msg`'s which the governance module will attempt
to resolve and then execute if the proposal passes. `Proposal`'s are identified by a
unique id and contains a series of timestamps: `submit_time`, `deposit_end_time`,
`voting_start_time`, `voting_end_time` which track the lifecycle of a proposal
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/gov/v1/gov.proto#L42-L59
A proposal will generally require more than just a set of messages to explain its
purpose but need some greater justification and allow a means for interested participants
to discuss and debate the proposal.
In most cases, **it is encouraged to have an off-chain system that supports the on-chain governance process**.
To accommodate for this, a proposal contains a special **`metadata`** field, a string,
which can be used to add context to the proposal. The `metadata` field allows custom use for networks,
however, it is expected that the field contains a URL or some form of CID using a system such as
[IPFS](https://docs.ipfs.io/concepts/content-addressing/). To support the case of
interoperability across networks, the SDK recommends that the `metadata` represents
the following `JSON` template:
```json
{
"title": "...",
"description": "...",
"forum": "...", // a link to the discussion platform (i.e. Discord)
"other": "..." // any extra data that doesn't correspond to the other fields
}
```
This makes it far easier for clients to support multiple networks.
The metadata has a maximum length that is chosen by the app developer, and
passed into the gov keeper as a config. The default maximum length in the SDK is 255 characters.
### Writing a module that uses governance
There are many aspects of a chain, or of the individual modules that you may want to
use governance to perform such as changing various parameters. This is very simple
to do. First, write out your message types and `MsgServer` implementation. Add an
`authority` field to the keeper which will be populated in the constructor with the
governance module account: `govKeeper.GetGovernanceAccount().GetAddress()`. Then for
the methods in the `msg_server.go`, perform a check on the message that the signer
matches `authority`. This will prevent any user from executing that message.
## Parameters and base types
`Parameters` define the rules according to which votes are run. There can only
be one active parameter set at any given time. If governance wants to change a
parameter set, either to modify a value or add/remove a parameter field, a new
parameter set has to be created and the previous one rendered inactive.
### DepositParams
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/gov/v1/gov.proto#L102-L112
### VotingParams
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/gov/v1/gov.proto#L114-L118
### TallyParams
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/gov/v1/gov.proto#L120-L132
Parameters are stored in a global `GlobalParams` KVStore.
Additionally, we introduce some basic types:
```go
type Vote byte
const (
VoteYes = 0x1
VoteNo = 0x2
VoteNoWithVeto = 0x3
VoteAbstain = 0x4
)
type ProposalType string
const (
ProposalTypePlainText = "Text"
ProposalTypeSoftwareUpgrade = "SoftwareUpgrade"
)
type ProposalStatus byte
const (
StatusNil ProposalStatus = 0x00
StatusDepositPeriod ProposalStatus = 0x01 // Proposal is submitted. Participants can deposit on it but not vote
StatusVotingPeriod ProposalStatus = 0x02 // MinDeposit is reached, participants can vote
StatusPassed ProposalStatus = 0x03 // Proposal passed and successfully executed
StatusRejected ProposalStatus = 0x04 // Proposal has been rejected
StatusFailed ProposalStatus = 0x05 // Proposal passed but failed execution
)
```
## Deposit
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/gov/v1/gov.proto#L34-L40
## ValidatorGovInfo
This type is used in a temp map when tallying
```go
type ValidatorGovInfo struct {
Minus sdk.Dec
Vote Vote
}
```
## Stores
_Note: Stores are KVStores in the multi-store. The key to find the store is the first parameter in the list_
We will use one KVStore `Governance` to store two mappings:
* A mapping from `proposalID|'proposal'` to `Proposal`.
* A mapping from `proposalID|'addresses'|address` to `Vote`. This mapping allows
us to query all addresses that voted on the proposal along with their vote by
doing a range query on `proposalID:addresses`.
* A mapping from `ParamsKey|'Params'` to `Params`. This map allows to query all
x/gov params.
For pseudocode purposes, here are the two function we will use to read or write in stores:
* `load(StoreKey, Key)`: Retrieve item stored at key `Key` in store found at key `StoreKey` in the multistore
* `store(StoreKey, Key, value)`: Write value `Value` at key `Key` in store found at key `StoreKey` in the multistore
## Proposal Processing Queue
**Store:**
* `ProposalProcessingQueue`: A queue `queue[proposalID]` containing all the
`ProposalIDs` of proposals that reached `MinDeposit`. During each `EndBlock`,
all the proposals that have reached the end of their voting period are processed.
To process a finished proposal, the application tallies the votes, computes the
votes of each validator and checks if every validator in the validator set has
voted. If the proposal is accepted, deposits are refunded. Finally, the proposal
content `Handler` is executed.
And the pseudocode for the `ProposalProcessingQueue`:
```go
in EndBlock do
for finishedProposalID in GetAllFinishedProposalIDs(block.Time)
proposal = load(Governance, <proposalID|'proposal'>) // proposal is a const key
validators = Keeper.getAllValidators()
tmpValMap := map(sdk.AccAddress)ValidatorGovInfo
// Initiate mapping at 0. This is the amount of shares of the validator's vote that will be overridden by their delegator's votes
for each validator in validators
tmpValMap(validator.OperatorAddr).Minus = 0
// Tally
voterIterator = rangeQuery(Governance, <proposalID|'addresses'>) //return all the addresses that voted on the proposal
for each (voterAddress, vote) in voterIterator
delegations = stakingKeeper.getDelegations(voterAddress) // get all delegations for current voter
for each delegation in delegations
// make sure delegation.Shares does NOT include shares being unbonded
tmpValMap(delegation.ValidatorAddr).Minus += delegation.Shares
proposal.updateTally(vote, delegation.Shares)
_, isVal = stakingKeeper.getValidator(voterAddress)
if (isVal)
tmpValMap(voterAddress).Vote = vote
tallyingParam = load(GlobalParams, 'TallyingParam')
// Update tally if validator voted
for each validator in validators
if tmpValMap(validator).HasVoted
proposal.updateTally(tmpValMap(validator).Vote, (validator.TotalShares - tmpValMap(validator).Minus))
// Check if proposal is accepted or rejected
totalNonAbstain := proposal.YesVotes + proposal.NoVotes + proposal.NoWithVetoVotes
if (proposal.Votes.YesVotes/totalNonAbstain > tallyingParam.Threshold AND proposal.Votes.NoWithVetoVotes/totalNonAbstain < tallyingParam.Veto)
// proposal was accepted at the end of the voting period
// refund deposits (non-voters already punished)
for each (amount, depositor) in proposal.Deposits
depositor.AtomBalance += amount
stateWriter, err := proposal.Handler()
if err != nil
// proposal passed but failed during state execution
proposal.CurrentStatus = ProposalStatusFailed
else
// proposal pass and state is persisted
proposal.CurrentStatus = ProposalStatusAccepted
stateWriter.save()
else
// proposal was rejected
proposal.CurrentStatus = ProposalStatusRejected
store(Governance, <proposalID|'proposal'>, proposal)
```
## Legacy Proposal
A legacy proposal is the old implementation of governance proposal.
Contrary to proposal that can contain any messages, a legacy proposal allows to submit a set of pre-defined proposals.
These proposal are defined by their types.
While proposals should use the new implementation of the governance proposal, we need still to use legacy proposal in order to submit a `software-upgrade` and a `cancel-software-upgrade` proposal.
More information on how to submit proposals in the [client section](07_client.md).

View File

@ -1,183 +0,0 @@
<!--
order: 3
-->
# Messages
## Proposal Submission
Proposals can be submitted by any account via a `MsgSubmitProposal`
transaction.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/gov/v1/tx.proto#L33-L43
All `sdk.Msgs` passed into the `messages` field of a `MsgSubmitProposal` message
must be registered in the app's `MsgServiceRouter`. Each of these messages must
have one signer, namely the gov module account. And finally, the metadata length
must not be larger than the `maxMetadataLen` config passed into the gov keeper.
**State modifications:**
* Generate new `proposalID`
* Create new `Proposal`
* Initialise `Proposal`'s attributes
* Decrease balance of sender by `InitialDeposit`
* If `MinDeposit` is reached:
* Push `proposalID` in `ProposalProcessingQueue`
* Transfer `InitialDeposit` from the `Proposer` to the governance `ModuleAccount`
A `MsgSubmitProposal` transaction can be handled according to the following
pseudocode.
```go
// PSEUDOCODE //
// Check if MsgSubmitProposal is valid. If it is, create proposal //
upon receiving txGovSubmitProposal from sender do
if !correctlyFormatted(txGovSubmitProposal)
// check if proposal is correctly formatted and the messages have routes to other modules. Includes fee payment.
// check if all messages' unique Signer is the gov acct.
// check if the metadata is not too long.
throw
initialDeposit = txGovSubmitProposal.InitialDeposit
if (initialDeposit.Atoms <= 0) OR (sender.AtomBalance < initialDeposit.Atoms)
// InitialDeposit is negative or null OR sender has insufficient funds
throw
if (txGovSubmitProposal.Type != ProposalTypePlainText) OR (txGovSubmitProposal.Type != ProposalTypeSoftwareUpgrade)
sender.AtomBalance -= initialDeposit.Atoms
depositParam = load(GlobalParams, 'DepositParam')
proposalID = generate new proposalID
proposal = NewProposal()
proposal.Messages = txGovSubmitProposal.Messages
proposal.Metadata = txGovSubmitProposal.Metadata
proposal.TotalDeposit = initialDeposit
proposal.SubmitTime = <CurrentTime>
proposal.DepositEndTime = <CurrentTime>.Add(depositParam.MaxDepositPeriod)
proposal.Deposits.append({initialDeposit, sender})
proposal.Submitter = sender
proposal.YesVotes = 0
proposal.NoVotes = 0
proposal.NoWithVetoVotes = 0
proposal.AbstainVotes = 0
proposal.CurrentStatus = ProposalStatusOpen
store(Proposals, <proposalID|'proposal'>, proposal) // Store proposal in Proposals mapping
return proposalID
```
## Deposit
Once a proposal is submitted, if
`Proposal.TotalDeposit < ActiveParam.MinDeposit`, Atom holders can send
`MsgDeposit` transactions to increase the proposal's deposit.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/gov/v1/tx.proto#L90-L97
**State modifications:**
* Decrease balance of sender by `deposit`
* Add `deposit` of sender in `proposal.Deposits`
* Increase `proposal.TotalDeposit` by sender's `deposit`
* If `MinDeposit` is reached:
* Push `proposalID` in `ProposalProcessingQueueEnd`
* Transfer `Deposit` from the `proposer` to the governance `ModuleAccount`
A `MsgDeposit` transaction has to go through a number of checks to be valid.
These checks are outlined in the following pseudocode.
```go
// PSEUDOCODE //
// Check if MsgDeposit is valid. If it is, increase deposit and check if MinDeposit is reached
upon receiving txGovDeposit from sender do
// check if proposal is correctly formatted. Includes fee payment.
if !correctlyFormatted(txGovDeposit)
throw
proposal = load(Proposals, <txGovDeposit.ProposalID|'proposal'>) // proposal is a const key, proposalID is variable
if (proposal == nil)
// There is no proposal for this proposalID
throw
if (txGovDeposit.Deposit.Atoms <= 0) OR (sender.AtomBalance < txGovDeposit.Deposit.Atoms) OR (proposal.CurrentStatus != ProposalStatusOpen)
// deposit is negative or null
// OR sender has insufficient funds
// OR proposal is not open for deposit anymore
throw
depositParam = load(GlobalParams, 'DepositParam')
if (CurrentBlock >= proposal.SubmitBlock + depositParam.MaxDepositPeriod)
proposal.CurrentStatus = ProposalStatusClosed
else
// sender can deposit
sender.AtomBalance -= txGovDeposit.Deposit.Atoms
proposal.Deposits.append({txGovVote.Deposit, sender})
proposal.TotalDeposit.Plus(txGovDeposit.Deposit)
if (proposal.TotalDeposit >= depositParam.MinDeposit)
// MinDeposit is reached, vote opens
proposal.VotingStartBlock = CurrentBlock
proposal.CurrentStatus = ProposalStatusActive
ProposalProcessingQueue.push(txGovDeposit.ProposalID)
store(Proposals, <txGovVote.ProposalID|'proposal'>, proposal)
```
## Vote
Once `ActiveParam.MinDeposit` is reached, voting period starts. From there,
bonded Atom holders are able to send `MsgVote` transactions to cast their
vote on the proposal.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/gov/v1/tx.proto#L64-L72
**State modifications:**
* Record `Vote` of sender
_Note: Gas cost for this message has to take into account the future tallying of the vote in EndBlocker._
Next is a pseudocode outline of the way `MsgVote` transactions are
handled:
```go
// PSEUDOCODE //
// Check if MsgVote is valid. If it is, count vote//
upon receiving txGovVote from sender do
// check if proposal is correctly formatted. Includes fee payment.
if !correctlyFormatted(txGovDeposit)
throw
proposal = load(Proposals, <txGovDeposit.ProposalID|'proposal'>)
if (proposal == nil)
// There is no proposal for this proposalID
throw
if (proposal.CurrentStatus == ProposalStatusActive)
// Sender can vote if
// Proposal is active
// Sender has some bonds
store(Governance, <txGovVote.ProposalID|'addresses'|sender>, txGovVote.Vote) // Voters can vote multiple times. Re-voting overrides previous vote. This is ok because tallying is done once at the end.
```

View File

@ -1,65 +0,0 @@
<!--
order: 4
-->
# Events
The governance module emits the following events:
## EndBlocker
| Type | Attribute Key | Attribute Value |
| ----------------- | --------------- | ---------------- |
| inactive_proposal | proposal_id | {proposalID} |
| inactive_proposal | proposal_result | {proposalResult} |
| active_proposal | proposal_id | {proposalID} |
| active_proposal | proposal_result | {proposalResult} |
## Handlers
### MsgSubmitProposal
| Type | Attribute Key | Attribute Value |
| ------------------- | ------------------- | --------------- |
| submit_proposal | proposal_id | {proposalID} |
| submit_proposal [0] | voting_period_start | {proposalID} |
| proposal_deposit | amount | {depositAmount} |
| proposal_deposit | proposal_id | {proposalID} |
| message | module | governance |
| message | action | submit_proposal |
| message | sender | {senderAddress} |
* [0] Event only emitted if the voting period starts during the submission.
### MsgVote
| Type | Attribute Key | Attribute Value |
| ------------- | ------------- | --------------- |
| proposal_vote | option | {voteOption} |
| proposal_vote | proposal_id | {proposalID} |
| message | module | governance |
| message | action | vote |
| message | sender | {senderAddress} |
### MsgVoteWeighted
| Type | Attribute Key | Attribute Value |
| ------------- | ------------- | ------------------------ |
| proposal_vote | option | {weightedVoteOptions} |
| proposal_vote | proposal_id | {proposalID} |
| message | module | governance |
| message | action | vote |
| message | sender | {senderAddress} |
### MsgDeposit
| Type | Attribute Key | Attribute Value |
| -------------------- | ------------------- | --------------- |
| proposal_deposit | amount | {depositAmount} |
| proposal_deposit | proposal_id | {proposalID} |
| proposal_deposit [0] | voting_period_start | {proposalID} |
| message | module | governance |
| message | action | deposit |
| message | sender | {senderAddress} |
* [0] Event only emitted if the voting period starts during the submission.

View File

@ -1,30 +0,0 @@
<!--
order: 5
-->
# Future Improvements
The current documentation only describes the minimum viable product for the
governance module. Future improvements may include:
* **`BountyProposals`:** If accepted, a `BountyProposal` creates an open
bounty. The `BountyProposal` specifies how many Atoms will be given upon
completion. These Atoms will be taken from the `reserve pool`. After a
`BountyProposal` is accepted by governance, anybody can submit a
`SoftwareUpgradeProposal` with the code to claim the bounty. Note that once a
`BountyProposal` is accepted, the corresponding funds in the `reserve pool`
are locked so that payment can always be honored. In order to link a
`SoftwareUpgradeProposal` to an open bounty, the submitter of the
`SoftwareUpgradeProposal` will use the `Proposal.LinkedProposal` attribute.
If a `SoftwareUpgradeProposal` linked to an open bounty is accepted by
governance, the funds that were reserved are automatically transferred to the
submitter.
* **Complex delegation:** Delegators could choose other representatives than
their validators. Ultimately, the chain of representatives would always end
up to a validator, but delegators could inherit the vote of their chosen
representative before they inherit the vote of their validator. In other
words, they would only inherit the vote of their validator if their other
appointed representative did not vote.
* **Better process for proposal review:** There would be two parts to
`proposal.Deposit`, one for anti-spam (same as in MVP) and an other one to
reward third party auditors.

View File

@ -1,28 +0,0 @@
<!--
order: 6
-->
# Parameters
The governance module contains the following parameters:
| Key | Type | Example |
|---------------|--------|----------------------------------------------------------------------------------------------------|
| depositparams | object | {"min_deposit":[{"denom":"uatom","amount":"10000000"}],"max_deposit_period":"172800000000000"} |
| votingparams | object | {"voting_period":"172800000000000"} |
| tallyparams | object | {"quorum":"0.334000000000000000","threshold":"0.500000000000000000","veto":"0.334000000000000000"} |
## SubKeys
| Key | Type | Example |
|--------------------|------------------|-----------------------------------------|
| min_deposit | array (coins) | [{"denom":"uatom","amount":"10000000"}] |
| max_deposit_period | string (time ns) | "172800000000000" |
| voting_period | string (time ns) | "172800000000000" |
| quorum | string (dec) | "0.334000000000000000" |
| threshold | string (dec) | "0.500000000000000000" |
| veto | string (dec) | "0.334000000000000000" |
__NOTE__: The governance module contains parameters that are objects unlike other
modules. If only a subset of parameters are desired to be changed, only they need
to be included and not the entire parameter object structure.

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +0,0 @@
<!--
order: 8
-->
# Metadata
The gov module has two locations for metadata where users can provide further context about the on-chain actions they are taking. By default all metadata fields have a 255 character length field where metadata can be stored in json format, either on-chain or off-chain depending on the amount of data required. Here we provide a recommendation for the json structure and where the data should be stored. There are two important factors in making these recommendations. First, that the gov and group modules are consistent with one another, note the number of proposals made by all groups may be quite large. Second, that client applications such as block explorers and governance interfaces have confidence in the consistency of metadata structure accross chains.
## Proposal
Location: off-chain as json object stored on IPFS (mirrors [group proposal](../../group/spec/06_metadata.md#proposal))
```json
{
"title": "",
"authors": "",
"summary": "",
"details": "",
"proposalForumURL": "",
"voteOptionContext": "",
}
```
## Vote
Location: on-chain as json within 255 character limit (mirrors [group vote](../../group/spec/06_metadata.md#vote))
```json
{
"justification": "",
}
```

View File

@ -1,65 +0,0 @@
<!--
order: 0
title: Gov Overview
parent:
title: "gov"
-->
# `gov`
## Abstract
This paper specifies the Governance module of the Cosmos-SDK, which was first
described in the [Cosmos Whitepaper](https://cosmos.network/about/whitepaper) in
June 2016.
The module enables Cosmos-SDK based blockchain to support an on-chain governance
system. In this system, holders of the native staking token of the chain can vote
on proposals on a 1 token 1 vote basis. Next is a list of features the module
currently supports:
* **Proposal submission:** Users can submit proposals with a deposit. Once the
minimum deposit is reached, proposal enters voting period
* **Vote:** Participants can vote on proposals that reached MinDeposit
* **Inheritance and penalties:** Delegators inherit their validator's vote if
they don't vote themselves.
* **Claiming deposit:** Users that deposited on proposals can recover their
deposits if the proposal was accepted OR if the proposal never entered voting period.
This module will be used in the Cosmos Hub, the first Hub in the Cosmos network.
Features that may be added in the future are described in [Future Improvements](05_future_improvements.md).
## Contents
The following specification uses *ATOM* as the native staking token. The module
can be adapted to any Proof-Of-Stake blockchain by replacing *ATOM* with the native
staking token of the chain.
1. **[Concepts](01_concepts.md)**
* [Proposal submission](01_concepts.md#proposal-submission)
* [Deposit](01_concepts.md#Deposit)
* [Vote](01_concepts.md#vote)
* [Software Upgrade](01_concepts.md#software-upgrade)
2. **[State](02_state.md)**
* [Parameters and base types](02_state.md#parameters-and-base-types)
* [Deposit](02_state.md#deposit)
* [ValidatorGovInfo](02_state.md#validatorgovinfo)
* [Proposals](02_state.md#proposals)
* [Stores](02_state.md#stores)
* [Proposal Processing Queue](02_state.md#proposal-processing-queue)
3. **[Messages](03_messages.md)**
* [Proposal Submission](03_messages.md#proposal-submission)
* [Deposit](03_messages.md#deposit)
* [Vote](03_messages.md#vote)
4. **[Events](04_events.md)**
* [EndBlocker](04_events.md#endblocker)
* [Handlers](04_events.md#handlers)
5. **[Future Improvements](05_future_improvements.md)**
6. **[Parameters](06_params.md)**
7. **[Client](07_client.md)**
* [CLI](07_client.md#cli)
* [gRPC](07_client.md#grpc)
* [REST](07_client.md#rest)
8. **[Metadata](08_metadata.md)**
* [Proposal](08_metadata.md#proposal)
* [Vote](08_metadata.md#vote)

View File

@ -1,7 +1,554 @@
<!--
order: 5
order: 0
title: Group Overview
parent:
title: "group"
-->
# Group Module
## Abstract
The following documents specify the group module.
This module allows the creation and management of on-chain multisig accounts and enables voting for message execution based on configurable decision policies.
## Contents
* [Concepts](#concepts)
* [Group](#group)
* [Group Policy](#group-policy)
* [Decision Policy](#decision-policy)
* [Proposal](#proposal)
* [Pruning](#pruning)
* [State](#state)
* [Group Table](#group-table)
* [Group Member Table](#group-member-table)
* [Group Policy Table](#group-policy-table)
* [Proposal Table](#proposal-table)
* [Vote Table](#vote-table)
* [Msg Service](#msg-service)
* [Msg/CreateGroup](#msgcreategroup)
* [Msg/UpdateGroupMembers](#msgupdategroupmembers)
* [Msg/UpdateGroupAdmin](#msgupdategroupadmin)
* [Msg/UpdateGroupMetadata](#msgupdategroupmetadata)
* [Msg/CreateGroupPolicy](#msgcreategrouppolicy)
* [Msg/CreateGroupWithPolicy](#msgcreategroupwithpolicy)
* [Msg/UpdateGroupPolicyAdmin](#msgupdategrouppolicyadmin)
* [Msg/UpdateGroupPolicyDecisionPolicy](#msgupdategrouppolicydecisionpolicy)
* [Msg/UpdateGroupPolicyMetadata](#msgupdategrouppolicymetadata)
* [Msg/SubmitProposal](#msgsubmitproposal)
* [Msg/WithdrawProposal](#msgwithdrawproposal)
* [Msg/Vote](#msgvote)
* [Msg/Exec](#msgexec)
* [Msg/LeaveGroup](#msgleavegroup)
* [Events](#events)
* [EventCreateGroup](#eventcreategroup)
* [EventUpdateGroup](#eventupdategroup)
* [EventCreateGroupPolicy](#eventcreategrouppolicy)
* [EventUpdateGroupPolicy](#eventupdategrouppolicy)
* [EventCreateProposal](#eventcreateproposal)
* [EventWithdrawProposal](#eventwithdrawproposal)
* [EventVote](#eventvote)
* [EventExec](#eventexec)
* [EventLeaveGroup](#eventleavegroup)
* [Client](#client)
* [CLI](#cli)
* [gRPC](#grpc)
* [REST](#rest)
* [Metadata](#metadata)
<!-- order: 1 -->
# Concepts
## Group
A group is simply an aggregation of accounts with associated weights. It is not
an account and doesn't have a balance. It doesn't in and of itself have any
sort of voting or decision weight. It does have an "administrator" which has
the ability to add, remove and update members in the group. Note that a
group policy account could be an administrator of a group, and that the
administrator doesn't necessarily have to be a member of the group.
## Group Policy
A group policy is an account associated with a group and a decision policy.
Group policies are abstracted from groups because a single group may have
multiple decision policies for different types of actions. Managing group
membership separately from decision policies results in the least overhead
and keeps membership consistent across different policies. The pattern that
is recommended is to have a single master group policy for a given group,
and then to create separate group policies with different decision policies
and delegate the desired permissions from the master account to
those "sub-accounts" using the `x/authz` module.
## Decision Policy
A decision policy is the mechanism by which members of a group can vote on
proposals, as well as the rules that dictate whether a proposal should pass
or not based on its tally outcome.
All decision policies generally would have a mininum execution period and a
maximum voting window. The minimum execution period is the minimum amount of time
that must pass after submission in order for a proposal to potentially be executed, and it may
be set to 0. The maximum voting window is the maximum time after submission that a proposal may
be voted on before it is tallied.
The chain developer also defines an app-wide maximum execution period, which is
the maximum amount of time after a proposal's voting period end where users are
allowed to execute a proposal.
The current group module comes shipped with two decision policies: threshold
and percentage. Any chain developer can extend upon these two, by creating
custom decision policies, as long as they adhere to the `DecisionPolicy`
interface:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/types.go#L27-L41
### Threshold decision policy
A threshold decision policy defines a threshold of yes votes (based on a tally
of voter weights) that must be achieved in order for a proposal to pass. For
this decision policy, abstain and veto are simply treated as no's.
### Percentage decision policy
A percentage decision policy is similar to a threshold decision policy, except
that the threshold is not defined as a constant weight, but as a percentage.
It's more suited for groups where the group members' weights can be updated, as
the percentage threshold stays the same, and doesn't depend on how those member
weights get updated.
## Proposal
Any member(s) of a group can submit a proposal for a group policy account to decide upon.
A proposal consists of a set of messages that will be executed if the proposal
passes as well as any metadata associated with the proposal.
### Voting
There are four choices to choose while voting - yes, no, abstain and veto. Not
all decision policies will take the four choices into account. Votes can contain some optional metadata.
In the current implementation, the voting window begins as soon as a proposal
is submitted, and the end is defined by the group policy's decision policy.
### Withdrawing Proposals
Proposals can be withdrawn any time before the voting period end, either by the
admin of the group policy or by one of the proposers. Once withdrawn, it is
marked as `PROPOSAL_STATUS_WITHDRAWN`, and no more voting or execution is
allowed on it.
### Aborted Proposals
If the group policy is updated during the voting period of the proposal, then
the proposal is marked as `PROPOSAL_STATUS_ABORTED`, and no more voting or
execution is allowed on it. This is because the group policy defines the rules
of proposal voting and execution, so if those rules change during the lifecycle
of a proposal, then the proposal should be marked as stale.
### Tallying
Tallying is the counting of all votes on a proposal. It happens only once in
the lifecycle of a proposal, but can be triggered by two factors, whichever
happens first:
* either someone tries to execute the proposal (see next section), which can
happen on a `Msg/Exec` transaction, or a `Msg/{SubmitProposal,Vote}`
transaction with the `Exec` field set. When a proposal execution is attempted,
a tally is done first to make sure the proposal passes.
* or on `EndBlock` when the proposal's voting period end just passed.
If the tally result passes the decision policy's rules, then the proposal is
marked as `PROPOSAL_STATUS_ACCEPTED`, or else it is marked as
`PROPOSAL_STATUS_REJECTED`. In any case, no more voting is allowed anymore, and the tally
result is persisted to state in the proposal's `FinalTallyResult`.
### Executing Proposals
Proposals are executed only when the tallying is done, and the group account's
decision policy allows the proposal to pass based on the tally outcome. They
are marked by the status `PROPOSAL_STATUS_ACCEPTED`. Execution must happen
before a duration of `MaxExecutionPeriod` (set by the chain developer) after
each proposal's voting period end.
Proposals will not be automatically executed by the chain in this current design,
but rather a user must submit a `Msg/Exec` transaction to attempt to execute the
proposal based on the current votes and decision policy. Any user (not only the
group members) can execute proposals that have been accepted, and execution fees are
paid by the proposal executor.
It's also possible to try to execute a proposal immediately on creation or on
new votes using the `Exec` field of `Msg/SubmitProposal` and `Msg/Vote` requests.
In the former case, proposers signatures are considered as yes votes.
In these cases, if the proposal can't be executed (i.e. it didn't pass the
decision policy's rules), it will still be opened for new votes and
could be tallied and executed later on.
A successful proposal execution will have its `ExecutorResult` marked as
`PROPOSAL_EXECUTOR_RESULT_SUCCESS`. The proposal will be automatically pruned
after execution. On the other hand, a failed proposal execution will be marked
as `PROPOSAL_EXECUTOR_RESULT_FAILURE`. Such a proposal can be re-executed
multiple times, until it expires after `MaxExecutionPeriod` after voting period
end.
## Pruning
Proposals and votes are automatically pruned to avoid state bloat.
Votes are pruned:
* either after a successful tally, i.e. a tally whose result passes the decision
policy's rules, which can be trigged by a `Msg/Exec` or a
`Msg/{SubmitProposal,Vote}` with the `Exec` field set,
* or on `EndBlock` right after the proposal's voting period end. This applies to proposals with status `aborted` or `withdrawn` too.
whichever happens first.
Proposals are pruned:
* on `EndBlock` whose proposal status is `withdrawn` or `aborted` on proposal's voting period end before tallying,
* and either after a successful proposal execution,
* or on `EndBlock` right after the proposal's `voting_period_end` +
`max_execution_period` (defined as an app-wide configuration) is passed,
whichever happens first.
<!-- order: 2 -->
# State
The `group` module uses the `orm` package which provides table storage with support for
primary keys and secondary indexes. `orm` also defines `Sequence` which is a persistent unique key generator based on a counter that can be used along with `Table`s.
Here's the list of tables and associated sequences and indexes stored as part of the `group` module.
## Group Table
The `groupTable` stores `GroupInfo`: `0x0 | BigEndian(GroupId) -> ProtocolBuffer(GroupInfo)`.
### groupSeq
The value of `groupSeq` is incremented when creating a new group and corresponds to the new `GroupId`: `0x1 | 0x1 -> BigEndian`.
The second `0x1` corresponds to the ORM `sequenceStorageKey`.
### groupByAdminIndex
`groupByAdminIndex` allows to retrieve groups by admin address:
`0x2 | len([]byte(group.Admin)) | []byte(group.Admin) | BigEndian(GroupId) -> []byte()`.
## Group Member Table
The `groupMemberTable` stores `GroupMember`s: `0x10 | BigEndian(GroupId) | []byte(member.Address) -> ProtocolBuffer(GroupMember)`.
The `groupMemberTable` is a primary key table and its `PrimaryKey` is given by
`BigEndian(GroupId) | []byte(member.Address)` which is used by the following indexes.
### groupMemberByGroupIndex
`groupMemberByGroupIndex` allows to retrieve group members by group id:
`0x11 | BigEndian(GroupId) | PrimaryKey -> []byte()`.
### groupMemberByMemberIndex
`groupMemberByMemberIndex` allows to retrieve group members by member address:
`0x12 | len([]byte(member.Address)) | []byte(member.Address) | PrimaryKey -> []byte()`.
## Group Policy Table
The `groupPolicyTable` stores `GroupPolicyInfo`: `0x20 | len([]byte(Address)) | []byte(Address) -> ProtocolBuffer(GroupPolicyInfo)`.
The `groupPolicyTable` is a primary key table and its `PrimaryKey` is given by
`len([]byte(Address)) | []byte(Address)` which is used by the following indexes.
### groupPolicySeq
The value of `groupPolicySeq` is incremented when creating a new group policy and is used to generate the new group policy account `Address`:
`0x21 | 0x1 -> BigEndian`.
The second `0x1` corresponds to the ORM `sequenceStorageKey`.
### groupPolicyByGroupIndex
`groupPolicyByGroupIndex` allows to retrieve group policies by group id:
`0x22 | BigEndian(GroupId) | PrimaryKey -> []byte()`.
### groupPolicyByAdminIndex
`groupPolicyByAdminIndex` allows to retrieve group policies by admin address:
`0x23 | len([]byte(Address)) | []byte(Address) | PrimaryKey -> []byte()`.
## Proposal Table
The `proposalTable` stores `Proposal`s: `0x30 | BigEndian(ProposalId) -> ProtocolBuffer(Proposal)`.
### proposalSeq
The value of `proposalSeq` is incremented when creating a new proposal and corresponds to the new `ProposalId`: `0x31 | 0x1 -> BigEndian`.
The second `0x1` corresponds to the ORM `sequenceStorageKey`.
### proposalByGroupPolicyIndex
`proposalByGroupPolicyIndex` allows to retrieve proposals by group policy account address:
`0x32 | len([]byte(account.Address)) | []byte(account.Address) | BigEndian(ProposalId) -> []byte()`.
### ProposalsByVotingPeriodEndIndex
`proposalsByVotingPeriodEndIndex` allows to retrieve proposals sorted by chronological `voting_period_end`:
`0x33 | sdk.FormatTimeBytes(proposal.VotingPeriodEnd) | BigEndian(ProposalId) -> []byte()`.
This index is used when tallying the proposal votes at the end of the voting period, and for pruning proposals at `VotingPeriodEnd + MaxExecutionPeriod`.
## Vote Table
The `voteTable` stores `Vote`s: `0x40 | BigEndian(ProposalId) | []byte(voter.Address) -> ProtocolBuffer(Vote)`.
The `voteTable` is a primary key table and its `PrimaryKey` is given by
`BigEndian(ProposalId) | []byte(voter.Address)` which is used by the following indexes.
### voteByProposalIndex
`voteByProposalIndex` allows to retrieve votes by proposal id:
`0x41 | BigEndian(ProposalId) | PrimaryKey -> []byte()`.
### voteByVoterIndex
`voteByVoterIndex` allows to retrieve votes by voter address:
`0x42 | len([]byte(voter.Address)) | []byte(voter.Address) | PrimaryKey -> []byte()`.
<!-- order: 3 -->
# Msg Service
## Msg/CreateGroup
A new group can be created with the `MsgCreateGroup`, which has an admin address, a list of members and some optional metadata.
The metadata has a maximum length that is chosen by the app developer, and
passed into the group keeper as a config.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L66-L78
It's expected to fail if
* metadata length is greater than `MaxMetadataLen`
config
* members are not correctly set (e.g. wrong address format, duplicates, or with 0 weight).
## Msg/UpdateGroupMembers
Group members can be updated with the `UpdateGroupMembers`.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L87-L100
In the list of `MemberUpdates`, an existing member can be removed by setting its weight to 0.
It's expected to fail if:
* the signer is not the admin of the group.
* for any one of the associated group policies, if its decision policy's `Validate()` method fails against the updated group.
## Msg/UpdateGroupAdmin
The `UpdateGroupAdmin` can be used to update a group admin.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L105-L117
It's expected to fail if the signer is not the admin of the group.
## Msg/UpdateGroupMetadata
The `UpdateGroupMetadata` can be used to update a group metadata.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L122-L134
It's expected to fail if:
* new metadata length is greater than `MaxMetadataLen` config.
* the signer is not the admin of the group.
## Msg/CreateGroupPolicy
A new group policy can be created with the `MsgCreateGroupPolicy`, which has an admin address, a group id, a decision policy and some optional metadata.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L143-L160
It's expected to fail if:
* the signer is not the admin of the group.
* metadata length is greater than `MaxMetadataLen` config.
* the decision policy's `Validate()` method doesn't pass against the group.
## Msg/CreateGroupWithPolicy
A new group with policy can be created with the `MsgCreateGroupWithPolicy`, which has an admin address, a list of members, a decision policy, a `group_policy_as_admin` field to optionally set group and group policy admin with group policy address and some optional metadata for group and group policy.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L183-L206
It's expected to fail for the same reasons as `Msg/CreateGroup` and `Msg/CreateGroupPolicy`.
## Msg/UpdateGroupPolicyAdmin
The `UpdateGroupPolicyAdmin` can be used to update a group policy admin.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L169-L181
It's expected to fail if the signer is not the admin of the group policy.
## Msg/UpdateGroupPolicyDecisionPolicy
The `UpdateGroupPolicyDecisionPolicy` can be used to update a decision policy.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L219-L235
It's expected to fail if:
* the signer is not the admin of the group policy.
* the new decision policy's `Validate()` method doesn't pass against the group.
## Msg/UpdateGroupPolicyMetadata
The `UpdateGroupPolicyMetadata` can be used to update a group policy metadata.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L240-L252
It's expected to fail if:
* new metadata length is greater than `MaxMetadataLen` config.
* the signer is not the admin of the group.
## Msg/SubmitProposal
A new proposal can be created with the `MsgSubmitProposal`, which has a group policy account address, a list of proposers addresses, a list of messages to execute if the proposal is accepted and some optional metadata.
An optional `Exec` value can be provided to try to execute the proposal immediately after proposal creation. Proposers signatures are considered as yes votes in this case.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L275-L298
It's expected to fail if:
* metadata length is greater than `MaxMetadataLen` config.
* if any of the proposers is not a group member.
## Msg/WithdrawProposal
A proposal can be withdrawn using `MsgWithdrawProposal` which has an `address` (can be either a proposer or the group policy admin) and a `proposal_id` (which has to be withdrawn).
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L307-L316
It's expected to fail if:
* the signer is neither the group policy admin nor proposer of the proposal.
* the proposal is already closed or aborted.
## Msg/Vote
A new vote can be created with the `MsgVote`, given a proposal id, a voter address, a choice (yes, no, veto or abstain) and some optional metadata.
An optional `Exec` value can be provided to try to execute the proposal immediately after voting.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L321-L339
It's expected to fail if:
* metadata length is greater than `MaxMetadataLen` config.
* the proposal is not in voting period anymore.
## Msg/Exec
A proposal can be executed with the `MsgExec`.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L341-L353
The messages that are part of this proposal won't be executed if:
* the proposal has not been accepted by the group policy.
* the proposal has already been successfully executed.
## Msg/LeaveGroup
The `MsgLeaveGroup` allows group member to leave a group.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L362-L370
It's expected to fail if:
* the group member is not part of the group.
* for any one of the associated group policies, if its decision policy's `Validate()` method fails against the updated group.
<!-- order: 4 -->
# Events
The group module emits the following events:
## EventCreateGroup
| Type | Attribute Key | Attribute Value |
| -------------------------------- | ------------- | -------------------------------- |
| message | action | /cosmos.group.v1.Msg/CreateGroup |
| cosmos.group.v1.EventCreateGroup | group_id | {groupId} |
## EventUpdateGroup
| Type | Attribute Key | Attribute Value |
| -------------------------------- | ------------- | ---------------------------------------------------------- |
| message | action | /cosmos.group.v1.Msg/UpdateGroup{Admin\|Metadata\|Members} |
| cosmos.group.v1.EventUpdateGroup | group_id | {groupId} |
## EventCreateGroupPolicy
| Type | Attribute Key | Attribute Value |
| -------------------------------------- | ------------- | -------------------------------------- |
| message | action | /cosmos.group.v1.Msg/CreateGroupPolicy |
| cosmos.group.v1.EventCreateGroupPolicy | address | {groupPolicyAddress} |
## EventUpdateGroupPolicy
| Type | Attribute Key | Attribute Value |
| -------------------------------------- | ------------- | ----------------------------------------------------------------------- |
| message | action | /cosmos.group.v1.Msg/UpdateGroupPolicy{Admin\|Metadata\|DecisionPolicy} |
| cosmos.group.v1.EventUpdateGroupPolicy | address | {groupPolicyAddress} |
## EventCreateProposal
| Type | Attribute Key | Attribute Value |
| ----------------------------------- | ------------- | ----------------------------------- |
| message | action | /cosmos.group.v1.Msg/CreateProposal |
| cosmos.group.v1.EventCreateProposal | proposal_id | {proposalId} |
## EventWithdrawProposal
| Type | Attribute Key | Attribute Value |
| ------------------------------------- | ------------- | ------------------------------------- |
| message | action | /cosmos.group.v1.Msg/WithdrawProposal |
| cosmos.group.v1.EventWithdrawProposal | proposal_id | {proposalId} |
## EventVote
| Type | Attribute Key | Attribute Value |
| ------------------------- | ------------- | ------------------------- |
| message | action | /cosmos.group.v1.Msg/Vote |
| cosmos.group.v1.EventVote | proposal_id | {proposalId} |
## EventExec
| Type | Attribute Key | Attribute Value |
| ------------------------- | ------------- | ------------------------- |
| message | action | /cosmos.group.v1.Msg/Exec |
| cosmos.group.v1.EventExec | proposal_id | {proposalId} |
| cosmos.group.v1.EventExec | logs | {logs_string} |
## EventLeaveGroup
| Type | Attribute Key | Attribute Value |
| ------------------------------- | ------------- | ------------------------------- |
| message | action | /cosmos.group.v1.Msg/LeaveGroup |
| cosmos.group.v1.EventLeaveGroup | proposal_id | {proposalId} |
| cosmos.group.v1.EventLeaveGroup | address | {address} |
<!-- order: 5 -->
# Client
## CLI
@ -1509,3 +2056,58 @@ Example Output:
}
}
```
<!-- order: 6 -->
# Metadata
The group module has four locations for metadata where users can provide further context about the on-chain actions they are taking. By default all metadata fields have a 255 character length field where metadata can be stored in json format, either on-chain or off-chain depending on the amount of data required. Here we provide a recommendation for the json structure and where the data should be stored. There are two important factors in making these recommendations. First, that the group and gov modules are consistent with one another, note the number of proposals made by all groups may be quite large. Second, that client applications such as block explorers and governance interfaces have confidence in the consistency of metadata structure accross chains.
## Proposal
Location: off-chain as json object stored on IPFS (mirrors [gov proposal](../../gov/spec/08_metadata.md#proposal))
```json
{
"title": "",
"authors": "",
"summary": "",
"details": "",
"proposalForumURL": "",
"voteOptionContext": "",
}
```
## Vote
Location: on-chain as json within 255 character limit (mirrors [gov vote](../../gov/spec/08_metadata.md#vote))
```json
{
"justification": "",
}
```
## Group
Location: off-chain as json object stored on IPFS
```json
{
"name": "",
"description": "",
"groupWebsiteURL": "",
"groupForumURL": "",
}
```
## Decision policy
Location: on-chain as json within 255 character limit
```json
{
"name": "",
"description": "",
}
```

View File

@ -0,0 +1,119 @@
# Abstract
The orm package provides a framework for creating relational database tables with primary and secondary keys.
## Contents
* [Table](#table)
* [AutoUInt64Table](#autouint64table)
* [PrimaryKeyTable](#primarykeytable)
* [PrimaryKeyed](#primarykeyed)
* [Key codec](#key-codec)
* [Secondary Index](#secondary-index)
* [MultiKeyIndex](#multikeyindex)
* [UniqueIndex](#uniqueindex)
* [Iterator and Pagination](#iterator-and-pagination)
* [Iterator](#iterator)
* [Pagination](#pagination)
# Table
A table can be built given a `codec.ProtoMarshaler` model type, a prefix to access the underlying prefix store used to store table data as well as a `Codec` for marshalling/unmarshalling.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/table.go#L30-L36
In the prefix store, entities should be stored by an unique identifier called `RowID` which can be based either on an `uint64` auto-increment counter, string or dynamic size bytes.
Regular CRUD operations can be performed on a table, these methods take a `sdk.KVStore` as parameter to get the table prefix store.
The `table` struct does not:
* enforce uniqueness of the `RowID`
* enforce prefix uniqueness of keys, i.e. not allowing one key to be a prefix of another
* optimize Gas usage conditions
The `table` struct is private, so that we only have custom tables built on top of it, that do satisfy these requirements.
`table` provides methods for exporting (using a [`PrefixScan` `Iterator`](03_iterator_pagination.md#iterator)) and importing genesis data. For the import to be successful, objects have to be aware of their primary key by implementing the [`PrimaryKeyed`](#primarykeyed) interface.
## AutoUInt64Table
`AutoUInt64Table` is a table type with an auto incrementing `uint64` ID.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/auto_uint64.go#L15-L18
It's based on the `Sequence` struct which is a persistent unique key generator based on a counter encoded using 8 byte big endian.
## PrimaryKeyTable
`PrimaryKeyTable` provides simpler object style orm methods where are persisted and loaded with a reference to their unique primary key.
### PrimaryKeyed
The model provided for creating a `PrimaryKeyTable` should implement the `PrimaryKeyed` interface:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/primary_key.go#L30-L44
`PrimaryKeyFields()` method returns the list of key parts for a given object.
The primary key parts can be []byte, string, and `uint64` types.
### Key codec
Key parts, except the last part, follow these rules:
* []byte is encoded with a single byte length prefix (which means the max []byte length is 255)
* strings are null-terminated
* `uint64` are encoded using 8 byte big endian.
# Secondary Index
Secondary indexes can be used on `Indexable` [tables](01_table.md). Indeed, those tables implement the `Indexable` interface that provides a set of functions that can be called by indexes to register and interact with the tables, like callback functions that are called on entries creation, update or deletion to create, update or remove corresponding entries in the table secondary indexes.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/types.go#L88-L93
## MultiKeyIndex
A `MultiKeyIndex` is an index where multiple entries can point to the same underlying object.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/index.go#L26-L32
Internally, it uses an `Indexer` that manages the persistence of the index based on searchable keys and create/update/delete operations.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/index.go#L15-L20
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/indexer.go#L15-L19
The currently used implementation of an `indexer`, `Indexer`, relies on an `IndexerFunc` that should be provided when instantiating the index. Based on the source object, this function returns one or multiple index keys as `[]interface{}`. Such secondary index keys should be bytes, string or `uint64` in order to be handled properly by the [key codec](01_table.md#key-codec) which defines specific encoding for those types.
In the index prefix store, the keys are built based on the source object's `RowID` and its secondary index key(s) using the key codec and the values are set as empty bytes.
## UniqueIndex
As opposed to `MultiKeyIndex`, `UniqueIndex` is an index where duplicate keys are prohibited.
# Iterator and Pagination
Both [tables](01_table.md) and [secondary indexes](02_secondary_index.md) support iterating over a domain of keys, through `PrefixScan` or `ReversePrefixScan`, as well pagination.
## Iterator
An `Iterator` allows iteration through a sequence of key value pairs.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/types.go#L77-L85
Tables rely on a `typeSafeIterator` that is used by `PrefixScan` and `ReversePrefixScan` `table` methods to iterate through a range of `RowID`s.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/table.go#L285-L290
Secondary indexes rely on an `indexIterator` that can strip the `RowID` from the full index key in order to get the underlying value in the table prefix store.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/index.go#L232-L238
Under the hood, both use a prefix store `Iterator` (alias for tm-db `Iterator`).
## Pagination
The `Paginate` function does pagination given an [`Iterator`](#iterator) and a `query.PageRequest`, and returns a `query.PageResponse`.
It unmarshals the results into the provided dest interface that should be a pointer to a slice of models.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/iterator.go#L102-L220
Secondary indexes have a `GetPaginated` method that returns an `Iterator` for the given searched secondary index key, starting from the `query.PageRequest` key if provided. It's important to note that this `query.PageRequest` key should be a `RowID` (that could have been returned by a previous paginated request). The returned `Iterator` can then be used with the `Paginate` function and the same `query.PageRequest`.

View File

@ -1,47 +0,0 @@
# Table
A table can be built given a `codec.ProtoMarshaler` model type, a prefix to access the underlying prefix store used to store table data as well as a `Codec` for marshalling/unmarshalling.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/table.go#L30-L36
In the prefix store, entities should be stored by an unique identifier called `RowID` which can be based either on an `uint64` auto-increment counter, string or dynamic size bytes.
Regular CRUD operations can be performed on a table, these methods take a `sdk.KVStore` as parameter to get the table prefix store.
The `table` struct does not:
* enforce uniqueness of the `RowID`
* enforce prefix uniqueness of keys, i.e. not allowing one key to be a prefix of another
* optimize Gas usage conditions
The `table` struct is private, so that we only have custom tables built on top of it, that do satisfy these requirements.
`table` provides methods for exporting (using a [`PrefixScan` `Iterator`](03_iterator_pagination.md#iterator)) and importing genesis data. For the import to be successful, objects have to be aware of their primary key by implementing the [`PrimaryKeyed`](#primarykeyed) interface.
## AutoUInt64Table
`AutoUInt64Table` is a table type with an auto incrementing `uint64` ID.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/auto_uint64.go#L15-L18
It's based on the `Sequence` struct which is a persistent unique key generator based on a counter encoded using 8 byte big endian.
## PrimaryKeyTable
`PrimaryKeyTable` provides simpler object style orm methods where are persisted and loaded with a reference to their unique primary key.
### PrimaryKeyed
The model provided for creating a `PrimaryKeyTable` should implement the `PrimaryKeyed` interface:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/primary_key.go#L30-L44
`PrimaryKeyFields()` method returns the list of key parts for a given object.
The primary key parts can be []byte, string, and `uint64` types.
### Key codec
Key parts, except the last part, follow these rules:
* []byte is encoded with a single byte length prefix (which means the max []byte length is 255)
* strings are null-terminated
* `uint64` are encoded using 8 byte big endian.

View File

@ -1,24 +0,0 @@
# Secondary Index
Secondary indexes can be used on `Indexable` [tables](01_table.md). Indeed, those tables implement the `Indexable` interface that provides a set of functions that can be called by indexes to register and interact with the tables, like callback functions that are called on entries creation, update or deletion to create, update or remove corresponding entries in the table secondary indexes.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/types.go#L88-L93
## MultiKeyIndex
A `MultiKeyIndex` is an index where multiple entries can point to the same underlying object.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/index.go#L26-L32
Internally, it uses an `Indexer` that manages the persistence of the index based on searchable keys and create/update/delete operations.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/index.go#L15-L20
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/indexer.go#L15-L19
The currently used implementation of an `indexer`, `Indexer`, relies on an `IndexerFunc` that should be provided when instantiating the index. Based on the source object, this function returns one or multiple index keys as `[]interface{}`. Such secondary index keys should be bytes, string or `uint64` in order to be handled properly by the [key codec](01_table.md#key-codec) which defines specific encoding for those types.
In the index prefix store, the keys are built based on the source object's `RowID` and its secondary index key(s) using the key codec and the values are set as empty bytes.
## UniqueIndex
As opposed to `MultiKeyIndex`, `UniqueIndex` is an index where duplicate keys are prohibited.

View File

@ -1,28 +0,0 @@
# Iterator and Pagination
Both [tables](01_table.md) and [secondary indexes](02_secondary_index.md) support iterating over a domain of keys, through `PrefixScan` or `ReversePrefixScan`, as well pagination.
## Iterator
An `Iterator` allows iteration through a sequence of key value pairs.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/types.go#L77-L85
Tables rely on a `typeSafeIterator` that is used by `PrefixScan` and `ReversePrefixScan` `table` methods to iterate through a range of `RowID`s.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/table.go#L285-L290
Secondary indexes rely on an `indexIterator` that can strip the `RowID` from the full index key in order to get the underlying value in the table prefix store.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/index.go#L232-L238
Under the hood, both use a prefix store `Iterator` (alias for tm-db `Iterator`).
## Pagination
The `Paginate` function does pagination given an [`Iterator`](#iterator) and a `query.PageRequest`, and returns a `query.PageResponse`.
It unmarshals the results into the provided dest interface that should be a pointer to a slice of models.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/internal/orm/iterator.go#L102-L220
Secondary indexes have a `GetPaginated` method that returns an `Iterator` for the given searched secondary index key, starting from the `query.PageRequest` key if provided. It's important to note that this `query.PageRequest` key should be a `RowID` (that could have been returned by a previous paginated request). The returned `Iterator` can then be used with the `Paginate` function and the same `query.PageRequest`.

View File

@ -1,15 +0,0 @@
# Abstract
The orm package provides a framework for creating relational database tables with primary and secondary keys.
## Contents
1. **[Table](01_table.md)**
* [AutoUInt64Table](01_table.md#autouint64table)
* [PrimaryKeyTable](01_table.md#primarykeytable)
2. **[Secondary Index](02_secondary_index.md)**
* [MultiKeyIndex](02_secondary_index.md#multikeyindex)
* [UniqueIndex](02_secondary_index.md#uniqueindex)
3. **[Iterator and Pagination](03_iterator_pagination.md)**
* [Iterator](03_iterator_pagination.md#iterator)
* [Pagination](03_iterator_pagination.md#pagination)

View File

@ -1,157 +0,0 @@
<!--
order: 1
-->
# Concepts
## Group
A group is simply an aggregation of accounts with associated weights. It is not
an account and doesn't have a balance. It doesn't in and of itself have any
sort of voting or decision weight. It does have an "administrator" which has
the ability to add, remove and update members in the group. Note that a
group policy account could be an administrator of a group, and that the
administrator doesn't necessarily have to be a member of the group.
## Group Policy
A group policy is an account associated with a group and a decision policy.
Group policies are abstracted from groups because a single group may have
multiple decision policies for different types of actions. Managing group
membership separately from decision policies results in the least overhead
and keeps membership consistent across different policies. The pattern that
is recommended is to have a single master group policy for a given group,
and then to create separate group policies with different decision policies
and delegate the desired permissions from the master account to
those "sub-accounts" using the `x/authz` module.
## Decision Policy
A decision policy is the mechanism by which members of a group can vote on
proposals, as well as the rules that dictate whether a proposal should pass
or not based on its tally outcome.
All decision policies generally would have a mininum execution period and a
maximum voting window. The minimum execution period is the minimum amount of time
that must pass after submission in order for a proposal to potentially be executed, and it may
be set to 0. The maximum voting window is the maximum time after submission that a proposal may
be voted on before it is tallied.
The chain developer also defines an app-wide maximum execution period, which is
the maximum amount of time after a proposal's voting period end where users are
allowed to execute a proposal.
The current group module comes shipped with two decision policies: threshold
and percentage. Any chain developer can extend upon these two, by creating
custom decision policies, as long as they adhere to the `DecisionPolicy`
interface:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/x/group/types.go#L27-L41
### Threshold decision policy
A threshold decision policy defines a threshold of yes votes (based on a tally
of voter weights) that must be achieved in order for a proposal to pass. For
this decision policy, abstain and veto are simply treated as no's.
### Percentage decision policy
A percentage decision policy is similar to a threshold decision policy, except
that the threshold is not defined as a constant weight, but as a percentage.
It's more suited for groups where the group members' weights can be updated, as
the percentage threshold stays the same, and doesn't depend on how those member
weights get updated.
## Proposal
Any member(s) of a group can submit a proposal for a group policy account to decide upon.
A proposal consists of a set of messages that will be executed if the proposal
passes as well as any metadata associated with the proposal.
### Voting
There are four choices to choose while voting - yes, no, abstain and veto. Not
all decision policies will take the four choices into account. Votes can contain some optional metadata.
In the current implementation, the voting window begins as soon as a proposal
is submitted, and the end is defined by the group policy's decision policy.
### Withdrawing Proposals
Proposals can be withdrawn any time before the voting period end, either by the
admin of the group policy or by one of the proposers. Once withdrawn, it is
marked as `PROPOSAL_STATUS_WITHDRAWN`, and no more voting or execution is
allowed on it.
### Aborted Proposals
If the group policy is updated during the voting period of the proposal, then
the proposal is marked as `PROPOSAL_STATUS_ABORTED`, and no more voting or
execution is allowed on it. This is because the group policy defines the rules
of proposal voting and execution, so if those rules change during the lifecycle
of a proposal, then the proposal should be marked as stale.
### Tallying
Tallying is the counting of all votes on a proposal. It happens only once in
the lifecycle of a proposal, but can be triggered by two factors, whichever
happens first:
* either someone tries to execute the proposal (see next section), which can
happen on a `Msg/Exec` transaction, or a `Msg/{SubmitProposal,Vote}`
transaction with the `Exec` field set. When a proposal execution is attempted,
a tally is done first to make sure the proposal passes.
* or on `EndBlock` when the proposal's voting period end just passed.
If the tally result passes the decision policy's rules, then the proposal is
marked as `PROPOSAL_STATUS_ACCEPTED`, or else it is marked as
`PROPOSAL_STATUS_REJECTED`. In any case, no more voting is allowed anymore, and the tally
result is persisted to state in the proposal's `FinalTallyResult`.
### Executing Proposals
Proposals are executed only when the tallying is done, and the group account's
decision policy allows the proposal to pass based on the tally outcome. They
are marked by the status `PROPOSAL_STATUS_ACCEPTED`. Execution must happen
before a duration of `MaxExecutionPeriod` (set by the chain developer) after
each proposal's voting period end.
Proposals will not be automatically executed by the chain in this current design,
but rather a user must submit a `Msg/Exec` transaction to attempt to execute the
proposal based on the current votes and decision policy. Any user (not only the
group members) can execute proposals that have been accepted, and execution fees are
paid by the proposal executor.
It's also possible to try to execute a proposal immediately on creation or on
new votes using the `Exec` field of `Msg/SubmitProposal` and `Msg/Vote` requests.
In the former case, proposers signatures are considered as yes votes.
In these cases, if the proposal can't be executed (i.e. it didn't pass the
decision policy's rules), it will still be opened for new votes and
could be tallied and executed later on.
A successful proposal execution will have its `ExecutorResult` marked as
`PROPOSAL_EXECUTOR_RESULT_SUCCESS`. The proposal will be automatically pruned
after execution. On the other hand, a failed proposal execution will be marked
as `PROPOSAL_EXECUTOR_RESULT_FAILURE`. Such a proposal can be re-executed
multiple times, until it expires after `MaxExecutionPeriod` after voting period
end.
## Pruning
Proposals and votes are automatically pruned to avoid state bloat.
Votes are pruned:
* either after a successful tally, i.e. a tally whose result passes the decision
policy's rules, which can be trigged by a `Msg/Exec` or a
`Msg/{SubmitProposal,Vote}` with the `Exec` field set,
* or on `EndBlock` right after the proposal's voting period end. This applies to proposals with status `aborted` or `withdrawn` too.
whichever happens first.
Proposals are pruned:
* on `EndBlock` whose proposal status is `withdrawn` or `aborted` on proposal's voting period end before tallying,
* and either after a successful proposal execution,
* or on `EndBlock` right after the proposal's `voting_period_end` +
`max_execution_period` (defined as an app-wide configuration) is passed,
whichever happens first.

View File

@ -1,105 +0,0 @@
<!--
order: 2
-->
# State
The `group` module uses the `orm` package which provides table storage with support for
primary keys and secondary indexes. `orm` also defines `Sequence` which is a persistent unique key generator based on a counter that can be used along with `Table`s.
Here's the list of tables and associated sequences and indexes stored as part of the `group` module.
## Group Table
The `groupTable` stores `GroupInfo`: `0x0 | BigEndian(GroupId) -> ProtocolBuffer(GroupInfo)`.
### groupSeq
The value of `groupSeq` is incremented when creating a new group and corresponds to the new `GroupId`: `0x1 | 0x1 -> BigEndian`.
The second `0x1` corresponds to the ORM `sequenceStorageKey`.
### groupByAdminIndex
`groupByAdminIndex` allows to retrieve groups by admin address:
`0x2 | len([]byte(group.Admin)) | []byte(group.Admin) | BigEndian(GroupId) -> []byte()`.
## Group Member Table
The `groupMemberTable` stores `GroupMember`s: `0x10 | BigEndian(GroupId) | []byte(member.Address) -> ProtocolBuffer(GroupMember)`.
The `groupMemberTable` is a primary key table and its `PrimaryKey` is given by
`BigEndian(GroupId) | []byte(member.Address)` which is used by the following indexes.
### groupMemberByGroupIndex
`groupMemberByGroupIndex` allows to retrieve group members by group id:
`0x11 | BigEndian(GroupId) | PrimaryKey -> []byte()`.
### groupMemberByMemberIndex
`groupMemberByMemberIndex` allows to retrieve group members by member address:
`0x12 | len([]byte(member.Address)) | []byte(member.Address) | PrimaryKey -> []byte()`.
## Group Policy Table
The `groupPolicyTable` stores `GroupPolicyInfo`: `0x20 | len([]byte(Address)) | []byte(Address) -> ProtocolBuffer(GroupPolicyInfo)`.
The `groupPolicyTable` is a primary key table and its `PrimaryKey` is given by
`len([]byte(Address)) | []byte(Address)` which is used by the following indexes.
### groupPolicySeq
The value of `groupPolicySeq` is incremented when creating a new group policy and is used to generate the new group policy account `Address`:
`0x21 | 0x1 -> BigEndian`.
The second `0x1` corresponds to the ORM `sequenceStorageKey`.
### groupPolicyByGroupIndex
`groupPolicyByGroupIndex` allows to retrieve group policies by group id:
`0x22 | BigEndian(GroupId) | PrimaryKey -> []byte()`.
### groupPolicyByAdminIndex
`groupPolicyByAdminIndex` allows to retrieve group policies by admin address:
`0x23 | len([]byte(Address)) | []byte(Address) | PrimaryKey -> []byte()`.
## Proposal Table
The `proposalTable` stores `Proposal`s: `0x30 | BigEndian(ProposalId) -> ProtocolBuffer(Proposal)`.
### proposalSeq
The value of `proposalSeq` is incremented when creating a new proposal and corresponds to the new `ProposalId`: `0x31 | 0x1 -> BigEndian`.
The second `0x1` corresponds to the ORM `sequenceStorageKey`.
### proposalByGroupPolicyIndex
`proposalByGroupPolicyIndex` allows to retrieve proposals by group policy account address:
`0x32 | len([]byte(account.Address)) | []byte(account.Address) | BigEndian(ProposalId) -> []byte()`.
### ProposalsByVotingPeriodEndIndex
`proposalsByVotingPeriodEndIndex` allows to retrieve proposals sorted by chronological `voting_period_end`:
`0x33 | sdk.FormatTimeBytes(proposal.VotingPeriodEnd) | BigEndian(ProposalId) -> []byte()`.
This index is used when tallying the proposal votes at the end of the voting period, and for pruning proposals at `VotingPeriodEnd + MaxExecutionPeriod`.
## Vote Table
The `voteTable` stores `Vote`s: `0x40 | BigEndian(ProposalId) | []byte(voter.Address) -> ProtocolBuffer(Vote)`.
The `voteTable` is a primary key table and its `PrimaryKey` is given by
`BigEndian(ProposalId) | []byte(voter.Address)` which is used by the following indexes.
### voteByProposalIndex
`voteByProposalIndex` allows to retrieve votes by proposal id:
`0x41 | BigEndian(ProposalId) | PrimaryKey -> []byte()`.
### voteByVoterIndex
`voteByVoterIndex` allows to retrieve votes by voter address:
`0x42 | len([]byte(voter.Address)) | []byte(voter.Address) | PrimaryKey -> []byte()`.

View File

@ -1,159 +0,0 @@
<!--
order: 3
-->
# Msg Service
## Msg/CreateGroup
A new group can be created with the `MsgCreateGroup`, which has an admin address, a list of members and some optional metadata.
The metadata has a maximum length that is chosen by the app developer, and
passed into the group keeper as a config.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L66-L78
It's expected to fail if
* metadata length is greater than `MaxMetadataLen`
config
* members are not correctly set (e.g. wrong address format, duplicates, or with 0 weight).
## Msg/UpdateGroupMembers
Group members can be updated with the `UpdateGroupMembers`.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L87-L100
In the list of `MemberUpdates`, an existing member can be removed by setting its weight to 0.
It's expected to fail if:
* the signer is not the admin of the group.
* for any one of the associated group policies, if its decision policy's `Validate()` method fails against the updated group.
## Msg/UpdateGroupAdmin
The `UpdateGroupAdmin` can be used to update a group admin.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L105-L117
It's expected to fail if the signer is not the admin of the group.
## Msg/UpdateGroupMetadata
The `UpdateGroupMetadata` can be used to update a group metadata.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L122-L134
It's expected to fail if:
* new metadata length is greater than `MaxMetadataLen` config.
* the signer is not the admin of the group.
## Msg/CreateGroupPolicy
A new group policy can be created with the `MsgCreateGroupPolicy`, which has an admin address, a group id, a decision policy and some optional metadata.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L143-L160
It's expected to fail if:
* the signer is not the admin of the group.
* metadata length is greater than `MaxMetadataLen` config.
* the decision policy's `Validate()` method doesn't pass against the group.
## Msg/CreateGroupWithPolicy
A new group with policy can be created with the `MsgCreateGroupWithPolicy`, which has an admin address, a list of members, a decision policy, a `group_policy_as_admin` field to optionally set group and group policy admin with group policy address and some optional metadata for group and group policy.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L183-L206
It's expected to fail for the same reasons as `Msg/CreateGroup` and `Msg/CreateGroupPolicy`.
## Msg/UpdateGroupPolicyAdmin
The `UpdateGroupPolicyAdmin` can be used to update a group policy admin.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L169-L181
It's expected to fail if the signer is not the admin of the group policy.
## Msg/UpdateGroupPolicyDecisionPolicy
The `UpdateGroupPolicyDecisionPolicy` can be used to update a decision policy.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L219-L235
It's expected to fail if:
* the signer is not the admin of the group policy.
* the new decision policy's `Validate()` method doesn't pass against the group.
## Msg/UpdateGroupPolicyMetadata
The `UpdateGroupPolicyMetadata` can be used to update a group policy metadata.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L240-L252
It's expected to fail if:
* new metadata length is greater than `MaxMetadataLen` config.
* the signer is not the admin of the group.
## Msg/SubmitProposal
A new proposal can be created with the `MsgSubmitProposal`, which has a group policy account address, a list of proposers addresses, a list of messages to execute if the proposal is accepted and some optional metadata.
An optional `Exec` value can be provided to try to execute the proposal immediately after proposal creation. Proposers signatures are considered as yes votes in this case.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L275-L298
It's expected to fail if:
* metadata length is greater than `MaxMetadataLen` config.
* if any of the proposers is not a group member.
## Msg/WithdrawProposal
A proposal can be withdrawn using `MsgWithdrawProposal` which has an `address` (can be either a proposer or the group policy admin) and a `proposal_id` (which has to be withdrawn).
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L307-L316
It's expected to fail if:
* the signer is neither the group policy admin nor proposer of the proposal.
* the proposal is already closed or aborted.
## Msg/Vote
A new vote can be created with the `MsgVote`, given a proposal id, a voter address, a choice (yes, no, veto or abstain) and some optional metadata.
An optional `Exec` value can be provided to try to execute the proposal immediately after voting.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L321-L339
It's expected to fail if:
* metadata length is greater than `MaxMetadataLen` config.
* the proposal is not in voting period anymore.
## Msg/Exec
A proposal can be executed with the `MsgExec`.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L341-L353
The messages that are part of this proposal won't be executed if:
* the proposal has not been accepted by the group policy.
* the proposal has already been successfully executed.
## Msg/LeaveGroup
The `MsgLeaveGroup` allows group member to leave a group.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/group/v1/tx.proto#L362-L370
It's expected to fail if:
* the group member is not part of the group.
* for any one of the associated group policies, if its decision policy's `Validate()` method fails against the updated group.

View File

@ -1,72 +0,0 @@
<!--
order: 4
-->
# Events
The group module emits the following events:
## EventCreateGroup
| Type | Attribute Key | Attribute Value |
| -------------------------------- | ------------- | -------------------------------- |
| message | action | /cosmos.group.v1.Msg/CreateGroup |
| cosmos.group.v1.EventCreateGroup | group_id | {groupId} |
## EventUpdateGroup
| Type | Attribute Key | Attribute Value |
| -------------------------------- | ------------- | ---------------------------------------------------------- |
| message | action | /cosmos.group.v1.Msg/UpdateGroup{Admin\|Metadata\|Members} |
| cosmos.group.v1.EventUpdateGroup | group_id | {groupId} |
## EventCreateGroupPolicy
| Type | Attribute Key | Attribute Value |
| -------------------------------------- | ------------- | -------------------------------------- |
| message | action | /cosmos.group.v1.Msg/CreateGroupPolicy |
| cosmos.group.v1.EventCreateGroupPolicy | address | {groupPolicyAddress} |
## EventUpdateGroupPolicy
| Type | Attribute Key | Attribute Value |
| -------------------------------------- | ------------- | ----------------------------------------------------------------------- |
| message | action | /cosmos.group.v1.Msg/UpdateGroupPolicy{Admin\|Metadata\|DecisionPolicy} |
| cosmos.group.v1.EventUpdateGroupPolicy | address | {groupPolicyAddress} |
## EventCreateProposal
| Type | Attribute Key | Attribute Value |
| ----------------------------------- | ------------- | ----------------------------------- |
| message | action | /cosmos.group.v1.Msg/CreateProposal |
| cosmos.group.v1.EventCreateProposal | proposal_id | {proposalId} |
## EventWithdrawProposal
| Type | Attribute Key | Attribute Value |
| ------------------------------------- | ------------- | ------------------------------------- |
| message | action | /cosmos.group.v1.Msg/WithdrawProposal |
| cosmos.group.v1.EventWithdrawProposal | proposal_id | {proposalId} |
## EventVote
| Type | Attribute Key | Attribute Value |
| ------------------------- | ------------- | ------------------------- |
| message | action | /cosmos.group.v1.Msg/Vote |
| cosmos.group.v1.EventVote | proposal_id | {proposalId} |
## EventExec
| Type | Attribute Key | Attribute Value |
| ------------------------- | ------------- | ------------------------- |
| message | action | /cosmos.group.v1.Msg/Exec |
| cosmos.group.v1.EventExec | proposal_id | {proposalId} |
| cosmos.group.v1.EventExec | logs | {logs_string} |
## EventLeaveGroup
| Type | Attribute Key | Attribute Value |
| ------------------------------- | ------------- | ------------------------------- |
| message | action | /cosmos.group.v1.Msg/LeaveGroup |
| cosmos.group.v1.EventLeaveGroup | proposal_id | {proposalId} |
| cosmos.group.v1.EventLeaveGroup | address | {address} |

View File

@ -1,52 +0,0 @@
<!--
order: 6
-->
# Metadata
The group module has four locations for metadata where users can provide further context about the on-chain actions they are taking. By default all metadata fields have a 255 character length field where metadata can be stored in json format, either on-chain or off-chain depending on the amount of data required. Here we provide a recommendation for the json structure and where the data should be stored. There are two important factors in making these recommendations. First, that the group and gov modules are consistent with one another, note the number of proposals made by all groups may be quite large. Second, that client applications such as block explorers and governance interfaces have confidence in the consistency of metadata structure accross chains.
## Proposal
Location: off-chain as json object stored on IPFS (mirrors [gov proposal](../../gov/spec/08_metadata.md#proposal))
```json
{
"title": "",
"authors": "",
"summary": "",
"details": "",
"proposalForumURL": "",
"voteOptionContext": "",
}
```
## Vote
Location: on-chain as json within 255 character limit (mirrors [gov vote](../../gov/spec/08_metadata.md#vote))
```json
{
"justification": "",
}
```
## Group
Location: off-chain as json object stored on IPFS
```json
{
"name": "",
"description": "",
"groupWebsiteURL": "",
"groupForumURL": "",
}
```
## Decision policy
Location: on-chain as json within 255 character limit
```json
{
"name": "",
"description": "",
}
```

View File

@ -1,63 +0,0 @@
<!--
order: 0
title: Group Overview
parent:
title: "group"
-->
# Group Module
## Abstract
The following documents specify the group module.
This module allows the creation and management of on-chain multisig accounts and enables voting for message execution based on configurable decision policies.
## Contents
1. **[Concepts](01_concepts.md)**
- [Group](01_concepts.md#group)
- [Group Policy](01_concepts.md#group-policy)
- [Group With Policy](01_concepts.md#group-with-policy)
- [Decision Policy](01_concepts.md#decision-policy)
- [Proposal](01_concepts.md#proposal)
- [Voting](01_concepts.md#voting)
- [Executing Proposals](01_concepts.md#executing-proposals)
2. **[State](02_state.md)**
* [Group Table](02_state.md#group-table)
* [Group Member Table](02_state.md#group-member-table)
* [Group Policy Table](02_state.md#group-policy-table)
* [Proposal](02_state.md#proposal-table)
* [Vote Table](02_state.md#vote-table)
3. **[Msg Service](03_messages.md)**
- [Msg/CreateGroup](03_messages.md#msgcreategroup)
- [Msg/UpdateGroupMembers](03_messages.md#msgupdategroupmembers)
- [Msg/UpdateGroupAdmin](03_messages.md#msgupdategroupadmin)
- [Msg/UpdateGroupMetadata](03_messages.md#msgupdategroupmetadata)
- [Msg/CreateGroupPolicy](03_messages.md#msgcreategrouppolicy)
- [Msg/CreateGroupWithPolicy](03_messages.md#msgcreategroupwithpolicy)
- [Msg/UpdateGroupPolicyAdmin](03_messages.md#msgupdategrouppolicyadmin)
- [Msg/UpdateGroupPolicyDecisionPolicy](03_messages.md#msgupdategrouppolicydecisionpolicy)
- [Msg/UpdateGroupPolicyMetadata](03_messages.md#msgupdategrouppolicymetadata)
- [Msg/CreateProposal](03_messages.md#msgcreateproposal)
- [Msg/WithdrawProposal](03_messages.md#msgwithdrawproposal)
- [Msg/Vote](03_messages.md#msgvote)
- [Msg/Exec](03_messages.md#msgexec)
4. **[Events](04_events.md)**
* [EventCreateGroup](04_events.md#eventcreategroup)
* [EventUpdateGroup](04_events.md#eventupdategroup)
* [EventCreateGroupPolicy](04_events.md#eventcreategrouppolicy)
* [EventUpdateGroupPolicy](04_events.md#eventupdategrouppolicy)
* [EventCreateProposal](04_events.md#eventcreateproposal)
* [EventWithdrawProposal](04_events.md#eventwithdrawproposal)
* [EventVote](04_events.md#eventvote)
* [EventExec](04_events.md#eventexec)
5. **[Client](05_client.md)**
* [CLI](05_client.md#cli)
* [gRPC](05_client.md#grpc)
* [REST](05_client.md#rest)
6. **[Metadata](06_metadata.md)**
* [Proposal](06_metadata.md#proposal)
* [Vote](06_metadata.md#vote)
* [Group](06_metadata.md#group)
* [Decision policy](06_metadata.md#decision%20policy)

View File

@ -1,7 +1,389 @@
<!--
order: 0
title: Mint Overview
parent:
title: "mint"
-->
# Mint
# `x/mint`
* [Mint](spec/README.md) - Creation of new units of staking token.
## Contents
* [State](#state)
* [Minter](#minter)
* [Params](#params)
* [Begin-Block](#begin-block)
* [NextInflationRate](#nextinflationrate)
* [NextAnnualProvisions](#nextannualprovisions)
* [BlockProvision](#blockprovision)
* [Parameters](#parameters)
* [Events](#events)
* [BeginBlocker](#beginblocker)
* [Client](#client)
* [CLI](#cli)
* [gRPC](#grpc)
* [REST](#rest)
# Concepts
## The Minting Mechanism
The minting mechanism was designed to:
* allow for a flexible inflation rate determined by market demand targeting a particular bonded-stake ratio
* effect a balance between market liquidity and staked supply
In order to best determine the appropriate market rate for inflation rewards, a
moving change rate is used. The moving change rate mechanism ensures that if
the % bonded is either over or under the goal %-bonded, the inflation rate will
adjust to further incentivize or disincentivize being bonded, respectively. Setting the goal
%-bonded at less than 100% encourages the network to maintain some non-staked tokens
which should help provide some liquidity.
It can be broken down in the following way:
* If the inflation rate is below the goal %-bonded the inflation rate will
increase until a maximum value is reached
* If the goal % bonded (67% in Cosmos-Hub) is maintained, then the inflation
rate will stay constant
* If the inflation rate is above the goal %-bonded the inflation rate will
decrease until a minimum value is reached
<!-- order: 1 -->
# State
## Minter
The minter is a space for holding current inflation information.
* Minter: `0x00 -> ProtocolBuffer(minter)`
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/mint/v1beta1/mint.proto#L9-L23
## Params
The mint module stores it's params in state with the prefix of `0x01`,
it can be updated with governance or the address with authority.
* Params: `mint/params -> legacy_amino(params)`
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/mint/v1beta1/mint.proto#L25-L57
<!-- order: 2 -->
# Begin-Block
Minting parameters are recalculated and inflation
paid at the beginning of each block.
## Inflation rate calculation
Inflation rate is calculated using an "inflation calculation function" that's
passed to the `NewAppModule` function. If no function is passed, then the SDK's
default inflation function will be used (`NextInflationRate`). In case a custom
inflation calculation logic is needed, this can be achieved by defining and
passing a function that matches `InflationCalculationFn`'s signature.
```go
type InflationCalculationFn func(ctx sdk.Context, minter Minter, params Params, bondedRatio sdk.Dec) sdk.Dec
```
### NextInflationRate
The target annual inflation rate is recalculated each block.
The inflation is also subject to a rate change (positive or negative)
depending on the distance from the desired ratio (67%). The maximum rate change
possible is defined to be 13% per year, however the annual inflation is capped
as between 7% and 20%.
```go
NextInflationRate(params Params, bondedRatio sdk.Dec) (inflation sdk.Dec) {
inflationRateChangePerYear = (1 - bondedRatio/params.GoalBonded) * params.InflationRateChange
inflationRateChange = inflationRateChangePerYear/blocksPerYr
// increase the new annual inflation for this next cycle
inflation += inflationRateChange
if inflation > params.InflationMax {
inflation = params.InflationMax
}
if inflation < params.InflationMin {
inflation = params.InflationMin
}
return inflation
}
```
## NextAnnualProvisions
Calculate the annual provisions based on current total supply and inflation
rate. This parameter is calculated once per block.
```go
NextAnnualProvisions(params Params, totalSupply sdk.Dec) (provisions sdk.Dec) {
return Inflation * totalSupply
```
## BlockProvision
Calculate the provisions generated for each block based on current annual provisions. The provisions are then minted by the `mint` module's `ModuleMinterAccount` and then transferred to the `auth`'s `FeeCollector` `ModuleAccount`.
```go
BlockProvision(params Params) sdk.Coin {
provisionAmt = AnnualProvisions/ params.BlocksPerYear
return sdk.NewCoin(params.MintDenom, provisionAmt.Truncate())
```
<!-- order: 3 -->
# Parameters
The minting module contains the following parameters:
| Key | Type | Example |
|---------------------|-----------------|------------------------|
| MintDenom | string | "uatom" |
| InflationRateChange | string (dec) | "0.130000000000000000" |
| InflationMax | string (dec) | "0.200000000000000000" |
| InflationMin | string (dec) | "0.070000000000000000" |
| GoalBonded | string (dec) | "0.670000000000000000" |
| BlocksPerYear | string (uint64) | "6311520" |
<!-- order: 4 -->
# Events
The minting module emits the following events:
## BeginBlocker
| Type | Attribute Key | Attribute Value |
|------|-------------------|--------------------|
| mint | bonded_ratio | {bondedRatio} |
| mint | inflation | {inflation} |
| mint | annual_provisions | {annualProvisions} |
| mint | amount | {amount} |
<!-- order: 5 -->
# Client
## CLI
A user can query and interact with the `mint` module using the CLI.
### Query
The `query` commands allow users to query `mint` state.
```sh
simd query mint --help
```
#### annual-provisions
The `annual-provisions` command allow users to query the current minting annual provisions value
```sh
simd query mint annual-provisions [flags]
```
Example:
```sh
simd query mint annual-provisions
```
Example Output:
```sh
22268504368893.612100895088410693
```
#### inflation
The `inflation` command allow users to query the current minting inflation value
```sh
simd query mint inflation [flags]
```
Example:
```sh
simd query mint inflation
```
Example Output:
```sh
0.199200302563256955
```
#### params
The `params` command allow users to query the current minting parameters
```sh
simd query mint params [flags]
```
Example:
```yml
blocks_per_year: "4360000"
goal_bonded: "0.670000000000000000"
inflation_max: "0.200000000000000000"
inflation_min: "0.070000000000000000"
inflation_rate_change: "0.130000000000000000"
mint_denom: stake
```
## gRPC
A user can query the `mint` module using gRPC endpoints.
### AnnualProvisions
The `AnnualProvisions` endpoint allow users to query the current minting annual provisions value
```sh
/cosmos.mint.v1beta1.Query/AnnualProvisions
```
Example:
```sh
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/AnnualProvisions
```
Example Output:
```json
{
"annualProvisions": "1432452520532626265712995618"
}
```
### Inflation
The `Inflation` endpoint allow users to query the current minting inflation value
```sh
/cosmos.mint.v1beta1.Query/Inflation
```
Example:
```sh
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Inflation
```
Example Output:
```json
{
"inflation": "130197115720711261"
}
```
### Params
The `Params` endpoint allow users to query the current minting parameters
```sh
/cosmos.mint.v1beta1.Query/Params
```
Example:
```sh
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Params
```
Example Output:
```json
{
"params": {
"mintDenom": "stake",
"inflationRateChange": "130000000000000000",
"inflationMax": "200000000000000000",
"inflationMin": "70000000000000000",
"goalBonded": "670000000000000000",
"blocksPerYear": "6311520"
}
}
```
## REST
A user can query the `mint` module using REST endpoints.
### annual-provisions
```sh
/cosmos/mint/v1beta1/annual_provisions
```
Example:
```sh
curl "localhost:1317/cosmos/mint/v1beta1/annual_provisions"
```
Example Output:
```json
{
"annualProvisions": "1432452520532626265712995618"
}
```
### inflation
```sh
/cosmos/mint/v1beta1/inflation
```
Example:
```sh
curl "localhost:1317/cosmos/mint/v1beta1/inflation"
```
Example Output:
```json
{
"inflation": "130197115720711261"
}
```
### params
```sh
/cosmos/mint/v1beta1/params
```
Example:
```sh
curl "localhost:1317/cosmos/mint/v1beta1/params"
```
Example Output:
```json
{
"params": {
"mintDenom": "stake",
"inflationRateChange": "130000000000000000",
"inflationMax": "200000000000000000",
"inflationMin": "70000000000000000",
"goalBonded": "670000000000000000",
"blocksPerYear": "6311520"
}
}
```

View File

@ -1,28 +0,0 @@
<!--
order: 1
-->
# Concepts
## The Minting Mechanism
The minting mechanism was designed to:
* allow for a flexible inflation rate determined by market demand targeting a particular bonded-stake ratio
* effect a balance between market liquidity and staked supply
In order to best determine the appropriate market rate for inflation rewards, a
moving change rate is used. The moving change rate mechanism ensures that if
the % bonded is either over or under the goal %-bonded, the inflation rate will
adjust to further incentivize or disincentivize being bonded, respectively. Setting the goal
%-bonded at less than 100% encourages the network to maintain some non-staked tokens
which should help provide some liquidity.
It can be broken down in the following way:
* If the inflation rate is below the goal %-bonded the inflation rate will
increase until a maximum value is reached
* If the goal % bonded (67% in Cosmos-Hub) is maintained, then the inflation
rate will stay constant
* If the inflation rate is above the goal %-bonded the inflation rate will
decrease until a minimum value is reached

View File

@ -1,22 +0,0 @@
<!--
order: 2
-->
# State
## Minter
The minter is a space for holding current inflation information.
* Minter: `0x00 -> ProtocolBuffer(minter)`
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/mint/v1beta1/mint.proto#L9-L23
## Params
The mint module stores it's params in state with the prefix of `0x01`,
it can be updated with governance or the address with authority.
* Params: `mint/params -> legacy_amino(params)`
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.46.0/proto/cosmos/mint/v1beta1/mint.proto#L25-L57

View File

@ -1,66 +0,0 @@
<!--
order: 3
-->
# Begin-Block
Minting parameters are recalculated and inflation
paid at the beginning of each block.
## Inflation rate calculation
Inflation rate is calculated using an "inflation calculation function" that's
passed to the `NewAppModule` function. If no function is passed, then the SDK's
default inflation function will be used (`NextInflationRate`). In case a custom
inflation calculation logic is needed, this can be achieved by defining and
passing a function that matches `InflationCalculationFn`'s signature.
```go
type InflationCalculationFn func(ctx sdk.Context, minter Minter, params Params, bondedRatio sdk.Dec) sdk.Dec
```
### NextInflationRate
The target annual inflation rate is recalculated each block.
The inflation is also subject to a rate change (positive or negative)
depending on the distance from the desired ratio (67%). The maximum rate change
possible is defined to be 13% per year, however the annual inflation is capped
as between 7% and 20%.
```go
NextInflationRate(params Params, bondedRatio sdk.Dec) (inflation sdk.Dec) {
inflationRateChangePerYear = (1 - bondedRatio/params.GoalBonded) * params.InflationRateChange
inflationRateChange = inflationRateChangePerYear/blocksPerYr
// increase the new annual inflation for this next cycle
inflation += inflationRateChange
if inflation > params.InflationMax {
inflation = params.InflationMax
}
if inflation < params.InflationMin {
inflation = params.InflationMin
}
return inflation
}
```
## NextAnnualProvisions
Calculate the annual provisions based on current total supply and inflation
rate. This parameter is calculated once per block.
```go
NextAnnualProvisions(params Params, totalSupply sdk.Dec) (provisions sdk.Dec) {
return Inflation * totalSupply
```
## BlockProvision
Calculate the provisions generated for each block based on current annual provisions. The provisions are then minted by the `mint` module's `ModuleMinterAccount` and then transferred to the `auth`'s `FeeCollector` `ModuleAccount`.
```go
BlockProvision(params Params) sdk.Coin {
provisionAmt = AnnualProvisions/ params.BlocksPerYear
return sdk.NewCoin(params.MintDenom, provisionAmt.Truncate())
```

View File

@ -1,16 +0,0 @@
<!--
order: 4
-->
# Parameters
The minting module contains the following parameters:
| Key | Type | Example |
|---------------------|-----------------|------------------------|
| MintDenom | string | "uatom" |
| InflationRateChange | string (dec) | "0.130000000000000000" |
| InflationMax | string (dec) | "0.200000000000000000" |
| InflationMin | string (dec) | "0.070000000000000000" |
| GoalBonded | string (dec) | "0.670000000000000000" |
| BlocksPerYear | string (uint64) | "6311520" |

View File

@ -1,16 +0,0 @@
<!--
order: 5
-->
# Events
The minting module emits the following events:
## BeginBlocker
| Type | Attribute Key | Attribute Value |
|------|-------------------|--------------------|
| mint | bonded_ratio | {bondedRatio} |
| mint | inflation | {inflation} |
| mint | annual_provisions | {annualProvisions} |
| mint | amount | {amount} |

View File

@ -1,224 +0,0 @@
<!--
order: 6
-->
# Client
## CLI
A user can query and interact with the `mint` module using the CLI.
### Query
The `query` commands allow users to query `mint` state.
```sh
simd query mint --help
```
#### annual-provisions
The `annual-provisions` command allow users to query the current minting annual provisions value
```sh
simd query mint annual-provisions [flags]
```
Example:
```sh
simd query mint annual-provisions
```
Example Output:
```sh
22268504368893.612100895088410693
```
#### inflation
The `inflation` command allow users to query the current minting inflation value
```sh
simd query mint inflation [flags]
```
Example:
```sh
simd query mint inflation
```
Example Output:
```sh
0.199200302563256955
```
#### params
The `params` command allow users to query the current minting parameters
```sh
simd query mint params [flags]
```
Example:
```yml
blocks_per_year: "4360000"
goal_bonded: "0.670000000000000000"
inflation_max: "0.200000000000000000"
inflation_min: "0.070000000000000000"
inflation_rate_change: "0.130000000000000000"
mint_denom: stake
```
## gRPC
A user can query the `mint` module using gRPC endpoints.
### AnnualProvisions
The `AnnualProvisions` endpoint allow users to query the current minting annual provisions value
```sh
/cosmos.mint.v1beta1.Query/AnnualProvisions
```
Example:
```sh
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/AnnualProvisions
```
Example Output:
```json
{
"annualProvisions": "1432452520532626265712995618"
}
```
### Inflation
The `Inflation` endpoint allow users to query the current minting inflation value
```sh
/cosmos.mint.v1beta1.Query/Inflation
```
Example:
```sh
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Inflation
```
Example Output:
```json
{
"inflation": "130197115720711261"
}
```
### Params
The `Params` endpoint allow users to query the current minting parameters
```sh
/cosmos.mint.v1beta1.Query/Params
```
Example:
```sh
grpcurl -plaintext localhost:9090 cosmos.mint.v1beta1.Query/Params
```
Example Output:
```json
{
"params": {
"mintDenom": "stake",
"inflationRateChange": "130000000000000000",
"inflationMax": "200000000000000000",
"inflationMin": "70000000000000000",
"goalBonded": "670000000000000000",
"blocksPerYear": "6311520"
}
}
```
## REST
A user can query the `mint` module using REST endpoints.
### annual-provisions
```sh
/cosmos/mint/v1beta1/annual_provisions
```
Example:
```sh
curl "localhost:1317/cosmos/mint/v1beta1/annual_provisions"
```
Example Output:
```json
{
"annualProvisions": "1432452520532626265712995618"
}
```
### inflation
```sh
/cosmos/mint/v1beta1/inflation
```
Example:
```sh
curl "localhost:1317/cosmos/mint/v1beta1/inflation"
```
Example Output:
```json
{
"inflation": "130197115720711261"
}
```
### params
```sh
/cosmos/mint/v1beta1/params
```
Example:
```sh
curl "localhost:1317/cosmos/mint/v1beta1/params"
```
Example Output:
```json
{
"params": {
"mintDenom": "stake",
"inflationRateChange": "130000000000000000",
"inflationMax": "200000000000000000",
"inflationMin": "70000000000000000",
"goalBonded": "670000000000000000",
"blocksPerYear": "6311520"
}
}
```

View File

@ -1,26 +0,0 @@
<!--
order: 0
title: Mint Overview
parent:
title: "mint"
-->
# `mint`
## Contents
1. **[Concept](01_concepts.md)**
2. **[State](02_state.md)**
* [Minter](02_state.md#minter)
* [Params](02_state.md#params)
3. **[Begin-Block](03_begin_block.md)**
* [NextInflationRate](03_begin_block.md#nextinflationrate)
* [NextAnnualProvisions](03_begin_block.md#nextannualprovisions)
* [BlockProvision](03_begin_block.md#blockprovision)
4. **[Parameters](04_params.md)**
5. **[Events](05_events.md)**
* [BeginBlocker](05_events.md#beginblocker)
6. **[Client](06_client.md)**
* [CLI](06_client.md#cli)
* [gRPC](06_client.md#grpc)
* [REST](06_client.md#rest)

88
x/nft/README.md Normal file
View File

@ -0,0 +1,88 @@
<!--
order: 0
title: NFT Overview
parent:
title: "nft"
-->
# `x/nft`
## Contents
## Abstract
`x/nft` is an implementation of a Cosmos SDK module, per [ADR 43](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-043-nft-module.md), that allows you to create nft classification, create nft, transfer nft, update nft, and support various queries by integrating the module. It is fully compatible with the ERC721 specification.
* [Concept](#concepts)
* [Class](#class)
* [NFT](#nft)
*[State](#state)
*[Messages](#messages)
* [MsgSend](#msgsend)
*[Events](#events)
# Concepts
## Class
`x/nft` module defines a struct `Class` to describe the common characteristics of a class of nft, under this class, you can create a variety of nft, which is equivalent to an erc721 contract for Ethereum. The design is defined in the [ADR 043](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-043-nft-module.md).
## NFT
The full name of NFT is Non-Fungible Tokens. Because of the irreplaceable nature of NFT, it means that it can be used to represent unique things. The nft implemented by this module is fully compatible with Ethereum ERC721 standard.
<!-- order: 1 -->
# State
## Class
Class is mainly composed of `id`, `name`, `symbol`, `description`, `uri`, `uri_hash`,`data` where `id` is the unique identifier of the class, similar to the Ethereum ERC721 contract address, the others are optional.
* Class: `0x01 | classID | -> ProtocolBuffer(Class)`
## NFT
NFT is mainly composed of `class_id`, `id`, `uri`, `uri_hash` and `data`. Among them, `class_id` and `id` are two-tuples that identify the uniqueness of nft, `uri` and `uri_hash` is optional, which identifies the off-chain storage location of the nft, and `data` is an Any type. Use Any chain of `x/nft` modules can be customized by extending this field
* NFT: `0x02 | classID | 0x00 | nftID |-> ProtocolBuffer(NFT)`
## NFTOfClassByOwner
NFTOfClassByOwner is mainly to realize the function of querying all nfts using classID and owner, without other redundant functions.
* NFTOfClassByOwner: `0x03 | owner | 0x00 | classID | 0x00 | nftID |-> 0x01`
## Owner
Since there is no extra field in NFT to indicate the owner of nft, an additional key-value pair is used to save the ownership of nft. With the transfer of nft, the key-value pair is updated synchronously.
* OwnerKey: `0x04 | classID | 0x00 | nftID |-> owner`
## TotalSupply
TotalSupply is responsible for tracking the number of all nfts under a certain class. Mint operation is performed under the changed class, supply increases by one, burn operation, and supply decreases by one.
* OwnerKey: `0x05 | classID |-> totalSupply`
<!-- order: 2 -->
# Messages
In this section we describe the processing of messages for the nft module.
## MsgSend
You can use the `MsgSend` message to transfer the ownership of nft. This is a function provided by the `x/nft` module. Of course, you can use the `Transfer` method to implement your own transfer logic, but you need to pay extra attention to the transfer permissions.
The message handling should fail if:
* provided `ClassID` is not exist.
* provided `Id` is not exist.
* provided `Sender` is not the owner of nft.
<!-- order: 3 -->
# Events
The nft module emits proto events defined in [the Protobuf reference](https://buf.build/cosmos/cosmos-sdk/docs/main:cosmos.nft.v1beta1).

View File

@ -1,13 +0,0 @@
<!--
order: 1
-->
# Concepts
## Class
`x/nft` module defines a struct `Class` to describe the common characteristics of a class of nft, under this class, you can create a variety of nft, which is equivalent to an erc721 contract for Ethereum. The design is defined in the [ADR 043](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-043-nft-module.md).
## NFT
The full name of NFT is Non-Fungible Tokens. Because of the irreplaceable nature of NFT, it means that it can be used to represent unique things. The nft implemented by this module is fully compatible with Ethereum ERC721 standard.

Some files were not shown because too many files have changed in this diff Show More