Merge pull request #180 from tendermint/feature/rige-docs
Feature/rige docs
This commit is contained in:
commit
fb4266249e
28
README.md
28
README.md
|
@ -1,17 +1,15 @@
|
||||||
# Basecoin
|
# Quark
|
||||||
|
|
||||||
_DISCLAIMER: Basecoin is not associated with Coinbase.com, an excellent Bitcoin/Ethereum service._
|
Quark is an [ABCI application](https://github.com/tendermint/abci) designed to
|
||||||
|
be used with the [Tendermint consensus engine](https://tendermint.com/) to form
|
||||||
|
a Proof-of-Stake cryptocurrency. It also provides a general purpose framework
|
||||||
|
for extending the feature-set of the cryptocurrency by implementing plugins.
|
||||||
|
|
||||||
Basecoin is an [ABCI application](https://github.com/tendermint/abci) designed to be used with the [Tendermint consensus engine](https://tendermint.com/) to form a Proof-of-Stake cryptocurrency.
|
Quark serves as a reference implementation for how we build ABCI applications
|
||||||
It also provides a general purpose framework for extending the feature-set of the cryptocurrency
|
in Go, and is the framework in which we implement the [Cosmos
|
||||||
by implementing plugins.
|
Hub](https://cosmos.network). **It's easy to use, and doesn't require any
|
||||||
|
forking** - just implement your plugin, import the quark libraries, and away
|
||||||
Basecoin serves as a reference implementation for how we build ABCI applications in Go,
|
you go with a full-stack blockchain and command line tool for transacting.
|
||||||
and is the framework in which we implement the [Cosmos Hub](https://cosmos.network).
|
|
||||||
**It's easy to use, and doesn't require any forking** - just implement your plugin, import the basecoin libraries,
|
|
||||||
and away you go with a full-stack blockchain and command line tool for transacting.
|
|
||||||
|
|
||||||
WARNING: Currently uses plain-text private keys for transactions and is otherwise not production ready.
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
|
@ -28,10 +26,10 @@ See the [install guide](/docs/guide/install.md) for more details.
|
||||||
|
|
||||||
## Guide
|
## Guide
|
||||||
|
|
||||||
1. Getting started with the [Basecoin basics](/docs/guide/basecoin-basics.md)
|
1. Getting started with the [Quark basics](/docs/guide/basecoin-basics.md)
|
||||||
1. Learning to [use the plugin system](/docs/guide/basecoin-plugins.md)
|
1. Learning to [use the plugin system](/docs/guide/basecoin-plugins.md)
|
||||||
1. More features of the [Basecoin tool](/docs/guide/basecoin-tool.md)
|
1. More features of the [Quark tool](/docs/guide/basecoin-tool.md)
|
||||||
1. Learn how to use [InterBlockchain Communication (IBC)](/docs/guide/ibc.md)
|
1. Learn how to use [Inter-Blockchain Communication (IBC)](/docs/guide/ibc.md)
|
||||||
1. See [more examples](github.com/tendermint/basecoin-examples)
|
1. See [more examples](github.com/tendermint/basecoin-examples)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,39 @@
|
||||||
# Quark
|
# Quark
|
||||||
|
|
||||||
Quarks are the building blocks of atoms. And in a similar vein, this
|
Quarks are the fundamental building blocks of atoms through which DNA, life,
|
||||||
package is a framework for building the cosmos. It gives you all the tools
|
and matter arise. Similarly this package is the core framework for constructing
|
||||||
you need to quickly build up powerful abci applications to run on tendermint,
|
the atom tokens which will power [The Cosmos Network](https://cosmos.network/).
|
||||||
while also providing maximum flexibility to customize aspects of your
|
|
||||||
application (do you require fees, how do you want to log messages, do you
|
|
||||||
enable IBC, do you even have a cryptocurrency?)
|
|
||||||
|
|
||||||
However, when power and flexibility meet, the result is also some level of
|
The Quark framework affords you all the tools you need to rapidly develop
|
||||||
|
robust blockchains and blockchain applications which are interoperable with The
|
||||||
|
Cosmos Hub. Quark is an abstraction of [Tendermint](https://tendermint.com/)
|
||||||
|
which provides the core consensus engine for your blockchain. Beyond consensus,
|
||||||
|
Quark provides a blockchain development 'starter-pack' of common blockchain
|
||||||
|
modules while not enforcing their use thus giving maximum flexibility for
|
||||||
|
application customization. For example, do you require fees, how do you
|
||||||
|
want to log messages, do you enable IBC, do you even have a cryptocurrency?
|
||||||
|
|
||||||
|
Disclaimer: when power and flexibility meet, the result is also some level of
|
||||||
complexity and a learning curve. Here is an introduction to the core concepts
|
complexity and a learning curve. Here is an introduction to the core concepts
|
||||||
embedded in quarks, so you can apply them properly.
|
embedded in Quark.
|
||||||
|
|
||||||
## Inspiration
|
## Inspiration
|
||||||
|
|
||||||
The basic concept came from years of web development. After decades of web
|
The basic concept came from years of web development. A number of patterns
|
||||||
development, a number of patterns have arisen that enabled people to build
|
have arisen in that realm of software which enable people to build remote
|
||||||
remote servers with APIs remarkably quickly and with high stability.
|
servers with APIs remarkably quickly and with high stability. The
|
||||||
I think the ABCI app interface is similar to a web api (DeliverTx is like POST
|
[ABCI](https://github.com/tendermint/abci) application interface is similar to
|
||||||
and Query is like GET and SetOption is like the admin playing with the config
|
a web API (DeliverTx is like POST and Query is like GET and `SetOption` is like
|
||||||
file). Here are some patterns that might be useful:
|
the admin playing with the config file). Here are some patterns that might be
|
||||||
|
useful:
|
||||||
|
|
||||||
* MVC - separate data model (storage) from business logic (controllers)
|
* MVC - separate data model (storage) from business logic (controllers)
|
||||||
* Routers - easily direct each request to the appropriate controller
|
* Routers - easily direct each request to the appropriate controller
|
||||||
* Middleware - a series of wrappers that provide global functionality (like
|
* Middleware - a series of wrappers that provide global functionality (like
|
||||||
authentication) to all controllers
|
authentication) to all controllers
|
||||||
* Modules (gems, package, ...) - people can write a self-contained package
|
* Modules (gems, package, ...) - developers can write a self-contained package
|
||||||
with a given set of functionality, which can be imported and reused in
|
with a given set of functionality, which can be imported and reused in other
|
||||||
other apps
|
apps
|
||||||
|
|
||||||
Also, the idea of different tables/schemas in databases, so you can keep the
|
Also, the idea of different tables/schemas in databases, so you can keep the
|
||||||
different modules safely separated and avoid any accidental (or malicious)
|
different modules safely separated and avoid any accidental (or malicious)
|
||||||
|
@ -41,6 +48,6 @@ into various applications.
|
||||||
* [Glossary of the terms](glossary.md)
|
* [Glossary of the terms](glossary.md)
|
||||||
* [Standard modules](stdlib.md)
|
* [Standard modules](stdlib.md)
|
||||||
* Guide to building a module
|
* Guide to building a module
|
||||||
* Demo of cli tool
|
* Demo of CLI tool
|
||||||
* IBC in detail
|
* IBC in detail
|
||||||
* Diagrams!!!
|
* Diagrams... Coming Soon!
|
||||||
|
|
|
@ -1,31 +1,33 @@
|
||||||
# Glossary
|
# Glossary
|
||||||
|
|
||||||
This defines many of the terms that are used in the other documents. If there
|
This glossary defines many terms used throughout documentation of Quark. If
|
||||||
is every a concept that seems unclear, check here. This is mainly to provide
|
there is every a concept that seems unclear, check here. This is mainly to
|
||||||
a background and general understanding of the different words and concepts
|
provide a background and general understanding of the different words and
|
||||||
that are used. Other documents will explain in more detail how to combine
|
concepts that are used. Other documents will explain in more detail how to
|
||||||
these concepts to build a particular application.
|
combine these concepts to build a particular application.
|
||||||
|
|
||||||
## Transaction
|
## Transaction (tx)
|
||||||
|
|
||||||
A transaction is a packet of binary data that contains all information to
|
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
|
validate and perform an action on the blockchain. The only other data that it
|
||||||
it interacts with is the current state of the chain (kv store), and it must
|
interacts with is the current state of the chain (key-value store), and
|
||||||
have a deterministic action. The transaction is the main piece of one request.
|
it must have a deterministic action. The tx is the main piece of one request.
|
||||||
|
|
||||||
We currently make heavy use of go-wire and go-data to provide automatic binary
|
We currently make heavy use of [go-wire](https://github.com/tendermint/go-wire)
|
||||||
and json encodings (and decodings) for objects, even when they embed many
|
and [data](https://github.com/tendermint/go-wire/tree/master/data) to provide
|
||||||
interfaces inside. There is one public `TxMapper` in the basecoin root package,
|
binary and json encodings and decodings for `struct` or interface` objects.
|
||||||
and all modules can register their own transaction types there. This allows us
|
Here, encoding and decoding operations are designed to operate with interfaces
|
||||||
to deserialize the entire tx in one location (even with types defined in other
|
nested any amount times (like an onion!). There is one public `TxMapper`
|
||||||
repos), to easily embed an arbitrary Tx inside another without specifying
|
in the basecoin root package, and all modules can register their own transaction types there. This allows us to deserialize the entire tx in
|
||||||
the specific type, and provide an automatic json representation to provide to
|
one location (even with types defined in other repos), to easily embed
|
||||||
users (or apps) to inspect the chain.
|
an arbitrary tx inside another without specifying the type, and provide
|
||||||
|
an automatic json representation to provide to users (or apps) to
|
||||||
|
inspect the chain.
|
||||||
|
|
||||||
Note how we can wrap any other transaction, add a fee level, and not worry
|
Note how we can wrap any other transaction, add a fee level, and not worry
|
||||||
about the encoding in our module any more?
|
about the encoding in our module any more?
|
||||||
|
|
||||||
```Go
|
```golang
|
||||||
type Fee struct {
|
type Fee struct {
|
||||||
Fee coin.Coin `json:"fee"`
|
Fee coin.Coin `json:"fee"`
|
||||||
Payer basecoin.Actor `json:"payer"` // the address who pays the fee
|
Payer basecoin.Actor `json:"payer"` // the address who pays the fee
|
||||||
|
@ -33,54 +35,68 @@ type Fee struct {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Context
|
## Context (ctx)
|
||||||
|
|
||||||
As the request passes through the system, it can pick up information, that must
|
As a request passes through the system, it may pick up information such as the
|
||||||
be carried along with it. Like the authorized it has received from another
|
authorization it has received from another middleware, or the block height the
|
||||||
middleware, or the block height it runs at. This is all deterministic
|
request runs at. In order to carry this information between modules it is
|
||||||
information from the context in which the request runs (based on the tx and
|
saved to the context. further, it all information must be deterministic from
|
||||||
the block it was included in) and can be used to validate the tx.
|
the context in which the request runs (based on the tx and the block it was
|
||||||
|
included in) and can be used to validate the tx.
|
||||||
|
|
||||||
## Data Store
|
## Data Store
|
||||||
|
|
||||||
To be able to provide proofs to tendermint, we keep all data in one key-value
|
To be able to provide proofs to Tendermint, we keep all data in one key-value
|
||||||
store, indexed with a merkle tree. This allows us to easily provide a root
|
(kv) store which is indexed with a merkle tree. This allows for the easy
|
||||||
hash and proofs for queries without requiring complex logic inside each
|
generation of a root hash and proofs for queries without requiring complex
|
||||||
module. Standarizing this also allows powerful light-client tooling as it knows
|
logic inside each module. Standardization of this process also allows powerful
|
||||||
how to verify all data in the store.
|
light-client tooling as any store data may be verified on the fly.
|
||||||
|
|
||||||
The downside is there is one quite simple interface that the application has
|
The largest limitation of the current implemenation of the kv-store is that
|
||||||
to `Get` and `Set` data. There is not even a range query. Although there are
|
interface that the application must use can only `Get` and `Set` single data
|
||||||
some data structures like queues and range queries that are also in the `state`
|
points. This said, there are some data structures like queues and range
|
||||||
package to provide higher-level functionality in a standard format.
|
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
|
## Isolation
|
||||||
|
|
||||||
One of the main arguments for blockchain is security. So while we encourage
|
One of the main arguments for blockchain is security. So while we encourage
|
||||||
the use of third-party modules, we must be vigilant against security holes.
|
the use of third-party modules, all developers must be vigilant against
|
||||||
If you use the `stack` package, it will provide two different types of
|
security holes. If you use the
|
||||||
sandboxing for you.
|
[stack](https://github.com/tendermint/basecoin/tree/unstable/stack)
|
||||||
|
package, it will provide two different types of compartmentalization security.
|
||||||
|
|
||||||
The first step, is that when `DeliverTx` is called on a module, it is never
|
The first is to limit the working kv-store space of each module. When
|
||||||
given the entire data store, but rather only its own prefixed section. This
|
`DeliverTx` is called for a module, it is never given the entire data store,
|
||||||
is achieved by prefixing all keys transparently with `<module name> + 0x0`,
|
but rather only its own prefixed subset of the store. This is achieved by
|
||||||
using the null byte as a separator. Since module name must be a string, no
|
prefixing all keys transparently with `<module name> + 0x0`, using the null
|
||||||
clever naming scheme can lead to a collision. Inside the module, we can write
|
byte as a separator. Since the module name must be a string, no malicious
|
||||||
anywhere we want, without worry that we have to touch some data that is not ours.
|
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 step involves the permissions in the context. The context can say
|
The second is to add permissions to the transaction context. The tx context
|
||||||
that this tx was signed by eg. Rigel. But if any module can add that permission,
|
can specify that the tx has been signed by one or multiple specific
|
||||||
it would be too easy to forge accounts. Thus, each permission is associated
|
[actors](https://github.com/tendermint/basecoin/blob/unstable/context.go#L18).
|
||||||
with the module that granted it (in this case `auth`), and if a module tries
|
A tx will only be executed if the permission requirements have been fulfilled.
|
||||||
to add a permission for another module, it will panic. There is also
|
For example the sender of funds must have signed, or 2 out of 3
|
||||||
protection if a module creates a brand new fake context to trick the downstream
|
multi-signature actors must have signed a joint account. To prevent the
|
||||||
modules.
|
forgery of account signatures from unintended modules each permission
|
||||||
|
is associated with the module that granted it (in this case
|
||||||
|
[auth](https://github.com/tendermint/basecoin/tree/unstable/modules/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 middleware builder
|
||||||
|
enforces that the context passed from one level to the next is a valid
|
||||||
|
child of the original one.
|
||||||
|
|
||||||
This means that modules can confidently write to their local section of the
|
These security measures ensure that modules can confidently write to their
|
||||||
database and trust the permissions associated with the context, without concern
|
local section of the database and trust the permissions associated with the
|
||||||
of interferance from other modules. (Okay, if you see a bunch of C-code in
|
context, without concern of interference from other modules. (Okay,
|
||||||
the module traversing through all the memory space of the application, then
|
if you see a bunch of C-code in the module traversing through all the
|
||||||
get worried....)
|
memory space of the application, then get worried....)
|
||||||
|
|
||||||
## Handler
|
## Handler
|
||||||
|
|
||||||
|
@ -89,19 +105,19 @@ 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`
|
wire. The basic interface for any code that modifies state is the `Handler`
|
||||||
interface, which provides four methods:
|
interface, which provides four methods:
|
||||||
|
|
||||||
```Go
|
```golang
|
||||||
Name() string
|
Name() string
|
||||||
CheckTx(ctx Context, store state.KVStore, tx Tx) (Result, error)
|
CheckTx(ctx Context, store state.KVStore, tx Tx) (Result, error)
|
||||||
DeliverTx(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)
|
SetOption(l log.Logger, store state.KVStore, module, key, value string) (string, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
Note the `Context`, `Store`, and `Tx` as principal carriers of information. And
|
Note the `Context`, `KVStore`, and `Tx` as principal carriers of information.
|
||||||
that Result is always success, and we have a second error return for errors
|
And that Result is always success, and we have a second error return
|
||||||
(which is much more standard go that `res.IsErr()`)
|
for errors (which is much more standard golang that `res.IsErr()`)
|
||||||
|
|
||||||
The `Handler` interface is designed to be the basis for all modules that
|
The `Handler` interface is designed to be the basis for all modules that
|
||||||
execute transaction, and this can provide a large degree of code
|
execute transactions, and this can provide a large degree of code
|
||||||
interoperability, much like `http.Handler` does in golang web development.
|
interoperability, much like `http.Handler` does in golang web development.
|
||||||
|
|
||||||
## Middleware
|
## Middleware
|
||||||
|
@ -110,16 +126,16 @@ Middleware is a series of processing steps that any request must travel through
|
||||||
before (and after) executing the registered `Handler`. Some examples are a
|
before (and after) executing the registered `Handler`. Some examples are a
|
||||||
logger (that records the time before executing the tx, then outputs info -
|
logger (that records the time before executing the tx, then outputs info -
|
||||||
including duration - after the execution), of a signature checker (which
|
including duration - after the execution), of a signature checker (which
|
||||||
unwraps the tx by one layer, verifies signatutes, and adds the permissions to
|
unwraps the tx by one layer, verifies signatures, and adds the permissions to
|
||||||
the Context before passing the request along).
|
the Context before passing the request along).
|
||||||
|
|
||||||
In keeping with the standardazation of `http.Handler` and inspired by the
|
In keeping with the standardization of `http.Handler` and inspired by the
|
||||||
super minimal [negroni](https://github.com/urfave/negroni/blob/master/README.md)
|
super minimal [negroni](https://github.com/urfave/negroni/blob/master/README.md)
|
||||||
package, we just provide one more `Middleware` interface, which has an extra
|
package, we just provide one more `Middleware` interface, which has an extra
|
||||||
`next` parameter, and a `Stack` that can wire all the levels together (which
|
`next` parameter, and a `Stack` that can wire all the levels together (which
|
||||||
also gives us a place to perform isolation of each step).
|
also gives us a place to perform isolation of each step).
|
||||||
|
|
||||||
```Go
|
```golang
|
||||||
Name() string
|
Name() string
|
||||||
CheckTx(ctx Context, store state.KVStore, tx Tx, next Checker) (Result, error)
|
CheckTx(ctx Context, store state.KVStore, tx Tx, next Checker) (Result, error)
|
||||||
DeliverTx(ctx Context, store state.KVStore, tx Tx, next Deliver) (Result, error)
|
DeliverTx(ctx Context, store state.KVStore, tx Tx, next Deliver) (Result, error)
|
||||||
|
@ -128,19 +144,20 @@ also gives us a place to perform isolation of each step).
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
A module is a set of functionality that is more or less self-sufficient. It
|
A module is a set of functionality which should be typically designed as
|
||||||
usually contains the following pieces:
|
self-sufficient. Common elements of a module are:
|
||||||
|
|
||||||
* transaction types (either end transactions, or transaction wrappers)
|
* transaction types (either end transactions, or transaction wrappers)
|
||||||
* custom error codes
|
* custom error codes
|
||||||
* data models (to persist in the kv store)
|
* data models (to persist in the kv-store)
|
||||||
* handler (to handle any end transactions)
|
* handler (to handle any end transactions)
|
||||||
* middleware (to handler any wrapper transactions)
|
* middleware (to handler any wrapper transactions)
|
||||||
|
|
||||||
To enable a module, you must add the appropriate middleware (if any) to the
|
To enable a module, you must add the appropriate middleware (if any) to the
|
||||||
stack in main.go, as well as adding the handler (if any) to the dispatcher.
|
stack in `main.go` for the client application (Quark default:
|
||||||
One the stack is compiled into a `Handler`, then all tx are handled by the
|
`basecli/main.go`), as well as adding the handler (if any) to the dispatcher
|
||||||
proper module.
|
(Quark default: `app/app.go). Once the stack is compiled into a `Handler`,
|
||||||
|
then each tx is handled by the appropriate module.
|
||||||
|
|
||||||
## Dispatcher
|
## Dispatcher
|
||||||
|
|
||||||
|
@ -163,47 +180,49 @@ This all seems a bit of magic, but really just making use of the other magic
|
||||||
thing you need to remember is to use the following pattern, then all the tx
|
thing you need to remember is to use the following pattern, then all the tx
|
||||||
will be properly routed:
|
will be properly routed:
|
||||||
|
|
||||||
```Go
|
```golang
|
||||||
const (
|
const (
|
||||||
NameCoin = "coin"
|
NameCoin = "coin"
|
||||||
TypeSend = NameCoin + "/send"
|
TypeSend = NameCoin + "/send"
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
## IPC (Inter-Plugin Communication)
|
## Inter-Plugin Communication (IPC)
|
||||||
|
|
||||||
But wait, there's more... since we have isolated all the modules from each
|
But wait, there's more... since we have isolated all the modules from each
|
||||||
other, we need to allow some way for them to interact in a controlled fashion.
|
other, we need to allow some way for them to interact in a controlled fashion.
|
||||||
Some examples are the `fee` middleware, which wants to deduct coins from
|
One example is the `fee` middleware, which wants to deduct coins from the
|
||||||
the calling account (in the `coin` module), or a vote that requires a payment.
|
calling account and can accomplished most easilty with the `coin` module.
|
||||||
|
|
||||||
If we want to make a call from the middleware, this is relatively simple.
|
If we want to make a call from the middleware, this is relatively simple. The
|
||||||
The middleware already has a handle to the `next` Handler, which will
|
middleware already has a handle to the `next` Handler, which will execute the
|
||||||
execute the rest of the stack. It can simple create a new SendTx and pass
|
rest of the stack. It can simple create a new SendTx and pass it down the
|
||||||
it down the stack. If it returns success, then do the rest of the processing
|
stack. If it returns success, then do the rest of the processing (and send the
|
||||||
(and send the original tx down the stack), otherwise abort.
|
original tx down the stack), otherwise abort.
|
||||||
|
|
||||||
However, if one `Handler` inside the `Dispatcher` wants to do this, it
|
However, if one `Handler` inside the `Dispatcher` wants to do this, it becomes
|
||||||
becomes more complex. The solution is that the `Dispatcher` accepts not
|
more complex. The solution is that the `Dispatcher` accepts not a `Handler`,
|
||||||
a `Handler`, but a `Dispatchable`, which looks like a middleware, except
|
but a `Dispatchable`, which looks like a middleware, except that the `next`
|
||||||
that the `next` argument is a callback to the dispatcher to execute a
|
argument is a callback to the dispatcher to execute a sub-transaction. If a
|
||||||
sub-transaction. If a module doesn't want to use this functionality,
|
module doesn't want to use this functionality, it can just implement `Handler`
|
||||||
it can just implement `Handler` and call `stack.WrapHandler(h)` to convert
|
and call `stack.WrapHandler(h)` to convert it to a `Dispatchable` that never
|
||||||
it to a `Dispatchable` that never uses the callback.
|
uses the callback.
|
||||||
|
|
||||||
One example of this is the counter app, which can optionally accept a payment.
|
One example of this is the counter app, which can optionally accept a payment.
|
||||||
If the tx contains a payment, it must create a SendTx and pass this to the
|
If the tx contains a payment, it must create a SendTx and pass this to the
|
||||||
dispatcher to deduct the amount from the proper account. Take a look at
|
dispatcher to deduct the amount from the proper account. Take a look at
|
||||||
[counter plugin](https://github.com/tendermint/basecoin/blob/unstable/docs/guide/counter/plugins/counter/counter.go) for a better idea.
|
[counter
|
||||||
|
plugin](https://github.com/tendermint/basecoin/blob/unstable/docs/guide/counter/plugins/counter/counter.go)
|
||||||
|
for a better idea.
|
||||||
|
|
||||||
## Permissions
|
## Permissions
|
||||||
|
|
||||||
This system requires a more complex permissioning system to allow the modules
|
IPC requires a more complex permissioning system to allow the modules to have
|
||||||
to have limited access to each other. Also to allow more types of permissions
|
limited access to each other. Also to allow more types of permissions than
|
||||||
than simple public key signatures. So, rather than just use an address to
|
simple public key signatures. So, rather than just use an address to identify
|
||||||
identify who is performing an action, we can use a more complex structure:
|
who is performing an action, we can use a more complex structure:
|
||||||
|
|
||||||
```Go
|
```golang
|
||||||
type Actor struct {
|
type Actor struct {
|
||||||
ChainID string `json:"chain"` // this is empty unless it comes from a different chain
|
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
|
App string `json:"app"` // the app that the actor belongs to
|
||||||
|
@ -211,32 +230,70 @@ type Actor struct {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
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 to be used for IBC, which is discussed below, but right now focus
|
`ChainID` is to be used for IBC, which is discussed below, but right now focus
|
||||||
on `App` and `Address`. For a signature, the App is `auth`, and any modules can
|
on `App` and `Address`. For a signature, the App is `auth`, and any modules
|
||||||
check to see if a specific public key address signed like this
|
can check to see if a specific public key address signed like this
|
||||||
`ctx.HasPermission(auth.SigPerm(addr))`. However, we can also authorize a
|
`ctx.HasPermission(auth.SigPerm(addr))`. However, we can also authorize a tx
|
||||||
tx with `roles`, which handles multi-sig accounts, it checks if there were
|
with `roles`, which handles multi-sig accounts, it checks if there were enough
|
||||||
enough signatures by checking as above, then it can add the role permission like
|
signatures by checking as above, then it can add the role permission like `ctx
|
||||||
`ctx = ctx.WithPermissions(NewPerm(assume.Role))`
|
= ctx.WithPermissions(NewPerm(assume.Role))`
|
||||||
|
|
||||||
In addition to permissioning, the Actors are addresses just like public key
|
In addition to permissioning, the Actors are addresses just like public key
|
||||||
addresses. So one can create a mulit-sig role, then send coin there, which
|
addresses. So one can create a mulit-sig role, then send coin there, which can
|
||||||
can only be moved upon meeting the authorization requirements from that module.
|
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
|
`coin` doesn't even know the existence of `roles` and one could build any other
|
||||||
other sort of module to provide permissions (like bind the outcome of an
|
sort of module to provide permissions (like bind the outcome of an election to
|
||||||
election to move coins or to modify the accounts on a role).
|
move coins or to modify the accounts on a role).
|
||||||
|
|
||||||
One idea (not implemented) is to provide scopes on the permissions. Right now,
|
One idea (not implemented) is to provide scopes on the permissions. Right now,
|
||||||
if I sign a tx to one module, it can pass it on to any other module over IPC
|
if I sign a tx 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
|
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
|
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)
|
this signature authorizes. The [oauth
|
||||||
also has to deal with a similar problem, and maybe could provide some inspiration.
|
protocol](https://api.slack.com/docs/oauth-scopes) also has to deal with a
|
||||||
|
similar problem, and maybe could provide some inspiration.
|
||||||
|
|
||||||
|
|
||||||
## Replay Protection
|
## Replay Protection
|
||||||
|
|
||||||
Is implemented as middleware. Rigel can add more info here. Or look
|
In order to prevent [replay
|
||||||
at [the github issue](https://github.com/tendermint/basecoin/issues/160)
|
attacks](https://en.wikipedia.org/wiki/Replay_attack) a multi account nonce system
|
||||||
|
has been constructed as a module, which can be found in
|
||||||
|
`modules/nonce`. By adding the nonce module to the stack, each
|
||||||
|
transaction is verified for authenticity against replay attacks. This is
|
||||||
|
achieved by requiring that a new signed copy of the sequence number which must
|
||||||
|
be exactly 1 greater than the sequence number of the previous transaction. A
|
||||||
|
distinct sequence number is assigned per chain-id, application, and group of
|
||||||
|
signers. Each sequence number is tracked as a nonce-store entry where the key
|
||||||
|
is the marshaled list of actors after having been sorted by chain, app, and
|
||||||
|
address.
|
||||||
|
|
||||||
|
```golang
|
||||||
|
// Tx - Nonce transaction structure, contains list of signers and current sequence number
|
||||||
|
type Tx struct {
|
||||||
|
Sequence uint32 `json:"sequence"`
|
||||||
|
Signers []basecoin.Actor `json:"signers"`
|
||||||
|
Tx basecoin.Tx `json:"tx"`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
By distinguishing sequence numbers across groups of Signers, multi-signature
|
||||||
|
Actors need not lock up use of their Address while waiting for all the members
|
||||||
|
of a multi-sig transaction to occur. Instead only the multi-sig account will
|
||||||
|
be locked, while other accounts belonging to that signer can be used and signed
|
||||||
|
with other sequence numbers.
|
||||||
|
|
||||||
|
By abstracting out the nonce module in the stack, entire series of transactions
|
||||||
|
can occur without needing to verify the nonce for each member of the series. An
|
||||||
|
common example is a stack which will send coins and charge a fee. Within Quark
|
||||||
|
this can be achieved using separate modules in a stack, one to send the coins
|
||||||
|
and the other to charge the fee, however both modules do not need to check the
|
||||||
|
nonce. This can occur as a separate module earlier in the stack.
|
||||||
|
|
||||||
## IBC (Inter-Blockchain Communication)
|
## IBC (Inter-Blockchain Communication)
|
||||||
|
|
||||||
|
|
|
@ -1,96 +1,106 @@
|
||||||
# Standard Library
|
# Standard Library
|
||||||
|
|
||||||
The quarks framework comes with a number of standard modules that provide a lot
|
The Quark framework comes bundled with a number of standard modules that
|
||||||
of common functionality that is useful to a wide variety of applications,
|
provide common functionality useful across a wide variety of applications.
|
||||||
and also provide good examples to use when developing your own modules. Before
|
Example usage of the modules is also provided. It is recommended to investigate
|
||||||
starting to write code, see if the functionality is already here.
|
if desired functionality is already provided before developing new modules.
|
||||||
|
|
||||||
## Basic Middleware
|
## Basic Middleware
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
|
|
||||||
`modules.base.Logger` is a middleware that records basic info on CheckTx,
|
`modules.base.Logger` is a middleware that records basic info on `CheckTx`,
|
||||||
DeliverTx, and SetOption, along with timing in microseconds. It can be installed
|
`DeliverTx`, and `SetOption`, along with timing in microseconds. It can be
|
||||||
standard at the top of all middleware stacks, or replace it with your own
|
installed standard at the top of all middleware stacks, or replaced with your
|
||||||
Middleware if you want to record more custom information with each request.
|
own middleware if you want to record custom information with each request.
|
||||||
|
|
||||||
### Recovery
|
### Recovery
|
||||||
|
|
||||||
To avoid accidental panics (eg. bad go-wire decoding) killing the abci app,
|
To avoid accidental panics (e.g. bad go-wire decoding) killing the ABCI app,
|
||||||
wrap the stack with `stack.Recovery`, which catches all panics and returns
|
wrap the stack with `stack.Recovery`, which catches all panics and returns
|
||||||
them as errors, so they can be handled normally.
|
them as errors, so they can be handled normally.
|
||||||
|
|
||||||
### Signatures
|
### Signatures
|
||||||
|
|
||||||
The first layer of the tx contains the signatures to authorize it. This is then
|
The first layer of the tx contains the signatures to authorize it. This is
|
||||||
verfied by `modules.auth.Signatures`. All tx may have one or multiple signatures
|
then verified by `modules.auth.Signatures`. All tx may have one or multiple
|
||||||
which are then processed and verified by this middleware and then passed down
|
signatures which are then processed and verified by this middleware and then
|
||||||
the stack.
|
passed down the stack.
|
||||||
|
|
||||||
### Chain
|
### Chain
|
||||||
|
|
||||||
The next layer of a tx (in the standard stack) binds the tx to a specific chain
|
The next layer of a tx (in the standard stack) binds the tx to a specific chain
|
||||||
with an optional expiration height. This keeps the tx from being replayed on
|
with an optional expiration height. This keeps the tx from being replayed on
|
||||||
a fork or other such chain, as well as a partially signed multisig being delayed
|
a fork or other such chain, as well as a partially signed multi-sig being delayed
|
||||||
months before being committed to the chain. This functionality is provided in
|
months before being committed to the chain. This functionality is provided in
|
||||||
`modules.base.Chain`
|
`modules.base.Chain`
|
||||||
|
|
||||||
### Nonce
|
### Nonce
|
||||||
|
|
||||||
To avoid replay protection within one chain, we want a nonce associated
|
To avoid replay attacks, a nonce can be associated with each actor. A separate
|
||||||
with each account. Rather than force everything to use coins as a payment,or force each module to implement its own replay protection, each tx is wraped with a nonce and
|
nonce is used for each distinct group signers required for a transaction as
|
||||||
the account it belongs to. This must be one higher than the last request or
|
well as for each separate application and chain-id. This creates replay
|
||||||
the request is rejected. This is implemented in `modules.nonce.ReplayCheck`
|
protection cross-IBC and cross-plugins and also allows signing parties to not
|
||||||
|
be bound to waiting for a particular transaction to be completed before being
|
||||||
|
able to sign a separate transaction.
|
||||||
|
|
||||||
You can also take a look at the [design discussion](https://github.com/tendermint/basecoin/issues/160)
|
Rather than force each module to implement its own replay protection, a tx
|
||||||
|
stack may contain a nonce wrap and the account it belongs to. The nonce must
|
||||||
|
contain a signed sequence number which is incremented one higher than the last
|
||||||
|
request or the request is rejected. This is implemented in
|
||||||
|
`modules.nonce.ReplayCheck`
|
||||||
|
|
||||||
|
If you're interested checkout this [design
|
||||||
|
discussion](https://github.com/tendermint/basecoin/issues/160).
|
||||||
|
|
||||||
### Fees
|
### Fees
|
||||||
|
|
||||||
An optional feature, but useful on many chains, is charging a fee for every
|
An optional feature, but useful on many chains, is charging transaction fees. A
|
||||||
transaction. A simple implementation of this is provided in
|
simple implementation of this is provided in `modules.fee.SimpleFeeMiddleware`.
|
||||||
`modules.fee.SimpleFeeMiddleware`. A fee currency and minimum amount are
|
A fee currency and minimum amount are defined in the constructor (eg. in code).
|
||||||
defined in the constructor (eg. in code). If the minimum amount is 0, then
|
If the minimum amount is 0, then the fee is optional. If it is above 0, then
|
||||||
the fee is optional. If it is above 0, then every tx with insufficient fee is
|
every tx with insufficient fee is rejected. This fee is deducted from the
|
||||||
rejected. This fee is deducted from the payers account before executing any
|
payers account before executing any other transaction.
|
||||||
other transaction.
|
|
||||||
|
|
||||||
This module depends on the `coin` module.
|
This module is dependent on the `coin` module.
|
||||||
|
|
||||||
## Other Apps
|
## Other Apps
|
||||||
|
|
||||||
### Coin
|
### Coin
|
||||||
|
|
||||||
What would a crypto-currency be without tokens? The sendtx logic from basecoin
|
What would a crypto-currency be without tokens? The `SendTx` logic from earlier
|
||||||
was extracted into one module, which is now optional, meaning most of the other
|
implementations of basecoin was extracted into one module, which is now
|
||||||
functionality would also work in a system with no built-in tokens, such as
|
optional, meaning most of the other functionality will also work in a system
|
||||||
a private network that provides another access control mechanism.
|
with no built-in tokens, such as a private network that provides other access
|
||||||
|
control mechanisms.
|
||||||
|
|
||||||
`modules.coin.Handler` defines a Handler that maintains a number of accounts
|
`modules.coin.Handler` defines a Handler that maintains a number of accounts
|
||||||
along with a set of various tokens, supporting multiple denominations. The
|
along with a set of various tokens, supporting multiple token denominations.
|
||||||
main access is `SendTx`, which can support any type of actor (other apps as
|
The main access is `SendTx`, which can support any type of actor (other apps as
|
||||||
well as public key addresses), and is a building block for any other app that
|
well as public key addresses) and is a building block for any other app that
|
||||||
requires some payment solution, like fees or trader.
|
requires some payment solution, like fees or trader.
|
||||||
|
|
||||||
### Roles
|
### Roles
|
||||||
|
|
||||||
Roles encapsulates what are typically called N-of-M multi-signatures accounts
|
Roles encapsulates what are typically called N-of-M multi-signatures accounts
|
||||||
in the crypto world. However, I view this as a type of role or group, which can
|
in the crypto world. However, I view this as a type of role or group, which can
|
||||||
be the basis for building a permision system. For example, a set of people could
|
be the basis for building a permission system. For example, a set of people
|
||||||
be called registrars, which can authorize a new IBC chain, and need eg. 2 out
|
could be called registrars, which can authorize a new IBC chain, and need eg. 2
|
||||||
of 7 signatures to approve it.
|
out of 7 signatures to approve it.
|
||||||
|
|
||||||
Currently, one can create a role with `modules.roles.Handler`, and assume one
|
Currently, one can create a role with `modules.roles.Handler`, and assume one
|
||||||
of those roles by wrapping another transaction with `AssumeRoleTx`, which is
|
of those roles by wrapping another transaction with `AssumeRoleTx`, which is
|
||||||
processed by `modules.roles.Middleware`. Updating the set of actors in
|
processed by `modules.roles.Middleware`. Updating the set of actors in
|
||||||
a role is planned in the near future.
|
a role is planned in the near future.
|
||||||
|
|
||||||
### IBC
|
### Inter-Blockchain Communication (IBC)
|
||||||
|
|
||||||
IBC, or inter-blockchain communication, is the cornerstone of cosmos, and built
|
IBC, is the cornerstone of The Cosmos Network, and is built into the quark
|
||||||
into the quark framework as a basic primative. To properly understand these
|
framework as a basic primitive. To fully grasp these concepts requires
|
||||||
concepts requires a much longer explanation, but in short, the chain works
|
a much longer explanation, but in short, the chain works as a light-client to
|
||||||
as a light-client to another chain and maintains input and output queue to
|
another chain and maintains input and output queue to send packets with that
|
||||||
send packets with that chain.
|
chain. This mechanism allows blockchains to prove the state of their respective
|
||||||
|
blockchains to each other ultimately invoke inter-blockchain transactions.
|
||||||
|
|
||||||
Most functionality is implemented in `modules.ibc.Handler`. Registering a chain
|
Most functionality is implemented in `modules.ibc.Handler`. Registering a chain
|
||||||
is a seed of trust that requires verification of the proper seed (or genesis
|
is a seed of trust that requires verification of the proper seed (or genesis
|
||||||
|
@ -100,7 +110,7 @@ as the new header can be completely verified by the existing knowledge of the
|
||||||
chain. Also, modules can initiate an outgoing IBC message to another chain
|
chain. Also, modules can initiate an outgoing IBC message to another chain
|
||||||
by calling `CreatePacketTx` over IPC (inter-plugin communication) with a tx
|
by calling `CreatePacketTx` over IPC (inter-plugin communication) with a tx
|
||||||
that belongs to their module. (This must be explicitly authorized by the
|
that belongs to their module. (This must be explicitly authorized by the
|
||||||
same module, so only the eg. coin module can authorize a sendtx to another
|
same module, so only the eg. coin module can authorize a `SendTx` to another
|
||||||
chain).
|
chain).
|
||||||
|
|
||||||
`PostPacketTx` can post a tx that was created on another chain along with the
|
`PostPacketTx` can post a tx that was created on another chain along with the
|
||||||
|
@ -127,6 +137,7 @@ governance.
|
||||||
|
|
||||||
### Trader
|
### Trader
|
||||||
|
|
||||||
Escrow, OTC option, Order book. Based on [basecoin-examples](https://github.com/tendermint/basecoin-examples/tree/develop/trader). This may be more appropriate
|
Escrow, OTC option, Order book. Based on
|
||||||
for an external repo.
|
[basecoin-examples](https://github.com/tendermint/basecoin-examples/tree/develop/trader).
|
||||||
|
This may be more appropriate for an external repo.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue