From cb253cbdf4ea30ccec62e7cfee0bb1ae2a2c0d11 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Sun, 5 Feb 2017 00:43:55 -0500 Subject: [PATCH] docs: design, examples --- README.md | 2 +- docs/guide/basecoin-design.md | 81 +++++++++++++++++++++++++++ docs/guide/more-examples.md | 11 +++- docs/guide/plugin-design.md | 100 +++++++++++++++++++++------------- 4 files changed, 153 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 6c5e917cd2..b6c468aa60 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ See `basecoin --help` and `basecoin [cmd] --help` for more details`. 1. Make your own [cryptocurrency using Basecoin plugins](/docs/guide/example-counter.md) 1. Learn more about [plugin design](/docs/guide/plugin-design.md) 1. See some [more example applications](/docs/guide/more-examples.md) -1. Learn how to use [InterBlockchain Communication (IBC)](ibc.md) +1. Learn how to use [InterBlockchain Communication (IBC)](/docs/guide/ibc.md) 1. [Deploy testnets](deployment.md) running your basecoin application. diff --git a/docs/guide/basecoin-design.md b/docs/guide/basecoin-design.md index e69de29bb2..8240106c11 100644 --- a/docs/guide/basecoin-design.md +++ b/docs/guide/basecoin-design.md @@ -0,0 +1,81 @@ +# Basecoin Design + +Basecoin is designed to be a simple cryptocurrency application with limitted built-in functionality, +but with the capacity to be extended by arbitrary plugins. +Its basic data structures are inspired by Ethereum, but it is much simpler, as there is no built in virtual machine. + +## Accounts + +The Basecoin state consists entirely of a set of accounts. +Each account contains an ED25519 public key, +a balance in many different coin denominations, +and a strictly increasing sequence number for replay protection. +This type of account was directly inspired by accounts in Ethereum, +and is unlike Bitcoin's use of Unspent Transaction Outputs (UTXOs). +Note Basecoin is a multi-asset cryptocurrency, so each account can have many different kinds of tokens. + +Accounts are serialized and stored in a Merkle tree using the account's address as the key, +where the address is the RIPEMD160 hash of the public key. +In particular, an account is stored in the Merkle tree under the key `base/a/
`, +where `
` is the 20-byte address of the account. +We use an implementation of a Merkle, balanced, binary search tree, also known as an [IAVL tree](https://github.com/tendermint/go-merkle). + +## Transactions + +Basecoin defines a simple transaction type, the `SendTx`, which allows tokens to be sent to other accounts. +The `SendTx` takes a list of inputs and a list of outputs, +and transfers all the tokens listed in the inputs from their corresponding accounts to the accounts listed in the output. +The `SendTx` is structured as follows: + +``` +type SendTx struct { + Gas int64 `json:"gas"` + Fee Coin `json:"fee"` + Inputs []TxInput `json:"inputs"` + Outputs []TxOutput `json:"outputs"` +} + +type TxInput struct { + Address []byte `json:"address"` // Hash of the PubKey + Coins Coins `json:"coins"` // + Sequence int `json:"sequence"` // Must be 1 greater than the last committed TxInput + Signature crypto.Signature `json:"signature"` // Depends on the PubKey type and the whole Tx + PubKey crypto.PubKey `json:"pub_key"` // Is present iff Sequence == 0 +} + +type TxOutput struct { + Address []byte `json:"address"` // Hash of the PubKey + Coins Coins `json:"coins"` // +} + +type Coins []Coin + +type Coin struct { + Denom string `json:"denom"` + Amount int64 `json:"amount"` +} + +``` + +There are a few things to note. First, the `SendTx` includes a field for `Gas` and `Fee`. +The `Gas` limits the total amount of computation that can be done by the transaction, +while the `Fee` refers to the total amount paid in fees. +This is slightly different from Ethereum's concept of `Gas` and `GasPrice`, +where `Fee = Gas x GasPrice`. In Basecoin, the `Gas` and `Fee` are independent, +and the `GasPrice` is implicit. + +Second, notice that the `PubKey` only needs to be sent for `Sequence == 0`. +After that, it is stored under the account in the Merkle tree and subsequent transactions can exclude it, +using only the `Address` to refer to the sender. Ethereum does not require public keys to be sent in transactions +as it uses a different elliptic curve scheme which enables the public key to be derrived from the signature itself. + +Finally, note that the use of multiple inputs and multiple outputs allows us to send many different types of tokens between many different accounts +at once in an atomic transaction. Thus, the `SendTx` can serve as a basic unit of decentralized exchange. + +## Next steps + +1. Make your own [cryptocurrency using Basecoin plugins](example-counter.md) +1. Learn more about [plugin design](plugin-design.md) +1. See some [more example applications](more-examples.md) +1. Learn how to use [InterBlockchain Communication (IBC)](ibc.md) +1. [Deploy testnets](deployment.md) running your basecoin application. diff --git a/docs/guide/more-examples.md b/docs/guide/more-examples.md index ba1d94b134..ad17c77a66 100644 --- a/docs/guide/more-examples.md +++ b/docs/guide/more-examples.md @@ -1,8 +1,17 @@ +# Plugin Examples + +Now that we've seen how to use Basecoin, talked about the design, +and looked at how to implement a simple plugin, let's take a look at some more interesting examples. ## Mintcoin +Basecoin does not provide any functionality for adding new tokens to the system. +The state is endowed with tokens by a `genesis.json` file which is read once when the system is first started. +From there, tokens can be sent to other accounts, even new accounts, but it's impossible to add more tokens to the system. +For this, we need a plugin. -You just read about the amazing [plugin system](https://github.com/tendermint/basecoin/blob/develop/Plugins.md), and want to use it to print your own money. Me too! Let's get started with a simple plugin extension to basecoin, called [mintcoin](./mintcoin/README.md). This plugin lets you register one or more accounts as "central bankers", who can unilaterally issue more currency into the system. It also serves as a simple test-bed to see how one can not just build a plugin, but also take advantage of existing codebases to provide a simple cli to use it. +The `mintcoin` plugin lets you register one or more accounts as "central bankers", +who can unilaterally issue more currency into the system. ## Financial Instruments diff --git a/docs/guide/plugin-design.md b/docs/guide/plugin-design.md index 6be526a8ae..127c51960b 100644 --- a/docs/guide/plugin-design.md +++ b/docs/guide/plugin-design.md @@ -1,50 +1,72 @@ # Basecoin Plugins -Basecoin is an extensible cryptocurrency module. -Each Basecoin account contains a ED25519 public key, -a balance in many different coin denominations, -and a strictly increasing sequence number for replay protection (like in Ethereum). -Accounts are serialized and stored in a merkle tree using the account's address as the key, -where the address is the RIPEMD160 hash of the public key. +Basecoin implements a simple cryptocurrency, which is useful in and of itself, +but is far more useful if it can support additional functionality. +Here we describe how that functionality can be achieved through a plugin system. -Sending tokens around is done via the `SendTx`, which takes a list of inputs and a list of outputs, -and transfers all the tokens listed in the inputs from their corresponding accounts to the accounts listed in the output. -The `SendTx` is structured as follows: + +## AppTx + +In addition to the `SendTx`, Basecoin also defines another transaction type, the `AppTx`: ``` -type SendTx struct { - Gas int64 `json:"gas"` // Gas - Fee Coin `json:"fee"` // Fee - Inputs []TxInput `json:"inputs"` - Outputs []TxOutput `json:"outputs"` +type AppTx struct { + Gas int64 `json:"gas"` + Fee Coin `json:"fee"` + Input TxInput `json:"input"` + Name string `json:"type"` // Name of the plugin + Data []byte `json:"data"` // Data for the plugin to process } - -type TxInput struct { - Address []byte `json:"address"` // Hash of the PubKey - Coins Coins `json:"coins"` // - Sequence int `json:"sequence"` // Must be 1 greater than the last committed TxInput - Signature crypto.Signature `json:"signature"` // Depends on the PubKey type and the whole Tx - PubKey crypto.PubKey `json:"pub_key"` // Is present iff Sequence == 0 -} - -type TxOutput struct { - Address []byte `json:"address"` // Hash of the PubKey - Coins Coins `json:"coins"` // -} - -type Coins []Coin - -type Coin struct { - Denom string `json:"denom"` - Amount int64 `json:"amount"` -} - ``` -Note it also includes a field for `Gas` and `Fee`. The `Gas` limits the total amount of computation that can be done by the transaction, -while the `Fee` refers to the total amount paid in fees. This is slightly different from Ethereum's concept of `Gas` and `GasPrice`, -where `Fee = Gas x GasPrice`. In Basecoin, the `Gas` and `Fee` are independent. +The `AppTx` enables Basecoin to be extended with arbitrary additional functionality through the use of plugins. +The `Name` field in the `AppTx` refers to the particular plugin which should process the transasaction, +and the `Data` field of the `AppTx` is the data to be forwarded to the plugin for processing. + +Note the `AppTx` also has a `Gas` and `Fee`, with the same meaning as for the `SendTx`. +It also includes a single `TxInput`, which specifies the sender of the transaction, +and some coins that can be forwarded to the plugin as well. + +## Plugins + +A plugin is simply a Go package that implements the `Plugin` interface: + +``` +type Plugin interface { + + // Name of this plugin, should be short. + Name() string + + // Run a transaction from ABCI DeliverTx + RunTx(store KVStore, ctx CallContext, txBytes []byte) (res abci.Result) + + // Other ABCI message handlers + SetOption(store KVStore, key string, value string) (log string) + InitChain(store KVStore, vals []*abci.Validator) + BeginBlock(store KVStore, height uint64) + EndBlock(store KVStore, height uint64) []*abci.Validator +} + +type CallContext struct { + CallerAddress []byte // Caller's Address (hash of PubKey) + CallerAccount *Account // Caller's Account, w/ fee & TxInputs deducted + Coins Coins // The coins that the caller wishes to spend, excluding fees +} +``` + +The workhorse of the plugin is `RunTx`, which is called when an `AppTx` is processed. +The `Data` from the `AppTx` is passed in as the `txBytes`, +while the `Input` from the `AppTx` is used to populate the `CallContext`. + +Note that `RunTx` also takes a `KVStore` - this is an abstraction for the underlying Merkle tree which stores the account data. +By passing this to the plugin, we enable plugins to update accounts in the Basecoin state directly, +and also to store arbitrary other information in the state. +In this way, the functionality and state of a Basecoin-derrived cryptocurrency can be greatly extended. +One could imagine going so far as to implement the Ethereum Virtual Machine as a plugin! -Basecoin also defines another transaction type, the `AppTx`: +## Next steps +1. Examples of [Basecoin plugins](more-examples.md) +1. Learn how to use [InterBlockchain Communication (IBC)](ibc.md) +1. [Deploy testnets](deployment.md) running your basecoin application.