diff --git a/docs/glossary.rst b/docs/glossary.rst new file mode 100644 index 000000000..dc2699074 --- /dev/null +++ b/docs/glossary.rst @@ -0,0 +1,307 @@ +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-wire `__ and +`data `__ 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? + +.. code:: golang + + 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 authorization it has received from another middleware, or 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 `__ +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 +`` + 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 `__), +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. + +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: + +.. code:: golang + + 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. + +Middleware +---------- + +Middleware is a series of processing steps that any request must travel +through before (and after) executing the registered ``Handler``. Some +examples are a logger (that records the time before executing the +transaction, then outputs info - including duration - after the +execution), of a signature checker (which unwraps the transaction by one +layer, verifies signatures, and adds the permissions to the Context +before passing the request along). + +In keeping with the standardization of ``http.Handler`` and inspired by +the super minimal +`negroni `__ +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 also gives us a place to perform isolation of each +step). + +.. code:: golang + + Name() string + CheckTx(ctx Context, store state.KVStore, tx Tx, next Checker) (Result, error) + DeliverTx(ctx Context, store state.KVStore, tx Tx, next Deliver) (Result, error) + SetOption(l log.Logger, store state.KVStore, module, key, value string, next Optioner) (string, error) + +Modules +------- + +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) +- middleware (to handler any wrapper transactions) + +To enable a module, you must add the appropriate middleware (if any) to +the stack in ``main.go`` for the client application (default: +``basecli/main.go``), as well as adding the handler (if any) to the +dispatcher (default: ``app/app.go``). Once the stack is compiled into a +``Handler``, then each transaction is handled by the appropriate module. + +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. + +After the chain of middleware, we can 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-wire via ``TxMapper``, so we just look at the registered name of this +transaction, which should be of the form ``/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-wire 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: + +.. code:: golang + + 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: + +.. code:: golang + + 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 `__ also has to deal +with a similar problem, and maybe could provide some inspiration. + +Replay Protection +----------------- + +In order to prevent `replay +attacks `__ 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. + +.. code:: 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 the SDK 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) +------------------------------------ + +Stay tuned! diff --git a/docs/index.rst b/docs/index.rst index 1b18206b8..911b4297f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -27,9 +27,7 @@ Basecoin :maxdepth: 2 basecoin/basics.rst - basecoin/tool.rst basecoin/plugins.rst - basecoin/kubernetes.rst Staking Module --------------