Review feedback from Adrian
This commit is contained in:
parent
c368b1062c
commit
3b09a3033a
166
docs/guide.md
166
docs/guide.md
@ -47,28 +47,26 @@ type Msg interface {
|
||||
|
||||
```
|
||||
|
||||
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 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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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`:
|
||||
For instance, the `Basecoin` message types are defined in `x/bank/tx.go`:
|
||||
|
||||
```golang
|
||||
type SendMsg struct {
|
||||
@ -100,8 +98,7 @@ func (msg IssueMsg) GetSigners() []crypto.Address {
|
||||
|
||||
### Transactions
|
||||
|
||||
A transaction is a message with additional information for
|
||||
authentication:
|
||||
A transaction is a message with additional information for authentication:
|
||||
|
||||
```golang
|
||||
type Tx interface {
|
||||
@ -127,9 +124,9 @@ type Tx interface {
|
||||
}
|
||||
```
|
||||
|
||||
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:
|
||||
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 {
|
||||
@ -139,25 +136,22 @@ type StdSignature struct {
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
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
|
||||
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.
|
||||
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`:
|
||||
The standard way to create a transaction from a message is to use the `StdTx`:
|
||||
|
||||
```golang
|
||||
type StdTx struct {
|
||||
@ -168,28 +162,27 @@ type StdTx struct {
|
||||
|
||||
### 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.
|
||||
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`:
|
||||
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.
|
||||
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:
|
||||
For instance, in `Basecoin`, we wish to register the `SendMsg` and `IssueMsg`
|
||||
types:
|
||||
|
||||
```golang
|
||||
cdc.RegisterInterface((*sdk.Msg)(nil), nil)
|
||||
@ -197,11 +190,10 @@ 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]().
|
||||
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-wire documentation](https://github.com/tendermint/go-wire/blob/develop).
|
||||
|
||||
|
||||
## MultiStore
|
||||
@ -222,38 +214,56 @@ TODO:
|
||||
|
||||
## 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 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.
|
||||
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.
|
||||
Many methods on SDK objects receive a context as the first argument.
|
||||
|
||||
## Handler
|
||||
|
||||
Transaction processing in the SDK is defined through `Handler`
|
||||
functions:
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
|
||||
```golang
|
||||
// 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
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
)
|
||||
|
||||
// Handle all "bank" type messages.
|
||||
// NOTE: Technically, NewHandler only needs a CoinMapper
|
||||
func NewHandler(am sdk.AccountMapper) sdk.Handler {
|
||||
|
||||
return func(ctx sdk.Context, msg sdk.Msg) sdk.Result {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user