diff --git a/README.md b/README.md index bf9caa790b..d0cd45ee43 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/docs/basics.md b/docs/basics.md deleted file mode 100644 index ec5dd82e71..0000000000 --- a/docs/basics.md +++ /dev/null @@ -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 diff --git a/docs/design.md b/docs/design.md deleted file mode 100644 index 55d0c8f943..0000000000 --- a/docs/design.md +++ /dev/null @@ -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 diff --git a/docs/guide.md b/docs/guide.md new file mode 100644 index 0000000000..74bfb9265e --- /dev/null +++ b/docs/guide.md @@ -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 diff --git a/docs/web-inspriation.md b/docs/web-inspriation.md deleted file mode 100644 index 2d1af12bea..0000000000 --- a/docs/web-inspriation.md +++ /dev/null @@ -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.