Fix guide docs

This commit is contained in:
Jae Kwon 2018-01-26 07:15:51 -08:00
parent b95b67d520
commit 2246a9c68b
5 changed files with 307 additions and 313 deletions

View File

@ -20,29 +20,32 @@ WARNING: the libraries are still undergoing breaking changes as we get better id
**Note: Requires Go 1.9+**
The Cosmos SDK is a platform for building multi-asset Proof-of-Stake cryptocurrencies,
like the [Cosmos Hub](https://cosmos.network). It is both a library for building applications
and a set of tools for securely interacting with them.
The Cosmos SDK is a platform for building multi-asset Proof-of-Stake
cryptocurrencies, like the [Cosmos Hub](https://cosmos.network). It is both a
library for building applications and a set of tools for securely interacting
with them.
The goals of the SDK are to abstract away the complexities of building a Tendermint ABCI application in Golang
and to provide a framework for building interoperable blockchain applications in the Cosmos Network.
The goals of the SDK are to abstract away the complexities of building a
Tendermint ABCI application in Golang and to provide a framework for building
interoperable blockchain applications in the Cosmos Network.
It is inspired by the routing and middleware model of many web application frameworks, and informed by years
of wrestling with blockchain state machines.
It is inspired by capabilities-based security, and informed by years of
wrestling with blockchain state machines.
The SDK is fast, safe, easy-to-use, and easy-to-reason-about.
It is generic enough to be used to implement the state machines of other existing blockchains,
like Bitcoin and Ethereum, allowing seamless integration with them and their data structures.
It comes with batteries included, is easily extensible, and does not require developers
to fork it to access any of its current or extended functionality.
The SDK is fast, safe, and easy-to-use. It is generic enough to be used to
implement the state machines of other existing blockchains, like Bitcoin and
Ethereum, allowing seamless integration with them and their data structures.
It comes with batteries included, is easily extensible, and does not require
developers to fork it to access any of its current or extended functionality.
It provides both REST and command line interfaces for secure user interactions.
Applications in the Cosmos-SDK are defined in terms of handlers that process messages
and read and write to a store. Handlers are given restricted capabilities that determine which
parts of the store they can access. The SDK provides common data structures for Accounts,
multi-asset Coins, checking signatures, preventing replay, and so on.
Applications in the Cosmos-SDK are defined in terms of handlers that process
messages and read and write to a store. Handlers are given restricted
capabilities that determine which parts of the store they can access. The SDK
provides common data structures for Accounts, multi-asset Coins, checking
signatures, preventing replay, and so on.
For more details on the design goals, see the [Design Document](docs/design.md)
For more details on the design goals, see the [SDK Guide](docs/guide.md)
## Prerequisites
@ -50,4 +53,4 @@ For more details on the design goals, see the [Design Document](docs/design.md)
## Getting Started
- See the [SDK Basics](docs/basics.md)
- See the [SDK Guide](docs/guide.md)

View File

@ -1,235 +0,0 @@
# SDK Basics
An SDK application consists primarily of a set of message types and set of handlers
that apply messages to an underlying data store.
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.
Here we explain the concepts of the SDK using Basecoin as an example.
## Transactions and Messages
The SDK distinguishes between transactions and messages.
A message is the core input data to the application.
A transaction is a message wrapped with authentication data,
like cryptographic signatures.
### Messages
Users can create messages containing arbitrary information by implementing the `Msg` interface:
```golang
type Msg interface {
// Return the message type.
// Must be alphanumeric or empty.
Type() string
// Get some property of the Msg.
Get(key interface{}) (value interface{})
// 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() []crypto.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.
Finally, messages can provide generic access to their contents via `Get(key)`,
but this is mostly for convenience and not type-safe.
For instance, the `Basecoin` message types are defined in `x/bank/tx.go`:
```golang
type SendMsg struct {
Inputs []Input `json:"inputs"`
Outputs []Output `json:"outputs"`
}
type IssueMsg struct {
Banker crypto.Address `json:"banker"`
Outputs []Output `json:"outputs"`
}
```
Each specifies the addresses that must sign the message:
```golang
func (msg SendMsg) GetSigners() []crypto.Address {
addrs := make([]crypto.Address, len(msg.Inputs))
for i, in := range msg.Inputs {
addrs[i] = in.Address
}
return addrs
}
func (msg IssueMsg) GetSigners() []crypto.Address {
return []crypto.Address{msg.Banker}
}
```
### Transactions
A transaction is a message with additional information for authentication:
```golang
type Tx interface {
Msg
// The address that pays the base fee for this message. The fee is
// deducted before the Msg is processed.
GetFeePayer() crypto.Address
// Get the canonical byte representation of the Tx.
// Includes any signatures (or empty slots).
GetTxBytes() []byte
// 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:
```golang
type StdSignature struct {
crypto.PubKey // optional
crypto.Signature
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.
Transactions can also specify the address responsible for paying the transaction's fees using the `tx.GetFeePayer()` method.
The standard way to create a transaction from a message is to use the `StdTx`:
```golang
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`:
```golang
type TxDecoder func(txBytes []byte) (Tx, error)
```
In `Basecoin`, we use the Tendermint wire format and the `go-wire` library for encoding and decoding all message types.
The `go-wire` 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:
```golang
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 determines the types 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-wire documentation]().
## Context
The SDK uses a `Context` to propogate common information across functions. The `Context` is modelled
off of 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.
## Handlers
Transaction processing in the SDK is defined through `Handler` functions:
```golang
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 store, a particular handler may only need
some subset of the store. Access to substores is managed using capabilities -
when a handler is initialized, it is passed capability keys that determine which parts of the
store it can access.
TODO: example
## Store
- 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.
## BaseApp
TODO

View File

@ -1,31 +0,0 @@
## Design philosphy
The design of the Cosmos SDK is based on the principles of "cababilities systems".
TODO If you see this on the sdk2 branch, it's because I'm still expanding this high-level section.
Sections:
* Introduction
- Note to skip to Basecoin example to dive into code.
* Capabilities systems
- Need for module isolation
- Capability is implied permission
- http://www.erights.org/elib/capability/ode/ode.pdf
* Tx & Msg
* MultiStore
- MultiStore is like a filesystem
- Mounting an IAVLStore
* Context & Handler
* AnteHandler
- Handling Fee payment
- Handling Authentication
* Accounts and x/auth
- sdk.Account
- auth.BaseAccount
- auth.AccountMapper
* Wire codec
- vs encoding/json
- vs protobuf
* Dummy example
* Basecoin example
* Conclusion

286
docs/guide.md Normal file
View File

@ -0,0 +1,286 @@
## 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 "cababilities 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 Msg wrapped with authentication and fee data.
### Messages
Users can create messages containing arbitrary information by
implementing the `Msg` interface:
```golang
type Msg interface {
// Return the message type.
// Must be alphanumeric or empty.
Type() string
// Get some property of the Msg.
Get(key interface{}) (value interface{})
// 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() []crypto.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.
Finally, messages can provide generic access to their contents
via `Get(key)`, but this is mostly for convenience and not
type-safe.
For instance, the `Basecoin` message types are defined in
`x/bank/tx.go`:
```golang
type SendMsg struct {
Inputs []Input `json:"inputs"`
Outputs []Output `json:"outputs"`
}
type IssueMsg struct {
Banker crypto.Address `json:"banker"`
Outputs []Output `json:"outputs"`
}
```
Each specifies the addresses that must sign the message:
```golang
func (msg SendMsg) GetSigners() []crypto.Address {
addrs := make([]crypto.Address, len(msg.Inputs))
for i, in := range msg.Inputs {
addrs[i] = in.Address
}
return addrs
}
func (msg IssueMsg) GetSigners() []crypto.Address {
return []crypto.Address{msg.Banker}
}
```
### Transactions
A transaction is a message with additional information for
authentication:
```golang
type Tx interface {
GetMsg() Msg
// The address that pays the base fee for this message. The fee is
// deducted before the Msg is processed.
GetFeePayer() crypto.Address
// Get the canonical byte representation of the Tx.
// Includes any signatures (or empty slots).
GetTxBytes() []byte
// 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:
```golang
type StdSignature struct {
crypto.PubKey // optional
crypto.Signature
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.
Transactions can also specify the address responsible for paying
the transaction's fees using the `tx.GetFeePayer()` method.
The standard way to create a transaction from a message is to use
the `StdTx`:
```golang
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`:
```golang
type TxDecoder func(txBytes []byte) (Tx, error)
```
In `Basecoin`, we use the Tendermint wire format and the
`go-wire` library for encoding and decoding all message types.
The `go-wire` 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:
```golang
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
determines the types 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-wire 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 off of 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:
```golang
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 store, a
particular handler may only need some subset of the store. Access
to substores is managed using capabilities - when a handler is
initialized, it is passed capability keys that determine which
parts of the store it can access.
## 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
## Dummy 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.
## Conclusion

View File

@ -1,29 +0,0 @@
TODO: write a blog post ...
# Inspiration
The basic concept for this SDK comes from years of web development. A number of
patterns have arisen in that realm of software which enable people to build remote
servers with APIs remarkably quickly and with high stability. The
[ABCI](https://github.com/tendermint/abci) application interface is similar to
a web API (`DeliverTx` is like POST and `Query` is like GET while `SetOption` is like
the admin playing with the config file). Here are some patterns that might be
useful:
* MVC - separate data model (storage) from business logic (controllers)
* Routers - easily direct each request to the appropriate controller
* Middleware - a series of wrappers that provide global functionality (like
authentication) to all controllers
* Modules (gems, package, etc) - developers can write a self-contained package
with a given set of functionality, which can be imported and reused in other
apps
Also at play is the concept of different tables/schemas in databases, thus you can
keep the different modules safely separated and avoid any accidental (or malicious)
overwriting of data.
Not all of these can be compare one-to-one in the blockchain world, but they do
provide inspiration for building orthogonal pieces that can easily be combined
into various applications.