docs cleanup
This commit is contained in:
committed by
Zach Ramsay
parent
1b9afdab48
commit
266ea5ce82
@@ -0,0 +1,70 @@
|
||||
# Apps in the SDK
|
||||
|
||||
The SDK has multiple levels of "application": the ABCI app, the BaseApp, the BasecoinApp, and now your App.
|
||||
|
||||
## ABCI App
|
||||
|
||||
The basic ABCI interface allowing Tendermint to drive the applications state machine with transaction blocks.
|
||||
|
||||
## BaseApp
|
||||
|
||||
Implements an ABCI App using a MultiStore for persistence and a Router to handle transactions.
|
||||
The goal is to provide a secure interface between the store and the extensible state machine
|
||||
while defining as little about that state machine as possible (staying true to the ABCI).
|
||||
|
||||
BaseApp requires stores to be mounted via capabilities keys - handlers can only access
|
||||
stores they're given the key for. The BaseApp ensures all stores are properly loaded, cached, and committed.
|
||||
One mounted store is considered the "main" - it holds the latest block header, from which we can find and load the
|
||||
most recent state ([TODO](https://github.com/cosmos/cosmos-sdk/issues/522)).
|
||||
|
||||
BaseApp distinguishes between two handler types - the `AnteHandler` and the `MsgHandler`.
|
||||
The former is a global validity check (checking nonces, sigs and sufficient balances to pay fees,
|
||||
e.g. things that apply to all transaction from all modules), the later is the full state transition function.
|
||||
During CheckTx the state transition function is only applied to the checkTxState and should return
|
||||
before any expensive state transitions are run (this is up to each developer). It also needs to return the estimated
|
||||
gas cost.
|
||||
During DeliverTx the state transition function is applied to the blockchain state and the transactions
|
||||
need to be fully executed.
|
||||
|
||||
BaseApp is responsible for managing the context passed into handlers -
|
||||
it makes the block header available and provides the right stores for CheckTx and DeliverTx.
|
||||
|
||||
BaseApp is completely agnostic to serialization formats.
|
||||
|
||||
## Basecoin
|
||||
|
||||
Basecoin is the first complete application in the stack.
|
||||
Complete applications require extensions to the core modules of the SDK to actually implement handler functionality.
|
||||
The native extensions of the SDK, useful for building Cosmos Zones, live under `x`.
|
||||
Basecoin implements a `BaseApp` state machine using the `x/auth` and `x/bank` extensions,
|
||||
which define how transaction signers are authenticated and how coins are transferred.
|
||||
It should also use `x/ibc` and probably a simple staking extension.
|
||||
|
||||
Basecoin and the native `x` extensions use go-amino for all serialization needs,
|
||||
including for transactions and accounts.
|
||||
|
||||
## Your Cosmos App
|
||||
|
||||
Your Cosmos App is a fork of Basecoin - copy the `examples/basecoin` directory and modify it to your needs.
|
||||
You might want to:
|
||||
|
||||
- add fields to accounts
|
||||
- copy and modify handlers
|
||||
- add new handlers for new transaction types
|
||||
- add new stores for better isolation across handlers
|
||||
|
||||
The Cosmos Hub takes Basecoin and adds more stores and extensions to handle additional
|
||||
transaction types and logic, like the advanced staking logic and the governance process.
|
||||
|
||||
## Ethermint
|
||||
|
||||
Ethermint is a new implementation of `BaseApp` that does not depend on Basecoin.
|
||||
Instead of `cosmos-sdk/x/` it has its own `ethermint/x` based on `go-ethereum`.
|
||||
|
||||
Ethermint uses a Patricia store for its accounts, and an IAVL store for IBC.
|
||||
It has `x/ante`, which is quite similar to Basecoin's but uses RLP instead of go-amino.
|
||||
Instead of `x/bank`, it has `x/eth`, which defines the single Ethereum transaction type
|
||||
and all the semantics of the Ethereum state machine.
|
||||
|
||||
Within `x/eth`, transactions sent to particular addresses can be handled in unique ways,
|
||||
for instance to handle IBC and staking.
|
||||
@@ -1,230 +0,0 @@
|
||||
Glossary
|
||||
========
|
||||
|
||||
This glossary defines many terms used throughout documentation of Quark.
|
||||
If there is every a concept that seems unclear, check here. This is
|
||||
mainly to provide a background and general understanding of the
|
||||
different words and concepts that are used. Other documents will explain
|
||||
in more detail how to combine these concepts to build a particular
|
||||
application.
|
||||
|
||||
Transaction
|
||||
-----------
|
||||
|
||||
A transaction is a packet of binary data that contains all information
|
||||
to validate and perform an action on the blockchain. The only other data
|
||||
that it interacts with is the current state of the chain (key-value
|
||||
store), and it must have a deterministic action. The transaction is the
|
||||
main piece of one request.
|
||||
|
||||
We currently make heavy use of
|
||||
`go-amino <https://github.com/tendermint/go-amino>`__ to
|
||||
provide binary and json encodings and decodings for ``struct`` or
|
||||
interface\ ``objects. Here, encoding and decoding operations are designed to operate with interfaces nested any amount times (like an onion!). There is one public``\ TxMapper\`
|
||||
in the basecoin root package, and all modules can register their own
|
||||
transaction types there. This allows us to deserialize the entire
|
||||
transaction in one location (even with types defined in other repos), to
|
||||
easily embed an arbitrary transaction inside another without specifying
|
||||
the type, and provide an automatic json representation allowing for
|
||||
users (or apps) to inspect the chain.
|
||||
|
||||
Note how we can wrap any other transaction, add a fee level, and not
|
||||
worry about the encoding in our module any more?
|
||||
|
||||
::
|
||||
|
||||
type Fee struct {
|
||||
Fee coin.Coin `json:"fee"`
|
||||
Payer basecoin.Actor `json:"payer"` // the address who pays the fee
|
||||
Tx basecoin.Tx `json:"tx"`
|
||||
}
|
||||
|
||||
Context (ctx)
|
||||
-------------
|
||||
|
||||
As a request passes through the system, it may pick up information such
|
||||
as the block height the request runs at. In order to carry this information
|
||||
between modules it is saved to the context. Further, all information
|
||||
must be deterministic from the context in which the request runs (based
|
||||
on the transaction and the block it was included in) and can be used to
|
||||
validate the transaction.
|
||||
|
||||
Data Store
|
||||
----------
|
||||
|
||||
In order to provide proofs to Tendermint, we keep all data in one
|
||||
key-value (kv) store which is indexed with a merkle tree. This allows
|
||||
for the easy generation of a root hash and proofs for queries without
|
||||
requiring complex logic inside each module. Standardization of this
|
||||
process also allows powerful light-client tooling as any store data may
|
||||
be verified on the fly.
|
||||
|
||||
The largest limitation of the current implemenation of the kv-store is
|
||||
that interface that the application must use can only ``Get`` and
|
||||
``Set`` single data points. That said, there are some data structures
|
||||
like queues and range queries that are available in ``state`` package.
|
||||
These provide higher-level functionality in a standard format, but have
|
||||
not yet been integrated into the kv-store interface.
|
||||
|
||||
Isolation
|
||||
---------
|
||||
|
||||
One of the main arguments for blockchain is security. So while we
|
||||
encourage the use of third-party modules, all developers must be
|
||||
vigilant against security holes. If you use the
|
||||
`stack <https://github.com/cosmos/cosmos-sdk/tree/master/stack>`__
|
||||
package, it will provide two different types of compartmentalization
|
||||
security.
|
||||
|
||||
The first is to limit the working kv-store space of each module. When
|
||||
``DeliverTx`` is called for a module, it is never given the entire data
|
||||
store, but rather only its own prefixed subset of the store. This is
|
||||
achieved by prefixing all keys transparently with
|
||||
``<module name> + 0x0``, using the null byte as a separator. Since the
|
||||
module name must be a string, no malicious naming scheme can ever lead
|
||||
to a collision. Inside a module, we can write using any key value we
|
||||
desire without the possibility that we have modified data belonging to
|
||||
separate module.
|
||||
|
||||
The second is to add permissions to the transaction context. The
|
||||
transaction context can specify that the tx has been signed by one or
|
||||
multiple specific actors.
|
||||
|
||||
A transactions will only be executed if the permission requirements have
|
||||
been fulfilled. For example the sender of funds must have signed, or 2
|
||||
out of 3 multi-signature actors must have signed a joint account. To
|
||||
prevent the forgery of account signatures from unintended modules each
|
||||
permission is associated with the module that granted it (in this case
|
||||
`auth <https://github.com/cosmos/cosmos-sdk/tree/master/x/auth>`__),
|
||||
and if a module tries to add a permission for another module, it will
|
||||
panic. There is also protection if a module creates a brand new fake
|
||||
context to trick the downstream modules. Each context enforces the rules
|
||||
on how to make child contexts, and the stack builder enforces
|
||||
that the context passed from one level to the next is a valid child of
|
||||
the original one.
|
||||
|
||||
These security measures ensure that modules can confidently write to
|
||||
their local section of the database and trust the permissions associated
|
||||
with the context, without concern of interference from other modules.
|
||||
(Okay, if you see a bunch of C-code in the module traversing through all
|
||||
the memory space of the application, then get worried....)
|
||||
|
||||
Handler
|
||||
-------
|
||||
|
||||
The ABCI interface is handled by ``app``, which translates these data
|
||||
structures into an internal format that is more convenient, but unable
|
||||
to travel over the wire. The basic interface for any code that modifies
|
||||
state is the ``Handler`` interface, which provides four methods:
|
||||
|
||||
::
|
||||
|
||||
Name() string
|
||||
CheckTx(ctx Context, store state.KVStore, tx Tx) (Result, error)
|
||||
DeliverTx(ctx Context, store state.KVStore, tx Tx) (Result, error)
|
||||
SetOption(l log.Logger, store state.KVStore, module, key, value string) (string, error)
|
||||
|
||||
Note the ``Context``, ``KVStore``, and ``Tx`` as principal carriers of
|
||||
information. And that Result is always success, and we have a second
|
||||
error return for errors (which is much more standard golang that
|
||||
``res.IsErr()``)
|
||||
|
||||
The ``Handler`` interface is designed to be the basis for all modules
|
||||
that execute transactions, and this can provide a large degree of code
|
||||
interoperability, much like ``http.Handler`` does in golang web
|
||||
development.
|
||||
|
||||
Modules
|
||||
-------
|
||||
|
||||
TODO: update (s/Modules/handlers+mappers+stores/g) & add Msg + Tx (a signed message)
|
||||
|
||||
A module is a set of functionality which should be typically designed as
|
||||
self-sufficient. Common elements of a module are:
|
||||
|
||||
- transaction types (either end transactions, or transaction wrappers)
|
||||
- custom error codes
|
||||
- data models (to persist in the kv-store)
|
||||
- handler (to handle any end transactions)
|
||||
|
||||
Dispatcher
|
||||
----------
|
||||
|
||||
We usually will want to have multiple modules working together, and need
|
||||
to make sure the correct transactions get to the correct module. So we
|
||||
have ``coin`` sending money, ``roles`` to create multi-sig accounts, and
|
||||
``ibc`` for following other chains all working together without
|
||||
interference.
|
||||
|
||||
We can then register a ``Dispatcher``, which
|
||||
also implements the ``Handler`` interface. We then register a list of
|
||||
modules with the dispatcher. Every module has a unique ``Name()``, which
|
||||
is used for isolating its state space. We use this same name for routing
|
||||
transactions. Each transaction implementation must be registed with
|
||||
go-amino via ``TxMapper``, so we just look at the registered name of this
|
||||
transaction, which should be of the form ``<module name>/xxx``. The
|
||||
dispatcher grabs the appropriate module name from the tx name and routes
|
||||
it if the module is present.
|
||||
|
||||
This all seems like a bit of magic, but really we're just making use of
|
||||
go-amino magic that we are already using, rather than add another layer.
|
||||
For all the transactions to be properly routed, the only thing you need
|
||||
to remember is to use the following pattern:
|
||||
|
||||
::
|
||||
|
||||
const (
|
||||
NameCoin = "coin"
|
||||
TypeSend = NameCoin + "/send"
|
||||
)
|
||||
|
||||
Permissions
|
||||
-----------
|
||||
|
||||
TODO: replaces perms with object capabilities/object capability keys
|
||||
- get rid of IPC
|
||||
|
||||
IPC requires a more complex permissioning system to allow the modules to
|
||||
have limited access to each other and also to allow more types of
|
||||
permissions than simple public key signatures. Rather than just use an
|
||||
address to identify who is performing an action, we can use a more
|
||||
complex structure:
|
||||
|
||||
::
|
||||
|
||||
type Actor struct {
|
||||
ChainID string `json:"chain"` // this is empty unless it comes from a different chain
|
||||
App string `json:"app"` // the app that the actor belongs to
|
||||
Address data.Bytes `json:"addr"` // arbitrary app-specific unique id
|
||||
}
|
||||
|
||||
Here, the ``Actor`` abstracts any address that can authorize actions,
|
||||
hold funds, or initiate any sort of transaction. It doesn't just have to
|
||||
be a pubkey on this chain, it could stem from another app (such as
|
||||
multi-sig account), or even another chain (via IBC)
|
||||
|
||||
``ChainID`` is for IBC, discussed below. Let's focus on ``App`` and
|
||||
``Address``. For a signature, the App is ``auth``, and any modules can
|
||||
check to see if a specific public key address signed like this
|
||||
``ctx.HasPermission(auth.SigPerm(addr))``. However, we can also
|
||||
authorize a tx with ``roles``, which handles multi-sig accounts, it
|
||||
checks if there were enough signatures by checking as above, then it can
|
||||
add the role permission like
|
||||
``ctx= ctx.WithPermissions(NewPerm(assume.Role))``
|
||||
|
||||
In addition to the permissions schema, the Actors are addresses just
|
||||
like public key addresses. So one can create a mulit-sig role, then send
|
||||
coin there, which can only be moved upon meeting the authorization
|
||||
requirements from that module. ``coin`` doesn't even know the existence
|
||||
of ``roles`` and one could build any other sort of module to provide
|
||||
permissions (like bind the outcome of an election to move coins or to
|
||||
modify the accounts on a role).
|
||||
|
||||
One idea - not yet implemented - is to provide scopes on the
|
||||
permissions. Currently, if I sign a transaction to one module, it can
|
||||
pass it on to any other module over IPC with the same permissions. It
|
||||
could move coins, vote in an election, or anything else. Ideally, when
|
||||
signing, one could also specify the scope(s) that this signature
|
||||
authorizes. The `oauth
|
||||
protocol <https://api.slack.com/docs/oauth-scopes>`__ also has to deal
|
||||
with a similar problem, and maybe could provide some inspiration.
|
||||
+6
-11
@@ -6,7 +6,8 @@ version of the code, please head to our
|
||||
`downloads <https://tendermint.com/download>`__ page to get a
|
||||
pre-compiled binary for your platform.
|
||||
|
||||
Usually, Cosmos SDK can be installed like a normal Go program:
|
||||
Usually, Cosmos SDK can be installed to
|
||||
`$GOPATH/src/github.com/cosmos/cosmos-sdk` like a normal Go program:
|
||||
|
||||
::
|
||||
|
||||
@@ -23,13 +24,7 @@ repo, the correct way to install is:
|
||||
git pull origin master
|
||||
make all
|
||||
|
||||
This will create the ``basecoin`` binary in ``$GOPATH/bin``.
|
||||
``make all`` implies ``make get_vendor_deps`` and uses ``dep`` to
|
||||
install the correct version of all dependencies. It also tests the code,
|
||||
including some cli tests to make sure your binary behaves properly.
|
||||
|
||||
If you need another branch, make sure to run ``git checkout <branch>``
|
||||
before ``make all``. And if you switch branches a lot, especially
|
||||
touching other tendermint repos, you may need to ``make fresh``
|
||||
sometimes so dep doesn't get confused with all the branches and
|
||||
versions lying around.
|
||||
This will create the ``basecoind`` and ``basecli`` binaries locally in
|
||||
``./build/bin``. ``make all`` implies ``make get_vendor_deps`` and uses
|
||||
``glide`` to install the correct version of all dependencies. It also tests the
|
||||
code, including some cli tests to make sure your binary behaves properly.
|
||||
|
||||
Reference in New Issue
Block a user