deprecate /docs/guides/sdk

This commit is contained in:
Ethan Buchman 2018-06-16 20:25:56 -07:00
parent a051091219
commit 7f603c8d57
7 changed files with 8 additions and 1800 deletions

View File

@ -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

View File

@ -0,0 +1,3 @@
DEPRECATED
See the [docs](/docs/sdk)

View File

@ -1,70 +1,2 @@
# Apps in the SDK
[Moved](/docs/sdk/overview/apps.md)
The SDK has multiple levels of "application": the ABCI app, the BaseApp, the BasecoinApp, and now your App.
## ABCI App
The basic ABCI interface allowing Tendermint to drive the applications state machine with transaction blocks.
## BaseApp
Implements an ABCI App using a MultiStore for persistence and a Router to handle transactions.
The goal is to provide a secure interface between the store and the extensible state machine
while defining as little about that state machine as possible (staying true to the ABCI).
BaseApp requires stores to be mounted via capabilities keys - handlers can only access
stores they're given the key for. The BaseApp ensures all stores are properly loaded, cached, and committed.
One mounted store is considered the "main" - it holds the latest block header, from which we can find and load the
most recent state ([TODO](https://github.com/cosmos/cosmos-sdk/issues/522)).
BaseApp distinguishes between two handler types - the `AnteHandler` and the `MsgHandler`.
The former is a global validity check (checking nonces, sigs and sufficient balances to pay fees,
e.g. things that apply to all transaction from all modules), the later is the full state transition function.
During CheckTx the state transition function is only applied to the checkTxState and should return
before any expensive state transitions are run (this is up to each developer). It also needs to return the estimated
gas cost.
During DeliverTx the state transition function is applied to the blockchain state and the transactions
need to be fully executed.
BaseApp is responsible for managing the context passed into handlers -
it makes the block header available and provides the right stores for CheckTx and DeliverTx.
BaseApp is completely agnostic to serialization formats.
## Basecoin
Basecoin is the first complete application in the stack.
Complete applications require extensions to the core modules of the SDK to actually implement handler functionality.
The native extensions of the SDK, useful for building Cosmos Zones, live under `x`.
Basecoin implements a `BaseApp` state machine using the `x/auth` and `x/bank` extensions,
which define how transaction signers are authenticated and how coins are transferred.
It should also use `x/ibc` and probably a simple staking extension.
Basecoin and the native `x` extensions use go-amino for all serialization needs,
including for transactions and accounts.
## Your Cosmos App
Your Cosmos App is a fork of Basecoin - copy the `examples/basecoin` directory and modify it to your needs.
You might want to:
- add fields to accounts
- copy and modify handlers
- add new handlers for new transaction types
- add new stores for better isolation across handlers
The Cosmos Hub takes Basecoin and adds more stores and extensions to handle additional
transaction types and logic, like the advanced staking logic and the governance process.
## Ethermint
Ethermint is a new implementation of `BaseApp` that does not depend on Basecoin.
Instead of `cosmos-sdk/x/` it has its own `ethermint/x` based on `go-ethereum`.
Ethermint uses a Patricia store for its accounts, and an IAVL store for IBC.
It has `x/ante`, which is quite similar to Basecoin's but uses RLP instead of go-amino.
Instead of `x/bank`, it has `x/eth`, which defines the single Ethereum transaction type
and all the semantics of the Ethereum state machine.
Within `x/eth`, transactions sent to particular addresses can be handled in unique ways,
for instance to handle IBC and staking.

View File

@ -1,59 +1 @@
# Install
The fastest and easiest way to install the Cosmos SDK binaries
is to run [this script](https://github.com/cosmos/cosmos-sdk/blob/develop/scripts/install_sdk_ubuntu.sh) on a fresh Ubuntu instance. Similarly, you can run [this script](https://github.com/cosmos/cosmos-sdk/blob/develop/scripts/install_sdk_bsd.sh) on a fresh FreeBSD instance. Read the scripts before running them to ensure no untrusted connection is being made, for example we're making curl requests to download golang. Also read the comments / instructions carefully (i.e., reset your terminal after running the script).
Cosmos SDK can be installed to
`$GOPATH/src/github.com/cosmos/cosmos-sdk` like a normal Go program:
```
go get github.com/cosmos/cosmos-sdk
```
If the dependencies have been updated with breaking changes, or if
another branch is required, `dep` is used for dependency management.
Thus, assuming you've already run `go get` or otherwise cloned the repo,
the correct way to install is:
```
cd $GOPATH/src/github.com/cosmos/cosmos-sdk
make get_tools
make get_vendor_deps
make install
make install_examples
```
This will install `gaiad` and `gaiacli` and four example binaries:
`basecoind`, `basecli`, `democoind`, and `democli`.
Verify that everything is OK by running:
```
gaiad version
```
you should see:
```
0.17.3-a5a78eb
```
then with:
```
gaiacli version
```
you should see the same version (or a later one for both).
## Update
Get latest code (you can also `git fetch` only the version desired),
ensure the dependencies are up to date, then recompile.
```
cd $GOPATH/src/github.com/cosmos/cosmos-sdk
git fetch -a origin
git checkout VERSION
make get_vendor_deps
make install
```
[Moved](/docs/sdk/install.md)

View File

@ -1,7 +1 @@
# Key Management
Here we cover many aspects of handling keys within the Cosmos SDK
framework.
// TODO add relevant key discussion
(related https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/encoding.md#public-key-cryptography)
[Moved](/docs/sdk/clients/key-management.md)

View File

@ -1,781 +1 @@
swagger: '2.0'
info:
version: '1.1.0'
title: Light client daemon to interface with Cosmos baseserver via REST
description: Specification for the LCD provided by `gaiacli advanced rest-server`
securityDefinitions:
kms:
type: basic
paths:
/version:
get:
summary: Version of the light client daemon
description: Get the version of the LCD running locally to compare against expected
responses:
200:
description: Plaintext version i.e. "v0.5.0"
/node_version:
get:
summary: Version of the connected node
description: Get the version of the SDK running on the connected node to compare against expected
responses:
200:
description: Plaintext version i.e. "v0.5.0"
/node_info:
get:
description: Only the node info. Block information can be queried via /block/latest
summary: The propertied of the connected node
produces:
- application/json
responses:
200:
description: Node status
schema:
type: object
properties:
pub_key:
$ref: '#/definitions/PubKey'
moniker:
type: string
example: 159.89.198.221
network:
type: string
example: gaia-2
remote_addr:
type: string
listen_addr:
type: string
example: 192.168.56.1:26656
version:
description: Tendermint version
type: string
example: 0.15.0
other:
description: more information on versions
type: array
items:
type: string
/syncing:
get:
summary: Syncing state of node
description: Get if the node is currently syning with other nodes
responses:
200:
description: '"true" or "false"'
/keys:
get:
summary: List of accounts stored locally
produces:
- application/json
responses:
200:
description: Array of accounts
schema:
type: array
items:
$ref: '#/definitions/Account'
post:
summary: Create a new account locally
consumes:
- application/json
parameters:
- in: body
name: account
description: The account to create
schema:
type: object
required:
- name
- password
- seed
properties:
name:
type: string
password:
type: string
seed:
type: string
responses:
200:
description: Returns address of the account created
/keys/seed:
get:
summary: Create a new seed to create a new account with
produces:
- application/json
responses:
200:
description: 16 word Seed
schema:
type: string
/keys/{name}:
parameters:
- in: path
name: name
description: Account name
required: true
type: string
get:
summary: Get a certain locally stored account
produces:
- application/json
responses:
200:
description: Locally stored account
schema:
$ref: "#/definitions/Account"
404:
description: Account is not available
put:
summary: Update the password for this account in the KMS
consumes:
- application/json
parameters:
- in: body
name: account
description: The new and old password
schema:
type: object
required:
- new_password
- old_password
properties:
new_password:
type: string
old_password:
type: string
responses:
200:
description: Updated password
401:
description: Password is wrong
404:
description: Account is not available
delete:
summary: Remove an account
consumes:
- application/json
parameters:
- in: body
name: account
description: The password of the account to remove from the KMS
schema:
type: object
required:
- password
properties:
password:
type: string
responses:
200:
description: Removed account
401:
description: Password is wrong
404:
description: Account is not available
# /accounts/send:
# post:
# summary: Send coins (build -> sign -> send)
# security:
# - sign: []
# requestBody:
# content:
# application/json:
# schema:
# type: object
# properties:
# fees:
# $ref: "#/definitions/Coins"
# outputs:
# type: array
# items:
# type: object
# properties:
# pub_key:
# $ref: "#/definitions/PubKey"
# amount:
# type: array
# items:
# $ref: "#/definitions/Coins"
# responses:
# 202:
# description: Tx was send and will probably be added to the next block
# 400:
# description: The Tx was malformated
/accounts/{address}:
parameters:
- in: path
name: address
description: Account address in bech32 format
required: true
type: string
get:
summary: Get the account balances
produces:
- application/json
responses:
200:
description: Account balances
schema:
$ref: "#/definitions/Balance"
204:
description: There is no data for the requested account. This is not a 404 as the account might exist, just does not hold data.
/accounts/{address}/send:
parameters:
- in: path
name: address
description: Account address in bech32 format
required: true
type: string
post:
summary: Send coins (build -> sign -> send)
security:
- kms: []
consumes:
- application/json
parameters:
- in: body
name: account
description: The password of the account to remove from the KMS
schema:
type: object
properties:
name:
type: string
password:
type: string
amount:
type: array
items:
$ref: "#/definitions/Coins"
chain_id:
type: string
squence:
type: number
responses:
202:
description: Tx was send and will probably be added to the next block
400:
description: The Tx was malformated
/blocks/latest:
get:
summary: Get the latest block
produces:
- application/json
responses:
200:
description: The latest block
schema:
$ref: "#/definitions/Block"
/blocks/{height}:
parameters:
- in: path
name: height
description: Block height
required: true
type: number
get:
summary: Get a block at a certain height
produces:
- application/json
responses:
200:
description: The block at a specific height
schema:
$ref: "#/definitions/Block"
404:
description: Block at height is not available
/validatorsets/latest:
get:
summary: Get the latest validator set
produces:
- application/json
responses:
200:
description: The validator set at the latest block height
schema:
type: object
properties:
block_height:
type: number
validators:
type: array
items:
$ref: "#/definitions/Validator"
/validatorsets/{height}:
parameters:
- in: path
name: height
description: Block height
required: true
type: number
get:
summary: Get a validator set a certain height
produces:
- application/json
responses:
200:
description: The validator set at a specific block height
schema:
type: object
properties:
block_height:
type: number
validators:
type: array
items:
$ref: "#/definitions/Validator"
404:
description: Block at height not available
# /txs:
# parameters:
# - in: query
# name: tag
# schema:
# type: string
# example: "coin.sender=EE5F3404034C524501629B56E0DDC38FAD651F04"
# required: true
# - in: query
# name: page
# description: Pagination page
# schema:
# type: number
# default: 0
# - in: query
# name: size
# description: Pagination size
# schema:
# type: number
# default: 50
# get:
# summary: Query Tx
# responses:
# 200:
# description: All Tx matching the provided tags
# content:
# application/json:
# schema:
# type: array
# items:
# $ref: "#/definitions/Tx"
# 404:
# description: Pagination is out of bounds
# /txs/sign:
# post:
# summary: Sign a Tx
# description: Sign a Tx providing locally stored account and according password
# security:
# - sign: []
# requestBody:
# content:
# application/json:
# schema:
# $ref: "#/definitions/TxBuild"
# responses:
# 200:
# description: The signed Tx
# content:
# application/json:
# schema:
# $ref: "#/definitions/TxSigned"
# 401:
# description: Account name and/or password where wrong
# /txs/broadcast:
# post:
# summary: Send signed Tx
# requestBody:
# content:
# application/json:
# schema:
# $ref: "#/definitions/TxSigned"
# responses:
# 202:
# description: Tx was send and will probably be added to the next block
# 400:
# description: The Tx was malformated
/txs/{hash}:
parameters:
- in: path
name: hash
description: Tx hash
required: true
type: string
get:
summary: Get a Tx by hash
produces:
- application/json
responses:
200:
description: Tx with the provided hash
schema:
$ref: "#/definitions/Tx"
404:
description: Tx not available for provided hash
# /delegates:
# parameters:
# - in: query
# name: delegator
# description: Query for all delegates a delegator has stake with
# schema:
# $ref: "#/definitions/Address"
# get:
# summary: Get a list of canidates/delegates/validators (optionally filtered by delegator)
# responses:
# 200:
# description: List of delegates, filtered by provided delegator address
# content:
# application/json:
# schema:
# type: array
# items:
# $ref: "#/definitions/Delegate"
# /delegates/bond:
# post:
# summary: Bond atoms (build -> sign -> send)
# security:
# - sign: []
# requestBody:
# content:
# application/json:
# schema:
# type: array
# items:
# type: object
# properties:
# amount:
# $ref: "#/definitions/Coins"
# pub_key:
# $ref: "#/definitions/PubKey"
# responses:
# 202:
# description: Tx was send and will probably be added to the next block
# 400:
# description: The Tx was malformated
# /delegates/unbond:
# post:
# summary: Unbond atoms (build -> sign -> send)
# security:
# - sign: []
# requestBody:
# content:
# application/json:
# schema:
# type: array
# items:
# type: object
# properties:
# amount:
# $ref: "#/definitions/Coins"
# pub_key:
# $ref: "#/definitions/PubKey"
# responses:
# 202:
# description: Tx was send and will probably be added to the next block
# 400:
# description: The Tx was malformated
# /delegates/{pubkey}:
# parameters:
# - in: path
# name: pubkey
# description: Pubkey of a delegate
# required: true
# schema:
# type: string
# example: 81B11E717789600CC192B26F452A983DF13B985EE75ABD9DD9E68D7BA007A958
# get:
# summary: Get a certain canidate/delegate/validator
# responses:
# 200:
# description: Delegate for specified pub_key
# content:
# application/json:
# schema:
# $ref: "#/definitions/Delegate"
# 404:
# description: No delegate found for provided pub_key
# /delegates/{pubkey}/bond:
# parameters:
# - in: path
# name: pubkey
# description: Pubkey of a delegate
# required: true
# schema:
# type: string
# example: 81B11E717789600CC192B26F452A983DF13B985EE75ABD9DD9E68D7BA007A958
# post:
# summary: Bond atoms (build -> sign -> send)
# security:
# - sign: []
# requestBody:
# content:
# application/json:
# schema:
# type: object
# properties:
# amount:
# $ref: "#/definitions/Coins"
# responses:
# 202:
# description: Tx was send and will probably be added to the next block
# 400:
# description: The Tx was malformated
# /delegates/{pubkey}/unbond:
# parameters:
# - in: path
# name: pubkey
# description: Pubkey of a delegate
# required: true
# schema:
# type: string
# example: 81B11E717789600CC192B26F452A983DF13B985EE75ABD9DD9E68D7BA007A958
# post:
# summary: Unbond atoms (build -> sign -> send)
# security:
# - sign: []
# requestBody:
# content:
# application/json:
# schema:
# type: object
# properties:
# amount:
# $ref: "#/definitions/Coins"
# responses:
# 202:
# description: Tx was send and will probably be added to the next block
# 400:
# description: The Tx was malformated
definitions:
Address:
type: string
description: bech32 encoded addres
example: cosmosaccaddr:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq
ValidatorAddress:
type: string
description: bech32 encoded addres
example: cosmosvaladdr:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq
PubKey:
type: string
description: bech32 encoded public key
example: cosmosaccpub:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq
ValidatorPubKey:
type: string
description: bech32 encoded public key
example: cosmosvalpub:zgnkwr7eyyv643dllwfpdwensmgdtz89yu73zq
Coins:
type: object
properties:
denom:
type: string
example: steak
amount:
type: number
example: 50
Hash:
type: string
example: EE5F3404034C524501629B56E0DDC38FAD651F04
Tx:
type: object
properties:
type:
type: string
enum:
- stake/delegate
data:
type: object
TxChain:
type: object
properties:
type:
type: string
default: chain/tx
data:
type: object
properties:
chain_id:
type: string
example: gaia-2
expires_at:
type: number
example: 0
tx:
type: object
properties:
type:
type: string
default: nonce
data:
type: object
properties:
sequence:
type: number
example: 0
signers:
type: array
items:
type: object
properties:
chain:
type: string
example: ''
app:
type: string
default: sigs
addr:
$ref: "#/definitions/Address"
tx:
$ref: "#/definitions/Tx"
TxBuild:
type: object
properties:
type:
type: string
default: sigs/one
data:
type: object
properties:
tx:
$ref: "#/definitions/Tx"
signature:
type: object
properties:
Sig:
type: string
default: ''
Pubkey:
type: string
default: ''
TxSigned:
type: object
properties:
type:
type: string
default: sigs/one
data:
type: object
properties:
tx:
$ref: "#/definitions/Tx"
signature:
type: object
properties:
Sig:
type: string
example: 81B11E717789600CC192B26F452A983DF13B985EE75ABD9DD9E68D7BA007A958
Pubkey:
$ref: "#/definitions/PubKey"
Account:
type: object
properties:
name:
type: string
example: Main Account
address:
$ref: "#/definitions/Address"
pub_key:
$ref: "#/definitions/PubKey"
Balance:
type: object
properties:
height:
type: number
example: 123456
coins:
type: array
items:
$ref: "#/definitions/Coins"
credit:
type: array
items:
type: object
BlockID:
type: object
properties:
hash:
$ref: "#/definitions/Hash"
parts:
type: object
properties:
total:
type: number
example: 0
hash:
$ref: "#/definitions/Hash"
Block:
type: object
properties:
header:
type: object
properties:
chain_id:
type: string
example: gaia-2
height:
type: number
example: 1
time:
type: string
example: '2017-12-30T05:53:09.287+01:00'
num_txs:
type: number
example: 0
last_block_id:
$ref: "#/definitions/BlockID"
total_txs:
type: number
example: 35
last_commit_hash:
$ref: "#/definitions/Hash"
data_hash:
$ref: "#/definitions/Hash"
validators_hash:
$ref: "#/definitions/Hash"
consensus_hash:
$ref: "#/definitions/Hash"
app_hash:
$ref: "#/definitions/Hash"
last_results_hash:
$ref: "#/definitions/Hash"
evidence_hash:
$ref: "#/definitions/Hash"
txs:
type: array
items:
$ref: "#/definitions/Tx"
evidence:
type: array
items:
type: object
last_commit:
type: object
properties:
blockID:
$ref: "#/definitions/BlockID"
precommits:
type: array
items:
type: object
Validator:
type: object
properties:
address:
$ref: '#/definitions/ValidatorAddress'
pub_key:
$ref: "#/definitions/ValidatorPubKey"
power:
type: number
example: 1000
accum:
type: number
example: 1000
# Added by API Auto Mocking Plugin
host: virtserver.swaggerhub.com
basePath: /faboweb1/Cosmos-LCD-2/1.0.0
schemes:
- https
[Moved](/docs/sdk/clients/lcd-rest-api.yaml)

View File

@ -1,420 +1 @@
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 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 <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).
Security Overview
-----------------
For examples, see the `examples <https://github.com/cosmos/cosmos-sdk/tree/develop/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 <https://github.com/tendermint/go-amino/tree/develop>`__.
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.
[Moved](/docs/sdk)