consolidate files into appX.md
This commit is contained in:
parent
b3b075cc12
commit
7566ac2a94
|
@ -1,101 +0,0 @@
|
||||||
# Accounts
|
|
||||||
|
|
||||||
### auth.Account
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Account is a standard account using a sequence number for replay protection
|
|
||||||
// and a pubkey for authentication.
|
|
||||||
type Account interface {
|
|
||||||
GetAddress() sdk.Address
|
|
||||||
SetAddress(sdk.Address) error // errors if already set.
|
|
||||||
|
|
||||||
GetPubKey() crypto.PubKey // can return nil.
|
|
||||||
SetPubKey(crypto.PubKey) error
|
|
||||||
|
|
||||||
GetAccountNumber() int64
|
|
||||||
SetAccountNumber(int64) error
|
|
||||||
|
|
||||||
GetSequence() int64
|
|
||||||
SetSequence(int64) error
|
|
||||||
|
|
||||||
GetCoins() sdk.Coins
|
|
||||||
SetCoins(sdk.Coins) error
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Accounts are the standard way for an application to keep track of addresses and their associated balances.
|
|
||||||
|
|
||||||
### auth.BaseAccount
|
|
||||||
|
|
||||||
```go
|
|
||||||
// BaseAccount - base account structure.
|
|
||||||
// Extend this by embedding this in your AppAccount.
|
|
||||||
// See the examples/basecoin/types/account.go for an example.
|
|
||||||
type BaseAccount struct {
|
|
||||||
Address sdk.Address `json:"address"`
|
|
||||||
Coins sdk.Coins `json:"coins"`
|
|
||||||
PubKey crypto.PubKey `json:"public_key"`
|
|
||||||
AccountNumber int64 `json:"account_number"`
|
|
||||||
Sequence int64 `json:"sequence"`
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `auth.BaseAccount` struct provides a standard implementation of the Account interface with replay protection.
|
|
||||||
BaseAccount can be extended by embedding it in your own Account struct.
|
|
||||||
|
|
||||||
### auth.AccountMapper
|
|
||||||
|
|
||||||
```go
|
|
||||||
// This AccountMapper encodes/decodes accounts using the
|
|
||||||
// go-amino (binary) encoding/decoding library.
|
|
||||||
type AccountMapper struct {
|
|
||||||
|
|
||||||
// The (unexposed) key used to access the store from the Context.
|
|
||||||
key sdk.StoreKey
|
|
||||||
|
|
||||||
// The prototypical Account concrete type.
|
|
||||||
proto Account
|
|
||||||
|
|
||||||
// The wire codec for binary encoding/decoding of accounts.
|
|
||||||
cdc *wire.Codec
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The AccountMapper is responsible for managing and storing the state of all accounts in the application.
|
|
||||||
|
|
||||||
Example Initialization:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// File: examples/basecoin/app/app.go
|
|
||||||
// Define the accountMapper.
|
|
||||||
app.accountMapper = auth.NewAccountMapper(
|
|
||||||
cdc,
|
|
||||||
app.keyAccount, // target store
|
|
||||||
&types.AppAccount{}, // prototype
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
The accountMapper allows you to retrieve the current account state by `GetAccount(ctx Context, addr auth.Address)` and change the state by
|
|
||||||
`SetAccount(ctx Context, acc Account)`.
|
|
||||||
|
|
||||||
Note: To update an account you will first have to get the account, update the appropriate fields with its associated setter method, and then call
|
|
||||||
`SetAccount(ctx Context, acc updatedAccount)`.
|
|
||||||
|
|
||||||
Updating accounts is made easier by using the `Keeper` struct in the `x/bank` module.
|
|
||||||
|
|
||||||
Example Initialization:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// File: examples/basecoin/app/app.go
|
|
||||||
app.coinKeeper = bank.NewKeeper(app.accountMapper)
|
|
||||||
```
|
|
||||||
|
|
||||||
Example Usage:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Finds account with addr in accountmapper
|
|
||||||
// Adds coins to account's coin array
|
|
||||||
// Sets updated account in accountmapper
|
|
||||||
app.coinKeeper.AddCoins(ctx, addr, coins)
|
|
||||||
```
|
|
||||||
|
|
|
@ -152,3 +152,105 @@ app.SetAnteHandler(auth.NewAnteHandler(app.accountMapper, app.feeCollectionKeepe
|
||||||
The antehandler is responsible for handling all authentication of a transaction before passing the message onto its handler.
|
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
|
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()`.
|
`tx.GetMsg().GetSigners()` signed the message and that they signed over `tx.GetMsg().GetSignBytes()`.
|
||||||
|
|
||||||
|
# Accounts
|
||||||
|
|
||||||
|
### auth.Account
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Account is a standard account using a sequence number for replay protection
|
||||||
|
// and a pubkey for authentication.
|
||||||
|
type Account interface {
|
||||||
|
GetAddress() sdk.Address
|
||||||
|
SetAddress(sdk.Address) error // errors if already set.
|
||||||
|
|
||||||
|
GetPubKey() crypto.PubKey // can return nil.
|
||||||
|
SetPubKey(crypto.PubKey) error
|
||||||
|
|
||||||
|
GetAccountNumber() int64
|
||||||
|
SetAccountNumber(int64) error
|
||||||
|
|
||||||
|
GetSequence() int64
|
||||||
|
SetSequence(int64) error
|
||||||
|
|
||||||
|
GetCoins() sdk.Coins
|
||||||
|
SetCoins(sdk.Coins) error
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Accounts are the standard way for an application to keep track of addresses and their associated balances.
|
||||||
|
|
||||||
|
### auth.BaseAccount
|
||||||
|
|
||||||
|
```go
|
||||||
|
// BaseAccount - base account structure.
|
||||||
|
// Extend this by embedding this in your AppAccount.
|
||||||
|
// See the examples/basecoin/types/account.go for an example.
|
||||||
|
type BaseAccount struct {
|
||||||
|
Address sdk.Address `json:"address"`
|
||||||
|
Coins sdk.Coins `json:"coins"`
|
||||||
|
PubKey crypto.PubKey `json:"public_key"`
|
||||||
|
AccountNumber int64 `json:"account_number"`
|
||||||
|
Sequence int64 `json:"sequence"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `auth.BaseAccount` struct provides a standard implementation of the Account interface with replay protection.
|
||||||
|
BaseAccount can be extended by embedding it in your own Account struct.
|
||||||
|
|
||||||
|
### auth.AccountMapper
|
||||||
|
|
||||||
|
```go
|
||||||
|
// This AccountMapper encodes/decodes accounts using the
|
||||||
|
// go-amino (binary) encoding/decoding library.
|
||||||
|
type AccountMapper struct {
|
||||||
|
|
||||||
|
// The (unexposed) key used to access the store from the Context.
|
||||||
|
key sdk.StoreKey
|
||||||
|
|
||||||
|
// The prototypical Account concrete type.
|
||||||
|
proto Account
|
||||||
|
|
||||||
|
// The wire codec for binary encoding/decoding of accounts.
|
||||||
|
cdc *wire.Codec
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The AccountMapper is responsible for managing and storing the state of all accounts in the application.
|
||||||
|
|
||||||
|
Example Initialization:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// File: examples/basecoin/app/app.go
|
||||||
|
// Define the accountMapper.
|
||||||
|
app.accountMapper = auth.NewAccountMapper(
|
||||||
|
cdc,
|
||||||
|
app.keyAccount, // target store
|
||||||
|
&types.AppAccount{}, // prototype
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
The accountMapper allows you to retrieve the current account state by `GetAccount(ctx Context, addr auth.Address)` and change the state by
|
||||||
|
`SetAccount(ctx Context, acc Account)`.
|
||||||
|
|
||||||
|
Note: To update an account you will first have to get the account, update the appropriate fields with its associated setter method, and then call
|
||||||
|
`SetAccount(ctx Context, acc updatedAccount)`.
|
||||||
|
|
||||||
|
Updating accounts is made easier by using the `Keeper` struct in the `x/bank` module.
|
||||||
|
|
||||||
|
Example Initialization:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// File: examples/basecoin/app/app.go
|
||||||
|
app.coinKeeper = bank.NewKeeper(app.accountMapper)
|
||||||
|
```
|
||||||
|
|
||||||
|
Example Usage:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Finds account with addr in accountmapper
|
||||||
|
// Adds coins to account's coin array
|
||||||
|
// Sets updated account in accountmapper
|
||||||
|
app.coinKeeper.AddCoins(ctx, addr, coins)
|
||||||
|
```
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
# BaseApp
|
|
||||||
|
|
||||||
The BaseApp is an abstraction over the [Tendermint
|
|
||||||
ABCI](https://github.com/tendermint/abci) that
|
|
||||||
simplifies application development by handling common low-level concerns.
|
|
||||||
It serves as the mediator between the two key components of an SDK app: the store
|
|
||||||
and the message handlers.
|
|
||||||
|
|
||||||
The BaseApp implements the
|
|
||||||
[`abci.Application`](https://godoc.org/github.com/tendermint/abci/types#Application) interface.
|
|
||||||
It uses a `MultiStore` to manage the state, a `Router` for transaction handling, and
|
|
||||||
`Set` methods to specify functions to run at the beginning and end of every
|
|
||||||
block.
|
|
||||||
|
|
||||||
Every SDK app begins with a BaseApp:
|
|
||||||
|
|
||||||
```
|
|
||||||
app := baseapp.NewBaseApp(appName, cdc, logger, db),
|
|
||||||
```
|
|
|
@ -1,26 +1,4 @@
|
||||||
# Message Handling
|
# Handlers
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
The SDK uses a `Context` to propogate common information across functions. The
|
|
||||||
`Context` is modeled after the Golang `context.Context` object, which has
|
|
||||||
become ubiquitous in networking middleware and routing applications as a means
|
|
||||||
to easily propogate request context through handler functions.
|
|
||||||
|
|
||||||
The main information stored in the `Context` includes the application
|
|
||||||
MultiStore, the last block header, and the transaction bytes.
|
|
||||||
Effectively, the context contains all data that may be necessary for processing
|
|
||||||
a transaction.
|
|
||||||
|
|
||||||
Many methods on SDK objects receive a context as the first argument.
|
|
||||||
|
|
||||||
## Handler
|
|
||||||
|
|
||||||
Message processing in the SDK is defined through `Handler` functions:
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Handler func(ctx Context, msg Msg) Result
|
|
||||||
```
|
|
||||||
|
|
||||||
A handler takes a context and a message and returns a result. All
|
A handler takes a context and a message and returns a result. All
|
||||||
information necessary for processing a message should be available in the
|
information necessary for processing a message should be available in the
|
||||||
|
@ -50,3 +28,4 @@ app.Router().AddRoute("foo", newFooHandler(fooKey))
|
||||||
```
|
```
|
||||||
|
|
||||||
Now it can only access the `foo` store, but not the `bar` or `cat` stores!
|
Now it can only access the `foo` store, but not the `bar` or `cat` stores!
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
Welcome to the Cosmos-SDK Core Documentation.
|
||||||
|
|
||||||
|
Here you will learn how to use the Cosmos-SDK to build Basecoin, a
|
||||||
|
complete proof-of-stake cryptocurrency system
|
||||||
|
|
||||||
|
We proceed through a series of increasingly advanced and complete implementations of
|
||||||
|
the Basecoin application, with each implementation showcasing a new component of
|
||||||
|
the SDK:
|
||||||
|
|
||||||
|
- App1 - The Basics - Messages, Stores, Handlers, BaseApp
|
||||||
|
- App2 - Amino - Unmarshalling into interfaces
|
||||||
|
- App3 - Authentication - Accounts and Transactions, Signatures and Replay protection
|
||||||
|
- App4 - Access Control - Keepers selective expose access to stores
|
||||||
|
- App5 - Validator Set Changes - Change the Tendermint validator set
|
||||||
|
- App6 - Basecoin - Bringing it all together
|
|
@ -1,76 +0,0 @@
|
||||||
# Messages
|
|
||||||
|
|
||||||
Messages are the primary inputs to application state machines.
|
|
||||||
Developers can create messages containing arbitrary information by
|
|
||||||
implementing the `Msg` interface:
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Msg interface {
|
|
||||||
|
|
||||||
// Return the message type.
|
|
||||||
// Must be alphanumeric or empty.
|
|
||||||
Type() string
|
|
||||||
|
|
||||||
// Get the canonical byte representation of the Msg.
|
|
||||||
GetSignBytes() []byte
|
|
||||||
|
|
||||||
// ValidateBasic does a simple validation check that
|
|
||||||
// doesn't require access to any other information.
|
|
||||||
ValidateBasic() error
|
|
||||||
|
|
||||||
// Signers returns the addrs of signers that must sign.
|
|
||||||
// CONTRACT: All signatures must be present to be valid.
|
|
||||||
// CONTRACT: Returns addrs in some deterministic order.
|
|
||||||
GetSigners() []Address
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Messages must specify their type via the `Type()` method. The type should
|
|
||||||
correspond to the messages handler, so there can be many messages with the same
|
|
||||||
type.
|
|
||||||
|
|
||||||
Messages must also specify how they are to be authenticated. The `GetSigners()`
|
|
||||||
method return a list of SDK addresses that must sign the message, while the
|
|
||||||
`GetSignBytes()` method returns the bytes that must be signed for a signature
|
|
||||||
to be valid.
|
|
||||||
|
|
||||||
Addresses in the SDK are arbitrary byte arrays that are hex-encoded when
|
|
||||||
displayed as a string or rendered in JSON.
|
|
||||||
|
|
||||||
Messages can specify basic self-consistency checks using the `ValidateBasic()`
|
|
||||||
method to enforce that message contents are well formed before any actual logic
|
|
||||||
begins.
|
|
||||||
|
|
||||||
For instance, the `Basecoin` message types are defined in `x/bank/tx.go`:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Send coins from many inputs to many outputs.
|
|
||||||
type MsgSend struct {
|
|
||||||
Inputs []Input `json:"inputs"`
|
|
||||||
Outputs []Output `json:"outputs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Issue new coins to many outputs.
|
|
||||||
type MsgIssue struct {
|
|
||||||
Banker sdk.Address `json:"banker"`
|
|
||||||
Outputs []Output `json:"outputs"`
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Each specifies the addresses that must sign the message:
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (msg MsgSend) GetSigners() []sdk.Address {
|
|
||||||
addrs := make([]sdk.Address, len(msg.Inputs))
|
|
||||||
for i, in := range msg.Inputs {
|
|
||||||
addrs[i] = in.Address
|
|
||||||
}
|
|
||||||
return addrs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg MsgIssue) GetSigners() []sdk.Address {
|
|
||||||
return []sdk.Address{msg.Banker}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# MultiStore
|
# MultiStore
|
||||||
|
|
||||||
|
TODO: reconcile this
|
||||||
|
|
||||||
The Cosmos-SDK provides a special Merkle database called a `MultiStore` to be used for all application
|
The Cosmos-SDK provides a special Merkle database called a `MultiStore` to be used for all application
|
||||||
storage. The MultiStore consists of multiple Stores that must be mounted to the
|
storage. The MultiStore consists of multiple Stores that must be mounted to the
|
||||||
MultiStore during application setup. Stores are mounted to the MultiStore using a capabilities key,
|
MultiStore during application setup. Stores are mounted to the MultiStore using a capabilities key,
|
||||||
|
@ -14,6 +16,7 @@ The goals of the MultiStore are as follows:
|
||||||
- Merkle proofs for various queries (existence, absence, range, etc.) on current and retained historical state
|
- Merkle proofs for various queries (existence, absence, range, etc.) on current and retained historical state
|
||||||
- Allow for iteration within Stores
|
- Allow for iteration within Stores
|
||||||
- Provide caching for intermediate state during execution of blocks and transactions (including for iteration)
|
- Provide caching for intermediate state during execution of blocks and transactions (including for iteration)
|
||||||
|
|
||||||
- Support historical state pruning and snapshotting
|
- Support historical state pruning and snapshotting
|
||||||
|
|
||||||
Currently, all Stores in the MultiStore must satisfy the `KVStore` interface,
|
Currently, all Stores in the MultiStore must satisfy the `KVStore` interface,
|
||||||
|
@ -55,9 +58,12 @@ through the `Context`.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
TODO: move this to the spec
|
||||||
|
|
||||||
In the example above, all IAVL nodes (inner and leaf) will be stored
|
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,
|
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
|
thus sharing the mainDB. All IAVL nodes (inner and leaf) for the
|
||||||
cat KVStore are stored separately in catDB with the prefix of
|
cat KVStore are stored separately in catDB with the prefix of
|
||||||
"s/\_/". The "s/k:KEY/" and "s/\_/" prefixes are there to
|
"s/\_/". The "s/k:KEY/" and "s/\_/" prefixes are there to
|
||||||
disambiguate store items from other items of non-storage concern.
|
disambiguate store items from other items of non-storage concern.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue