Fix guide docs
This commit is contained in:
parent
b95b67d520
commit
2246a9c68b
39
README.md
39
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)
|
||||
|
||||
235
docs/basics.md
235
docs/basics.md
@ -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
|
||||
@ -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
286
docs/guide.md
Normal 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
|
||||
@ -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.
|
||||
Loading…
Reference in New Issue
Block a user