diff --git a/README.md b/README.md index 3af98fb4f..5b4ebfde2 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![version](https://img.shields.io/github/tag/cosmos/cosmos-sdk.svg)](https://github.com/cosmos/cosmos-sdk/releases/latest) [![API Reference](https://godoc.org/github.com/cosmos/cosmos-sdk?status.svg )](https://godoc.org/github.com/cosmos/cosmos-sdk) -[![Rocket.Chat](https://demo.rocket.chat/images/join-chat.svg)](https://cosmos.rocket.chat/) +[![riot.im](https://img.shields.io/badge/riot.im-JOIN%20CHAT-green.svg)](https://riot.im/app/#/room/#cosmos-sdk:matrix.org) [![license](https://img.shields.io/github/license/cosmos/cosmos-sdk.svg)](https://github.com/cosmos/cosmos-sdk/blob/master/LICENSE) [![LoC](https://tokei.rs/b1/github/cosmos/cosmos-sdk)](https://github.com/cosmos/cosmos-sdk) [![Go Report Card](https://goreportcard.com/badge/github.com/cosmos/cosmos-sdk)](https://goreportcard.com/report/github.com/cosmos/cosmos-sdk) @@ -14,11 +14,15 @@ Branch | Tests | Coverage develop | [![CircleCI](https://circleci.com/gh/cosmos/cosmos-sdk/tree/develop.svg?style=shield)](https://circleci.com/gh/cosmos/cosmos-sdk/tree/develop) | [![codecov](https://codecov.io/gh/cosmos/cosmos-sdk/branch/develop/graph/badge.svg)](https://codecov.io/gh/cosmos/cosmos-sdk) master | [![CircleCI](https://circleci.com/gh/cosmos/cosmos-sdk/tree/master.svg?style=shield)](https://circleci.com/gh/cosmos/cosmos-sdk/tree/master) | [![codecov](https://codecov.io/gh/cosmos/cosmos-sdk/branch/master/graph/badge.svg)](https://codecov.io/gh/cosmos/cosmos-sdk) -**WARNING**: the libraries are still undergoing breaking changes as we get better ideas and start building out the Apps. +The Cosmos-SDK is a framework for building blockchain applications in Golang. +It is being used to build `Gaia`, the first implementation of the [Cosmos Hub](https://cosmos.network), + +**WARNING**: The SDK has mostly stabilized, but we are still making some +breaking changes. **Note**: Requires [Go 1.10+](https://golang.org/dl/) -## Testnet +## Gaia Testnet For more information on connecting to the testnet, see [cmd/gaia/testnets](/cmd/gaia/testnets) @@ -26,59 +30,14 @@ For more information on connecting to the testnet, see For the latest status of the testnet, see the [status file](/cmd/gaia/testnets/STATUS.md). +## Install -## Overview +See the [install instructions](/docs/install.md) -The Cosmos-SDK is a platform for building multi-asset Proof-of-Stake (PoS) blockchains, like the [Cosmos Hub](https://cosmos.network). It is both a library for building and securely interacting with blockchain applications. +## Quick Start -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 abstracting away the complexities 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 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 `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 their 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/). - -_Note: For now the Cosmos-SDK only exists in [Golang](https://golang.org/), which means that developers can only develop SDK modules in Golang. In the future, we expect that the SDK will be implemented in other programming languages. Funding opportunities supported by the Tendermint team may be available eventually._ - -## Application architecture - -#### Modules - -The Cosmos-SDK has all the necessary pre-built modules to add functionality on top of a `BaseApp`, which is the template to build a blockchain dApp in Cosmos. In this context, a `module` is a fundamental unit in the Cosmos-SDK. Each module is an extension of the `BaseApp` functionalities that defines transactions, handles application state and the state transition logic. Each module also contains handlers for messages and transactions, as well as REST and CLI for secure user interactions. - -Some of the most important modules already integrated in the SDK are: - -- `Auth`: Defines a standard account structure (`BaseAccount`) and how transaction signers are authenticated. -- `Bank`: Defines how coins (i.e cryptocurrencies) are transferred. -- `Governance`: Governance related implementation including proposals and voting. -- `Staking`: Proof of Stake related implementation including bonding and delegation transactions, inflation, fees, unbonding, etc. -- `IBC`: Defines the intereoperability of blockchain zones according to the specifications of the [IBC Protocol](https://cosmos.network/whitepaper#inter-blockchain-communication-ibc). - - -#### Directories - -The key directories of the SDK are: - -- `baseapp`: Defines the template for a basic [ABCI ](https://cosmos.network/whitepaper#abci) application so that your Cosmos-SDK application can communicate with the underlying Tendermint node. -- `client`: CLI and REST server tooling. -- `server`: RPC server to communicate with the node. -- `examples`: Contains examples on how to build working standalone applications. -- `store`: Contains code for the multistore (_i.e._ state). Each module can create any number of `KVStores` (key-value stores) from the multistore. -- `types`: Common types required in any SDK-based application. -- `x`(for e**X**tensions): Folder for storing the `BaseApp` module and all the already-built modules described in the previous section. - -## Prerequisites - -- [Golang](https://golang.org/doc/install) - -## Getting Started - -See the [documentation](https://cosmos-sdk.readthedocs.io). +- [Documentation](/docs/sdk) +- [Examples](/examples) ## Disambiguation diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index f4bccf3bd..000000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = python -msphinx -SPHINXPROJ = Cosmos-SDK -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..38609c585 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,38 @@ +# Cosmos SDK Documentation + +NOTE: This documentation is a work-in-progress! + +- [Overview](overview) + - [Overview](overview/overview.md) - An overview of the Cosmos-SDK + - [The Object-Capability Model](overview/capabilities.md) - Security by + least-privilege + - [Application Architecture](overview/apps.md) - Layers in the application architecture +- [Install](install.md) - Install the library and example applications +- [Core](core) + - [Messages](core/messages.md) - Messages contain the content of a transaction + - [Handlers](core/handlers.md) - Handlers are the workhorse of the app! + - [BaseApp](core/baseapp.md) - BaseApp is the base layer of the application + - [The MultiStore](core/multistore.md) - MultiStore is a rich Merkle database + - [Amino](core/amino.md) - Amino is the primary serialization library used in the SDK + - [Accounts](core/accounts.md) - Accounts are the prototypical object kept in the store + - [Transactions](core/transactions.md) - Transactions wrap messages and provide authentication + - [Keepers](core/keepers.md) - Keepers are the interfaces between handlers + - [Clients](core/clients.md) - Hook up your app to standard CLI and REST + interfaces for clients to use! + - [Advanced](core/advanced.md) - Trigger logic on a timer, use custom + serialization formats, advanced Merkle proofs, and more! + +- [Modules](modules) + - [Bank](modules/bank.md) + - [Staking](modules/staking.md) + - [Slashing](modules/slashing.md) + - [Provisions](modules/provisions.md) + - [Governance](modules/governance.md) + - [IBC](modules/ibc.md) + +- [Clients](clients) + - [Running a Node](clients/node.md) - Run a full node! + - [Key Management](clients/keys.md) - Managing user keys + - [CLI](clients/cli.md) - Queries and transactions via command line + - [Light Client Daemon](clients/lcd.md) - Queries and transactions via REST + API diff --git a/docs/guides/sdk/key-management.md b/docs/clients/key-management.md similarity index 100% rename from docs/guides/sdk/key-management.md rename to docs/clients/key-management.md diff --git a/docs/guides/sdk/lcd-rest-api.yaml b/docs/clients/lcd-rest-api.yaml similarity index 100% rename from docs/guides/sdk/lcd-rest-api.yaml rename to docs/clients/lcd-rest-api.yaml diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index 3f7cb19b5..000000000 --- a/docs/conf.py +++ /dev/null @@ -1,176 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Cosmos-SDK documentation build configuration file, created by -# sphinx-quickstart on Fri Sep 1 21:37:02 2017. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - -import sphinx_rtd_theme - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: - -from recommonmark.parser import CommonMarkParser - -source_parsers = { - '.md': CommonMarkParser, -} - -source_suffix = ['.rst', '.md'] -#source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Cosmos-SDK' -copyright = u'2018, The Authors' -author = u'The Authors' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = u'' -# The full version, including alpha/beta/rc tags. -release = u'' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '_attic', 'spec'] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'sphinx_rtd_theme' -# html_theme = 'alabaster' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# This is required for the alabaster theme -# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars -html_sidebars = { - '**': [ - 'about.html', - 'navigation.html', - 'relations.html', # needs 'show_related': True theme option to display - 'searchbox.html', - 'donate.html', - ] -} - - -# -- Options for HTMLHelp output ------------------------------------------ - -# Output file base name for HTML help builder. -htmlhelp_basename = 'Cosmos-SDKdoc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'Cosmos-SDK.tex', u'Cosmos-SDK Documentation', - u'The Authors', 'manual'), -] - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'cosmos-sdk', u'Cosmos-SDK Documentation', - [author], 1) -] - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'Cosmos-SDK', u'Cosmos-SDK Documentation', - author, 'Cosmos-SDK', 'One line description of project.', - 'Miscellaneous'), -] diff --git a/docs/core/accounts.md b/docs/core/accounts.md new file mode 100644 index 000000000..194c5e4d5 --- /dev/null +++ b/docs/core/accounts.md @@ -0,0 +1,101 @@ +# Accounts + +### auth.Account + +```go +// Account is a standard account using a sequence number for replay protection +// and a pubkey for authentication. +type Account interface { + GetAddress() sdk.Address + SetAddress(sdk.Address) error // errors if already set. + + GetPubKey() crypto.PubKey // can return nil. + SetPubKey(crypto.PubKey) error + + GetAccountNumber() int64 + SetAccountNumber(int64) error + + GetSequence() int64 + SetSequence(int64) error + + GetCoins() sdk.Coins + SetCoins(sdk.Coins) error +} +``` + +Accounts are the standard way for an application to keep track of addresses and their associated balances. + +### auth.BaseAccount + +```go +// BaseAccount - base account structure. +// Extend this by embedding this in your AppAccount. +// See the examples/basecoin/types/account.go for an example. +type BaseAccount struct { + Address sdk.Address `json:"address"` + Coins sdk.Coins `json:"coins"` + PubKey crypto.PubKey `json:"public_key"` + AccountNumber int64 `json:"account_number"` + Sequence int64 `json:"sequence"` +} +``` + +The `auth.BaseAccount` struct provides a standard implementation of the Account interface with replay protection. +BaseAccount can be extended by embedding it in your own Account struct. + +### auth.AccountMapper + +```go +// This AccountMapper encodes/decodes accounts using the +// go-amino (binary) encoding/decoding library. +type AccountMapper struct { + + // The (unexposed) key used to access the store from the Context. + key sdk.StoreKey + + // The prototypical Account concrete type. + proto Account + + // The wire codec for binary encoding/decoding of accounts. + cdc *wire.Codec +} +``` + +The AccountMapper is responsible for managing and storing the state of all accounts in the application. + +Example Initialization: + +```go +// File: examples/basecoin/app/app.go +// Define the accountMapper. +app.accountMapper = auth.NewAccountMapper( + cdc, + app.keyAccount, // target store + &types.AppAccount{}, // prototype +) +``` + +The accountMapper allows you to retrieve the current account state by `GetAccount(ctx Context, addr auth.Address)` and change the state by +`SetAccount(ctx Context, acc Account)`. + +Note: To update an account you will first have to get the account, update the appropriate fields with its associated setter method, and then call +`SetAccount(ctx Context, acc updatedAccount)`. + +Updating accounts is made easier by using the `Keeper` struct in the `x/bank` module. + +Example Initialization: + +```go +// File: examples/basecoin/app/app.go +app.coinKeeper = bank.NewKeeper(app.accountMapper) +``` + +Example Usage: + +```go +// Finds account with addr in accountmapper +// Adds coins to account's coin array +// Sets updated account in accountmapper +app.coinKeeper.AddCoins(ctx, addr, coins) +``` + diff --git a/docs/core/amino.md b/docs/core/amino.md new file mode 100644 index 000000000..f2c0aa4a6 --- /dev/null +++ b/docs/core/amino.md @@ -0,0 +1,36 @@ +# Amino + +The SDK is flexible about serialization - application developers can use any +serialization scheme to encode transactions and state. However, the SDK provides +a native serialization format called +[Amino](https://github.com/tendermint/go-amino). + +The goal of Amino is to improve over the latest version of Protocol Buffers, +`proto3`. To that end, Amino is compatible with the subset of `proto3` that +excludes the `oneof` keyword. + +While `oneof` provides union types, Amino aims to provide interfaces. +The main difference being that with union types, you have to know all the types +up front. But anyone can implement an interface type whenever and however +they like. + +To implement interface types, Amino allows any concrete implementation of an +interface to register a globally unique name that is carried along whenever the +type is serialized. This allows Amino to seamlessly deserialize into interface +types! + +The primary use for Amino in the SDK is for messages that implement the +`Msg` interface. By registering each message with a distinct name, they are each +given a distinct Amino prefix, allowing them to be easily distinguished in +transactions. + +Amino can also be used for persistent storage of interfaces. + +To use Amino, simply create a codec, and then register types: + +``` +cdc := wire.NewCodec() + +cdc.RegisterConcrete(MsgSend{}, "cosmos-sdk/Send", nil) +cdc.RegisterConcrete(MsgIssue{}, "cosmos-sdk/Issue", nil) +``` diff --git a/docs/core/baseapp.md b/docs/core/baseapp.md new file mode 100644 index 000000000..7029b16ea --- /dev/null +++ b/docs/core/baseapp.md @@ -0,0 +1,19 @@ +# BaseApp + +The BaseApp is an abstraction over the [Tendermint +ABCI](https://github.com/tendermint/abci) that +simplifies application development by handling common low-level concerns. +It serves as the mediator between the two key components of an SDK app: the store +and the message handlers. + +The BaseApp implements the +[`abci.Application`](https://godoc.org/github.com/tendermint/abci/types#Application) interface. +It uses a `MultiStore` to manage the state, a `Router` for transaction handling, and +`Set` methods to specify functions to run at the beginning and end of every +block. + +Every SDK app begins with a BaseApp: + +``` +app := baseapp.NewBaseApp(appName, cdc, logger, db), +``` diff --git a/docs/core/handlers.md b/docs/core/handlers.md new file mode 100644 index 000000000..5dbc22ef3 --- /dev/null +++ b/docs/core/handlers.md @@ -0,0 +1,52 @@ +# Message Handling + +## Context + +The SDK uses a `Context` to propogate common information across functions. The +`Context` is modeled after the Golang `context.Context` object, which has +become ubiquitous in networking middleware and routing applications as a means +to easily propogate request context through handler functions. + +The main information stored in the `Context` includes the application +MultiStore, the last block header, and the transaction bytes. +Effectively, the context contains all data that may be necessary for processing +a transaction. + +Many methods on SDK objects receive a context as the first argument. + +## Handler + +Message processing in the SDK is defined through `Handler` functions: + +```go +type Handler func(ctx Context, msg Msg) Result +``` + +A handler takes a context and a message and returns a result. All +information necessary for processing a message should be available in the +context. + +While the context holds the entire application state (ie. the +MultiStore), handlers are restricted in what they can do based on the +capabilities they were given when the application was set up. + +For instance, suppose we have a `newFooHandler`: + +```go +func newFooHandler(key sdk.StoreKey) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + store := ctx.KVStore(key) + // ... + } +} +``` + +This handler can only access one store based on whichever key its given. +So when we register the handler for the `foo` message type, we make sure +to give it the `fooKey`: + +``` +app.Router().AddRoute("foo", newFooHandler(fooKey)) +``` + +Now it can only access the `foo` store, but not the `bar` or `cat` stores! diff --git a/docs/core/keepers.md b/docs/core/keepers.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/core/messages.md b/docs/core/messages.md new file mode 100644 index 000000000..15190a886 --- /dev/null +++ b/docs/core/messages.md @@ -0,0 +1,76 @@ +# Messages + +Messages are the primary inputs to application state machines. +Developers can create messages containing arbitrary information by +implementing the `Msg` interface: + +```go +type Msg interface { + + // Return the message type. + // Must be alphanumeric or empty. + Type() string + + // Get the canonical byte representation of the Msg. + GetSignBytes() []byte + + // ValidateBasic does a simple validation check that + // doesn't require access to any other information. + ValidateBasic() error + + // 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() []Address +} + +``` + +Messages must specify their type via the `Type()` method. The type should +correspond to the messages handler, so there can be many messages with the same +type. + +Messages must also specify how they are to be authenticated. The `GetSigners()` +method return a list of SDK addresses that must sign the message, while the +`GetSignBytes()` method returns the bytes that must be signed for a signature +to be valid. + +Addresses in the SDK are arbitrary byte arrays that are hex-encoded when +displayed as a string or rendered in JSON. + +Messages can specify basic self-consistency checks using the `ValidateBasic()` +method to enforce that message contents are well formed before any actual logic +begins. + +For instance, the `Basecoin` message types are defined in `x/bank/tx.go`: + +```go +// Send coins from many inputs to many outputs. +type MsgSend struct { + Inputs []Input `json:"inputs"` + Outputs []Output `json:"outputs"` +} + +// Issue new coins to many outputs. +type MsgIssue struct { + Banker sdk.Address `json:"banker"` + Outputs []Output `json:"outputs"` +} +``` + +Each specifies the addresses that must sign the message: + +```go +func (msg MsgSend) GetSigners() []sdk.Address { + addrs := make([]sdk.Address, len(msg.Inputs)) + for i, in := range msg.Inputs { + addrs[i] = in.Address + } + return addrs +} + +func (msg MsgIssue) GetSigners() []sdk.Address { + return []sdk.Address{msg.Banker} +} +``` + diff --git a/docs/core/multistore.md b/docs/core/multistore.md new file mode 100644 index 000000000..1ac80af8e --- /dev/null +++ b/docs/core/multistore.md @@ -0,0 +1,63 @@ +# MultiStore + +The Cosmos-SDK provides a special Merkle database called a `MultiStore` to be used for all application +storage. The MultiStore consists of multiple Stores that must be mounted to the +MultiStore during application setup. Stores are mounted to the MultiStore using a capabilities key, +ensuring that only parts of the program with access to the key can access the store. + +The goals of the MultiStore are as follows: + +- Enforce separation of concerns at the storage level +- Restrict access to storage using capabilities +- Support multiple Store implementations in a single MultiStore, for instance the Tendermint IAVL tree and + the Ethereum Patricia Trie +- Merkle proofs for various queries (existence, absence, range, etc.) on current and retained historical state +- Allow for iteration within Stores +- Provide caching for intermediate state during execution of blocks and transactions (including for iteration) +- Support historical state pruning and snapshotting + +Currently, all Stores in the MultiStore must satisfy the `KVStore` interface, +which defines a simple key-value store. In the future, +we may support more kinds of stores, such as a HeapStore +or a NDStore for multidimensional storage. + +## Mounting Stores + +Stores are mounted during application setup. To mount some stores, first create +their capability-keys: + +``` +fooKey := sdk.NewKVStoreKey("foo") +barKey := sdk.NewKVStoreKey("bar") +catKey := sdk.NewKVStoreKey("cat") +``` + +Stores are mounted directly on the BaseApp. +They can either specify their own database, or share the primary one already +passed to the BaseApp. + +In this example, `foo` and `bar` will share the primary database, while `cat` will +specify its own: + +``` +catDB := dbm.NewMemDB() +app.MountStore(fooKey, sdk.StoreTypeIAVL) +app.MountStore(barKey, sdk.StoreTypeIAVL) +app.MountStoreWithDB(catKey, sdk.StoreTypeIAVL, catDB) +``` + +## Accessing Stores + +In the Cosmos-SDK, the only way to access a store is with a capability-key. +Only modules given explicit access to the capability-key will +be able to access the corresponding store. Access to the MultiStore is mediated +through the `Context`. + +## Notes + +In the example above, all IAVL nodes (inner and leaf) will be stored +in mainDB with the prefix of "s/k:foo/" and "s/k:bar/" respectively, +thus sharing the mainDB. All IAVL nodes (inner and leaf) for the +cat KVStore are stored separately in catDB with the prefix of +"s/\_/". The "s/k:KEY/" and "s/\_/" prefixes are there to +disambiguate store items from other items of non-storage concern. diff --git a/docs/core/transactions.md b/docs/core/transactions.md new file mode 100644 index 000000000..aafcb105c --- /dev/null +++ b/docs/core/transactions.md @@ -0,0 +1,154 @@ +### Transactions + +A message is a set of instructions for a state transition. + +For a message to be valid, it must be accompanied by at least one +digital signature. The signatures required are determined solely +by the contents of the message. + +A transaction is a message with additional information for authentication: + +```go +type Tx interface { + + GetMsg() Msg + +} +``` + +The standard way to create a transaction from a message is to use the `StdTx` struct defined in the `x/auth` module. + +```go +type StdTx struct { + Msg sdk.Msg `json:"msg"` + Fee StdFee `json:"fee"` + Signatures []StdSignature `json:"signatures"` +} +``` + +The `StdTx.GetSignatures()` method returns a list of signatures, which must match +the list of addresses returned by `tx.Msg.GetSigners()`. The signatures come in +a standard form: + +```go +type StdSignature struct { + crypto.PubKey // optional + crypto.Signature + AccountNumber int64 + Sequence int64 +} +``` + +It contains the signature itself, as well as the corresponding account's +sequence number. The sequence number is expected to increment every time a +message is signed by a given account. This prevents "replay attacks", where +the same message could be executed over and over again. + +The `StdSignature` can also optionally include the public key for verifying the +signature. An application can store the public key for each address it knows +about, making it optional to include the public key in the transaction. In the +case of Basecoin, the public key only needs to be included in the first +transaction send by a given account - after that, the public key is forever +stored by the application and can be left out of transactions. + +The address responsible for paying the transactions fee is the first address +returned by msg.GetSigners(). The convenience function `FeePayer(tx Tx)` is provided +to return this. + +The standard bytes for signers to sign over is provided by: + +```go +func StdSignByes(chainID string, accnums []int64, sequences []int64, fee StdFee, msg sdk.Msg) []byte +``` + +in `x/auth`. The standard way to construct fees to pay for the processing of transactions is: + +```go +// StdFee includes the amount of coins paid in fees and the maximum +// gas to be used by the transaction. The ratio yields an effective "gasprice", +// which must be above some miminum to be accepted into the mempool. +type StdFee struct { + Amount sdk.Coins `json:"amount"` + Gas int64 `json:"gas"` +} +``` + +### Encoding and Decoding Transactions + +Messages and transactions are designed to be generic enough for developers to +specify their own encoding schemes. This enables the SDK to be used as the +framwork for constructing already specified cryptocurrency state machines, for +instance Ethereum. + +When initializing an application, a developer can specify a `TxDecoder` +function which determines how an arbitrary byte array should be unmarshalled +into a `Tx`: + +```go +type TxDecoder func(txBytes []byte) (Tx, error) +``` + +The default tx decoder is the Tendermint wire format which uses the go-amino library +for encoding and decoding all message types. + +In `Basecoin`, we use the default transaction decoder. The `go-amino` library has the nice +property that it can unmarshal into interface types, but it requires the +relevant types to be registered ahead of type. Registration happens on a +`Codec` object, so as not to taint the global name space. + +For instance, in `Basecoin`, we wish to register the `MsgSend` and `MsgIssue` +types: + +```go +cdc.RegisterInterface((*sdk.Msg)(nil), nil) +cdc.RegisterConcrete(bank.MsgSend{}, "cosmos-sdk/MsgSend", nil) +cdc.RegisterConcrete(bank.MsgIssue{}, "cosmos-sdk/MsgIssue", nil) +``` + +Note how each concrete type is given a name - these name determine the type's +unique "prefix bytes" during encoding. A registered type will always use the +same prefix-bytes, regardless of what interface it is satisfying. For more +details, see the [go-amino documentation](https://github.com/tendermint/go-amino/blob/develop). + +If you wish to use a custom encoding scheme, you must define a TxDecoder function +and set it as the decoder in your extended baseapp using the `SetTxDecoder(decoder sdk.TxDecoder)`. + +Ex: + +```go +app.SetTxDecoder(CustomTxDecodeFn) +``` + + +## AnteHandler + +The AnteHandler is used to do all transaction-level processing (i.e. Fee payment, signature verification) +before passing the message to its respective handler. + +```go +type AnteHandler func(ctx Context, tx Tx) (newCtx Context, result Result, abort bool) +``` + +The antehandler takes a Context and a transaction and returns a new Context, a Result, and the abort boolean. +As with the handler, all information necessary for processing a message should be available in the +context. + +If the transaction fails, then the application should not waste time processing the message. Thus, the antehandler should +return an Error's Result method and set the abort boolean to `true` so that the application knows not to process the message in a handler. + +Most applications can use the provided antehandler implementation in `x/auth` which handles signature verification +as well as collecting fees. + +Note: Signatures must be over `auth.StdSignDoc` introduced above to use the provided antehandler. + +```go +// File: cosmos-sdk/examples/basecoin/app/app.go +app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper)) +``` + +### Handling Fee payment +### Handling Authentication + +The antehandler is responsible for handling all authentication of a transaction before passing the message onto its handler. +This generally involves signature verification. The antehandler should check that all of the addresses that are returned in +`tx.GetMsg().GetSigners()` signed the message and that they signed over `tx.GetMsg().GetSignBytes()`. diff --git a/docs/guides/guide.md b/docs/guides/guide.md deleted file mode 100644 index 21e8b70fe..000000000 --- a/docs/guides/guide.md +++ /dev/null @@ -1,464 +0,0 @@ -## Introduction - -If you want to see some examples, take a look at the [examples/basecoin](/examples/basecoin) directory. - -## Design Goals - -The design of the Cosmos SDK is based on the principles of "capabilities systems". - -## Capabilities systems - -### Need for module isolation -### Capability is implied permission -### TODO Link to thesis - -## Tx & Msg - -The SDK distinguishes between transactions (Tx) and messages -(Msg). A Tx is a list of Msgs wrapped with authentication and fee data. - -### Messages - -Users can create messages containing arbitrary information by -implementing the `Msg` interface: - -```go -type Msg interface { - - // Return the message type. - // Must be alphanumeric or empty. - Type() string - - // Get the canonical byte representation of the Msg. - GetSignBytes() []byte - - // ValidateBasic does a simple validation check that - // doesn't require access to any other information. - ValidateBasic() error - - // 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() []Address -} - -``` - -Messages must specify their type via the `Type()` method. The type should -correspond to the messages handler, so there can be many messages with the same -type. - -Messages must also specify how they are to be authenticated. The `GetSigners()` -method return a list of addresses that must sign the message, while the -`GetSignBytes()` method returns the bytes that must be signed for a signature -to be valid. - -Addresses in the SDK are arbitrary byte arrays that are hex-encoded when -displayed as a string or rendered in JSON. - -Messages can specify basic self-consistency checks using the `ValidateBasic()` -method to enforce that message contents are well formed before any actual logic -begins. - -For instance, the `Basecoin` message types are defined in `x/bank/tx.go`: - -```go -type MsgSend struct { - Inputs []Input `json:"inputs"` - Outputs []Output `json:"outputs"` -} - -type MsgIssue struct { - Banker sdk.Address `json:"banker"` - Outputs []Output `json:"outputs"` -} -``` - -Each specifies the addresses that must sign the message: - -```go -func (msg MsgSend) GetSigners() []sdk.Address { - addrs := make([]sdk.Address, len(msg.Inputs)) - for i, in := range msg.Inputs { - addrs[i] = in.Address - } - return addrs -} - -func (msg MsgIssue) GetSigners() []sdk.Address { - return []sdk.Address{msg.Banker} -} -``` - -### Transactions - -A transaction is a list of messages with additional information for authentication: - -```go -type Tx interface { - - GetMsgs() Msg -} -``` - -The standard way to create a transaction from a message is to use the `StdTx` struct defined in the `x/auth` module. - -```go -type StdTx struct { - Msg sdk.Msg `json:"msg"` - Fee StdFee `json:"fee"` - Signatures []StdSignature `json:"signatures"` -} -``` - -The `StdTx.GetSignatures()` method returns a list of signatures, which must match -the list of addresses returned by `tx.Msg.GetSigners()`. The signatures come in -a standard form: - -```go -type StdSignature struct { - crypto.PubKey // optional - crypto.Signature - AccountNumber int64 - Sequence int64 -} -``` - -It contains the signature itself, as well as the corresponding account's -sequence number. The sequence number is expected to increment every time a -message is signed by a given account. This prevents "replay attacks", where -the same message could be executed over and over again. - -The `StdSignature` can also optionally include the public key for verifying the -signature. An application can store the public key for each address it knows -about, making it optional to include the public key in the transaction. In the -case of Basecoin, the public key only needs to be included in the first -transaction send by a given account - after that, the public key is forever -stored by the application and can be left out of transactions. - -The address responsible for paying the transactions fee is the first address -returned by msg.GetSigners(). The convenience function `FeePayer(tx Tx)` is provided -to return this. - -The standard bytes for signers to sign over is provided by: - -```go -func StdSignByes(chainID string, accnums []int64, sequences []int64, fee StdFee, msg sdk.Msg) []byte -``` - -in `x/auth`. The standard way to construct fees to pay for the processing of transactions is: - -```go -// StdFee includes the amount of coins paid in fees and the maximum -// gas to be used by the transaction. The ratio yields an effective "gasprice", -// which must be above some miminum to be accepted into the mempool. -type StdFee struct { - Amount sdk.Coins `json:"amount"` - Gas int64 `json:"gas"` -} -``` - -### Encoding and Decoding Transactions - -Messages and transactions are designed to be generic enough for developers to -specify their own encoding schemes. This enables the SDK to be used as the -framwork for constructing already specified cryptocurrency state machines, for -instance Ethereum. - -When initializing an application, a developer can specify a `TxDecoder` -function which determines how an arbitrary byte array should be unmarshalled -into a `Tx`: - -```go -type TxDecoder func(txBytes []byte) (Tx, error) -``` - -The default tx decoder is the Tendermint wire format which uses the go-amino library -for encoding and decoding all message types. - -In `Basecoin`, we use the default transaction decoder. The `go-amino` library has the nice -property that it can unmarshal into interface types, but it requires the -relevant types to be registered ahead of type. Registration happens on a -`Codec` object, so as not to taint the global name space. - -For instance, in `Basecoin`, we wish to register the `MsgSend` and `MsgIssue` -types: - -```go -cdc.RegisterInterface((*sdk.Msg)(nil), nil) -cdc.RegisterConcrete(bank.MsgSend{}, "cosmos-sdk/MsgSend", nil) -cdc.RegisterConcrete(bank.MsgIssue{}, "cosmos-sdk/MsgIssue", nil) -``` - -Note how each concrete type is given a name - these name determine the type's -unique "prefix bytes" during encoding. A registered type will always use the -same prefix-bytes, regardless of what interface it is satisfying. For more -details, see the [go-amino documentation](https://github.com/tendermint/go-amino/blob/develop). - -If you wish to use a custom encoding scheme, you must define a TxDecoder function -and set it as the decoder in your extended baseapp using the `SetTxDecoder(decoder sdk.TxDecoder)`. - -Ex: - -```go -app.SetTxDecoder(CustomTxDecodeFn) -``` - -## Storage - -### MultiStore - -MultiStore is like a root filesystem of an operating system, except -all the entries are fully Merkleized. You mount onto a MultiStore -any number of Stores. Currently only KVStores are supported, but in -the future we may support more kinds of stores, such as a HeapStore -or a NDStore for multidimensional storage. - -The MultiStore as well as all mounted stores provide caching (aka -cache-wrapping) for intermediate state (aka software transactional -memory) during the execution of transactions. In the case of the -KVStore, this also works for iterators. For example, after running -the app's AnteHandler, the MultiStore is cache-wrapped (and each -store is also cache-wrapped) so that should processing of the -transaction fail, at least the transaction fees are paid and -sequence incremented. - -The MultiStore as well as all stores support (or will support) -historical state pruning and snapshotting and various kinds of -queries with proofs. - -### KVStore - -Here we'll focus on the IAVLStore, which is a kind of KVStore. - -IAVLStore is a fast balanced dynamic Merkle store that also supports -iteration, and of course cache-wrapping, state pruning, and various -queries with proofs, such as proofs of existence, absence, range, -and so on. - -Here's how you mount them to a MultiStore. - -```go -mainDB, catDB := dbm.NewMemDB(), dbm.NewMemDB() -fooKey := sdk.NewKVStoreKey("foo") -barKey := sdk.NewKVStoreKey("bar") -catKey := sdk.NewKVStoreKey("cat") -ms := NewCommitMultiStore(mainDB) -ms.MountStoreWithDB(fooKey, sdk.StoreTypeIAVL, nil) -ms.MountStoreWithDB(barKey, sdk.StoreTypeIAVL, nil) -ms.MountStoreWithDB(catKey, sdk.StoreTypeIAVL, catDB) -``` - -In the example above, all IAVL nodes (inner and leaf) will be stored -in mainDB with the prefix of "s/k:foo/" and "s/k:bar/" respectively, -thus sharing the mainDB. All IAVL nodes (inner and leaf) for the -cat KVStore are stored separately in catDB with the prefix of -"s/\_/". The "s/k:KEY/" and "s/\_/" prefixes are there to -disambiguate store items from other items of non-storage concern. - - -## Context - -The SDK uses a `Context` to propogate common information across functions. The -`Context` is modeled after the Golang `context.Context` object, which has -become ubiquitous in networking middleware and routing applications as a means -to easily propogate request context through handler functions. - -The main information stored in the `Context` includes the application -MultiStore (see below), the last block header, and the transaction bytes. -Effectively, the context contains all data that may be necessary for processing -a transaction. - -Many methods on SDK objects receive a context as the first argument. - -## Handler - -Message processing in the SDK is defined through `Handler` functions: - -```go -type Handler func(ctx Context, msg Msg) Result -``` - -A handler takes a context and a message and returns a result. All -information necessary for processing a message should be available in the -context. - -While the context holds the entire application state (all referenced from the -root MultiStore), a particular handler only needs a particular kind of access -to a particular store (or two or more). Access to stores is managed using -capabilities keys and mappers. When a handler is initialized, it is passed a -key or mapper that gives it access to the relevant stores. - -```go -// File: cosmos-sdk/examples/basecoin/app/init_stores.go -app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL) -app.accountMapper = auth.NewAccountMapper( - app.capKeyMainStore, // target store - &types.AppAccount{}, // prototype -) - -// File: cosmos-sdk/examples/basecoin/app/init_handlers.go -app.router.AddRoute("bank", bank.NewHandler(app.accountMapper)) - -// File: cosmos-sdk/x/bank/handler.go -// NOTE: Technically, NewHandler only needs a CoinMapper -func NewHandler(am sdk.AccountMapper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - cm := CoinMapper{am} - ... - } -} -``` - -## AnteHandler - -The AnteHandler is used to do all transaction-level processing (i.e. Fee payment, signature verification) -before passing the message to its respective handler. - -```go -type AnteHandler func(ctx Context, tx Tx) (newCtx Context, result Result, abort bool) -``` - -The antehandler takes a Context and a transaction and returns a new Context, a Result, and the abort boolean. -As with the handler, all information necessary for processing a message should be available in the -context. - -If the transaction fails, then the application should not waste time processing the message. Thus, the antehandler should -return an Error's Result method and set the abort boolean to `true` so that the application knows not to process the message in a handler. - -Most applications can use the provided antehandler implementation in `x/auth` which handles signature verification -as well as collecting fees. - -Note: Signatures must be over `auth.StdSignDoc` introduced above to use the provided antehandler. - -```go -// File: cosmos-sdk/examples/basecoin/app/app.go -app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeeper)) -``` - -### Handling Fee payment -### Handling Authentication - -The antehandler is responsible for handling all authentication of a transaction before passing the message onto its handler. -This generally involves signature verification. The antehandler should check that all of the addresses that are returned in -`tx.GetMsg().GetSigners()` signed the message and that they signed over `tx.GetMsg().GetSignBytes()`. - -## Accounts and x/auth - -### auth.Account - -```go -// Account is a standard account using a sequence number for replay protection -// and a pubkey for authentication. -type Account interface { - GetAddress() sdk.Address - SetAddress(sdk.Address) error // errors if already set. - - GetPubKey() crypto.PubKey // can return nil. - SetPubKey(crypto.PubKey) error - - GetAccountNumber() int64 - SetAccountNumber(int64) error - - GetSequence() int64 - SetSequence(int64) error - - GetCoins() sdk.Coins - SetCoins(sdk.Coins) error -} -``` - -Accounts are the standard way for an application to keep track of addresses and their associated balances. - -### auth.BaseAccount - -```go -// BaseAccount - base account structure. -// Extend this by embedding this in your AppAccount. -// See the examples/basecoin/types/account.go for an example. -type BaseAccount struct { - Address sdk.Address `json:"address"` - Coins sdk.Coins `json:"coins"` - PubKey crypto.PubKey `json:"public_key"` - AccountNumber int64 `json:"account_number"` - Sequence int64 `json:"sequence"` -} -``` - -The `auth.BaseAccount` struct provides a standard implementation of the Account interface with replay protection. -BaseAccount can be extended by embedding it in your own Account struct. - -### auth.AccountMapper - -```go -// This AccountMapper encodes/decodes accounts using the -// go-amino (binary) encoding/decoding library. -type AccountMapper struct { - - // The (unexposed) key used to access the store from the Context. - key sdk.StoreKey - - // The prototypical Account concrete type. - proto Account - - // The wire codec for binary encoding/decoding of accounts. - cdc *wire.Codec -} -``` - -The AccountMapper is responsible for managing and storing the state of all accounts in the application. - -Example Initialization: - -```go -// File: examples/basecoin/app/app.go -// Define the accountMapper. -app.accountMapper = auth.NewAccountMapper( - cdc, - app.keyAccount, // target store - &types.AppAccount{}, // prototype -) -``` - -The accountMapper allows you to retrieve the current account state by `GetAccount(ctx Context, addr auth.Address)` and change the state by -`SetAccount(ctx Context, acc Account)`. - -Note: To update an account you will first have to get the account, update the appropriate fields with its associated setter method, and then call -`SetAccount(ctx Context, acc updatedAccount)`. - -Updating accounts is made easier by using the `Keeper` struct in the `x/bank` module. - -Example Initialization: - -```go -// File: examples/basecoin/app/app.go -app.coinKeeper = bank.NewKeeper(app.accountMapper) -``` - -Example Usage: - -```go -// Finds account with addr in accountmapper -// Adds coins to account's coin array -// Sets updated account in accountmapper -app.coinKeeper.AddCoins(ctx, addr, coins) -``` - -## Wire codec - -### Why another codec? -### vs encoding/json -### vs protobuf - -## KVStore example - -## Basecoin example - -The quintessential SDK application is Basecoin - a simple -multi-asset cryptocurrency. Basecoin consists of a set of -accounts stored in a Merkle tree, where each account may have -many coins. There are two message types: MsgSend and MsgIssue. -MsgSend allows coins to be sent around, while MsgIssue allows a -set of predefined users to issue new coins. - -## Conclusion diff --git a/docs/guides/sdk/overview.rst b/docs/guides/sdk/overview.rst deleted file mode 100644 index 0cb7e7304..000000000 --- a/docs/guides/sdk/overview.rst +++ /dev/null @@ -1,420 +0,0 @@ -Overview -======== - -The SDK design 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. - -Framework Overview ------------------- - -Object-Capability Model -~~~~~~~~~~~~~~~~~~~~~~~ - -When thinking about security, it's good to start with a specific threat model. Our threat model is the following: - -:: - - We assume that a thriving ecosystem of Cosmos-SDK modules that are easy to compose into a blockchain application will contain faulty or malicious modules. - -The Cosmos-SDK is designed to address this threat by being the foundation of an object capability system. - -:: - - The structural properties of object capability systems favor - modularity in code design and ensure reliable encapsulation in - code implementation. - - These structural properties facilitate the analysis of some - security properties of an object-capability program or operating - system. Some of these — in particular, information flow properties - — can be analyzed at the level of object references and - connectivity, independent of any knowledge or analysis of the code - that determines the behavior of the objects. As a consequence, - these security properties can be established and maintained in the - presence of new objects that contain unknown and possibly - malicious code. - - These structural properties stem from the two rules governing - access to existing objects: - - 1) An object A can send a message to B only if object A holds a - reference to B. - - 2) An object A can obtain a reference to C only - if object A receives a message containing a reference to C. As a - consequence of these two rules, an object can obtain a reference - to another object only through a preexisting chain of references. - In short, "Only connectivity begets connectivity." - -See the `wikipedia article `__ for more information. - -Strictly speaking, Golang does not implement object capabilities completely, because of several issues: - -* pervasive ability to import primitive modules (e.g. "unsafe", "os") -* pervasive ability to override module vars https://github.com/golang/go/issues/23161 -* data-race vulnerability where 2+ goroutines can create illegal interface values - -The first is easy to catch by auditing imports and using a proper dependency version control system like Dep. The second and third are unfortunate but it can be audited with some cost. - -Perhaps `Go2 will implement the object capability model `__. - -What does it look like? -^^^^^^^^^^^^^^^^^^^^^^^ - -Only reveal what is necessary to get the work done. - -For example, the following code snippet violates the object capabilities principle: - -:: - - type AppAccount struct {...} - var account := &AppAccount{ - Address: pub.Address(), - Coins: sdk.Coins{{"ATM", 100}}, - } - var sumValue := externalModule.ComputeSumValue(account) - -The method "ComputeSumValue" implies a pure function, yet the implied capability of accepting a pointer value is the capability to modify that value. The preferred method signature should take a copy instead. - -:: - - var sumValue := externalModule.ComputeSumValue(*account) - -In the Cosmos SDK, you can see the application of this principle in the basecoin examples folder. - -:: - - // File: cosmos-sdk/examples/basecoin/app/init_handlers.go - package app - - import ( - "github.com/cosmos/cosmos-sdk/x/bank" - "github.com/cosmos/cosmos-sdk/x/sketchy" - ) - - func (app *BasecoinApp) initRouterHandlers() { - - // All handlers must be added here. - // The order matters. - app.router.AddRoute("bank", bank.NewHandler(app.accountMapper)) - app.router.AddRoute("sketchy", sketchy.NewHandler()) - } - -In the Basecoin example, the sketchy handler isn't provided an account mapper, which does provide the bank handler with the capability (in conjunction with the context of a transaction run). - -Security Overview ------------------ - -For examples, see the `examples `__ directory. - -Design Goals -~~~~~~~~~~~~ - -The design of the Cosmos SDK is based on the principles of "capabilities systems". - -Capabilities systems -~~~~~~~~~~~~~~~~~~~~ - -TODO: - -* Need for module isolation -* Capability is implied permission -* Link to thesis - -Tx & Msg -~~~~~~~~ - -The SDK distinguishes between transactions (Tx) and messages -(Msg). A Tx is a Msg wrapped with authentication and fee data. - -Messages -^^^^^^^^ - -Users can create messages containing arbitrary information by -implementing the ``Msg`` interface: - -:: - - type Msg interface { - - // Return the message type. - // Must be alphanumeric or empty. - Type() string - - // Get the canonical byte representation of the Msg. - GetSignBytes() []byte - - // ValidateBasic does a simple validation check that - // doesn't require access to any other information. - ValidateBasic() error - - // 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() []Address - } - -Messages must specify their type via the ``Type()`` method. The type should -correspond to the messages handler, so there can be many messages with the same -type. - -Messages must also specify how they are to be authenticated. The ``GetSigners()`` -method return a list of addresses that must sign the message, while the -``GetSignBytes()`` method returns the bytes that must be signed for a signature -to be valid. - -Addresses in the SDK are arbitrary byte arrays that are hex-encoded when -displayed as a string or rendered in JSON. - -Messages can specify basic self-consistency checks using the ``ValidateBasic()`` -method to enforce that message contents are well formed before any actual logic -begins. - -For instance, the ``Basecoin`` message types are defined in ``x/bank/tx.go``: - -:: - - type SendMsg struct { - Inputs []Input `json:"inputs"` - Outputs []Output `json:"outputs"` - } - - type IssueMsg struct { - Banker sdk.Address `json:"banker"` - Outputs []Output `json:"outputs"` - } - -Each specifies the addresses that must sign the message: - -:: - - func (msg SendMsg) GetSigners() []sdk.Address { - addrs := make([]sdk.Address, len(msg.Inputs)) - for i, in := range msg.Inputs { - addrs[i] = in.Address - } - return addrs - } - - func (msg IssueMsg) GetSigners() []sdk.Address { - return []sdk.Address{msg.Banker} - } - -Transactions -^^^^^^^^^^^^ - -A transaction is a message with additional information for authentication: - -:: - - type Tx interface { - - GetMsg() Msg - - // Signatures returns the signature of signers who signed the Msg. - // CONTRACT: Length returned is same as length of - // pubkeys returned from MsgKeySigners, and the order - // matches. - // CONTRACT: If the signature is missing (ie the Msg is - // invalid), then the corresponding signature is - // .Empty(). - GetSignatures() []StdSignature - } - -The ``tx.GetSignatures()`` method returns a list of signatures, which must match -the list of addresses returned by ``tx.Msg.GetSigners()``. The signatures come in -a standard form: - -:: - - type StdSignature struct { - crypto.PubKey // optional - crypto.Signature - AccountNumber int64 - Sequence int64 - } - -It contains the signature itself, as well as the corresponding account's account and -sequence numbers. The sequence number is expected to increment every time a -message is signed by a given account. The account number stays the same and is assigned -when the account is first generated. These prevent "replay attacks", where -the same message could be executed over and over again. - -The ``StdSignature`` can also optionally include the public key for verifying the -signature. An application can store the public key for each address it knows -about, making it optional to include the public key in the transaction. In the -case of Basecoin, the public key only needs to be included in the first -transaction send by a given account - after that, the public key is forever -stored by the application and can be left out of transactions. - -The standard way to create a transaction from a message is to use the ``StdTx``: - -:: - - type StdTx struct { - Msg - Signatures []StdSignature - } - -Encoding and Decoding Transactions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Messages and transactions are designed to be generic enough for developers to -specify their own encoding schemes. This enables the SDK to be used as the -framwork for constructing already specified cryptocurrency state machines, for -instance Ethereum. - -When initializing an application, a developer must specify a ``TxDecoder`` -function which determines how an arbitrary byte array should be unmarshalled -into a ``Tx``: - -:: - - type TxDecoder func(txBytes []byte) (Tx, error) - -In ``Basecoin``, we use the Tendermint wire format and the ``go-amino`` library for -encoding and decoding all message types. The ``go-amino`` library has the nice -property that it can unmarshal into interface types, but it requires the -relevant types to be registered ahead of type. Registration happens on a -``Codec`` object, so as not to taint the global name space. - -For instance, in ``Basecoin``, we wish to register the ``SendMsg`` and ``IssueMsg`` -types: - -:: - - cdc.RegisterInterface((*sdk.Msg)(nil), nil) - cdc.RegisterConcrete(bank.SendMsg{}, "cosmos-sdk/SendMsg", nil) - cdc.RegisterConcrete(bank.IssueMsg{}, "cosmos-sdk/IssueMsg", nil) - -Note how each concrete type is given a name - these name determine the type's -unique "prefix bytes" during encoding. A registered type will always use the -same prefix-bytes, regardless of what interface it is satisfying. For more -details, see the `go-amino documentation `__. - - -MultiStore -~~~~~~~~~~ - -MultiStore is like a filesystem -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Mounting an IAVLStore -^^^^^^^^^^^^^^^^^^^^^ - -TODO: - -* IAVLStore: Fast balanced dynamic Merkle store. - - * supports iteration. - -* MultiStore: multiple Merkle tree backends in a single store - - * allows using Ethereum Patricia Trie and Tendermint IAVL in same app - -* Provide caching for intermediate state during execution of blocks and transactions (including for iteration) -* Historical state pruning and snapshotting. -* Query proofs (existence, absence, range, etc.) on current and retained historical state. - -Context -------- - -The SDK uses a ``Context`` to propogate common information across functions. The -``Context`` is modelled after the Golang ``context.Context`` object, which has -become ubiquitous in networking middleware and routing applications as a means -to easily propogate request context through handler functions. - -The main information stored in the ``Context`` includes the application -MultiStore (see below), the last block header, and the transaction bytes. -Effectively, the context contains all data that may be necessary for processing -a transaction. - -Many methods on SDK objects receive a context as the first argument. - -Handler -------- - -Transaction processing in the SDK is defined through ``Handler`` functions: - -:: - - type Handler func(ctx Context, tx Tx) Result - -A handler takes a context and a transaction and returns a result. All -information necessary for processing a transaction should be available in the -context. - -While the context holds the entire application state (all referenced from the -root MultiStore), a particular handler only needs a particular kind of access -to a particular store (or two or more). Access to stores is managed using -capabilities keys and mappers. When a handler is initialized, it is passed a -key or mapper that gives it access to the relevant stores. - -:: - - // File: cosmos-sdk/examples/basecoin/app/init_stores.go - app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL) - app.accountMapper = auth.NewAccountMapper( - app.capKeyMainStore, // target store - &types.AppAccount{}, // prototype - ) - - // File: cosmos-sdk/examples/basecoin/app/init_handlers.go - app.router.AddRoute("bank", bank.NewHandler(app.accountMapper)) - - // File: cosmos-sdk/x/bank/handler.go - // NOTE: Technically, NewHandler only needs a CoinMapper - func NewHandler(am sdk.AccountMapper) sdk.Handler { - return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { - cm := CoinMapper{am} - ... - } - } - -AnteHandler ------------ - -Handling Fee payment -~~~~~~~~~~~~~~~~~~~~ - -Handling Authentication -~~~~~~~~~~~~~~~~~~~~~~~ - -Accounts and x/auth -------------------- - -sdk.Account -~~~~~~~~~~~ - -auth.BaseAccount -~~~~~~~~~~~~~~~~ - -auth.AccountMapper -~~~~~~~~~~~~~~~~~~ - -Wire codec ----------- - -Why another codec? -~~~~~~~~~~~~~~~~~~ - -vs encoding/json -~~~~~~~~~~~~~~~~ - -vs protobuf -~~~~~~~~~~~ - -KVStore example ---------------- - -Basecoin example ----------------- - -The quintessential SDK application is Basecoin - a simple -multi-asset cryptocurrency. Basecoin consists of a set of -accounts stored in a Merkle tree, where each account may have -many coins. There are two message types: SendMsg and IssueMsg. -SendMsg allows coins to be sent around, while IssueMsg allows a -set of predefined users to issue new coins. diff --git a/docs/guides/staking/intro.rst b/docs/guides/staking/intro.rst deleted file mode 100644 index 3ed20852b..000000000 --- a/docs/guides/staking/intro.rst +++ /dev/null @@ -1,402 +0,0 @@ -Using The Staking Module -======================== - -This project is a demonstration of the Cosmos Hub staking functionality; it is -designed to get validator acquianted with staking concepts and procedures. - -Potential validators will be declaring their candidacy, after which users can -delegate and, if they so wish, unbond. This can be practiced using a local or -public testnet. - -This example covers initial setup of a two-node testnet between a server in the cloud and a local machine. Begin this tutorial from a cloud machine that you've ``ssh``'d into. - -Install -------- - -The ``gaiad`` and ``gaiacli`` binaries: - -:: - - go get github.com/cosmos/cosmos-sdk - cd $GOPATH/src/github.com/cosmos/cosmos-sdk - make get_vendor_deps - make install - -Let's jump right into it. First, we initialize some default files: - -:: - - gaiad init - -which will output: - -:: - - I[03-30|11:20:13.365] Found private validator module=main path=/root/.gaiad/config/priv_validator.json - I[03-30|11:20:13.365] Found genesis file module=main path=/root/.gaiad/config/genesis.json - Secret phrase to access coins: - citizen hungry tennis noise park hire glory exercise link glow dolphin labor design grit apple abandon - -This tell us we have a ``priv_validator.json`` and ``genesis.json`` in the ``~/.gaiad/config`` directory. A ``config.toml`` was also created in the same directory. It is a good idea to get familiar with those files. Write down the seed. - -The next thing we'll need to is add the key from ``priv_validator.json`` to the ``gaiacli`` key manager. For this we need a seed and a password: - -:: - - gaiacli keys add alice --recover - -which will give you three prompts: - -:: - - Enter a passphrase for your key: - Repeat the passphrase: - Enter your recovery seed phrase: - -create a password and copy in your seed phrase. The name and address of the key will be output: - -:: - NAME: ADDRESS: PUBKEY: - alice 67997DD03D527EB439B7193F2B813B05B219CC02 1624DE6220BB89786C1D597050438C728202436552C6226AB67453CDB2A4D2703402FB52B6 - -You can see all available keys with: - -:: - - gaiacli keys list - -Setup Testnet -------------- - -Next, we start the daemon (do this in another window): - -:: - - gaiad start - -and you'll see blocks start streaming through. - -For this example, we're doing the above on a cloud machine. The next steps should be done on your local machine or another server in the cloud, which will join the running testnet then bond/unbond. - -Accounts --------- - -We have: - -- ``alice`` the initial validator (in the cloud) -- ``bob`` receives tokens from ``alice`` then declares candidacy (from local machine) -- ``charlie`` will bond and unbond to ``bob`` (from local machine) - -Remember that ``alice`` was already created. On your second machine, install the binaries and create two new keys: - -:: - - gaiacli keys add bob - gaiacli keys add charlie - -both of which will prompt you for a password. Now we need to copy the ``genesis.json`` and ``config.toml`` from the first machine (with ``alice``) to the second machine. This is a good time to look at both these files. - -The ``genesis.json`` should look something like: - -:: - - { - "app_state": { - "accounts": [ - { - "address": "1D9B2356CAADF46D3EE3488E3CCE3028B4283DEE", - "coins": [ - { - "denom": "steak", - "amount": 100000 - } - ] - } - ], - "stake": { - "pool": { - "total_supply": 0, - "bonded_shares": { - "num": 0, - "denom": 1 - }, - "unbonded_shares": { - "num": 0, - "denom": 1 - }, - "bonded_pool": 0, - "unbonded_pool": 0, - "inflation_last_time": 0, - "inflation": { - "num": 7, - "denom": 100 - } - }, - "params": { - "inflation_rate_change": { - "num": 13, - "denom": 100 - }, - "inflation_max": { - "num": 20, - "denom": 100 - }, - "inflation_min": { - "num": 7, - "denom": 100 - }, - "goal_bonded": { - "num": 67, - "denom": 100 - }, - "max_validators": 100, - "bond_denom": "steak" - } - } - }, - "validators": [ - { - "pub_key": { - "type": "AC26791624DE60", - "value": "rgpc/ctVld6RpSfwN5yxGBF17R1PwMTdhQ9gKVUZp5g=" - }, - "power": 10, - "name": "" - } - ], - "app_hash": "", - "genesis_time": "0001-01-01T00:00:00Z", - "chain_id": "test-chain-Uv1EVU" - } - - -To notice is that the ``accounts`` field has a an address and a whole bunch of "mycoin". This is ``alice``'s address (todo: dbl check). Under ``validators`` we see the ``pub_key.data`` field, which will match the same field in the ``priv_validator.json`` file. - -The ``config.toml`` is long so let's focus on one field: - -:: - - # Comma separated list of seed nodes to connect to - seeds = "" - -On the ``alice`` cloud machine, we don't need to do anything here. Instead, we need its IP address. After copying this file (and the ``genesis.json`` to your local machine, you'll want to put the IP in the ``seeds = "138.197.161.74"`` field, in this case, we have a made-up IP. For joining testnets with many nodes, you can add more comma-seperated IPs to the list. - - -Now that your files are all setup, it's time to join the network. On your local machine, run: - -:: - - gaiad start - -and your new node will connect to the running validator (``alice``). - -Sending Tokens --------------- - -We'll have ``alice`` send some ``mycoin`` to ``bob``, who has now joined the network: - -:: - - gaiacli send --amount=1000mycoin --sequence=0 --name=alice --to=5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 --chain-id=test-chain-Uv1EVU - -where the ``--sequence`` flag is to be incremented for each transaction, the ``--name`` flag is the sender (alice), and the ``--to`` flag takes ``bob``'s address. You'll see something like: - -:: - - Please enter passphrase for alice: - { - "check_tx": { - "gas": 30 - }, - "deliver_tx": { - "tags": [ - { - "key": "height", - "value_type": 1, - "value_int": 2963 - }, - { - "key": "coin.sender", - "value_string": "5D93A6059B6592833CBC8FA3DA90EE0382198985" - }, - { - "key": "coin.receiver", - "value_string": "5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6" - } - ] - }, - "hash": "423BD7EA3C4B36AF8AFCCA381C0771F8A698BA77", - "height": 2963 - } - -TODO: check the above with current actual output. - -Check out ``bob``'s account, which should now have 1000 mycoin: - -:: - - gaiacli account 5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6 - -Adding a Second Validator -------------------------- - -**This section is wrong/needs to be updated** - -Next, let's add the second node as a validator. - -First, we need the pub_key data: - -** need to make bob a priv_Val above? - -:: - - cat $HOME/.gaia2/priv_validator.json - -the first part will look like: - -:: - - {"address":"7B78527942C831E16907F10C3263D5ED933F7E99","pub_key":{"type":"ed25519","data":"96864CE7085B2E342B0F96F2E92B54B18C6CC700186238810D5AA7DFDAFDD3B2"}, - -and you want the ``pub_key`` ``data`` that starts with ``96864CE``. - -Now ``bob`` can create a validator with that pubkey. - -:: - - gaiacli stake create-validator --amount=10mycoin --name=bob --address-validator=
--pub-key= --moniker=bobby - -with an output like: - -:: - - Please enter passphrase for bob: - { - "check_tx": { - "gas": 30 - }, - "deliver_tx": {}, - "hash": "2A2A61FFBA1D7A59138E0068C82CC830E5103799", - "height": 4075 - } - - -We should see ``bob``'s account balance decrease by 10 mycoin: - -:: - - gaiacli account 5D93A6059B6592833CBC8FA3DA90EE0382198985 - -To confirm for certain the new validator is active, ask the tendermint node: - -:: - - curl localhost:26657/validators - -If you now kill either node, blocks will stop streaming in, because -there aren't enough validators online. Turn it back on and they will -start streaming again. - -Now that ``bob`` has declared candidacy, which essentially bonded 10 mycoin and made him a validator, we're going to get ``charlie`` to delegate some coins to ``bob``. - -Delegating ----------- - -First let's have ``alice`` send some coins to ``charlie``: - -:: - - gaiacli send --amount=1000mycoin --sequence=2 --name=alice --to=48F74F48281C89E5E4BE9092F735EA519768E8EF - -Then ``charlie`` will delegate some mycoin to ``bob``: - -:: - - gaiacli stake delegate --amount=10mycoin --address-delegator= --address-validator= --name=charlie - -You'll see output like: - -:: - - Please enter passphrase for charlie: - { - "check_tx": { - "gas": 30 - }, - "deliver_tx": {}, - "hash": "C3443BA30FCCC1F6E3A3D6AAAEE885244F8554F0", - "height": 51585 - } - -And that's it. You can query ``charlie``'s account to see the decrease in mycoin. - -To get more information about the candidate, try: - -:: - - gaiacli stake validator
- -and you'll see output similar to: - -:: - - { - "height": 51899, - "data": { - "pub_key": { - "type": "ed25519", - "data": "52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B" - }, - "owner": { - "chain": "", - "app": "sigs", - "addr": "5A35E4CC7B7DC0A5CB49CEA91763213A9AE92AD6" - }, - "shares": 20, - "voting_power": 20, - "description": { - "moniker": "bobby", - "identity": "", - "website": "", - "details": "" - } - } - } - -It's also possible the query the delegator's bond like so: - -:: - - gaiacli stake delegation --address-delegator=
--address-validator=
- -with an output similar to: - -:: - - { - "height": 325782, - "data": { - "PubKey": { - "type": "ed25519", - "data": "52D6FCD8C92A97F7CCB01205ADF310A18411EA8FDCC10E65BF2FCDB05AD1689B" - }, - "Shares": 20 - } - } - - -where the ``--address-delegator`` is ``charlie``'s address and the ``--address-validator`` is ``bob``'s address. - - -Unbonding ---------- - -Finally, to relinquish your voting power, unbond some coins. You should see -your VotingPower reduce and your account balance increase. - -:: - - gaiacli stake unbond --amount=5mycoin --name=charlie --address-delegator=
--address-validator=
- gaiacli account 48F74F48281C89E5E4BE9092F735EA519768E8EF - -See the bond decrease with ``gaiacli stake delegation`` like above. diff --git a/docs/guides/staking/overview.md b/docs/guides/staking/overview.md deleted file mode 100644 index 79033fe1e..000000000 --- a/docs/guides/staking/overview.md +++ /dev/null @@ -1,216 +0,0 @@ -//TODO update .rst - -# Staking Module - -## Overview - -The Cosmos Hub is a Tendermint-based Delegated Proof of Stake (DPos) blockchain -system that serves as a backbone of the Cosmos ecosystem. It is operated and -secured by an open and globally decentralized set of validators. Tendermint is -a Byzantine fault-tolerant distributed protocol for consensus among distrusting -parties, in this case the group of validators which produce the blocks for the -Cosmos Hub. To avoid the nothing-at-stake problem, a validator in Tendermint -needs to lock up coins in a bond deposit. Each bond's atoms are illiquid, they -cannot be transferred - in order to become liquid, they must be unbonded, a -process which will take 3 weeks by default at Cosmos Hub launch. Tendermint -protocol messages are signed by the validator's private key and are therefor -attributable. Validators acting outside protocol specifications can be made -accountable through punishing by slashing (burning) their bonded Atoms. On the -other hand, validators are rewarded for their service of securing blockchain -network by the inflationary provisions and transactions fees. This incentivizes -correct behavior of the validators and provides the economic security of the -network. - -The native token of the Cosmos Hub is called the Atom; becoming a validator of the -Cosmos Hub requires holding Atoms. However, not all Atom holders are validators -of the Cosmos Hub. More precisely, there is a selection process that determines -the validator set as a subset of all validators (Atom holders that -want to become a validator). The other option for Atom holders is to delegate -their atoms to validators, i.e., being a delegator. A delegator is an Atom -holder that has put its Atoms at stake by delegating it to a validator. By bonding -Atoms to secure the network (and taking a risk of being slashed in case of -misbehaviour), a user is rewarded with inflationary provisions and transaction -fees proportional to the amount of its bonded Atoms. The Cosmos Hub is -designed to efficiently facilitate a small numbers of validators (hundreds), -and large numbers of delegators (tens of thousands). More precisely, it is the -role of the Staking module of the Cosmos Hub to support various staking -functionality including validator set selection, delegating, bonding and -withdrawing Atoms, and the distribution of inflationary provisions and -transaction fees. - -## Basic Terms and Definitions - -* Cosmsos Hub - a Tendermint-based Delegated Proof of Stake (DPos) - blockchain system -* Atom - native token of the Cosmsos Hub -* Atom holder - an entity that holds some amount of Atoms -* Pool - Global object within the Cosmos Hub which accounts global state - including the total amount of bonded, unbonding, and unbonded atoms -* Validator Share - Share which a validator holds to represent its portion of - bonded, unbonding or unbonded atoms in the pool -* Delegation Share - Shares which a delegation bond holds to represent its - portion of bonded, unbonding or unbonded shares in a validator -* Bond Atoms - a process of locking Atoms in a delegation share which holds them - under protocol control. -* Slash Atoms - the process of burning atoms in the pool and assoiated - validator shares of a misbehaving validator, (not behaving according to the - protocol specification). This process devalues the worth of delegation shares - of the given validator -* Unbond Shares - Process of retrieving atoms from shares. If the shares are - bonded the shares must first remain in an inbetween unbonding state for the - duration of the unbonding period -* Redelegating Shares - Process of redelegating atoms from one validator to - another. This process is instantaneous, but the redelegated atoms are - retrospecively slashable if the old validator is found to misbehave for any - blocks before the redelegation. These atoms are simultaniously slashable - for any new blocks which the new validator misbehavess -* Validator - entity with atoms which is either actively validating the Tendermint - protocol (bonded validator) or vying to validate . -* Bonded Validator - a validator whose atoms are currently bonded and liable to - be slashed. These validators are to be able to sign protocol messages for - Tendermint consensus. At Cosmos Hub genesis there is a maximum of 100 - bonded validator positions. Only Bonded Validators receive atom provisions - and fee rewards. -* Delegator - an Atom holder that has bonded Atoms to a validator -* Unbonding period - time required in the unbonding state when unbonding - shares. Time slashable to old validator after a redelegation. Time for which - validators can be slashed after an infraction. To provide the requisite - cryptoeconomic security guarantees, all of these must be equal. -* Atom provisions - The process of increasing the Atom supply. Atoms are - periodically created on the Cosmos Hub and issued to bonded Atom holders. - The goal of inflation is to incentize most of the Atoms in existence to be - bonded. Atoms are distributed unbonded and using the fee_distribution mechanism -* Transaction fees - transaction fee is a fee that is included in a Cosmsos Hub - transaction. The fees are collected by the current validator set and - distributed among validators and delegators in proportion to their bonded - Atom share -* Commission fee - a fee taken from the transaction fees by a validator for - their service - -## The pool and the share - -At the core of the Staking module is the concept of a pool which denotes a -collection of Atoms contributed by different Atom holders. There are three -pools in the Staking module: the bonded, unbonding, and unbonded pool. Bonded -Atoms are part of the global bonded pool. If a validator or delegator wants to -unbond its shares, these Shares are moved to the the unbonding pool for the -duration of the unbonding period. From here normally Atoms will be moved -directly into the delegators wallet, however under the situation thatn an -entire validator gets unbonded, the Atoms of the delegations will remain with -the validator and moved to the unbonded pool. For each pool, the total amount -of bonded, unbonding, or unbonded Atoms are tracked as well as the current -amount of issued pool-shares, the specific holdings of these shares by -validators are tracked in protocol by the validator object. - -A share is a unit of Atom distribution and the value of the share -(share-to-atom exchange rate) can change during system execution. The -share-to-atom exchange rate can be computed as: - -`share-to-atom-exchange-rate = size of the pool / ammount of issued shares` - -Then for each validator (in a per validator data structure) the protocol keeps -track of the amount of shares the validator owns in a pool. At any point in -time, the exact amount of Atoms a validator has in the pool can be computed as -the number of shares it owns multiplied with the current share-to-atom exchange -rate: - -`validator-coins = validator.Shares * share-to-atom-exchange-rate` - -The benefit of such accounting of the pool resources is the fact that a -modification to the pool from bonding/unbonding/slashing of Atoms affects only -global data (size of the pool and the number of shares) and not the related -validator data structure, i.e., the data structure of other validators do not -need to be modified. This has the advantage that modifying global data is much -cheaper computationally than modifying data of every validator. Let's explain -this further with several small examples: - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -XXX TODO make way less verbose lets use bullet points to describe the example -XXX Also need to update to not include bonded atom provisions all atoms are -XXX redistributed with the fee pool now - -We consider initially 4 validators p1, p2, p3 and p4, and that each validator -has bonded 10 Atoms to the bonded pool. Furthermore, let's assume that we have -issued initially 40 shares (note that the initial distribution of the shares, -i.e., share-to-atom exchange rate can be set to any meaningful value), i.e., -share-to-atom-ex-rate = 1 atom per share. Then at the global pool level we -have, the size of the pool is 40 Atoms, and the amount of issued shares is -equal to 40. And for each validator we store in their corresponding data -structure that each has 10 shares of the bonded pool. Now lets assume that the -validator p4 starts process of unbonding of 5 shares. Then the total size of -the pool is decreased and now it will be 35 shares and the amount of Atoms is -35 . Note that the only change in other data structures needed is reducing the -number of shares for a validator p4 from 10 to 5. - -Let's consider now the case where a validator p1 wants to bond 15 more atoms to -the pool. Now the size of the pool is 50, and as the exchange rate hasn't -changed (1 share is still worth 1 Atom), we need to create more shares, i.e. we -now have 50 shares in the pool in total. Validators p2, p3 and p4 still have -(correspondingly) 10, 10 and 5 shares each worth of 1 atom per share, so we -don't need to modify anything in their corresponding data structures. But p1 -now has 25 shares, so we update the amount of shares owned by p1 in its -data structure. Note that apart from the size of the pool that is in Atoms, all -other data structures refer only to shares. - -Finally, let's consider what happens when new Atoms are created and added to -the pool due to inflation. Let's assume that the inflation rate is 10 percent -and that it is applied to the current state of the pool. This means that 5 -Atoms are created and added to the pool and that each validator now -proportionally increase it's Atom count. Let's analyse how this change is -reflected in the data structures. First, the size of the pool is increased and -is now 55 atoms. As a share of each validator in the pool hasn't changed, this -means that the total number of shares stay the same (50) and that the amount of -shares of each validator stays the same (correspondingly 25, 10, 10, 5). But -the exchange rate has changed and each share is now worth 55/50 Atoms per -share, so each validator has effectively increased amount of Atoms it has. So -validators now have (correspondingly) 55/2, 55/5, 55/5 and 55/10 Atoms. - -The concepts of the pool and its shares is at the core of the accounting in the -Staking module. It is used for managing the global pools (such as bonding and -unbonding pool), but also for distribution of Atoms between validator and its -delegators (we will explain this in section X). - -#### Delegator shares - -A validator is, depending on its status, contributing Atoms to either the -unbonding or unbonded pool - the validator in turn holds some amount of pool -shares. Not all of a validator's Atoms (and respective shares) are necessarily -owned by the validator, some may be owned by delegators to that validator. The -mechanism for distribution of Atoms (and shares) between a validator and its -delegators is based on a notion of delegator shares. More precisely, every -validator is issuing (local) delegator shares -(`Validator.IssuedDelegatorShares`) that represents some portion of global -shares managed by the validator (`Validator.GlobalStakeShares`). The principle -behind managing delegator shares is the same as described in [Section](#The -pool and the share). We now illustrate it with an example. - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -XXX TODO make way less verbose lets use bullet points to describe the example -XXX Also need to update to not include bonded atom provisions all atoms are -XXX redistributed with the fee pool now - -Let's consider 4 validators p1, p2, p3 and p4, and assume that each validator -has bonded 10 Atoms to the bonded pool. Furthermore, let's assume that we have -issued initially 40 global shares, i.e., that -`share-to-atom-exchange-rate = 1 atom per share`. So we will set -`GlobalState.BondedPool = 40` and `GlobalState.BondedShares = 40` and in the -Validator data structure of each validator `Validator.GlobalStakeShares = 10`. -Furthermore, each validator issued 10 delegator shares which are initially -owned by itself, i.e., `Validator.IssuedDelegatorShares = 10`, where -`delegator-share-to-global-share-ex-rate = 1 global share per delegator share`. -Now lets assume that a delegator d1 delegates 5 atoms to a validator p1 and -consider what are the updates we need to make to the data structures. First, -`GlobalState.BondedPool = 45` and `GlobalState.BondedShares = 45`. Then, for -validator p1 we have `Validator.GlobalStakeShares = 15`, but we also need to -issue also additional delegator shares, i.e., -`Validator.IssuedDelegatorShares = 15` as the delegator d1 now owns 5 delegator -shares of validator p1, where each delegator share is worth 1 global shares, -i.e, 1 Atom. Lets see now what happens after 5 new Atoms are created due to -inflation. In that case, we only need to update `GlobalState.BondedPool` which -is now equal to 50 Atoms as created Atoms are added to the bonded pool. Note -that the amount of global and delegator shares stay the same but they are now -worth more as share-to-atom-exchange-rate is now worth 50/45 Atoms per share. -Therefore, a delegator d1 now owns: - -`delegatorCoins = 5 (delegator shares) * 1 (delegator-share-to-global-share-ex-rate) * 50/45 (share-to-atom-ex-rate) = 5.55 Atoms` - diff --git a/docs/guides/staking/testnet.md b/docs/guides/staking/testnet.md deleted file mode 100644 index b2bbd8f1a..000000000 --- a/docs/guides/staking/testnet.md +++ /dev/null @@ -1,94 +0,0 @@ -# Testnet Setup - -**Note:** This document is incomplete and may not be up-to-date with the -state of the code. - -See the [installation guide](../sdk/install.html) for details on -installation. - -Here is a quick example to get you off your feet: - -First, generate a couple of genesis transactions to be incorporated into -the genesis file, this will create two keys with the password -`1234567890`: - -``` -gaiad init gen-tx --name=foo --home=$HOME/.gaiad1 -gaiad init gen-tx --name=bar --home=$HOME/.gaiad2 -gaiacli keys list -``` - -**Note:** If you've already run these tests you may need to overwrite -keys using the `--owk` flag When you list the keys you should see two -addresses, we'll need these later so take note. Now let's actually -create the genesis files for both nodes: - -``` -cp -a ~/.gaiad2/config/gentx/. ~/.gaiad1/config/gentx/ -cp -a ~/.gaiad1/config/gentx/. ~/.gaiad2/config/gentx/ -gaiad init --gen-txs --home=$HOME/.gaiad1 --chain-id=test-chain -gaiad init --gen-txs --home=$HOME/.gaiad2 --chain-id=test-chain -``` - -**Note:** If you've already run these tests you may need to overwrite -genesis using the `-o` flag. What we just did is copy the genesis -transactions between each of the nodes so there is a common genesis -transaction set; then we created both genesis files independently from -each home directory. Importantly both nodes have independently created -their `genesis.json` and `config.toml` files, which should be identical -between nodes. - -Great, now that we've initialized the chains, we can start both nodes in -the background: - -``` -gaiad start --home=$HOME/.gaiad1 &> gaia1.log & -NODE1_PID=$! -gaia start --home=$HOME/.gaiad2 &> gaia2.log & -NODE2_PID=$! -``` - -Note that we save the PID so we can later kill the processes. You can -peak at your logs with `tail gaia1.log`, or follow them for a bit with -`tail -f gaia1.log`. - -Nice. We can also lookup the validator set: - -``` -gaiacli validatorset -``` - -Then, we try to transfer some `steak` to another account: - -``` -gaiacli account -gaiacli account -gaiacli send --amount=10steak --to= --name=foo --chain-id=test-chain -``` - -**Note:** We need to be careful with the `chain-id` and `sequence` - -Check the balance & sequence with: - -``` -gaiacli account -``` - -To confirm for certain the new validator is active, check tendermint: - -``` -curl localhost:46657/validators -``` - -Finally, to relinquish all your power, unbond some coins. You should see -your VotingPower reduce and your account balance increase. - -``` -gaiacli unbond --chain-id= --name=test -``` - -That's it! - -**Note:** TODO demonstrate edit-candidacy **Note:** TODO demonstrate -delegation **Note:** TODO demonstrate unbond of delegation **Note:** -TODO demonstrate unbond candidate diff --git a/docs/guides/staking/testnet.rst b/docs/guides/staking/testnet.rst deleted file mode 100644 index 0e86a952d..000000000 --- a/docs/guides/staking/testnet.rst +++ /dev/null @@ -1,82 +0,0 @@ -Testnet Setup -============= - -**Note:** This document is incomplete and may not be up-to-date with the state of the code. - -See the `installation guide <../sdk/install.html>`__ for details on installation. - -Here is a quick example to get you off your feet: - -First, generate a couple of genesis transactions to be incorparated into the genesis file, this will create two keys with the password ``1234567890`` - -:: - - gaiad init gen-tx --name=foo --home=$HOME/.gaiad1 - gaiad init gen-tx --name=bar --home=$HOME/.gaiad2 - gaiacli keys list - -**Note:** If you've already run these tests you may need to overwrite keys using the ``--OWK`` flag -When you list the keys you should see two addresses, we'll need these later so take note. -Now let's actually create the genesis files for both nodes: - -:: - - cp -a ~/.gaiad2/config/gentx/. ~/.gaiad1/config/gentx/ - cp -a ~/.gaiad1/config/gentx/. ~/.gaiad2/config/gentx/ - gaiad init --gen-txs --home=$HOME/.gaiad1 --chain-id=test-chain - gaiad init --gen-txs --home=$HOME/.gaiad2 --chain-id=test-chain - -**Note:** If you've already run these tests you may need to overwrite genesis using the ``-o`` flag -What we just did is copy the genesis transactions between each of the nodes so there is a common genesis transaction set; then we created both genesis files independently from each home directory. Importantly both nodes have independently created their ``genesis.json`` and ``config.toml`` files, which should be identical between nodes. - -Great, now that we've initialized the chains, we can start both nodes in the background: - -:: - - gaiad start --home=$HOME/.gaiad1 &> gaia1.log & - NODE1_PID=$! - gaia start --home=$HOME/.gaiad2 &> gaia2.log & - NODE2_PID=$! - -Note that we save the PID so we can later kill the processes. You can peak at your logs with ``tail gaia1.log``, or follow them for a bit with ``tail -f gaia1.log``. - -Nice. We can also lookup the validator set: - -:: - - gaiacli advanced tendermint validator-set - -Then, we try to transfer some ``steak`` to another account: - -:: - - gaiacli account - gaiacli account - gaiacli send --amount=10steak --to= --name=foo --chain-id=test-chain - -**Note:** We need to be careful with the ``chain-id`` and ``sequence`` - -Check the balance & sequence with: - -:: - - gaiacli account - -To confirm for certain the new validator is active, check tendermint: - -:: - - curl localhost:26657/validators - -Finally, to relinquish all your power, unbond some coins. You should see your VotingPower reduce and your account balance increase. - -:: - - gaiacli stake unbond --chain-id= --name=test - -That's it! - -**Note:** TODO demonstrate edit-candidacy -**Note:** TODO demonstrate delegation -**Note:** TODO demonstrate unbond of delegation -**Note:** TODO demonstrate unbond candidate diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index 3a2237a3c..000000000 --- a/docs/index.rst +++ /dev/null @@ -1,60 +0,0 @@ -.. Cosmos-SDK documentation master file, created by - sphinx-quickstart on Fri Sep 1 21:37:02 2017. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to the Cosmos SDK! -========================== - -.. image:: graphics/cosmos-sdk-image.png - :height: 250px - :width: 500px - :align: center - -SDK ---- - -.. toctree:: - :maxdepth: 1 - - guides/sdk/install.md - guides/sdk/key-management.md - -.. sdk/overview.rst # needs to be updated -.. old/glossary.rst # not completely up to date but has good content - -.. Basecoin -.. -------- - -.. .. toctree:: - :maxdepth: 2 - -.. old/basecoin/basics.rst # has a decent getting-start tutorial that's relatively up to date, should be consolidated with the other getting started doc - -.. Extensions -.. ---------- - -.. old/basecoin/extensions.rst # probably not worth salvaging - -.. Replay Protection -.. ~~~~~~~~~~~~~~~~~ - -.. old/replay-protection.rst # not sure if worth salvaging - - -Staking -~~~~~~~ - -.. toctree:: - :maxdepth: 1 - - guides/staking/testnet.md -.. staking/intro.rst -.. staking/key-management.rst -.. staking/local-testnet.rst -.. staking/public-testnet.rst - -.. IBC -.. --- - -.. old/ibc.rst # needs to be updated diff --git a/docs/guides/sdk/install.md b/docs/install.md similarity index 100% rename from docs/guides/sdk/install.md rename to docs/install.md diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 916e57ee7..000000000 --- a/docs/make.bat +++ /dev/null @@ -1,36 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=python -msphinx -) -set SOURCEDIR=. -set BUILDDIR=_build -set SPHINXPROJ=Cosmos-SDK - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The Sphinx module was not found. Make sure you have Sphinx installed, - echo.then set the SPHINXBUILD environment variable to point to the full - echo.path of the 'sphinx-build' executable. Alternatively you may add the - echo.Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% - -:end -popd diff --git a/docs/guides/sdk/apps.md b/docs/overview/apps.md similarity index 100% rename from docs/guides/sdk/apps.md rename to docs/overview/apps.md diff --git a/docs/overview/capabilities.md b/docs/overview/capabilities.md new file mode 100644 index 000000000..ded5928a9 --- /dev/null +++ b/docs/overview/capabilities.md @@ -0,0 +1,118 @@ +Overview +======== + +The SDK design 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. + +Framework Overview +------------------ + +### Object-Capability Model + +When thinking about security, it's good to start with a specific threat +model. Our threat model is the following: + + We assume that a thriving ecosystem of Cosmos-SDK modules that are easy to compose into a blockchain application will contain faulty or malicious modules. + +The Cosmos-SDK is designed to address this threat by being the +foundation of an object capability system. + + The structural properties of object capability systems favor + modularity in code design and ensure reliable encapsulation in + code implementation. + + These structural properties facilitate the analysis of some + security properties of an object-capability program or operating + system. Some of these — in particular, information flow properties + — can be analyzed at the level of object references and + connectivity, independent of any knowledge or analysis of the code + that determines the behavior of the objects. As a consequence, + these security properties can be established and maintained in the + presence of new objects that contain unknown and possibly + malicious code. + + These structural properties stem from the two rules governing + access to existing objects: + + 1) An object A can send a message to B only if object A holds a + reference to B. + + 2) An object A can obtain a reference to C only + if object A receives a message containing a reference to C. As a + consequence of these two rules, an object can obtain a reference + to another object only through a preexisting chain of references. + In short, "Only connectivity begets connectivity." + +See the [wikipedia +article](https://en.wikipedia.org/wiki/Object-capability_model) for more +information. + +Strictly speaking, Golang does not implement object capabilities +completely, because of several issues: + +- pervasive ability to import primitive modules (e.g. "unsafe", "os") +- pervasive ability to override module vars + +- data-race vulnerability where 2+ goroutines can create illegal + interface values + +The first is easy to catch by auditing imports and using a proper +dependency version control system like Dep. The second and third are +unfortunate but it can be audited with some cost. + +Perhaps [Go2 will implement the object capability +model](https://github.com/golang/go/issues/23157). + +#### What does it look like? + +Only reveal what is necessary to get the work done. + +For example, the following code snippet violates the object capabilities +principle: + + type AppAccount struct {...} + var account := &AppAccount{ + Address: pub.Address(), + Coins: sdk.Coins{{"ATM", 100}}, + } + var sumValue := externalModule.ComputeSumValue(account) + +The method "ComputeSumValue" implies a pure function, yet the implied +capability of accepting a pointer value is the capability to modify that +value. The preferred method signature should take a copy instead. + + var sumValue := externalModule.ComputeSumValue(*account) + +In the Cosmos SDK, you can see the application of this principle in the +basecoin examples folder. + + // File: cosmos-sdk/examples/basecoin/app/init_handlers.go + package app + + import ( + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/sketchy" + ) + + func (app *BasecoinApp) initRouterHandlers() { + + // All handlers must be added here. + // The order matters. + app.router.AddRoute("bank", bank.NewHandler(app.accountMapper)) + app.router.AddRoute("sketchy", sketchy.NewHandler()) + } + +In the Basecoin example, the sketchy handler isn't provided an account +mapper, which does provide the bank handler with the capability (in +conjunction with the context of a transaction run). + +### Capabilities systems + +TODO: + +- Need for module isolation +- Capability is implied permission +- Link to thesis + diff --git a/docs/overview/overview.md b/docs/overview/overview.md new file mode 100644 index 000000000..9da8c233b --- /dev/null +++ b/docs/overview/overview.md @@ -0,0 +1,34 @@ +# 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. + +We envision the SDK as the `npm`-like framework to build secure blockchain applications on top of Tendermint. + +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 +privelege](https://en.wikipedia.org/wiki/Principle_of_least_privilege). + +For an introduction to object-capabilities, see this [article](http://habitatchronicles.com/2017/05/what-are-capabilities/). + +## Languages + +The Cosmos-SDK is currently writen in [Golang](https://golang.org/), though the +framework could be implemented similarly in other languages. +Contact us for information about funding an implementation in another language. + +## Directory Structure + +The SDK is laid out in the following directories: + +- `baseapp`: Defines the template for a basic [ABCI](https://cosmos.network/whitepaper#abci) application so that your Cosmos-SDK application can communicate with the underlying Tendermint node. +- `client`: CLI and REST server tooling for interacting with SDK application. +- `examples`: Examples of how to build working standalone applications. +- `server`: The full node server for running an SDK application on top of + Tendermint. +- `store`: The database of the SDK - a Merkle multistore supporting multiple types of underling Merkle key-value stores. +- `types`: Common types in SDK applications. +- `x`: Extensions to the core, where all messages and handlers are defined. diff --git a/docs/spec/README.md b/docs/spec/README.md index 4b58baf9e..0b708aba2 100644 --- a/docs/spec/README.md +++ b/docs/spec/README.md @@ -1,20 +1,27 @@ # Cosmos Hub Spec -This directory contains specifications for the application level components of -the Cosmos Hub. +This directory contains specifications for the state transition machine of the +Cosmos Hub. -NOTE: the specifications are not yet complete and very much a work in progress. +The Cosmos Hub holds all of its state in a Merkle store. Updates to +the store may be made during transactions and at the beginning and end of every +block. + +While the first implementation of the Cosmos Hub is built using the Cosmos-SDK, +these specifications aim to be independent of any implementation details. That +said, they provide a detailed resource for understanding the Cosmos-SDK. - [Store](store) - The core Merkle store that holds the state. -- [Auth](auth) - The structure and authnentication of accounts and transactions. +- [Auth](auth) - The structure and authentication of accounts and transactions. - [Bank](bank) - Sending tokens. - [Governance](governance) - Proposals and voting. -- [IBC](ibc) - Inter-Blockchain Communication (IBC) protocol. - [Staking](staking) - Proof-of-stake bonding, delegation, etc. - [Slashing](slashing) - Validator punishment mechanisms. - [Provisioning](provisioning) - Fee distribution, and atom provision distribution +- [IBC](ibc) - Inter-Blockchain Communication (IBC) protocol. - [Other](other) - Other components of the Cosmos Hub, including the reserve pool, All in Bits vesting, etc. -The [specification for Tendermint](https://github.com/tendermint/tendermint/tree/develop/docs/specification/new-spec), -i.e. the underlying blockchain, can be found elsewhere. +For details on the underlying blockchain and p2p protocols, see +the [Tendermint specification](https://github.com/tendermint/tendermint/tree/develop/docs/spec). + diff --git a/examples/examples.md b/examples/README.md similarity index 100% rename from examples/examples.md rename to examples/README.md