From b655d902deeea83ae80457216a4ab25ddd37cd46 Mon Sep 17 00:00:00 2001 From: Zach Ramsay Date: Fri, 2 Feb 2018 20:28:47 +0000 Subject: [PATCH] docs: remove reference to middleware/isolation --- docs/glossary.rst | 29 +-- docs/ibc.rst | 424 ++++++++++++++++++++++++++++++++++++++++++ docs/sdk/overview.rst | 399 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 832 insertions(+), 20 deletions(-) create mode 100644 docs/ibc.rst create mode 100644 docs/sdk/overview.rst diff --git a/docs/glossary.rst b/docs/glossary.rst index dc2699074..165b6a74b 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -44,8 +44,7 @@ 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 +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 @@ -90,18 +89,18 @@ 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 `__. +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 `__), +`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 +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. @@ -152,7 +151,7 @@ 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 +together (which also gives us a place to perform seperation of each step). .. code:: golang @@ -165,6 +164,8 @@ step). 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: @@ -172,13 +173,6 @@ self-sufficient. Common elements of a module are: - 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 ---------- @@ -189,7 +183,7 @@ 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 +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 @@ -300,8 +294,3 @@ 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/ibc.rst b/docs/ibc.rst new file mode 100644 index 000000000..ab6539fa5 --- /dev/null +++ b/docs/ibc.rst @@ -0,0 +1,424 @@ +InterBlockchain Communication with the Cosmos SDK +================================================= + +TODO: update in light of latest SDK (this document is currently out of date) + +One of the most exciting elements of the Cosmos Network is the +InterBlockchain Communication (IBC) protocol, which enables +interoperability across different blockchains. We implemented IBC as a +basecoin plugin, and we'll show you how to use it to send tokens across +blockchains! + +Please note: this tutorial assumes familiarity with the Cosmos SDK. + +The IBC plugin defines a new set of transactions as subtypes of the +``AppTx``. The plugin's functionality is accessed by setting the +``AppTx.Name`` field to ``"IBC"``, and setting the ``Data`` field to the +serialized IBC transaction type. + +We'll demonstrate exactly how this works below. + +IBC +--- + +Let's review the IBC protocol. The purpose of IBC is to enable one +blockchain to function as a light-client of another. Since we are using +a classical Byzantine Fault Tolerant consensus algorithm, light-client +verification is cheap and easy: all we have to do is check validator +signatures on the latest block, and verify a Merkle proof of the state. + +In Tendermint, validators agree on a block before processing it. This +means that the signatures and state root for that block aren't included +until the next block. Thus, each block contains a field called +``LastCommit``, which contains the votes responsible for committing the +previous block, and a field in the block header called ``AppHash``, +which refers to the Merkle root hash of the application after processing +the transactions from the previous block. So, if we want to verify the +``AppHash`` from height H, we need the signatures from ``LastCommit`` at +height H+1. (And remember that this ``AppHash`` only contains the +results from all transactions up to and including block H-1) + +Unlike Proof-of-Work, the light-client protocol does not need to +download and check all the headers in the blockchain - the client can +always jump straight to the latest header available, so long as the +validator set has not changed much. If the validator set is changing, +the client needs to track these changes, which requires downloading +headers for each block in which there is a significant change. Here, we +will assume the validator set is constant, and postpone handling +validator set changes for another time. + +Now we can describe exactly how IBC works. Suppose we have two +blockchains, ``chain1`` and ``chain2``, and we want to send some data +from ``chain1`` to ``chain2``. We need to do the following: 1. Register +the details (ie. chain ID and genesis configuration) of ``chain1`` on +``chain2`` 2. Within ``chain1``, broadcast a transaction that creates an +outgoing IBC packet destined for ``chain2`` 3. Broadcast a transaction +to ``chain2`` informing it of the latest state (ie. header and commit +signatures) of ``chain1`` 4. Post the outgoing packet from ``chain1`` to +``chain2``, including the proof that it was indeed committed on +``chain1``. Note ``chain2`` can only verify this proof because it has a +recent header and commit. + +Each of these steps involves a separate IBC transaction type. Let's take +them up in turn. + +IBCRegisterChainTx +~~~~~~~~~~~~~~~~~~ + +The ``IBCRegisterChainTx`` is used to register one chain on another. It +contains the chain ID and genesis configuration of the chain to +register: + +.. code:: golang + + type IBCRegisterChainTx struct { BlockchainGenesis } + + type BlockchainGenesis struct { ChainID string Genesis string } + +This transaction should only be sent once for a given chain ID, and +successive sends will return an error. + +IBCUpdateChainTx +~~~~~~~~~~~~~~~~ + +The ``IBCUpdateChainTx`` is used to update the state of one chain on +another. It contains the header and commit signatures for some block in +the chain: + +.. code:: golang + + type IBCUpdateChainTx struct { + Header tm.Header + Commit tm.Commit + } + +In the future, it needs to be updated to include changes to the +validator set as well. Anyone can relay an ``IBCUpdateChainTx``, and +they only need to do so as frequently as packets are being sent or the +validator set is changing. + +IBCPacketCreateTx +~~~~~~~~~~~~~~~~~ + +The ``IBCPacketCreateTx`` is used to create an outgoing packet on one +chain. The packet itself contains the source and destination chain IDs, +a sequence number (i.e. an integer that increments with every message +sent between this pair of chains), a packet type (e.g. coin, data, +etc.), and a payload. + +.. code:: golang + + type IBCPacketCreateTx struct { + Packet + } + + type Packet struct { + SrcChainID string + DstChainID string + Sequence uint64 + Type string + Payload []byte + } + +We have yet to define the format for the payload, so, for now, it's just +arbitrary bytes. + +One way to think about this is that ``chain2`` has an account on +``chain1``. With a ``IBCPacketCreateTx`` on ``chain1``, we send funds to +that account. Then we can prove to ``chain2`` that there are funds +locked up for it in it's account on ``chain1``. Those funds can only be +unlocked with corresponding IBC messages back from ``chain2`` to +``chain1`` sending the locked funds to another account on ``chain1``. + +IBCPacketPostTx +~~~~~~~~~~~~~~~ + +The ``IBCPacketPostTx`` is used to post an outgoing packet from one +chain to another. It contains the packet and a proof that the packet was +committed into the state of the sending chain: + +.. code:: golang + + type IBCPacketPostTx struct { + FromChainID string // The immediate source of the packet, not always Packet.SrcChainID + FromChainHeight uint64 // The block height in which Packet was committed, to check Proof Packet + Proof *merkle.IAVLProof + } + +The proof is a Merkle proof in an IAVL tree, our implementation of a +balanced, Merklized binary search tree. It contains a list of nodes in +the tree, which can be hashed together to get the Merkle root hash. This +hash must match the ``AppHash`` contained in the header at +``FromChainHeight + 1`` + +- note the ``+ 1`` is necessary since ``FromChainHeight`` is the height + in which the packet was committed, and the resulting state root is + not included until the next block. + +IBC State +~~~~~~~~~ + +Now that we've seen all the transaction types, let's talk about the +state. Each chain stores some IBC state in its Merkle tree. For each +chain being tracked by our chain, we store: + +- Genesis configuration +- Latest state +- Headers for recent heights + +We also store all incoming (ingress) and outgoing (egress) packets. + +The state of a chain is updated every time an ``IBCUpdateChainTx`` is +committed. New packets are added to the egress state upon +``IBCPacketCreateTx``. New packets are added to the ingress state upon +``IBCPacketPostTx``, assuming the proof checks out. + +Merkle Queries +-------------- + +The Basecoin application uses a single Merkle tree that is shared across +all its state, including the built-in accounts state and all plugin +state. For this reason, it's important to use explicit key names and/or +hashes to ensure there are no collisions. + +We can query the Merkle tree using the ABCI Query method. If we pass in +the correct key, it will return the corresponding value, as well as a +proof that the key and value are contained in the Merkle tree. + +The results of a query can thus be used as proof in an +``IBCPacketPostTx``. + +Relay +----- + +While we need all these packet types internally to keep track of all the +proofs on both chains in a secure manner, for the normal work-flow, we +can run a relay node that handles the cross-chain interaction. + +In this case, there are only two steps. First ``basecoin relay init``, +which must be run once to register each chain with the other one, and +make sure they are ready to send and recieve. And then +``basecoin relay start``, which is a long-running process polling the +queue on each side, and relaying all new message to the other block. + +This requires that the relay has access to accounts with some funds on +both chains to pay for all the ibc packets it will be forwarding. + +Try it out +---------- + +Now that we have all the background knowledge, let's actually walk +through the tutorial. + +Make sure you have installed `basecoin and +basecli `__. + +Basecoin is a framework for creating new cryptocurrency applications. It +comes with an ``IBC`` plugin enabled by default. + +You will also want to install the +`jq `__ for handling JSON at the command +line. + +If you have any trouble with this, you can also look at the `test +scripts `__ or just run ``make test_cli`` in basecoin +repo. Otherwise, open up 5 (yes 5!) terminal tabs.... + +Preliminaries +~~~~~~~~~~~~~ + +:: + + # first, clean up any old garbage for a fresh slate... + rm -rf ~/.ibcdemo/ + +Let's start by setting up some environment variables and aliases: + +:: + + export BCHOME1_CLIENT=~/.ibcdemo/chain1/client + export BCHOME1_SERVER=~/.ibcdemo/chain1/server + export BCHOME2_CLIENT=~/.ibcdemo/chain2/client + export BCHOME2_SERVER=~/.ibcdemo/chain2/server + alias basecli1="basecli --home $BCHOME1_CLIENT" + alias basecli2="basecli --home $BCHOME2_CLIENT" + alias basecoin1="basecoin --home $BCHOME1_SERVER" + alias basecoin2="basecoin --home $BCHOME2_SERVER" + +This will give us some new commands to use instead of raw ``basecli`` +and ``basecoin`` to ensure we're using the right configuration for the +chain we want to talk to. + +We also want to set some chain IDs: + +:: + + export CHAINID1="test-chain-1" + export CHAINID2="test-chain-2" + +And since we will run two different chains on one machine, we need to +maintain different sets of ports: + +:: + + export PORT_PREFIX1=1234 + export PORT_PREFIX2=2345 + export RPC_PORT1=${PORT_PREFIX1}7 + export RPC_PORT2=${PORT_PREFIX2}7 + +Setup Chain 1 +~~~~~~~~~~~~~ + +Now, let's create some keys that we can use for accounts on +test-chain-1: + +:: + + basecli1 keys new money + basecli1 keys new gotnone + export MONEY=$(basecli1 keys get money | awk '{print $2}') + export GOTNONE=$(basecli1 keys get gotnone | awk '{print $2}') + +and create an initial configuration giving lots of coins to the $MONEY +key: + +:: + + basecoin1 init --chain-id $CHAINID1 $MONEY + +Now start basecoin: + +:: + + sed -ie "s/4665/$PORT_PREFIX1/" $BCHOME1_SERVER/config.toml + + basecoin1 start &> basecoin1.log & + +Note the ``sed`` command to replace the ports in the config file. You +can follow the logs with ``tail -f basecoin1.log`` + +Now we can attach the client to the chain and verify the state. The +first account should have money, the second none: + +:: + + basecli1 init --node=tcp://localhost:${RPC_PORT1} --genesis=${BCHOME1_SERVER}/genesis.json + basecli1 query account $MONEY + basecli1 query account $GOTNONE + +Setup Chain 2 +~~~~~~~~~~~~~ + +This is the same as above, except with ``basecli2``, ``basecoin2``, and +``$CHAINID2``. We will also need to change the ports, since we're +running another chain on the same local machine. + +Let's create new keys for test-chain-2: + +:: + + basecli2 keys new moremoney + basecli2 keys new broke + MOREMONEY=$(basecli2 keys get moremoney | awk '{print $2}') + BROKE=$(basecli2 keys get broke | awk '{print $2}') + +And prepare the genesis block, and start the server: + +:: + + basecoin2 init --chain-id $CHAINID2 $(basecli2 keys get moremoney | awk '{print $2}') + + sed -ie "s/4665/$PORT_PREFIX2/" $BCHOME2_SERVER/config.toml + + basecoin2 start &> basecoin2.log & + +Now attach the client to the chain and verify the state. The first +account should have money, the second none: + +:: + + basecli2 init --node=tcp://localhost:${RPC_PORT2} --genesis=${BCHOME2_SERVER}/genesis.json + basecli2 query account $MOREMONEY + basecli2 query account $BROKE + +Connect these chains +~~~~~~~~~~~~~~~~~~~~ + +OK! So we have two chains running on your local machine, with different +keys on each. Let's hook them up together by starting a relay process to +forward messages from one chain to the other. + +The relay account needs some money in it to pay for the ibc messages, so +for now, we have to transfer some cash from the rich accounts before we +start the actual relay. + +:: + + # note that this key.json file is a hardcoded demo for all chains, this will + # be updated in a future release + RELAY_KEY=$BCHOME1_SERVER/key.json + RELAY_ADDR=$(cat $RELAY_KEY | jq .address | tr -d \") + + basecli1 tx send --amount=100000mycoin --sequence=1 --to=$RELAY_ADDR--name=money + basecli1 query account $RELAY_ADDR + + basecli2 tx send --amount=100000mycoin --sequence=1 --to=$RELAY_ADDR --name=moremoney + basecli2 query account $RELAY_ADDR + +Now we can start the relay process. + +:: + + basecoin relay init --chain1-id=$CHAINID1 --chain2-id=$CHAINID2 \ + --chain1-addr=tcp://localhost:${RPC_PORT1} --chain2-addr=tcp://localhost:${RPC_PORT2} \ + --genesis1=${BCHOME1_SERVER}/genesis.json --genesis2=${BCHOME2_SERVER}/genesis.json \ + --from=$RELAY_KEY + + basecoin relay start --chain1-id=$CHAINID1 --chain2-id=$CHAINID2 \ + --chain1-addr=tcp://localhost:${RPC_PORT1} --chain2-addr=tcp://localhost:${RPC_PORT2} \ + --from=$RELAY_KEY &> relay.log & + +This should start up the relay, and assuming no error messages came out, +the two chains are now fully connected over IBC. Let's use this to send +our first tx accross the chains... + +Sending cross-chain payments +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The hard part is over, we set up two blockchains, a few private keys, +and a secure relay between them. Now we can enjoy the fruits of our +labor... + +:: + + # Here's an empty account on test-chain-2 + basecli2 query account $BROKE + +:: + + # Let's send some funds from test-chain-1 + basecli1 tx send --amount=12345mycoin --sequence=2 --to=test-chain-2/$BROKE --name=money + +:: + + # give it time to arrive... + sleep 2 + # now you should see 12345 coins! + basecli2 query account $BROKE + +You're no longer broke! Cool, huh? Now have fun exploring and sending +coins across the chains. And making more accounts as you want to. + +Conclusion +---------- + +In this tutorial we explained how IBC works, and demonstrated how to use +it to communicate between two chains. We did the simplest communciation +possible: a one way transfer of data from chain1 to chain2. The most +important part was that we updated chain2 with the latest state (i.e. +header and commit) of chain1, and then were able to post a proof to +chain2 that a packet was committed to the outgoing state of chain1. + +In a future tutorial, we will demonstrate how to use IBC to actually +transfer tokens between two blockchains, but we'll do it with real +testnets deployed across multiple nodes on the network. Stay tuned! diff --git a/docs/sdk/overview.rst b/docs/sdk/overview.rst new file mode 100644 index 000000000..b64288ae7 --- /dev/null +++ b/docs/sdk/overview.rst @@ -0,0 +1,399 @@ +SDK Overview +============ + +The SDK design optimizes flexibility and security. The +framework is designed around a modular execution stack which allows +applications to mix and match modular elements as desired. In addition, +all modules are sandboxed for greater application security. + +Framework Overview +------------------ + +### Object-Capability Model + +When thinking about security, it's good to start with a specific threat model. Our threat model is the following: + +> We want to assume a thriving ecosystem of Cosmos-SDK modules that are easy to compose into a blockchain application. Some of these modules will be faulty or malicious. + +The Cosmos-SDK is designed to address this threat by being the foundation of an object capability system. + +``` +The structural properties of object capability systems favor +modularity in code design and ensure reliable encapsulation in +code implementation. + +These structural properties facilitate the analysis of some +security properties of an object-capability program or operating +system. Some of these — in particular, information flow properties +— can be analyzed at the level of object references and +connectivity, independent of any knowledge or analysis of the code +that determines the behavior of the objects. As a consequence, +these security properties can be established and maintained in the +presence of new objects that contain unknown and possibly +malicious code. + +These structural properties stem from the two rules governing +access to existing objects: + +1) An object A can send a message to B only if object A holds a +reference to B. + +2) An object A can obtain a reference to C only +if object A receives a message containing a reference to C. As a +consequence of these two rules, an object can obtain a reference +to another object only through a preexisting chain of references. +In short, "Only connectivity begets connectivity." + +- https://en.wikipedia.org/wiki/Object-capability_model +``` + +Strictly speaking, Golang does not implement object capabilities completely, because of several issues: + +* pervasive ability to import primitive modules (e.g. "unsafe", "os") +* pervasive ability to override module vars https://github.com/golang/go/issues/23161 +* data-race vulnerability where 2+ goroutines can create illegal interface values + +The first is easy to catch by auditing imports and using a proper dependency version control system like Glide. The second and third are unfortunate but it can be audited with some cost. + +Perhaps [Go2 will implement the object capability model](https://github.com/golang/go/issues/23157). + +### What does it look like? + +Only reveal what is necessary to get the work done. + +For example, the following code snippet violates the object capabilities principle: + +```golang +type AppAccount struct {...} +var account := &AppAccount{ + Address: pub.Address(), + Coins: sdk.Coins{{"ATM", 100}}, +} +var sumValue := externalModule.ComputeSumValue(account) +``` + +The method "ComputeSumValue" implies a pure function, yet the implied capability of accepting a pointer value is the capability to modify that value. The preferred method signature should take a copy instead. + +```golang +var sumValue := externalModule.ComputeSumValue(*account) +``` + +In the Cosmos SDK, you can see the application of this principle in the basecoin examples folder. + +```golang +// File: cosmos-sdk/examples/basecoin/app/init_handlers.go +package app + +import ( + "github.com/cosmos/cosmos-sdk/x/bank" + "github.com/cosmos/cosmos-sdk/x/sketchy" +) + +func (app *BasecoinApp) initRouterHandlers() { + + // All handlers must be added here. + // The order matters. + app.router.AddRoute("bank", bank.NewHandler(app.accountMapper)) + app.router.AddRoute("sketchy", sketchy.NewHandler()) +} +``` + +In the Basecoin example, the sketchy handler isn't provided an account mapper, which does provide the bank handler with the capability (in conjunction with the context of a transaction run). + +Security Overview +----------------- + +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 "capabilities 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 determine the type's +unique "prefix bytes" during encoding. A registered type will always use the +same prefix-bytes, regardless of what interface it is satisfying. For more +details, see the [go-wire documentation](https://github.com/tendermint/go-wire/blob/develop). + + +## MultiStore + +### 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 after the Golang `context.Context` object, which has +become ubiquitous in networking middleware and routing applications as a means +to easily propogate request context through handler functions. + +The main information stored in the `Context` includes the application +MultiStore (see below), the last block header, and the transaction bytes. +Effectively, the context contains all data that may be necessary for processing +a transaction. + +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 state (all referenced from the +root MultiStore), a particular handler only needs a particular kind of access +to a particular store (or two or more). Access to stores is managed using +capabilities keys and mappers. When a handler is initialized, it is passed a +key or mapper that gives it access to the relevant stores. + +```golang +// File: cosmos-sdk/examples/basecoin/app/init_stores.go +app.BaseApp.MountStore(app.capKeyMainStore, sdk.StoreTypeIAVL) +app.accountMapper = auth.NewAccountMapper( + app.capKeyMainStore, // target store + &types.AppAccount{}, // prototype +) + +// File: cosmos-sdk/examples/basecoin/app/init_handlers.go +app.router.AddRoute("bank", bank.NewHandler(app.accountMapper)) + +// File: cosmos-sdk/x/bank/handler.go +// NOTE: Technically, NewHandler only needs a CoinMapper +func NewHandler(am sdk.AccountMapper) sdk.Handler { + return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { + cm := CoinMapper{am} + ... + } +} +``` + +## AnteHandler + +### 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