Merge branch 'develop' into rigel/piggy-bank-fee-spec

This commit is contained in:
Rigel
2018-08-15 23:54:44 -04:00
committed by GitHub
164 changed files with 4034 additions and 2498 deletions
+10 -2
View File
@@ -1,8 +1,8 @@
## Fees
- Collection
- Gas price based on parameter
- (which gets changed automatically)
- https://github.com/cosmos/cosmos-sdk/issues/1921
- Per block gas usage as %
- Windowing function
- Block N,
@@ -22,7 +22,8 @@
- Only use text proposals
- On-chain mechanism for agreeing on when to "flip" to new functionality
## Slashing/Stability
## Staking/Slashing/Stability
- Unbonding state for validators https://github.com/cosmos/cosmos-sdk/issues/1676
- current: downtime, double signing during unbonding
- who gets slashed when -- needs review about edge cases
- need to communicate to everyone that lite has this edge case
@@ -68,3 +69,10 @@
## Slashing/Stability
- tendermint evidence: we dont yet slash byzantine signatures (signing at all) when not bonded.
# Other priority
## gaiad // gaiacli
- Documentation // language
## gaialite
- Documentation // language
+43
View File
@@ -493,6 +493,49 @@ paths:
500:
description: Internal Server Error
/stake/delegators/{delegatorAddr}/validators:
parameters:
- in: path
name: delegatorAddr
description: Bech32 AccAddress of Delegator
required: true
type: string
get:
summary: Query all validators that a delegator is bonded to
tags:
- stake
produces:
- application/json
responses:
200:
description: OK
404:
description: Not Found
/stake/delegators/{delegatorAddr}/validators/{validatorAddr}:
parameters:
- in: path
name: delegatorAddr
description: Bech32 AccAddress of Delegator
required: true
type: string
- in: path
name: validatorAddr
description: Bech32 ValAddress of Delegator
required: true
type: string
get:
summary: Query a validator that a delegator is bonded to
tags:
- stake
produces:
- application/json
responses:
200:
description: OK
404:
description: Not Found
/stake/delegators/{delegatorAddr}/txs:
parameters:
- in: path
+21 -5
View File
@@ -1,5 +1,11 @@
# Join the Testnet
::: tip Current Testnet
See the [testnet repo](https://github.com/cosmos/testnets) for
information on the latest testnet, including the correct version
of the Cosmos-SDK to use and details about the genesis file.
:::
Please ensure you have the [Cosmos SDK](/getting-started/installation.md) installed. If you ran a full node on a previous testnet, please skip to [Upgrading From Previous Testnet](#upgrading-from-previous-testnet).
## Setting Up a New Node
@@ -35,7 +41,7 @@ First, remove the outdated files and reset the data.
```bash
rm $HOME/.gaiad/config/addrbook.json $HOME/.gaiad/config/genesis.json
gaiad unsafe_reset_all
gaiad unsafe-reset-all
```
Your node is now in a pristine state while keeping the original `priv_validator.json` and `config.toml`. If you had any sentry nodes or full nodes setup before,
@@ -52,30 +58,40 @@ Now it is time to upgrade the software:
```bash
cd $GOPATH/src/github.com/cosmos/cosmos-sdk
git fetch --all && git checkout v0.19.0
git fetch --all && git checkout master
make update_tools && make get_vendor_deps && make install
```
Note we use `master` here since it contains the latest stable release.
See the [testnet repo](https://github.com/cosmos/testnets)
for details on which version is needed for which testnet,
and the [SDK release page](https://github.com/cosmos/cosmos-sdk/releases)
for details on each release.
Your full node has been cleanly upgraded!
## Genesis & Seeds
### Copy the Genesis File
Copy the testnet's `genesis.json` file and place it in `gaiad`'s config directory.
Fetch the testnet's `genesis.json` file into `gaiad`'s config directory.
```bash
mkdir -p $HOME/.gaiad/config
cp -a $GOPATH/src/github.com/cosmos/cosmos-sdk/cmd/gaia/testnets/gaia-6002/genesis.json $HOME/.gaiad/config/genesis.json
curl https://raw.githubusercontent.com/cosmos/testnets/master/latest/genesis.json > $HOME/.gaiad/config/genesis.json
```
Note we use the `latest` directory in the [testnets repo](https://github.com/cosmos/testnets)
which contains details for the latest testnet. If you are connecting to a different testnet, ensure you
get the right files.
### Add Seed Nodes
Your node needs to know how to find peers. You'll need to add healthy seed nodes to `$HOME/.gaiad/config/config.toml`. Here are some seed nodes you can use:
```toml
# Comma separated list of seed nodes to connect to
seeds = "38aa9bec3998f12ae9088b21a2d910d19d565c27@gaia-6002.coinculture.net:46656,80a35a46ce09cfb31ee220c8141a25e73e0b239b@seed.cosmos.cryptium.ch:46656,80a35a46ce09cfb31ee220c8141a25e73e0b239b@35.198.166.171:46656,032fa56301de335d835057fb6ad9f7ce2242a66d@165.227.236.213:46656"
seeds = "718145d422a823fd2a4e1e36e91b92bb0c4ddf8e@gaia-testnet.coinculture.net:26656,5922bf29b48a18c2300b85cc53f424fce23927ab@67.207.73.206:26656,7c8b8fd03577cd4817f5be1f03d506f879df98d8@gaia-7000-seed1.interblock.io:26656,a28737ff02391a6e00a1d3b79befd57e68e8264c@gaia-7000-seed2.interblock.io:26656,987ffd26640cd03d08ed7e53b24dfaa7956e612d@gaia-7000-seed3.interblock.io:26656"
```
If those seeds aren't working, you can find more seeds and persistent peers on the [Cosmos Explorer](https://explorecosmos.network/nodes). Open the the `Full Nodes` pane and select nodes that do not have private (`10.x.x.x`) or [local IP addresses](https://en.wikipedia.org/wiki/Private_network). The `Persistent Peer` field contains the connection string. For best results use 4-6.
+7 -4
View File
@@ -20,12 +20,18 @@ echo "export PATH=$PATH:$GOBIN" >> ~/.bash_profile
## Install Cosmos SDK
Next, let's install the testnet's version of the Cosmos SDK.
You can find information about the latest testnet and the right
version of the Cosmos-SDK for it in the [testnets
repo](https://github.com/cosmos/testnets#testnet-status).
Here we'll use the `master` branch, which contains the latest stable release.
If necessary, make sure you `git checkout` the correct
[released version](https://github.com/cosmos/cosmos-sdk/releases).
```bash
mkdir -p $GOPATH/src/github.com/cosmos
cd $GOPATH/src/github.com/cosmos
git clone https://github.com/cosmos/cosmos-sdk
cd cosmos-sdk && git checkout v0.19.0
cd cosmos-sdk && git checkout master
make get_tools && make get_vendor_deps && make install
```
@@ -33,10 +39,7 @@ That will install the `gaiad` and `gaiacli` binaries. Verify that everything is
```bash
$ gaiad version
0.19.0-c6711810
$ gaiacli version
0.19.0-c6711810
```
## Run a Full Node
-59
View File
@@ -1,59 +0,0 @@
# Install
The fastest and easiest way to install the Cosmos SDK binaries
is to run [this script](https://github.com/cosmos/cosmos-sdk/blob/develop/scripts/install_sdk_ubuntu.sh) on a fresh Ubuntu instance. Similarly, you can run [this script](https://github.com/cosmos/cosmos-sdk/blob/develop/scripts/install_sdk_bsd.sh) on a fresh FreeBSD instance. Read the scripts before running them to ensure no untrusted connection is being made, for example we're making curl requests to download golang. Also read the comments / instructions carefully (i.e., reset your terminal after running the script).
Cosmos SDK can be installed to
`$GOPATH/src/github.com/cosmos/cosmos-sdk` like a normal Go program:
```
go get github.com/cosmos/cosmos-sdk
```
If the dependencies have been updated with breaking changes, or if
another branch is required, `dep` is used for dependency management.
Thus, assuming you've already run `go get` or otherwise cloned the repo,
the correct way to install is:
```
cd $GOPATH/src/github.com/cosmos/cosmos-sdk
make get_tools
make get_vendor_deps
make install
make install_examples
```
This will install `gaiad` and `gaiacli` and four example binaries:
`basecoind`, `basecli`, `democoind`, and `democli`.
Verify that everything is OK by running:
```
gaiad version
```
you should see:
```
0.17.3-a5a78eb
```
then with:
```
gaiacli version
```
you should see the same version (or a later one for both).
## Update
Get latest code (you can also `git fetch` only the version desired),
ensure the dependencies are up to date, then recompile.
```
cd $GOPATH/src/github.com/cosmos/cosmos-sdk
git fetch -a origin
git checkout VERSION
make get_vendor_deps
make install
```
+27
View File
@@ -0,0 +1,27 @@
## Tendermint and Cosmos
Blockchains can be divided into three conceptual layers:
- **Networking:** Responsible for propagating transactions.
- **Consensus:** Enables validator nodes to agree on the next set of transactions to process (i.e. add blocks of transactions to the blockchain).
- **Application:** Responsible for updating the state given a set of transactions, i.e. processing transactions.
The *networking* layer makes sure that each node receives transactions. The *consensus* layer makes sure that each node agrees on the same transactions to modify their local state. As for the *application* layer, it processes transactions. Given a transaction and a state, the application will return a new state. In Bitcoin for example, the application state is a ledger or list of balances for each account (in reality, it's a list of UTXO, short for Unspent Transaction Output, but let's call them balances for the sake of simplicity), and the transactions modify the application's state by changing these list of balances. In the case of Ethereum, the application is a virtual machine. Each transaction goes through this virtual machine and modifies the application state according to the the smart contract that is called within it.
Before Tendermint, building a blockchain required building all three layers from the ground up. It was such a tedious task that most developers preferred to fork or replicate the Bitcoin codebase, but were constrainted by the limitations of Bitcoin's protocol. The Ethereum Virtual Machine (EVM) was designed to solve this problem and simplify decentralized application development by allowing customizable logic to be executed through smart contracts. But it did not resolve the limitations (interoperability, scalability and customization) of blockchains themselves. Go-Ethereum remains a very monolithic tech stack that is difficult to hard-fork much like Bitcoin's codebase.
Tendermint was designed to address these issues and provide developers with an laternative. The goal of Tendermint is to provide the *networking* and *consensus* layers of a blockchain as a generic engine to power any application developers want to build. With Tendermint, developers only have to focus on the *application* layer, thereby saving hundreds of hours of work and costly development set-ups. For reference, Tendermint also designates the name of the byzantine fault tolerant consensus algorithm used within the Tendermint Core engine.
Tendermint connects the blockchain engine, Tendermint Core (*networking* and *consensus* layers), to the *application* layer via a socket protocol called the [ABCI](https://github.com/tendermint/abci), short for Application-BlockChain Interface. Developers only have to implement a few messages to build an ABCI-enabled application that runs on top of the Tendermint Core engine. ABCI is language agnostic, meaning that developers can build the *application* part of their blockchain in any programming language. Building on top of the Tendermint Core engine also provides the following benefits:
- **Public or private blockchain capable.** Developers can deploy any blockchain application, permissioned (private) and permissionless (public), on top of Tendermint Core.
- **Performance.** Tendermint Core is a state-of-the-art blockchain consensus engine able to handle large number of transactions in short timespan. A block time on Tendermint Core can be as low as one second and can process thousands of transactions in that time period.
- **Instant finality.** A property of the Tendermint consensus algorithm is instant finality, meaning that forks are never created, as long as less than a third of the validators are malicious (byzantine). Users can be sure their transactions are finalized as soon as a block is created.
- **Security.** Tendermint Core's consensus is not only fault tolerant, its optimally Byzantine fault-tolerant (BFT), with accountability. If the blockchain forks, there is a way to determine liability.
- **Light-client support**. Tendermint provides built-in light-clients.
But most importantly, Tendermint is natively compatible with the [Inter-Blockchain Communication Protocol](https://github.com/cosmos/cosmos-sdk/tree/develop/docs/spec/ibc) (IBC). This means that any Tendermint-based blockchain, whether public or private, can be natively connected to the Cosmos ecosystem and securely exchange tokens with other blockchains in the ecosystem. Note that benefiting from interoperability via IBC and Cosmos preserves the sovereignty of your Tendermint chain. Non-Tendermint chains can also be connected to Cosmos via IBC adapters or Peg-Zones, but this is out of scope for this document.
For a more detailed overview of the Cosmos ecosystem, you can read [this article](https://blog.cosmos.network/understanding-the-value-proposition-of-cosmos-ecaef63350d).
For more on Tendermint, go [here](tendermint.md)
+35 -1
View File
@@ -5,9 +5,43 @@ Tendermint is software for securely and consistently replicating an application
Tendermint is designed to be easy-to-use, simple-to-understand, highly performant, and useful for a wide variety of distributed applications.
## Byzantine Fault Tolerance
The ability to tolerate machines failing in arbitrary ways, including becoming malicious, is known as Byzantine fault tolerance (BFT). The theory of BFT is decades old, but software implementations have only became popular recently, due largely to the success of “blockchain technology” like Bitcoin and Ethereum. Blockchain technology is just a re-formalization of BFT in a more modern setting, with emphasis on peer-to-peer networking and cryptographic authentication. The name derives from the way transactions are batched in blocks, where each block contains a cryptographic hash of the previous one, forming a chain. In practice, the blockchain data structure actually optimizes BFT design.
## Application Blockchain Interface
Tendermint consists of two chief technical components: a blockchain consensus engine and a generic application interface. The consensus engine, called Tendermint Core, ensures that the same transactions are recorded on every machine in the same order. The application interface, called the Application Blockchain Interface (ABCI), enables the transactions to be processed in any programming language. Unlike other blockchain and consensus solutions developers can use Tendermint for BFT state machine replication in any programming language or development environment. Visit the [Tendermint docs](https://tendermint.readthedocs.io/projects/tools/en/master/introduction.html#abci-overview) for a deep dive into the ABCI.
The [Cosmos SDK](/sdk/overview.md) is an ABCI framework written in Go. [Lotion JS](/lotion/overview.md) is an ABCI framework written in JavaScript.
## Understanding the roles of the different layers
It is important to have a good understanding of the respective responsibilities of both the *Application* and the *Consensus Engine*.
Responsibilities of the *Consensus Engine*:
- Propagate transactions
- Agree on the order of valid transactions
Reponsibilities of the *Application*:
- Generate Transactions
- Check if transactions are valid
- Process Transactions (includes state changes)
It is worth underlining that the *Consensus Engine* has knowledge of a given validator set for each block, but that it is the responsiblity of the *Application* to trigger validator set changes. This is the reason why it is possible to build both **public and private chains** with the Cosmos-SDK and Tendermint. A chain will be public or private depending on the rules, defined at application level, that governs a validator's set changes.
The ABCI establishes the connection between the *Consensus Engine* and the *Application*. Essentially, it boils down to two messages:
- `CheckTx`: Ask the application if the transaction is valid. When a validator's node receives a transaction, it will run `CheckTx` on it. If the transaction is valid, it is added to the mempool.
- `DeliverTx`: Ask the application to process the transaction and update the state.
Let us give a high-level overview of how the *Consensus Engine* and the *Application* interract with each other.
- At all times, when the consensus engine (Tendermint Core) of a validator node receives a transaction, it passes it to the application via `CheckTx` to check its validity. If it is valid, the transaction is added to the mempool.
- Let us say we are at block N. There is a validator set V. A proposer of the next block is selected from V by the *Consensus Engine*. The proposer gathers valid transaction from its mempool to form a new block. Then, the block is gossiped to other validators to be signed/commited. The block becomes block N+1 once 2/3+ of V have signed a *precommit* on it (For a more detailed explanation of the consensus algorithm, click [here](https://github.com/tendermint/tendermint/wiki/Byzantine-Consensus-Algorithm)).
- When block N+1 is signed by 2/3+ of V, it is gossipped to full-nodes. When full-nodes receive the block, they confirm its validity. A block is valid if it it holds valid signatures from more than 2/3 of V and if all the transactions in the block are valid. To check the validity of transactions, the *Consensus Engine* transfers them to the application via `DeliverTx`. After each transaction, `DeliverTx` returns a new state if the transaction was valid. At the end of the block, a final state is committed. Of course, this means that the order of transaction within a block matters.
## Application frameworks
Even if Tendermint makes it easy for developers to build their own blockchain by enabling them to focus on the *Application* layer of their blockchain, building an *Application* can be a challenging task in itself. This is why *Application Frameworks* exist. They provide developers with a secure and features-heavy environment to develop Tendermint-based applications. Here are some examples of *Application Frameworks* :
- The [Cosmos SDK](/sdk/overview.md) is an ABCI framework written in Go.
- [Lotion JS](/lotion/overview.md) is an ABCI framework written in JavaScript.
+1 -1
View File
@@ -4,4 +4,4 @@ Cosmos is a decentralized network of independent parallel blockchains, each powe
The first blockchain in the Cosmos Network is the [Cosmos Hub](), whose native token is the Atom. Cosmos is a permission-less network, meaning that anybody can build a blockchain on it.
Cosmos can interoperate with multiple other applications and cryptocurrencies. By creating a new zone, you can plug any blockchain system into the Cosmos hub and pass tokens back and forth between those zones, without the need for an intermediary.
Cosmos can interoperate with multiple other applications and cryptocurrencies. By creating a new zone, you can plug any blockchain system into the Cosmos hub and pass tokens back and forth between those zones, without the need for an intermediary.
+56
View File
@@ -479,6 +479,62 @@ Returns on error:
}
```
### /stake/delegators/{delegatorAddr}/validators - GET
url: /stake/delegators/{delegatorAddr}/validators
Functionality: Query all validators that a delegator is bonded to.
Returns on success:
```json
{
"rest api":"2.0",
"code":200,
"error":"",
"result":{}
}
```
Returns on failure:
```json
{
"rest api":"2.0",
"code":500,
"error":"TODO",
"result":{}
}
```
### /stake/delegators/{delegatorAddr}/validators/{validatorAddr} - GET
url: /stake/delegators/{delegatorAddr}/validators/{validatorAddr}
Functionality: Query a validator that a delegator is bonded to
Returns on success:
```json
{
"rest api":"2.0",
"code":200,
"error":"",
"result":{}
}
```
Returns on failure:
```json
{
"rest api":"2.0",
"code":500,
"error":"TODO",
"result":{}
}
```
### /stake/delegators/{delegatorAddr}/txs - GET
url: /stake/delegators/{delegatorAddr}/txs
+8
View File
@@ -323,6 +323,14 @@ return KeyOutput{
TODO
### [/stake/delegators/{delegatorAddr}/validators](api.md#stakedelegatorsdelegatorAddrvalidators---get)
TODO
### [/stake/delegators/{delegatorAddr}/validators/{validatorAddr}](api.md#stakedelegatorsdelegatorAddrvalidatorsvalidatorAddr---get)
TODO
### [/stake/delegators/{delegatorAddr}/txs](api.md#stakedelegatorsdelegatorAddrtxs---get)
TODO
+23 -22
View File
@@ -10,7 +10,6 @@
🚧 We are actively working on improving documentation for Gaiacli and Gaiad.
:::
`gaiacli` is the command line interface to manage accounts and transactions on Cosmos testnets. Here is a list of useful `gaiacli` commands, including usage examples.
### Key Types
@@ -18,18 +17,20 @@
There are three types of key representations that are used:
- `cosmosaccaddr`
* Derived from account keys generated by `gaiacli keys add`
* Used to receive funds
* e.g. `cosmosaccaddr15h6vd5f0wqps26zjlwrc6chah08ryu4hzzdwhc`
- Derived from account keys generated by `gaiacli keys add`
- Used to receive funds
- e.g. `cosmosaccaddr15h6vd5f0wqps26zjlwrc6chah08ryu4hzzdwhc`
- `cosmosaccpub`
* Derived from account keys generated by `gaiacli keys add`
* e.g. `cosmosaccpub1zcjduc3q7fu03jnlu2xpl75s2nkt7krm6grh4cc5aqth73v0zwmea25wj2hsqhlqzm`
- Derived from account keys generated by `gaiacli keys add`
- e.g. `cosmosaccpub1zcjduc3q7fu03jnlu2xpl75s2nkt7krm6grh4cc5aqth73v0zwmea25wj2hsqhlqzm`
- `cosmosvalpub`
* Generated when the node is created with `gaiad init`.
* Get this value with `gaiad tendermint show_validator`
* e.g. `cosmosvalpub1zcjduc3qcyj09qc03elte23zwshdx92jm6ce88fgc90rtqhjx8v0608qh5ssp0w94c`
- Generated when the node is created with `gaiad init`.
- Get this value with `gaiad tendermint show-validator`
- e.g. `cosmosvalpub1zcjduc3qcyj09qc03elte23zwshdx92jm6ce88fgc90rtqhjx8v0608qh5ssp0w94c`
### Generate Keys
@@ -58,11 +59,11 @@ gaiacli keys list
View the validator pubkey for your node by typing:
```bash
gaiad tendermint show_validator
gaiad tendermint show-validator
```
::: danger Warning
We strongly recommend *NOT* using the same passphrase for multiple keys. The Tendermint team and the Interchain Foundation will not be responsible for the loss of funds.
We strongly recommend _NOT_ using the same passphrase for multiple keys. The Tendermint team and the Interchain Foundation will not be responsible for the loss of funds.
:::
### Get Tokens
@@ -86,7 +87,7 @@ We're working on improving our error messages!
```bash
gaiacli send \
--amount=10faucetToken \
--chain-id=gaia-6002 \
--chain-id=gaia-7005 \
--name=<key_name> \
--to=<destination_cosmosaccaddr>
```
@@ -119,15 +120,15 @@ On the testnet, we delegate `steak` instead of `atom`. Here's how you can bond t
```bash
gaiacli stake delegate \
--amount=10steak \
--address-validator=$(gaiad tendermint show_validator) \
--from=<key_name> \
--chain-id=gaia-6002
--address-validator=$(gaiad tendermint show-validator) \
--name=<key_name> \
--chain-id=gaia-7005
```
While tokens are bonded, they are pooled with all the other bonded tokens in the network. Validators and delegators obtain a percentage of shares that equal their stake in this pool.
::: tip Note
Don't use more `steak` thank you have! You can always get more by using the [Faucet](https://faucetcosmos.network/)!
Don't use more `steak` thank you have! You can always get more by using the [Faucet](https://faucetcosmos.network/)!
:::
### Unbond Tokens
@@ -136,10 +137,10 @@ If for any reason the validator misbehaves, or you want to unbond a certain amou
```bash
gaiacli stake unbond begin \
--address-validator=$(gaiad tendermint show_validator) \
--shares-percent=1 \
--from=<key_name> \
--chain-id=gaia-6002
--address-validator=$(gaiad tendermint show-validator) \
--shares=MAX \
--name=<key_name> \
--chain-id=gaia-7005
```
Later you must use the `gaiacli stake unbond complete` command to finish
@@ -151,8 +152,8 @@ gaiacli account <account_cosmosaccaddr>
gaiacli stake delegation \
--address-delegator=<account_cosmosaccaddr> \
--address-validator=$(gaiad tendermint show_validator) \
--chain-id=gaia-6002
--address-validator=$(gaiad tendermint show-validator) \
--chain-id=gaia-7005
```
## Light Client Daemon
+2 -2
View File
@@ -150,7 +150,7 @@ func NewCodec() *wire.Codec {
```
Note: We also register the types in the `tendermint/tendermint/crypto` module so that `crypto.PubKey`
and `crypto.Signature` are encoded/decoded correctly.
is encoded/decoded correctly.
Amino supports encoding and decoding in both a binary and JSON format.
See the [codec API docs](https://godoc.org/github.com/tendermint/go-amino#Codec) for more details.
@@ -166,7 +166,7 @@ type app2Tx struct {
sdk.Msg
PubKey crypto.PubKey
Signature crypto.Signature
Signature []byte
}
// This tx only has one Msg.
+1 -1
View File
@@ -160,7 +160,7 @@ The standard form for signatures is `StdSignature`:
// the first transaction made by the account.
type StdSignature struct {
crypto.PubKey `json:"pub_key"` // optional
crypto.Signature `json:"signature"`
[]byte `json:"signature"`
AccountNumber int64 `json:"account_number"`
Sequence int64 `json:"sequence"`
}
+2 -2
View File
@@ -183,7 +183,7 @@ type app2Tx struct {
sdk.Msg
PubKey crypto.PubKey
Signature crypto.Signature
Signature []byte
}
// This tx only has one Msg.
@@ -191,7 +191,7 @@ func (tx app2Tx) GetMsgs() []sdk.Msg {
return []sdk.Msg{tx.Msg}
}
func (tx app2Tx) GetSignature() crypto.Signature {
func (tx app2Tx) GetSignature() []byte {
return tx.Signature
}
+10 -8
View File
@@ -1,14 +1,16 @@
# Cosmos SDK Overview
The Cosmos-SDK is a framework for building Tendermint ABCI applications in
Golang. It is designed to allow developers to easily create custom interoperable
blockchain applications within the Cosmos Network.
The [Cosmos-SDK](https://github.com/cosmos/cosmos-sdk) is a framework for building multi-asset Proof-of-Stake (PoS) blockchains, like the Cosmos Hub, as well as Proof-Of-Authority (PoA) blockchains.
To achieve its goals of flexibility and security, the SDK makes extensive use of
the [object-capability
model](https://en.wikipedia.org/wiki/Object-capability_model)
and the [principle of least
privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege).
The goal of the Cosmos-SDK is to allow developers to easily create custom interoperable blockchain applications within the Cosmos Network without having to recreate common blockchain functionality, thus removing the complexity of building a Tendermint ABCI application. We envision the SDK as the npm-like framework to build secure blockchain applications on top of Tendermint.
In terms of its design, the SDK optimizes flexibility and security. The framework is designed around a modular execution stack which allows applications to mix and match elements as desired. In addition, all modules are sandboxed for greater application security.
It is based on two major principles:
- **Composability:** Anyone can create a module for the Cosmos-SDK and integrating the already-built modules is as simple as importing them into your blockchain application.
- **Capabilities:** The SDK is inspired by capabilities-based security, and informed by years of wrestling with blockchain state-machines. Most developers will need to access other 3rd party modules when building their own modules. Given that the Cosmos-SDK is an open framework and that we assume that some of those modules may be malicious, we designed the SDK using object-capabilities (ocaps) based principles. In practice, this means that instead of having each module keep an access control list for other modules, each module implements special objects called keepers that can be passed to other modules to grant a pre-defined set of capabilities. For example, if an instance of module A's keepers is passed to module B, the latter will be able to call a restricted set of module A's functions. The capabilities of each keeper are defined by the module's developer, and it's the developer's job to understand and audit the safety of foreign code from 3rd party modules based on the capabilities they are passing into each 3rd party module. For a deeper look at capabilities, you can read this [article](http://habitatchronicles.com/2017/05/what-are-capabilities/).
For an introduction to object-capabilities, see this [article](http://habitatchronicles.com/2017/05/what-are-capabilities/).
+7
View File
@@ -0,0 +1,7 @@
**SDK by Examples** offers an alternative and complementary way to learn about the Cosmos-SDK. It contains several examples that showcase how to build a decentralised application on top of the Cosmos-SDK from start to finish.
Without further ado, let us get into it!
- [Simple governance example](./simple-governance/intro.md)
If you have an example you would like to add to the list, feel free to open a PR [here](https://github.com/cosmos/cosmos-sdk/pulls).
@@ -0,0 +1,23 @@
## Application CLI
**File: [`cmd/simplegovcli/maing.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/cmd/simplegovcli/main.go)**
To interact with our application, let us add the commands from the `simple_governance` module to our `simpleGov` application, as well as the pre-built SDK commands:
```go
// cmd/simplegovcli/main.go
...
rootCmd.AddCommand(
client.GetCommands(
simplegovcmd.GetCmdQueryProposal("proposals", cdc),
simplegovcmd.GetCmdQueryProposals("proposals", cdc),
simplegovcmd.GetCmdQueryProposalVotes("proposals", cdc),
simplegovcmd.GetCmdQueryProposalVote("proposals", cdc),
)...)
rootCmd.AddCommand(
client.PostCommands(
simplegovcmd.PostCmdPropose(cdc),
simplegovcmd.PostCmdVote(cdc),
)...)
...
```
@@ -0,0 +1,21 @@
## Application codec
**File: [`app/app.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/app/app.go)**
Finally, we need to define the `MakeCodec()` function and register the concrete types and interface from the various modules.
```go
func MakeCodec() *wire.Codec {
var cdc = wire.NewCodec()
wire.RegisterCrypto(cdc) // Register crypto.
sdk.RegisterWire(cdc) // Register Msgs
bank.RegisterWire(cdc)
simplestake.RegisterWire(cdc)
simpleGov.RegisterWire(cdc)
// Register AppAccount
cdc.RegisterInterface((*auth.Account)(nil), nil)
cdc.RegisterConcrete(&types.AppAccount{}, "simpleGov/Account", nil)
return cdc
}
```
@@ -0,0 +1,9 @@
## App commands
We will need to add the newly created commands to our application. To do so, go to the `cmd` folder inside your root directory:
```bash
// At root level of directory
cd cmd
```
`simplegovd` is the folder that stores the command for running the server daemon, whereas `simplegovcli` defines the commands of your application.
@@ -0,0 +1,61 @@
## Application constructor
**File: [`app/app.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/app/app.go)**
Now, we need to define the constructor for our application.
```go
func NewSimpleGovApp(logger log.Logger, db dbm.DB) *SimpleGovApp
```
In this function, we will:
- Create the codec
```go
var cdc = MakeCodec()
```
- Instantiate our application. This includes creating the keys to access each of the substores.
```go
// Create your application object.
var app = &SimpleGovApp{
BaseApp: bam.NewBaseApp(appName, cdc, logger, db),
cdc: cdc,
capKeyMainStore: sdk.NewKVStoreKey("main"),
capKeyAccountStore: sdk.NewKVStoreKey("acc"),
capKeyStakingStore: sdk.NewKVStoreKey("stake"),
capKeySimpleGovStore: sdk.NewKVStoreKey("simpleGov"),
}
```
- Instantiate the keepers. Note that keepers generally need access to other module's keepers. In this case, make sure you only pass an instance of the keeper for the functionality that is needed. If a keeper only needs to read in another module's store, a read-only keeper should be passed to it.
```go
app.coinKeeper = bank.NewKeeper(app.accountMapper)
app.stakeKeeper = simplestake.NewKeeper(app.capKeyStakingStore, app.coinKeeper,app.RegisterCodespace(simplestake.DefaultCodespace))
app.simpleGovKeeper = simpleGov.NewKeeper(app.capKeySimpleGovStore, app.coinKeeper, app.stakeKeeper, app.RegisterCodespace(simpleGov.DefaultCodespace))
```
- Declare the handlers.
```go
app.Router().
AddRoute("bank", bank.NewHandler(app.coinKeeper)).
AddRoute("simplestake", simplestake.NewHandler(app.stakeKeeper)).
AddRoute("simpleGov", simpleGov.NewHandler(app.simpleGovKeeper))
```
- Initialize the application.
```go
// Initialize BaseApp.
app.MountStoresIAVL(app.capKeyMainStore, app.capKeyAccountStore, app.capKeySimpleGovStore, app.capKeyStakingStore)
app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper))
err := app.LoadLatestVersion(app.capKeyMainStore)
if err != nil {
cmn.Exit(err.Error())
}
return app
```
@@ -0,0 +1,78 @@
## Application design
### Application description
For this tutorial, we will code a **simple governance application**, accompagnied by a **simple governance module**. It will allow us to explain most of the basic notions required to build a functioning application on the Cosmos-SDK. Note that this is not the governance module used for the Cosmos Hub. A much more [advanced governance module](https://github.com/cosmos/cosmos-sdk/tree/develop/x/gov) will be used instead.
All the code for the `simple_governance` application can be found [here](https://github.com/gamarin2/cosmos-sdk/tree/module_tutorial/examples/simpleGov/x/simple_governance). You'll notice that the module and app aren't located at the root level of the repo but in the examples directory. This is just for convenience, you can code your module and application directly in the root directory.
Without further talk, let's get into it!
### Requirements
We will start by writting down your module's requirements. We are designing a simple governance module, in which we want:
- Simple text proposals, that any coin holder can submit.
- Proposals must be submitted with a deposit in Atoms. If the deposit is larger than a `MinDeposit`, the associated proposal enters the voting period. Otherwise it is rejected.
- Bonded Atom holders can vote on proposal on a 1 bonded Atom 1 vote basis
- Bonded Atom holders can choose between 3 options when casting a vote: `Yes`, `No` and `Abstain`.
- If, at the end of the voting period, there are more `Yes` votes than `No` votes, the proposal is accepted. Otherwise, it is rejected.
- Voting period is 2 weeks
When designing a module, it is good to adopt a certain methodology. Remember that a blockchain application is just a replicated state-machine. The state is the representation of the application at a given time. It is up to the application developer to define what the state represents, depending on the goal of the application. For example, the state of a simple cryptocurrency application will be a mapping of addresses to balances.
The state can be updated according to predefined rules. Given a state and a transaction, the state-machine (i.e. the application) will return a new state. In a blockchain application, transactions are bundled in blocks, but the logic is the same. Given a state and a set of transactions (a block), the application returns a new state. A SDK-module is just a subset of the application, but it is based on the same principles. As a result, module developers only have to define a subset of the state and a subset of the transaction types, which trigger state transitions.
In summary, we have to define:
- A `State`, which represents a subset of the current state of the application.
- `Transactions`, which contain messages that trigger state transitions.
### State
Here, we will define the types we need (excluding transaction types), as well as the stores in the multistore.
Our voting module is very simple, we only need a single type: `Proposal`. `Proposals` are item to be voted upon. They can be submitted by any user. A deposit has to be provided.
```go
type Proposal struct {
Title string // Title of the proposal
Description string // Description of the proposal
Submitter sdk.Address // Address of the submitter. Needed to refund deposit if proposal is accepted.
SubmitBlock int64 // Block at which proposal is submitted. Also the block at which voting period begins.
State string // State can be either "Open", "Accepted" or "Rejected"
YesVotes int64 // Total number of Yes votes
NoVotes int64 // Total number of No votes
AbstainVotes int64 // Total number of Abstain votes
}
```
In terms of store, we will just create one [KVStore](#kvstore) in the multistore to store `Proposals`. We will also store the `Vote` (`Yes`, `No` or `Abstain`) chosen by each voter on each proposal.
### Messages
As a module developer, what you have to define are not `Transactions`, but `Messages`. Both transactions and messages exist in the Cosmos-SDK, but a transaction differs from a message in that a message is contained in a transaction. Transactions wrap around messages and add standard information like signatures and fees. As a module developer, you do not have to worry about transactions, only messages.
Let us define the messages we need in order to modify the state. Based on the requirements above, we need to define two types of messages:
- `SubmitProposalMsg`: to submit proposals
- `VoteMsg`: to vote on proposals
```go
type SubmitProposalMsg struct {
Title string // Title of the proposal
Description string // Description of the proposal
Deposit sdk.Coins // Deposit paid by submitter. Must be > MinDeposit to enter voting period
Submitter sdk.Address // Address of the submitter
}
```
```go
type VoteMsg struct {
ProposalID int64 // ID of the proposal
Option string // Option chosen by voter
Voter sdk.Address // Address of the voter
}
```
@@ -0,0 +1,11 @@
## Application initialization
In the root of your fork of the SDK, create an `app` and `cmd` folder. In this folder, we will create the main file for our application, `app.go` and the repository to handle REST and CLI commands for our app.
```bash
mkdir app cmd
mkdir -p cmd/simplegovcli cmd/simplegovd
touch app/app.go cmd/simplegovcli/main.go cmd/simplegovd/main.go
```
We will take care of these files later in the tutorial. The first step is to take care of our simple governance module.
@@ -0,0 +1,22 @@
## Makefile
The [Makefile](https://en.wikipedia.org/wiki/Makefile) compiles the Go program by defining a set of rules with targets and recipes. We'll need to add our application commands to it:
```
// Makefile
build_examples:
ifeq ($(OS),Windows_NT)
...
go build $(BUILD_FLAGS) -o build/simplegovd.exe ./examples/simpleGov/cmd/simplegovd
go build $(BUILD_FLAGS) -o build/simplegovcli.exe ./examples/simpleGov/cmd/simplegovcli
else
...
go build $(BUILD_FLAGS) -o build/simplegovd ./examples/simpleGov/cmd/simplegovd
go build $(BUILD_FLAGS) -o build/simplegovcli ./examples/simpleGov/cmd/simplegovcli
endif
...
install_examples:
...
go install $(BUILD_FLAGS) ./examples/simpleGov/cmd/simplegovd
go install $(BUILD_FLAGS) ./examples/simpleGov/cmd/simplegovcli
```
@@ -0,0 +1,57 @@
##### Rest server
**File: [`cmd/simplegovd/main.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/cmd/simplegovd/main.go)**
The `simplegovd` command will run the daemon server as a background process. First, let us create some `utils` functions:
```go
// cmd/simplegovd/main.go
// SimpleGovAppInit initial parameters
var SimpleGovAppInit = server.AppInit{
AppGenState: SimpleGovAppGenState,
AppGenTx: server.SimpleAppGenTx,
}
// SimpleGovAppGenState sets up the app_state and appends the simpleGov app state
func SimpleGovAppGenState(cdc *wire.Codec, appGenTxs []json.RawMessage) (appState json.RawMessage, err error) {
appState, err = server.SimpleAppGenState(cdc, appGenTxs)
if err != nil {
return
}
return
}
func newApp(logger log.Logger, db dbm.DB) abci.Application {
return app.NewSimpleGovApp(logger, db)
}
func exportAppState(logger log.Logger, db dbm.DB) (json.RawMessage, error) {
dapp := app.NewSimpleGovApp(logger, db)
return dapp.ExportAppStateJSON()
}
```
Now, let us define the command for the daemon server within the `main()` function:
```go
// cmd/simplegovd/main.go
func main() {
cdc := app.MakeCodec()
ctx := server.NewDefaultContext()
rootCmd := &cobra.Command{
Use: "simplegovd",
Short: "Simple Governance Daemon (server)",
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
}
server.AddCommands(ctx, cdc, rootCmd, SimpleGovAppInit,
server.ConstructAppCreator(newApp, "simplegov"),
server.ConstructAppExporter(exportAppState, "simplegov"))
// prepare and add flags
rootDir := os.ExpandEnv("$HOME/.simplegovd")
executor := cli.PrepareBaseCmd(rootCmd, "BC", rootDir)
executor.Execute()
}
```
@@ -0,0 +1,55 @@
## Application structure
Now, that we have built all the pieces we need, it is time to integrate them into the application. Let us exit the `/x` director go back at the root of the SDK directory.
```bash
// At root level of directory
cd app
```
We are ready to create our simple governance application!
*Note: You can check the full file (with comments!) [here](link)*
The `app.go` file is the main file that defines your application. In it, you will declare all the modules you need, their keepers, handlers, stores, etc. Let us take a look at each section of this file to see how the application is constructed.
Secondly, we need to define the name of our application.
```go
const (
appName = "SimpleGovApp"
)
```
Then, let us define the structure of our application.
```go
// Extended ABCI application
type SimpleGovApp struct {
*bam.BaseApp
cdc *wire.Codec
// keys to access the substores
capKeyMainStore *sdk.KVStoreKey
capKeyAccountStore *sdk.KVStoreKey
capKeyStakingStore *sdk.KVStoreKey
capKeySimpleGovStore *sdk.KVStoreKey
// keepers
feeCollectionKeeper auth.FeeCollectionKeeper
coinKeeper bank.Keeper
stakeKeeper simplestake.Keeper
simpleGovKeeper simpleGov.Keeper
// Manage getting and setting accounts
accountMapper auth.AccountMapper
}
```
- Each application builds on top of the `BaseApp` template, hence the pointer.
- `cdc` is the codec used in our application.
- Then come the keys to the stores we need in our application. For our simple governance app, we need 3 stores + the main store.
- Then come the keepers and mappers.
Let us do a quick reminder so that it is clear why we need these stores and keepers. Our application is primarily based on the `simple_governance` module. However, we have established in section [Keepers for our app](module-keeper.md) that our module needs access to two other modules: the `bank` module and the `stake` module. We also need the `auth` module for basic account functionalities. Finally, we need access to the main multistore to declare the stores of each of the module we use.
@@ -0,0 +1,19 @@
## Cast a vote to an existing proposal
Let's cast a vote on the created proposal:
```bash
simplegovcli vote --proposal-id=1 --option="No"
```
Get the value of the option from your casted vote :
```bash
simplegovcli proposal-vote 1 <your_address>
```
You can also check all the casted votes of a proposal:
```bash
simplegovcli proposals-votes 1
```
@@ -0,0 +1,58 @@
# SDK By Examples - Simple Governance Application
In this tutorial, you will learn the basics of coding an application with the Cosmos-SDK. Applications built on top of the SDK are called *Application-specific blockchains*. They are decentralised applications running on their own blockchains. The application we will build in this tutorial is a simple governance application.
Before getting in the bulk of the code, we will start by some introductory content on Tendermint, Cosmos and the programming philosophy of the SDK. Let us get started!
## Table of contents:
### Introduction - Prerequsite reading
- [Intro to Tendermint and Cosmos](../../../introduction/tendermint-cosmos.md)
- [Tendermint Core and ABCI](../../../introduction/tendermint.md)
- [Intro to Cosmos-SDK](../../overview.md)
- [Starting your own project](start.md)
### Setup and design phase
- [Setup](setup.md)
- [Application design](app-design.md)
### Implementation of the application
**Important note: All the code for this application can be found [here](https://github.com/cosmos/cosmos-sdk/tree/fedekunze/module_tutorial/examples/simpleGov). Snippets will be provided throughout the tutorial, but please refer to the provided link for the full implementation details**
- [Application initialization](app-init.md)
- Simple Governance module
+ [Module initialization](module-init.md)
+ [Types](module-types.md)
+ [Keeper](module-keeper.md)
+ [Handler](module-handler.md)
+ [Wire](module-wire.md)
+ [Errors](module-errors.md)
+ Command-Line Interface and Rest API
* [Command-Line Interface](module-cli.md)
* [Rest API](module-rest.md)
- Bridging it all together
+ [Application structure](app-structure.md)
+ [Application CLI and Rest Server](app-commands.md)
* [Application CLI](app-cli.md)
* [Rest Server](app-rest.md)
+ [Makefile](app-makefile.md)
+ [Application constructor](app-constructor.md)
+ [Application codec](app-codec.md)
- Running the application
+ [Installation](run-install.md)
+ [Submit a proposal](submit-proposal.md)
+ [Cast a vote](cast-vote.md)
## Useful links
If you have any question regarding this tutorial or about development on the SDK, please reach out us through our official communication channels:
- [Cosmos-SDK Riot Channel](https://riot.im/app/#/room/#cosmos-sdk:matrix.org)
- [Telegram](https://t.me/cosmosproject)
Or open an issue on the SDK repo:
- [Cosmos-SDK repo](https://github.com/cosmos/cosmos-sdk/)
@@ -0,0 +1,33 @@
## Command-Line Interface (CLI)
**File: [`x/simple_governance/client/cli/simple_governance.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/x/simple_governance/client/cli/simple_governance.go)**
Go in the `cli` folder and create a `simple_governance.go` file. This is where we will define the commands for our module.
The CLI builds on top of [Cobra](https://github.com/spf13/cobra). Here is the schema to build a command on top of Cobra:
```go
// Declare flags
const(
Flag = "flag"
...
)
// Main command function. One function for each command.
func Command(codec *wire.Codec) *cobra.Command {
// Create the command to return
command := &cobra.Command{
Use: "actual command",
Short: "Short description",
Run: func(cmd *cobra.Command, args []string) error {
// Actual function to run when command is used
},
}
// Add flags to the command
command.Flags().<Type>(FlagNameConstant, <example_value>, "<Description>")
return command
}
```
@@ -0,0 +1,7 @@
## Errors
**File: [`x/simple_governance/errors.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/x/simple_governance/errors.go)**
The `error.go` file allows us to define custom error messages for our module. Declaring errors should be relatively similar in all modules. You can look in the `error.go` file directly for a concrete example. The code is self-explanatory.
Note that the errors of our module inherit from the `sdk.Error` interface and therefore possess the method `Result()`. This method is useful when there is an error in the `handler` and an error has to be returned in place of an actual result.
@@ -0,0 +1,73 @@
## Handler
**File: [`x/simple_governance/handler.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/x/simple_governance/handler.go)**
### Constructor and core handlers
Handlers implement the core logic of the state-machine. When a transaction is routed from the app to the module, it is run by the `handler` function.
In practice, one `handler` will be implemented for each message of the module. In our case, we have two message types. We will therefore need two `handler` functions. We will also need a constructor function to route the message to the correct `handler`:
```go
func NewHandler(k Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
switch msg := msg.(type) {
case SubmitProposalMsg:
return handleSubmitProposalMsg(ctx, k, msg)
case VoteMsg:
return handleVoteMsg(ctx, k, msg)
default:
errMsg := "Unrecognized gov Msg type: " + reflect.TypeOf(msg).Name()
return sdk.ErrUnknownRequest(errMsg).Result()
}
}
}
```
The messages are routed to the appropriate `handler` depending on their type. For our simple governance module, we only have two `handlers`, that correspond to our two message types. They have similar signatures:
```go
func handleSubmitProposalMsg(ctx sdk.Context, k Keeper, msg SubmitProposalMsg) sdk.Result
```
Let us take a look at the parameters of this function:
- The context `ctx` to access the stores.
- The keeper `k` allows the handler to read and write from the different stores, including the module's store (`SimpleGovernance` in our case) and all the stores from other modules that the keeper `k` has been granted an access to (`stake` and `bank` in our case).
- The message `msg` that holds all the information provided by the sender of the transaction.
The function returns a `Result` that is returned to the application. It contains several useful information such as the amount of `Gas` for this transaction and wether the message was succesfully processed or not. At this point, we exit the boundaries of our simple governance module and go back to root application level. The `Result` will differ from application to application. You can check the `sdk.Result` type directly [here](https://github.com/cosmos/cosmos-sdk/blob/develop/types/result.go) for more info.
### BeginBlocker and EndBlocker
In contrast to most smart-contracts platform, it is possible to perform automatic (i.e. not triggered by a transaction sent by an end-user) execution of logic in Cosmos-SDK applications.
This automatic execution of code takes place in the `BeginBlock` and `EndBlock` functions that are called at the beginning and at the end of every block. They are powerful tools, but it is important for application developers to be careful with them. For example, it is crutial that developers control the amount of computing that happens in these functions, as expensive computation could delay the block time, and never-ending loop freeze the chain altogether.
`BeginBlock` and `EndBlock` are composable functions, meaning that each module can implement its own `BeginBlock` and `EndBlock` logic. When needed, `BeginBlock` and `EndBlock` logic is implemented in the module's `handler`. Here is the standard way to proceed for `EndBlock` (`BeginBlock` follows the exact same pattern):
```go
func NewEndBlocker(k Keeper) sdk.EndBlocker {
return func(ctx sdk.Context, req abci.RequestEndBlock) (res abci.ResponseEndBlock) {
err := checkProposal(ctx, k)
if err != nil {
panic(err)
}
return
}
}
```
Do not forget that each module need to declare its `BeginBlock` and `EndBlock` constructors at application level. See the [Application - Bridging it all together](app-structure.md).
For the purpose of our simple governance application, we will use `EndBlock` to automatically tally the results of the vote. Here are the different steps that will be performed:
1. Get the oldest proposal from the `ProposalProcessingQueue`
2. Check if the `CurrentBlock` is the block at which the voting period for this proposal ends. If Yes, go to 3.. If no, exit.
3. Check if proposal is accepted or rejected. Update the proposal status.
4. Pop the proposal from the `ProposalProcessingQueue` and go back to 1.
Let us perform a quick safety analysis on this process.
- The loop will not run forever because the number of proposals in `ProposalProcessingQueue` is finite
- The computation should not be too expensive because tallying of individual proposals is not expensive and the number of proposals is expected be relatively low. That is because proposals require a `Deposit` to be accepted. `MinDeposit` should be high enough so that we don't have too many `Proposals` in the queue.
- In the eventuality that the application becomes so successful that the `ProposalProcessingQueue` ends up containing so many proposals that the blockchain starts slowing down, the module should be modified to mitigate the situation. One clever way of doing it is to cap the number of iteration per individual `EndBlock` at `MaxIteration`. This way, tallying will be spread over many blocks if the number of proposals is too important and block time should remain stable. This would require to modify the current check `if (CurrentBlock == Proposal.SubmitBlock + VotingPeriod)` to `if (CurrentBlock > Proposal.SubmitBlock + VotingPeriod) AND (Proposal.Status == ProposalStatusActive)`.
@@ -0,0 +1,31 @@
## Module initialization
First, let us go into the module's folder and create a folder for our module.
```bash
cd x/
mkdir simple_governance
cd simple_governance
mkdir -p client/cli client/rest
touch client/cli/simple_governance.go client/rest/simple_governance.go errors.go handler.go handler_test.go keeper_keys.go keeper_test.go keeper.go test_common.go test_types.go types.go wire.go
```
Let us start by adding the files we will need. Your module's folder should look something like that:
```
x
└─── simple_governance
├─── client
│ ├─── cli
│ │ └─── simple_governance.go
│ └─── rest
│ └─── simple_governance.go
├─── errors.go
├─── handler.go
├─── keeper_keys.go
├─── keeper.go
├─── types.go
└─── wire.go
```
Let us go into the detail of each of these files.
@@ -0,0 +1,96 @@
## Keeper
**File: [`x/simple_governance/keeper.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/x/simple_governance/keeper.go)**
### Short intro to keepers
`Keepers` are a module abstraction that handle reading/writing to the module store. This is a practical implementation of the **Object Capability Model** for Cosmos.
As module developers, we have to define keepers to interact with our module's store(s) not only from within our module, but also from other modules. When another module wants to access one of our module's store(s), a keeper for this store has to be passed to it at the application level. In practice, it will look like that:
```go
// in app.go
// instanciate keepers
keeperA = moduleA.newKeeper(app.moduleAStoreKey)
keeperB = moduleB.newKeeper(app.moduleBStoreKey)
// pass instance of keeperA to handler of module B
app.Router().
AddRoute("moduleA", moduleA.NewHandler(keeperA)).
AddRoute("moduleB", moduleB.NewHandler(keeperB, keeperA)) // Here module B can access one of module A's store via the keeperA instance
```
`KeeperA` grants a set of capabilities to the handler of module B. When developing a module, it is good practice to think about the sensitivity of the different capabilities that can be granted through keepers. For example, some module may need to read and write to module A's main store, while others only need to read it. If a module has multiple stores, then some keepers could grant access to all of them, while others would only grant access to specific sub-stores. It is the job of the module developer to make sure it is easy for application developers to instanciate a keeper with the right capabilities. Of course, the handler of a module will most likely get an unrestricted instance of that module's keeper.
### Store for our app
Before we delve into the keeper itself, let us see what objects we need to store in our governance sub-store, and how to index them.
- `Proposals` will be indexed by `'proposals'|<proposalID>`.
- `Votes` (`Yes`, `No`, `Abstain`) will be indexed by `'proposals'|<proposalID>|'votes'|<voterAddress>`.
Notice the quote mark on `'proposals'` and `'votes'`. They indicate that these are constant keywords. So, for example, the option casted by voter with address `0x01` on proposal `0101` will be stored at index `'proposals'|0101|'votes'|0x01`.
These keywords are used to faciliate range queries. Range queries (TODO: Link to formal spec) allow developer to query a subspace of the store, and return an iterator. They are made possible by the nice properties of the [IAVL+ tree](https://github.com/tendermint/iavl) that is used in the background. In practice, this means that it is possible to store and query a Key-Value pair in O(1), while still being able to iterate over a given subspace of Key-Value pairs. For example, we can query all the addresses that voted on a given proposal, along with their votes, by calling `rangeQuery(SimpleGovStore, <proposalID|'addresses'>)`.
### Keepers for our app
In our case, we only have one store to access, the `SimpleGov` store. We will need to set and get values inside this store via our keeper. However, these two actions do not have the same impact in terms of security. While there should no problem in granting read access to our store to other modules, write access is way more sensitive. So ideally application developers should be able to create either a governance mapper that can only get values from the store, or one that can both get and set values. To this end, we will introduce two keepers: `Keeper` and `KeeperRead`. When application developers create their application, they will be able to decide which of our module's keeper to use.
Now, let us try to think about which keeper from **external** modules our module's keepers need access to.
Each proposal requires a deposit. This means our module needs to be able to both read and write to the module that handles tokens, which is the `bank` module. We also need to be able to determine the voting power of each voter based on their stake. To this end, we need read access to the store of the `staking` module. However, we don't need write access to this store. We should therefore indicate that in our module, and the application developer should be careful to only pass a read-only keeper of the `staking` module to our module's handler.
With all that in mind, we can define the structure of our `Keeper`:
```go
type Keeper struct {
SimpleGov sdk.StoreKey // Key to our module's store
cdc *wire.Codec // Codec to encore/decode structs
ck bank.Keeper // Needed to handle deposits. This module onlyl requires read/writes to Atom balance
sm stake.Keeper // Needed to compute voting power. This module only needs read access to the staking store.
codespace sdk.CodespaceType // Reserves space for error codes
}
```
And the structure of our `KeeperRead`:
```go
type KeeperRead struct {
Keeper
}
```
`KeeperRead` will inherit all methods from `Keeper`, except those that we override. These will be the methods that perform writes to the store.
### Functions and Methods
The first function we have to create is the constructor.
```go
func NewKeeper(SimpleGov sdk.StoreKey, ck bank.Keeper, sm stake.Keeper, codespace sdk.CodespaceType) Keeper
```
This function is called from the main [`app.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/app/app.go) file to instanciate a new `Keeper`. A similar function exits for `KeeperRead`.
```go
func NewKeeperRead(SimpleGov sdk.StoreKey, ck bank.Keeper, sm stake.Keeper, codespace sdk.CodespaceType) KeeperRead
```
Depending on the needs of the application and its modules, either `Keeper`, `KeeperRead`, or both, will be instanciated at application level.
*Note: Both the `Keeper` type name and `NewKeeper()` function's name are standard names used in every module. It is no requirement to follow this standard, but doing so can facilitate the life of application developers*
Now, let us describe the methods we need for our module's `Keeper`. For the full implementation, please refer to `keeper.go`.
- `GetProposal`: Get a `Proposal` given a `proposalID`. Proposals need to be decoded from `byte` before they can be read.
- `SetProposal`: Set a `Proposal` at index `'proposals'|<proposalID>`. Proposals need to be encoded to `byte` before they can be stored.
- `NewProposalID`: A function to generate a new unique `proposalID`.
- `GetVote`: Get a vote `Option` given a `proposalID` and a `voterAddress`.
- `SetVote`: Set a vote `Option` given a `proposalID` and a `voterAddress`.
- Proposal Queue methods: These methods implement a standard proposal queue to store `Proposals` on a First-In First-Out basis. It is used to tally the votes at the end of the voting period.
The last thing that needs to be done is to override certain methods for the `KeeperRead` type. `KeeperRead` should not have write access to the stores. Therefore, we will override the methods `SetProposal()`, `SetVote()` and `NewProposalID()`, as well as `setProposalQueue()` from the Proposal Queue's methods. For `KeeperRead`, these methods will just throw an error.
*Note: If you look at the code, you'll notice that the context `ctx` is a parameter of many of the methods. The context `ctx` provides useful information on the current state such as the current block height and allows the keeper `k` to access the `KVStore`. You can check all the methods of `ctx` [here](https://github.com/cosmos/cosmos-sdk/blob/develop/types/context.go#L144-L168)*.
@@ -0,0 +1,32 @@
## Rest API
**File: [`x/simple_governance/client/rest/simple_governance.goo`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/x/simple_governance/client/rest/simple_governance.go)**
The Rest Server, also called [Light-Client Daemon (LCD)](https://github.com/cosmos/cosmos-sdk/tree/master/client/lcd), provides support for **HTTP queries**.
________________________________________________________
USER INTERFACE <=======> REST SERVER <=======> FULL-NODE
________________________________________________________
It allows end-users that do not want to run full-nodes themselves to interract with the chain. The LCD can be configured to perform **Light-Client verification** via the flag `--trust-node`, which can be set to `true` or `false`.
- If *light-client verification* is enabled, the Rest Server acts as a light-client and needs to be run on the end-user's machine. It allows them to interract with the chain in a trustless way without having to store the whole chain locally.
- If *light-client verification* is disabled, the Rest Server acts as a simple relayer for HTTP calls. In this setting, the Rest server needs not be run on the end-user's machine. Instead, it will probably be run by the same entity that operates the full-node the server connects to. This mode is useful if end-users trust the full-node operator and do not want to store anything locally.
Now, let us define endpoints that will be available for users to query through HTTP requests. These endpoints will be defined in a `simple_governance.go` file stored in the `rest` folder.
| Method | URL | Description |
|--------|---------------------------------|-------------------------------------------------------------|
| GET | /proposals | Range query to get all submitted proposals |
| POST | /proposals | Submit a new proposal |
| GET | /proposals/{id} | Returns a proposal given its ID |
| GET | /proposals/{id}/votes | Range query to get all the votes casted on a given proposal |
| POST | /proposals/{id}/votes | Cast a vote on a given proposal |
| GET | /proposals/{id}/votes/{address} | Returns the vote of a given address on a given proposal |
It is the job of module developers to provide sensible endpoints so that front-end developers and service providers can properly interact with it.
Additionaly, here is a [link](https://hackernoon.com/restful-api-designing-guidelines-the-best-practices-60e1d954e7c9) for REST APIs best practices.
@@ -0,0 +1,23 @@
## Types
**File: [`x/simple_governance/types.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/x/simple_governance/types.go)**
In this file, we define the custom types for our module. This includes the types from the [State](app-design.md#State) section and the custom message types defined in the [Messages](app-design#Messages) section.
For each new type that is not a message, it is possible to add methods that make sense in the context of the application. In our case, we will implement an `updateTally` function to easily update the tally of a given proposal as vote messages come in.
Messages are a bit different. They implement the `Message` interface defined in the SDK's `types` folder. Here are the methods you need to implement when you define a custom message type:
- `Type()`: This function returns the name of our module's route. When messages are processed by the application, they are routed using the string returned by the `Type()` method.
- `GetSignBytes()`: Returns the byte representation of the message. It is used to sign the message.
- `GetSigners()`: Returns address(es) of the signer(s).
- `ValidateBasic()`: This function is used to discard obviously invalid messages. It is called at the beginning of `runTx()` in the baseapp file. If `ValidateBasic()` does not return `nil`, the app stops running the transaction.
- `Get()`: A basic getter, returns some property of the message.
- `String()`: Returns a human-readable version of the message
For our simple governance messages, this means:
- `Type()` will return `"simpleGov"`
- For `SubmitProposalMsg`, we need to make sure that the attributes are not empty and that the deposit is both valid and positive. Note that this is only basic validation, we will therefore not check in this method that the sender has sufficient funds to pay for the deposit
- For `VoteMsg`, we check that the address and option are valid and that the proposalID is not negative.
- As for other methods, less customization is required. You can check the code to see a standard way of implementing these.
@@ -0,0 +1,13 @@
## Wire
**File: [`x/simple_governance/wire.go`](https://github.com/cosmos/cosmos-sdk/blob/fedekunze/module_tutorial/examples/simpleGov/x/simple_governance/wire.go)**
The `wire.go` file allows developers to register the concrete message types of their module into the codec. In our case, we have two messages to declare:
```go
func RegisterWire(cdc *wire.Codec) {
cdc.RegisterConcrete(SubmitProposalMsg{}, "simple_governance/SubmitProposalMsg", nil)
cdc.RegisterConcrete(VoteMsg{}, "simple_governance/VoteMsg", nil)
}
```
Don't forget to call this function in `app.go` (see [Application - Bridging it all together](app-structure.md)) for more).
@@ -0,0 +1,18 @@
## Installation
Once you have finallized your application, install it using `go get`. The following commands will install the pre-built modules and examples of the SDK as well as your `simpleGov` application:
```bash
go get github.com/<your_username>/cosmos-sdk
cd $GOPATH/src/github.com/<your_username>/cosmos-sdk
make get_vendor_deps
make install
make install_examples
```
Check that the app is correctly installed by typing:
```bash
simplegovcli -h
simplegovd -h
```
@@ -0,0 +1,32 @@
## Setup
### Prerequisites
- Have [go](https://golang.org/dl/) and [git](https://git-scm.com/downloads) installed
- Don't forget to set your `PATH` and `GOPATH`
### Setup work environment
Go to the [Cosmos-SDK repo](https://githum.com/cosmos/cosmos-sdk) and fork it. Then open a terminal and:
```bash
cd $GOPATH/src/github.com/your_username
git clone github.com/your_username/cosmos-sdk
cd cosmos-sdk
```
Now we'll add the origin Cosmos-SDK as upstream in case some cool feature or module gets merged:
```bash
git remote add upstream github.com/cosmos/cosmos-sdk
git fetch upstream
git rebase upstream/master
```
We will also create a branch dedicated to our module:
```bash
git checkout -b my_new_application
```
We are all set!
@@ -0,0 +1,10 @@
## Starting your own project
To get started, you just have to follow these simple steps:
1. Clone the [Cosmos-SDK](https://github.com/cosmos/cosmos-sdk/tree/develop)repo
2. Code the modules needed by your application that do not already exist.
3. Create your app directory. In the app main file, import the module you need and instantiate the different stores.
4. Launch your blockchain.
Easy as pie! With the introduction over, let us delve into practice and learn how to code a SDK application with an example.
@@ -0,0 +1,19 @@
## Submit a proposal
Uuse the CLI to create a new proposal:
```bash
simplegovcli propose --title="Voting Period update" --description="Should we change the proposal voting period to 3 weeks?" --deposit=300Atoms
```
Get the details of your newly created proposal:
```bash
simplegovcli proposal 1
```
You can also check all the existing open proposals:
```bash
simplegovcli proposals --active=true
```
+9 -9
View File
@@ -25,9 +25,9 @@ type VotingProcedure struct {
```go
type TallyingProcedure struct {
Threshold rational.Rational // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Veto rational.Rational // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
GovernancePenalty sdk.Rat // Penalty if validator does not vote
Threshold sdk.Dec // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
GovernancePenalty sdk.Dec // Penalty if validator does not vote
GracePeriod int64 // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply
}
```
@@ -81,7 +81,7 @@ This type is used in a temp map when tallying
```go
type ValidatorGovInfo struct {
Minus sdk.Rat
Minus sdk.Dec
Vote Vote
}
```
@@ -103,17 +103,17 @@ type Proposal struct {
VotingStartBlock int64 // Height of the block where MinDeposit was reached. -1 if MinDeposit is not reached
CurrentStatus ProposalStatus // Current status of the proposal
YesVotes sdk.Rat
NoVotes sdk.Rat
NoWithVetoVotes sdk.Rat
AbstainVotes sdk.Rat
YesVotes sdk.Dec
NoVotes sdk.Dec
NoWithVetoVotes sdk.Dec
AbstainVotes sdk.Dec
}
```
We also mention a method to update the tally for a given proposal:
```go
func (proposal Proposal) updateTally(vote byte, amount sdk.Rat)
func (proposal Proposal) updateTally(vote byte, amount sdk.Dec)
```
### Stores
+1 -1
View File
@@ -7,7 +7,7 @@
The current annual inflation rate.
```golang
type Inflation sdk.Rat
type Inflation sdk.Dec
```
### InflationLastTime
-1
View File
@@ -16,4 +16,3 @@ EndBlock() ValidatorSetChanges
ClearTendermintUpdates()
return vsc
```
+15 -15
View File
@@ -13,7 +13,7 @@ type Pool struct {
LooseTokens int64 // tokens not associated with any bonded validator
BondedTokens int64 // reserve of bonded tokens
InflationLastTime int64 // block which the last inflation was processed // TODO make time
Inflation sdk.Rat // current annual inflation rate
Inflation sdk.Dec // current annual inflation rate
DateLastCommissionReset int64 // unix timestamp for last commission accounting reset (daily)
}
@@ -28,10 +28,10 @@ overall functioning of the stake module.
```golang
type Params struct {
InflationRateChange sdk.Rat // maximum annual change in inflation rate
InflationMax sdk.Rat // maximum inflation rate
InflationMin sdk.Rat // minimum inflation rate
GoalBonded sdk.Rat // Goal of percent bonded atoms
InflationRateChange sdk.Dec // maximum annual change in inflation rate
InflationMax sdk.Dec // maximum inflation rate
InflationMin sdk.Dec // minimum inflation rate
GoalBonded sdk.Dec // Goal of percent bonded atoms
MaxValidators uint16 // maximum number of validators
BondDenom string // bondable coin denomination
@@ -74,9 +74,9 @@ type Validator struct {
Revoked bool // has the validator been revoked?
Status sdk.BondStatus // validator status (bonded/unbonding/unbonded)
Tokens sdk.Rat // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Rat // total shares issued to a validator's delegators
SlashRatio sdk.Rat // increases each time the validator is slashed
Tokens sdk.Dec // delegated tokens (incl. self-delegation)
DelegatorShares sdk.Dec // total shares issued to a validator's delegators
SlashRatio sdk.Dec // increases each time the validator is slashed
Description Description // description terms for the validator
@@ -88,10 +88,10 @@ type Validator struct {
}
type CommissionInfo struct {
Rate sdk.Rat // the commission rate of fees charged to any delegators
Max sdk.Rat // maximum commission rate which this validator can ever charge
ChangeRate sdk.Rat // maximum daily increase of the validator commission
ChangeToday sdk.Rat // commission rate change today, reset each day (UTC time)
Rate sdk.Dec // the commission rate of fees charged to any delegators
Max sdk.Dec // maximum commission rate which this validator can ever charge
ChangeRate sdk.Dec // maximum daily increase of the validator commission
ChangeToday sdk.Dec // commission rate change today, reset each day (UTC time)
LastChange int64 // unix timestamp of last commission change
}
@@ -117,7 +117,7 @@ the transaction is the owner of the bond.
```golang
type Delegation struct {
Shares sdk.Rat // delegation shares recieved
Shares sdk.Dec // delegation shares recieved
Height int64 // last height bond updated
}
```
@@ -178,8 +178,8 @@ the original redelegation has been completed.
```golang
type Redelegation struct {
SourceShares sdk.Rat // amount of source shares redelegating
DestinationShares sdk.Rat // amount of destination shares created at redelegation
SourceShares sdk.Dec // amount of source shares redelegating
DestinationShares sdk.Dec // amount of destination shares created at redelegation
CompleteTime int64 // unix time to complete redelegation
}
```
+6 -6
View File
@@ -18,7 +18,7 @@ Other notes:
- `sender` denotes the address of the sender of the transaction
- `getXxx`, `setXxx`, and `removeXxx` functions are used to retrieve and
modify objects from the store
- `sdk.Rat` refers to a rational numeric type specified by the SDK.
- `sdk.Dec` refers to a decimal type specified by the SDK.
### TxCreateValidator
@@ -34,9 +34,9 @@ type TxCreateValidator struct {
SelfDelegation coin.Coin
Description Description
Commission sdk.Rat
CommissionMax sdk.Rat
CommissionMaxChange sdk.Rat
Commission sdk.Dec
CommissionMax sdk.Dec
CommissionMaxChange sdk.Dec
}
@@ -65,7 +65,7 @@ If either the `Description` (excluding `DateBonded` which is constant),
```golang
type TxEditCandidacy struct {
GovernancePubKey crypto.PubKey
Commission sdk.Rat
Commission sdk.Dec
Description Description
}
@@ -199,7 +199,7 @@ type TxRedelegate struct {
DelegatorAddr Address
ValidatorFrom Validator
ValidatorTo Validator
Shares sdk.Rat
Shares sdk.Dec
CompletedTime int64
}
+51 -20
View File
@@ -14,9 +14,9 @@ The [Cosmos Hub](/introduction/cosmos-hub.md) is based on [Tendermint](/introduc
The Cosmos Hub is a public Proof-Of-Stake (PoS) blockchain, meaning that validator's weight is determined by the amount of staking tokens (Atoms) bonded as collateral. These Atoms can be staked directly by the validator or delegated to them by Atom holders.
Any user in the system can declare its intention to become a validator by sending a "declare-candidacy" transaction. From there, they become validator candidates.
Any user in the system can declare its intention to become a validator by sending a `create-validator` transaction. From there, they become validators.
The weight (i.e. total stake) of a candidate determines wether or not it is a validator, and also how frequently this node will have to propose a block and how much revenue it will obtain. Initially, only the top 100 validator candidates with the most weight will be validators. If validators double sign, are frequently offline or do not participate in governance, their staked Atoms (including Atoms of users that delegated to them) can be destroyed, or 'slashed'.
The weight (i.e. total stake) of a validator determines wether or not it is an active validator, and also how frequently this node will have to propose a block and how much revenue it will obtain. Initially, only the top 100 validators with the most weight will be active validators. If validators double sign, are frequently offline or do not participate in governance, their staked Atoms (including Atoms of users that delegated to them) can be destroyed, or 'slashed'.
### What is a full-node?
@@ -28,7 +28,7 @@ Of course, it is possible and encouraged for any user to run full-nodes even if
Delegators are Atom holders who cannot, or do not want to run validator operations themselves. Through [Cosmos Voyager](/getting-started/voyager.md), a user can delegate Atoms to a validator and obtain a part of its revenue in exchange (for more detail on how revenue is distributed, see **What is the incentive to stake?** and **What is a validator's commission?** sections below).
Because they share revenue with their validators, delegators also share responsibility. Should a validator misbehave, each of its delegators will be partially slashed in proportion to their stake. This is why delegators should perform due diligence on validator candidates before delegating, as well as spreading their stake over multiple validators.
Because they share revenue with their validators, delegators also share responsibility. Should a validator misbehave, each of its delegators will be partially slashed in proportion to their stake. This is why delegators should perform due diligence on validators before delegating, as well as spreading their stake over multiple validators.
Delegators play a critical role in the system, as they are responsible for choosing validators. Being a delegator is not a passive role: Delegators should actively monitor the actions of their validators and participate in governance.
@@ -36,21 +36,22 @@ Delegators play a critical role in the system, as they are responsible for choos
### How to become a validator?
Any participant in the network can signal that they want to become a validator by sending a "declare-candidacy" transaction, where they must fill out the following parameters:
Any participant in the network can signal that they want to become a validator by sending a `create-validator` transaction, where they must fill out the following parameters:
* Validator's PubKey: The validator must signal an account with which it will perform its validator duties. The private key associated with PubKey is used to sign _prevotes_ and _precommits_. This way, validators can have different accounts for validating and holding liquid funds.
* Validator's name
* Validator's PubKey: The private key associated with PubKey is used to sign _prevotes_ and _precommits_. This way, validators can have different accounts for validating and holding liquid funds.
* Validator's Address: Application level address. This is the address used to identify your validator publicly. The private key associated with this address is used to bond, unbond, claim rewards, and participate in governance (in MVP only).
* Validator's name (moniker)
* Validator's website (Optional)
* Validator's description (Optional)
* Initial commission rate: The commission rate on block provisions, block rewards and fees charged to delegators
* Maximum commission: The maximum commission rate which this validator candidate can charge
* Commission change rate: The maximum daily increase of the validator candidate commission
* Minimum self-bond amount: Minimum amount of Atoms the validator candidate need to have bonded at all time. If the validator's self-bonded stake falls below this limit, its entire staking pool will unbond.
* Initial self-bond amount: Initial amount Atoms the validator candidate wants to self-bond
* Maximum commission: The maximum commission rate which this validator can charge
* Commission change rate: The maximum daily increase of the validator commission
* Minimum self-bond amount: Minimum amount of Atoms the validator need to have bonded at all time. If the validator's self-bonded stake falls below this limit, its entire staking pool will unbond.
* Initial self-bond amount: Initial amount of Atoms the validator wants to self-bond
Once a PubKey has declared candidacy, Atom holders can delegate atoms to it, effectively adding stake to this pool. The total stake of an address is the combination of Atoms bonded by delegators and Atoms self-bonded by the entity which designated itself.
Once a validator is created, Atom holders can delegate atoms to it, effectively adding stake to this pool. The total stake of an address is the combination of Atoms bonded by delegators and Atoms self-bonded by the entity which designated itself.
Out of all the candidates that signaled themselves, the 100 with the most stake are the ones who are designated as validators. If a validator's total stake falls below the top 100 then that validator loses its validator privileges. Over time, the maximum number of validators will increase, according to a predefined schedule:
Out of all validators that signaled themselves, the 100 with the most stake are the ones who are designated as validators. They become **bonded validators** If a validator's total stake falls below the top 100 then that validator loses its validator privileges, it enters **unbonding mode** and, eventually, becomes **unbonded** . Over time, the maximum number of validators will increase, according to a predefined schedule:
* **Year 0:** 100
* **Year 1:** 113
@@ -64,19 +65,48 @@ Out of all the candidates that signaled themselves, the 100 with the most stake
* **Year 9:** 300
* **Year 10:** 300
## Testnet
### How can I join the testnet?
The Testnet is a great environment to test your validator setup before launch.
We view testnet participation as a great way to signal to the community that you are ready and able to operate a validator. You can find all relevant information about the [testnet and more here](/getting-started/full-node.md).
We view testnet participation as a great way to signal to the community that you are ready and able to operate a validator. You can find all relevant information about the testnet [here](https://github.com/cosmos/cosmos-sdk/tree/develop/cmd/gaia/testnets) and [here](https://github.com/cosmos/testnets).
### What are the different types of keys?
In short, there are two types of keys:
- **Tendermint Key**: This is a unique key used to sign block hashes. It is associated with a public key `cosmosvalpub`.
+ Generated when the node is created with gaiad init.
+ Get this value with gaiad tendermint show_validator
+M e.g. cosmosvalpub1zcjduc3qcyj09qc03elte23zwshdx92jm6ce88fgc90rtqhjx8v0608qh5ssp0w94c
- **Application keys**: These keys are created from the application and used to sign transactions. As a validator, you will probably use one key to sign staking-related transactions, and another key to sign governance-related transactions. Application keys are associated with a public key `cosmosaccpub` and an address `cosmosaccaddr`. Both are derived from account keys generated by `gaiacli keys add`.
### What are the different states a validator can be in?
After a validator is created with a `create-validator` transaction, it can be in three states:
- `bonded`: Validator is in the active set and participates in consensus. Validator is earning rewards and can be slashed for misbehaviour.
- `unbonding`: Validator is not in the active set and does not participate in consensus. Validator is not earning rewards, but can still be slashed for misbehaviour. This is a transition state from `bonded` to `unbonded`. If validator does not send a `rebond` transaction while in `unbonding` mode, it will take three weeks for the state transition to complete.
- `unbonded`: Validator is not in the active set, and therefore not signing blocs. Validator cannot be slashed, and does not earn any reward. It is still possible to delegate Atoms to this validator. Un-delegating from an `unbonded` validator is immediate.
Delegators have the same state as their validator.
*Note that delegation are not necessarily bonded. Atoms can be delegated and bonded, delegated and unbonding, delegated and unbonded, or liquid*
### What is 'self-bond'? How can I increase my 'self-bond'?
### Is there a faucet?
If you want to obtain coins for the testnet, you can do so by using [this faucet](https://faucetcosmos.network)
If you want to obtain coins for the testnet, you can do so by using [this faucet](https://gaia.faucetcosmos.network/)
### Is there a minimum amount of Atoms that must be staked to be a validator?
### Is there a minimum amount of Atoms that must be staked to be an active (=bonded) validator?
There is no minimum. The top 100 validator candidates with the highest total stake (where total stake = self-bonded stake + delegators stake) are the validators.
There is no minimum. The top 100 validators with the highest total stake (where total stake = self-bonded stake + delegators stake) are the active validators.
### How will delegators choose their validators?
@@ -87,7 +117,7 @@ Delegators are free to choose validators according to their own subjective crite
* **Commission rate:** Commission applied on revenue by validators before it is distributed to their delegators
* **Track record:** Delegators will likely look at the track record of the validators they plan to delegate to. This includes seniority, past votes on proposals, historical average uptime and how often the node was compromised.
Apart from these criteria that will be displayed in Cosmos Voyager, there will be a possibility for validators to signal a website address to complete their resume. Validators will need to build reputation one way or another to attract delegators. For example, it would be a good practice for validators to have their setup audited by third parties. Note though, that the Tendermint team will not approve or conduct any audit itself.
Apart from these criteria that will be displayed in Cosmos Voyager, there will be a possibility for validators to signal a website address to complete their resume. Validators will need to build reputation one way or another to attract delegators. For example, it would be a good practice for validators to have their setup audited by third parties. Note though, that the Tendermint team will not approve or conduct any audit itself. For more on due diligence, see [this blog post](https://medium.com/@interchain_io/3d0faf10ce6f)
## Responsibilites
@@ -199,9 +229,9 @@ If a validator misbehaves, its bonded stake along with its delegators' stake and
* **Double signing:** If someone reports on chain A that a validator signed two blocks at the same height on chain A and chain B, this validator will get slashed on chain A
* **Unavailability:** If a validator's signature has not been included in the last X blocks, the validator will get slashed by a marginal amount proportional to X. If X is above a certain limit Y, then the validator will get unbonded
* **Non-voting:** If a validator did not vote on a proposal and once the fault is reported by a someone, its stake will receive a minor slash.
* **Non-voting:** If a validator did not vote on a proposal, its stake will receive a minor slash.
Note that even if a validator does not intentionally misbehave, it can still be slashed if its node crashes, looses connectivity, gets DDOSed, or if its private key is compromised. A complete document on the economics of the network will be published soon.
Note that even if a validator does not intentionally misbehave, it can still be slashed if its node crashes, looses connectivity, gets DDOSed, or if its private key is compromised.
### Do validators need to self-bond Atoms?
@@ -251,7 +281,6 @@ Validators should expect to run an HSM that supports ed25519 keys. Here are pote
* Ledger Nano S
* Ledger BOLOS SGX enclave
* Thales nShield support
* Tendermint SGX enclave
The Tendermint team does not recommend one solution above the other. The community is encouraged to bolster the effort to improve HSMs and the security of key management.
@@ -276,3 +305,5 @@ Validator nodes should only connect to full-nodes they trust because they operat
Sentry nodes can be quickly spun up or change their IP addresses. Because the links to the sentry nodes are in private IP space, an internet based attacked cannot disturb them directly. This will ensure validator block proposals and votes always make it to the rest of the network.
It is expected that good operating procedures on that part of validators will completely mitigate these threats.
For more on sentry node architecture, see [this](https://forum.cosmos.network/t/sentry-node-architecture-overview/454).
+13 -8
View File
@@ -1,5 +1,9 @@
# Validator Setup
::: warning Current Testnet
The current testnet is `gaia-7005`.
:::
Before setting up your validator node, make sure you've already gone through the [Full Node Setup](/getting-started/full-node.md) guide.
## Running a Validator Node
@@ -15,7 +19,7 @@ If you want to become a validator for the Hub's `mainnet`, you should [research
Your `cosmosvalpub` can be used to create a new validator by staking tokens. You can find your validator pubkey by running:
```bash
gaiad tendermint show_validator
gaiad tendermint show-validator
```
Next, craft your `gaiacli stake create-validator` command:
@@ -27,10 +31,10 @@ Don't use more `steak` thank you have! You can always get more by using the [Fau
```bash
gaiacli stake create-validator \
--amount=5steak \
--pubkey=$(gaiad tendermint show_validator) \
--pubkey=$(gaiad tendermint show-validator) \
--address-validator=<account_cosmosaccaddr>
--moniker="choose a moniker" \
--chain-id=gaia-6002 \
--chain-id=gaia-7005 \
--name=<key_name>
```
@@ -47,17 +51,18 @@ gaiacli stake edit-validator
--website="https://cosmos.network" \
--identity=6A0D65E29A4CBC8E
--details="To infinity and beyond!"
--chain-id=gaia-6002 \
--chain-id=gaia-7005 \
--name=<key_name>
```
### View Validator Description
View the validator's information with this command:
```bash
gaiacli stake validator \
--address-validator=<account_cosmosaccaddr> \
--chain-id=gaia-6002
--chain-id=gaia-7005
```
### Confirm Your Validator is Running
@@ -65,7 +70,7 @@ gaiacli stake validator \
Your validator is active if the following command returns anything:
```bash
gaiacli advanced tendermint validator-set | grep "$(gaiad tendermint show_validator)"
gaiacli advanced tendermint validator-set | grep "$(gaiad tendermint show-validator)"
```
You should also be able to see your validator on the [Explorer](https://explorecosmos.network/validators). You are looking for the `bech32` encoded `address` in the `~/.gaiad/config/priv_validator.json` file.
@@ -79,7 +84,7 @@ To be in the validator set, you need to have more total voting power than the 10
### Problem #1: My validator has `voting_power: 0`
Your validator has become auto-unbonded. In `gaia-6002`, we unbond validators if they do not vote on `50` of the last `100` blocks. Since blocks are proposed every ~2 seconds, a validator unresponsive for ~100 seconds will become unbonded. This usually happens when your `gaiad` process crashes.
Your validator has become auto-unbonded. In `gaia-7005`, we unbond validators if they do not vote on `50` of the last `100` blocks. Since blocks are proposed every ~2 seconds, a validator unresponsive for ~100 seconds will become unbonded. This usually happens when your `gaiad` process crashes.
Here's how you can return the voting power back to your validator. First, if `gaiad` is not running, start it up again:
@@ -90,7 +95,7 @@ gaiad start
Wait for your full node to catch up to the latest block. Next, run the following command. Note that `<cosmosaccaddr>` is the address of your validator account, and `<name>` is the name of the validator account. You can find this info by running `gaiacli keys list`.
```bash
gaiacli stake unrevoke <cosmosaccaddr> --chain-id=gaia-6002 --name=<name>
gaiacli stake unrevoke <cosmosaccaddr> --chain-id=gaia-7005 --name=<name>
```
::: danger Warning