major docs upgrade

This commit is contained in:
Ethan Buchman 2017-02-03 21:17:11 -05:00
parent 5c9d63c6e0
commit 8fda433847
9 changed files with 488 additions and 93 deletions

View File

@ -2,20 +2,16 @@
DISCLAIMER: Basecoin is not associated with Coinbase.com, an excellent Bitcoin/Ethereum service.
Basecoin is a sample [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. This project has two main purposes:
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.
It also provides a general purpose framework for extending the feature-set of the cryptocurrency
by implementing plugins.
1. As an example for anyone wishing to build a custom application using tendermint.
2. As a framework for anyone wishing to build a tendermint-based currency, extensible using the plugin system.
Basecoin serves as a reference implementation for how we build ABCI applications in Go,
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.
If you wish to use basecoin as a framework to build your application, you most likely do not need to fork basecoin or modify it in any way. In fact, even the cli tool is designed to be easily extended by third party repos with almost no copying of code. You just need to add basecoin as a dependency in the `vendor` dir and take a look at [some examples](https://github.com/tendermint/basecoin-examples/blob/master/README.md) of how to customize it without modifying the code.
## Contents
1. [Installation](#installation)
1. [Using the plugin system](#using-the-plugin-system)
1. [Using the cli](#using-the-cli)
1. [Tutorials and other reading](#tutorials-and-other-reading)
1. [Contributing](#contributing)
WARNING: Currently uses plain-text private keys for transactions and is otherwise not production ready.
## Installation
@ -30,49 +26,21 @@ make install
This will create the `basecoin` binary in `$GOPATH/bin`.
## Using the Plugin System
## Command Line Interface
Basecoin is designed to serve as a common base layer for developers building cryptocurrency applications.
It handles public-key authentication of transactions, maintaining the balance of arbitrary types of currency (BTC, ATOM, ETH, MYCOIN, ...),
sending currency (one-to-one or n-to-m multisig), and providing merkle-proofs of the state.
These are common factors that many people wish to have in a crypto-currency system,
so instead of trying to start from scratch, developers can extend the functionality of Basecoin using the plugin system, just writing the custom business logic they need, and leaving the rest to the basecoin system.
Interested in building a plugin? Then [read more details here](./Plugins.md) and then you can follow a [simple tutorial](https://github.com/tendermint/basecoin-examples/blob/master/pluginDev/tutorial.md) to get your first plugin working.
### Best Practices
We are still trying out sort out the best practices for basecoin plugins, and ABCi apps in general. Flexibility is very powerful once one has mastered a system, but when starting out, it is nice to have a set of guidelines to follow (and then expand beyond when no longer needed). I have attempted to gather some [good design practices](https://github.com/tendermint/basecoin-examples/tree/master/trader#code-design) I have discovered/invented while building progress. These are not hard rules, but should give you a good start. And please give feedback to improve and extend them.
## Using the CLI
The basecoin cli can be used to start a stand-alone basecoin instance (`basecoin start`),
The basecoin CLI can be used to start a stand-alone basecoin instance (`basecoin start`),
or to start basecoin with tendermint in the same process (`basecoin start --in-proc`).
It can also be used to send transactions, eg. `basecoin sendtx --to 0x4793A333846E5104C46DD9AB9A00E31821B2F301 --amount 100`
See `basecoin --help` and `basecoin [cmd] --help` for more details`.
Or follow through a [step-by-step introduction](https://github.com/tendermint/basecoin-examples/blob/master/tutorial.md) to testing basecoin locally.
## Learn more
## Tutorials and Other Reading
1. Getting started with the [Basecoin tool](/docs/guide/basecoin-basics.md)
1. Learn more about [Basecoin's design](/docs/guide/basecoin-design.md)
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. [Deploy testnets](deployment.md) running your basecoin application.
See our [introductory blog post](https://cosmos.network/blog/cosmos-creating-interoperable-blockchains-part-1), which explains the motivation behind Basecoin.
There are a [number of examples](https://github.com/tendermint/basecoin-examples/blob/master/README.md) along with some tutorials and introductory texts, that should give you some pointers on how to wirte you own plugins and integrate them into your own custom app.
We are working on extending these examples, as well as documenting (and automating) setting up a testnet, and providing an example GUI for viewing basecoin, which can all be used as a starting point for your application. They should be published during the course of February 2017, so stay tuned....
## Contributing
We will merge in interesting plugin implementations and improvements to Basecoin.
If you don't have much experience forking in go, there are a few tricks you want to keep in mind to avoid headaches. Basically, all imports in go are absolute from GOPATH, so if you fork a repo with more than one directory, and you put it under github.com/MYNAME/repo, all the code will start calling github.com/ORIGINAL/repo, which is very confusing. My preferred solution to this is as follows:
* Create your own fork on github, using the fork button.
* Go to the original repo checked out locally (from `go get`)
* `git remote rename origin upstream`
* `git remote add origin git@github.com:YOUR-NAME/basecoin.git`
* `git push -u origin master`
* You can now push all changes to your fork and all code compiles, all other code referencing the original repo, now references your fork.
* If you want to pull in updates from the original repo:
* `git fetch upstream`
* `git rebase upstream/master` (or whatever branch you want)

View File

@ -0,0 +1,145 @@
# Basecoin Basics
Here we explain how to get started with a simple Basecoin blockchain, and how to send transactions between accounts using the `basecoin` tool.
## Install
Make sure you have [basecoin installed](install.md).
You will also need to [install tendermint](https://tendermint.com/intro/getting-started/download).
## Initialization
Basecoin is an ABCI application that runs on Tendermint, so we first need to initialize Tendermint:
```
tendermint init
```
This will create the necessary files for a single Tendermint node in `~/.tendermint`.
If you had previously run tendermint, make sure you reset the chain
(note this will delete all chain data, so back it up if you need it):
```
tendermint unsafe_reset_all
```
Now we need some initialization files for basecoin.
We have included some defaults in the basecoin directory, under `data`.
For purposes of convenience, change to that directory:
```
cd $GOPATH/src/github.com/tendermint/basecoin/data
```
The directory contains a genesis file and two private keys.
You can generate your own private keys with `tendermint gen_validator`,
and construct the `genesis.json` as you like.
## Start
Now we can start basecoin:
```
basecoin start --in-proc
```
This will initialize the chain with the `genesis.json` file from the current directory. If you want to specify another location, you can run:
```
basecoin start --in-proc --dir PATH/TO/CUSTOM/DATA
```
Note that `--in-proc` stands for "in process", which means
basecoin will be started with the Tendermint node running in the same process.
To start Tendermint in a separate process instead, use:
```
basecoin start
```
and in another window:
```
tendermint node
```
In either case, you should see blocks start streaming in!
## Send transactions
Now we are ready to send some transactions.
If you take a look at the `genesis.json` file, you will see one account listed there.
This account corresponds to the private key in `priv_validator.json`.
We also included the private key for another account, in `priv_validator2.json`.
Let's check the balance of these two accounts:
```
basecoin account 0xD397BC62B435F3CF50570FBAB4340FE52C60858F
basecoin account 0x4793A333846E5104C46DD9AB9A00E31821B2F301
```
The first account is flush with cash, while the second account doesn't exist.
Let's send funds from the first account to the second:
```
basecoin sendtx --to 0x4793A333846E5104C46DD9AB9A00E31821B2F301 --amount 10
```
By default, the CLI looks for a `priv_validator.json` to sign the transaction with,
so this will only work if you are in the `$GOPATH/src/github.com/tendermint/basecoin/data`.
To specify a different key, we can use the `--from` flag.
Now if we check the second account, it should have `10` coins!
```
basecoin account 0x4793A333846E5104C46DD9AB9A00E31821B2F301
```
We can send some of these coins back like so:
```
basecoin sendtx --to 0xD397BC62B435F3CF50570FBAB4340FE52C60858F --from priv_validator2.json --amount 5
```
Note how we use the `--from` flag to select a different account to send from.
If we try to send too much, we'll get an error:
```
basecoin sendtx --to 0xD397BC62B435F3CF50570FBAB4340FE52C60858F --from priv_validator2.json --amount 100
```
See `basecoin sendtx --help` for additional details.
## Plugins
The `sendtx` command creates and broadcasts a transaction of type `SendTx`,
which is only useful for moving tokens around.
Fortunately, Basecoin supports another transaction type, the `AppTx`,
which can trigger code registered via a plugin system.
For instance, we implemented a simple plugin called `counter`,
which just counts the number of transactions it processed.
To run it, kill the other processes, run `tendermint unsafe_reset_all`, and then
```
basecoin start --in-proc --counter-plugin
```
Now in another window, we can send transactions with:
```
TODO
```
## Next steps
1. Learn more about [Basecoin's design](basecoin-design.md)
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.

View File

7
docs/guide/deployment.md Normal file
View File

@ -0,0 +1,7 @@
## Deployment
Up until this point, we have only been testing the code as a stand-alone abci app, which is nice for developing, but it is no blockchain. Just a blockchain-ready application.
This section will demonstrate how to launch your basecoin-based application along with a tendermint testnet and initialize the genesis block for fun and profit.
**TODO** Maybe we link to a blog post for this???

View File

@ -0,0 +1 @@
Rigel explains how to build your own basecoin-based app

288
docs/guide/ibc.md Normal file
View File

@ -0,0 +1,288 @@
# InterBlockchain Communication with Basecoin
One of the most exciting elements of the Cosmos Network is the InterBlockchain Communication (IBC) protocol,
which enables interoperability across different blockchains.
The simplest example of using the IBC protocol is to send a data packet from one blockchain to another.
We implemented IBC as a basecoin plugin.
and here we'll show you how to use the Basecoin IBC-plugin to send a packet of data across blockchains!
Please note, this tutorial assumes you are familiar with [Basecoin plugins](/docs/guide/plugin-design.md)
and with the [Basecoin CLI](/docs/guide/basecoin-basics), but we'll explain how IBC works.
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 some state from height H, we need the signatures and root
hash from the header at height 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:
```
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:
```
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 (ie. an integer that increments with every message sent between this pair of chains),
a packet type (eg. coin, data, etc.),
and a payload.
```
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:
```
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`.
## Try it out
Now that we have all the background knowledge, let's actually walk through the tutorial.
Make sure you have installed
[tendermint](https://tendermint.com/intro/getting-started/download) and
[basecoin](/docs/guide/install.md).
Now let's start the two blockchains.
In this tutorial, each chain will have only a single validator,
where the initial configuration files are already generated.
Let's change directory so these files are easily accessible:
```
cd $GOPATH/src/github.com/tendermint/basecoin/demo
```
The relevant data is now in the `data` directory.
We can start the two chains as follows:
```
TMROOT=./data/chain1/tendermint tendermint node &> chain1_tendermint.log &
basecoin start --ibc-plugin --dir ./data/chain1/basecoin &> chain1_basecoin.log &
```
and
```
TMROOT=./data/chain2/tendermint tendermint node --node_laddr tcp://localhost:36656 --rpc_laddr tcp://localhost:36657 --proxy_app tcp://localhost:36658 &> chain2_tendermint.log &
basecoin start --address tcp://localhost:36658 --ibc-plugin --dir ./data/chain2/basecoin &> chain2_basecoin.log &
```
Note how we refer to the relevant data directories. Also note how we have to set the various addresses for the second node so as not to conflict with the first.
We can now check on the status of the two chains:
```
curl localhost:46657/status
curl localhost:36657/status
```
If either command fails, the nodes may not have finished starting up. Wait a couple seconds and try again.
Once you see the status of both chains, it's time to move on.
In this tutorial, we're going to send some data from `test_chain_1` to `test_chain_2`.
For the sake of convenience, let's first set some environment variables:
```
export CHAIN_ID1=test_chain_1
export CHAIN_ID2=test_chain_2
export CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from ./data/chain1/basecoin/priv_validator.json"
export CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from ./data/chain2/basecoin/priv_validator.json --node tcp://localhost:36657"
```
Let's start by registering `test_chain_1` on `test_chain_2`:
```
basecoin ibc --amount 10 $CHAIN_FLAGS2 register --chain_id $CHAIN_ID1 --genesis ./data/chain1/tendermint/genesis.json
```
Now we can create the outgoing packet on `test_chain_1`:
```
basecoin ibc --amount 10 $CHAIN_FLAGS1 packet create --from $CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload 0xDEADBEEF --sequence 1
```
Note our payload is just `DEADBEEF`.
Now that the packet is committed in the chain, let's get some proof by querying:
```
basecoin query ibc,egress,$CHAIN_ID1,$CHAIN_ID2,1
```
The result contains the latest height, a value (ie. the hex-encoded binary serialization of our packet),
and a proof (ie. hex-encoded binary serialization of a list of nodes from the Merkle tree) that the value is in the Merkle tree.
If we want to send this data to `test_chain_2`, we first have to update what it knows about `test_chain_1`.
We'll need a recent block header and a set of commit signatures.
Fortunately, we can get them with the `block` command:
```
basecoin block <height>
```
where `<height>` is the height returned in the previous query.
Note the result contains both a hex-encoded and json-encoded version of the header and the commit.
The former is used as input for later commands; the latter is human-readable, so you know what's going on!
Let's send this updated information about `test_chain_1` to `test_chain_2`:
```
basecoin ibc --amount 10 $CHAIN_FLAGS2 update --header 0x<header>--commit 0x<commit>
```
where `<header>` and `<commit>` are the hex-encoded header and commit returned by the previous `block` command.
Now that `test_chain_2` knows about some recent state of `test_chain_1`, we can post the packet to `test_chain_2`,
along with proof the packet was committed on `test_chain_1`. Since `test_chain_2` knows about some recent state
of `test_chain_1`, it will be able to verify the proof!
```
basecoin ibc --amount 10 $CHAIN_FLAGS2 packet post --from $CHAIN_ID1 --height <height + 1> --packet 0x<packet> --proof 0x<proof>
```
Here, `<height + 1>` is one greater than the height retuned by the previous `query` command, and `<packet>` and `<proof>` are the
`value` and `proof` returned in that same query.
Tada!
## Conclusion

13
docs/guide/install.md Normal file
View File

@ -0,0 +1,13 @@
# Install
We use glide for dependency management. The prefered way of compiling from source is the following:
```
go get -d github.com/tendermint/basecoin/cmd/basecoin
cd $GOPATH/src/github.com/tendermint/basecoin
make get_vendor_deps
make install
```
This will create the `basecoin` binary in `$GOPATH/bin`.

View File

@ -0,0 +1,16 @@
## Mintcoin
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.
## Financial Instruments
Sure, printing money and sending it is nice, but sometimes I don't fully trust the guy at the other end. Maybe we could add an escrow service? Or how about options for currency trading, since we support multiple currencies? No problem, this is also just a plugin away. Checkout our [trader application](./trader).
**Running code, still WIP**
## IBC
Now, let's hook up your personal crypto-currency with the wide world of other currencies, in a distributed, proof-of-stake based exchange. Hard, you say? Well half the work is already done for you with the [IBC, InterBlockchain Communication, plugin](./ibc.md). Now, we just need to get cosmos up and running and time to go and trade.

View File

@ -48,46 +48,3 @@ where `Fee = Gas x GasPrice`. In Basecoin, the `Gas` and `Fee` are independent.
Basecoin also defines another transaction type, the `AppTx`:
```
type AppTx struct {
Gas int64 `json:"gas"` // Gas
Fee Coin `json:"fee"` // Fee
Name string `json:"type"` // Which plugin
Input TxInput `json:"input"`
Data []byte `json:"data"`
}
```
The `AppTx` enables arbitrary additional functionality through the use of 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 `Name` field in the `AppTx` refers to the plugin name, and the `Data` field of the `AppTx` is
forward to the `RunTx` function.
You can look at some example plugins in the [basecoin repo](https://github.com/tendermint/basecoin/tree/develop/plugins).
If you want to see how you can write a plugin in your own repo, and make use of all the basecoin tooling, cli, etc. please take a look at the [mintcoin example](https://github.com/tendermint/basecoin-examples/tree/master/mintcoin) for inspiration, not just the plugin itself, but also the `cmd/mintcoin` directory to create the custom command.