Rewrote ibc guide for basecli and relay

This commit is contained in:
Ethan Frey 2017-06-19 16:34:41 +02:00
parent 9bb3493f78
commit 0b7b639c58
3 changed files with 202 additions and 102 deletions

View File

@ -23,6 +23,8 @@ BREAKING CHANGES:
- enhanced relay subcommand - enhanced relay subcommand
- relay start did what relay used to do - relay start did what relay used to do
- relay init registers both chains on one another (to set it up so relay start just works) - relay init registers both chains on one another (to set it up so relay start just works)
- docs
- removed `example-plugin`, put `counter` inside `docs/guide`
ENHANCEMENTS: ENHANCEMENTS:
- intergrates tendermint 0.10.0 (not the rc-2, but the real thing) - intergrates tendermint 0.10.0 (not the rc-2, but the real thing)
@ -33,6 +35,7 @@ ENHANCEMENTS:
BUG FIXES: BUG FIXES:
- no longer panics on missing app_options in genesis (thanks, anton) - no longer panics on missing app_options in genesis (thanks, anton)
- updated all docs... again
## 0.5.2 (June 2, 2017) ## 0.5.2 (June 2, 2017)

View File

@ -158,6 +158,22 @@ the key and value are contained in the Merkle tree.
The results of a query can thus be used as proof in an `IBCPacketPostTx`. 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, where
we just use the FIFO queue on each side for pending message to send as soon
as possible.
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 ## Try it out
Now that we have all the background knowledge, let's actually walk through the Now that we have all the background knowledge, let's actually walk through the
@ -173,116 +189,197 @@ comes with an `IBC` plugin enabled by default.
You will also want to install the [jq](https://stedolan.github.io/jq/) for You will also want to install the [jq](https://stedolan.github.io/jq/) for
handling JSON at the command line. handling JSON at the command line.
Now let's start the two blockchains. In this tutorial, each chain will have If you have any trouble with this, you can also look at the
only a single validator, where the initial configuration files are already [test scripts](/tests/cli/ibc.sh) or just run `make test_cli` in basecoin repo.
generated. Let's change directory so these files are easily accessible: Otherwise, open up 5 (yes 5!) terminal tabs....
``` cd $GOPATH/src/github.com/tendermint/basecoin/demo ``` ### Setup Chain 1
The relevant data is now in the `data` directory. Before we begin, let's set All commands will be prefixed by the name of the terminal window in which to
some environment variables for convenience: run it...
``` export BCHOME="." BCHOME1="./data/chain1" BCHOME2="./data/chain2"
export CHAIN_ID1=test_chain_1 export CHAIN_ID2=test_chain_2
CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from $BCHOME1/key.json"
CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from $BCHOME2/key.json --node
tcp://localhost:36657" ```
In previous examples, we started basecoin in-process with tendermint. Here, we
will run them in different processes, using the `--without-tendermint` flag, as
described in the [guide to the basecoin tool](basecoin-tool.md). We can start
the two chains as follows:
``` TMROOT=$BCHOME1 tendermint node --log_level=info &> chain1_tendermint.log &
BCHOME=$BCHOME1 basecoin start --without-tendermint &> chain1_basecoin.log &
```
and
``` TMROOT=$BCHOME2 tendermint node --log_level=info --node_laddr
tcp://localhost:36656 --rpc_laddr tcp://localhost:36657 --proxy_app
tcp://localhost:36658 &> chain2_tendermint.log & BCHOME=$BCHOME2 basecoin start
--address tcp://localhost:36658 --without-tendermint &> chain2_basecoin.log &
```
Note how we refer to the relevant data directories, and how we 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`. We begin by registering `test_chain_1` on `test_chain_2`:
``` basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --ibc_chain_id
$CHAIN_ID1 --genesis $BCHOME1/genesis.json ```
Now we can create the outgoing packet on `test_chain_1`:
``` basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS1 packet create --ibc_from
$CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload 0xDEADBEEF --ibc_sequence 1
```
Note our payload is just `DEADBEEF`. Now that the packet is committed in the
chain, let's get some proof by querying:
``` QUERY=$(basecoin query ibc,egress,$CHAIN_ID1,$CHAIN_ID2,1) echo $QUERY ```
The result contains the latest height, a value (i.e. the hex-encoded binary
serialization of our packet), and a proof (i.e. hex-encoded binary
serialization of a list of nodes from the Merkle tree) that the value is in the
Merkle tree. We keep the result in the `QUERY` variable so we can easily
reference subfields using the `jq` tool.
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:
``` BLOCK=$(basecoin block $(echo $QUERY | jq .height)) echo $BLOCK ```
Here, we are passing `basecoin block` the `height` from our earlier 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`.
First, output the header and commit for reference:
``` echo $BLOCK | jq .hex.header echo $BLOCK | jq .hex.commit ```
And now forward those values to `test_chain_2`:
``` basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 update --header 0x<header>
--commit 0x<commit> ```
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!
First, output the height, packet, and proof for reference:
``` ```
echo $QUERY | jq .height # first, clean up any old garbage for a fresh slate...
echo $QUERY | jq .value rm -rf ~/.ibcdemo/
echo $QUERY | jq .proof
``` ```
And forward those values to `test_chain_2`: Set up some accounts so we can init everything nicely:
**Client1**
``` ```
basecoin tx ibc --amount=10mycoin $CHAIN_FLAGS2 packet post --ibc_from $CHAIN_ID1 --height <height> --packet 0x<packet> --proof 0x<proof> export BCHOME=~/.ibcdemo/chain1/client
CHAIN_ID=test-chain-1
PORT=12347
basecli keys new money
basecli keys new gotnone
``` ```
If the command does not return an error, then we have successfuly transfered Prepare the genesis block and start the server:
data from `test_chain_1` to `test_chain_2`. Tada!
**Server1**
```
# set up the directory, chainid and port of this chain...
export BCHOME=~/.ibcdemo/chain1/server
CHAIN_ID=test-chain-1
PREFIX=1234
basecoin init
GENKEY=`basecli keys get money -o json --home=$HOME/.ibcdemo/chain1/client | jq .pubkey.data`
GENJSON=`cat $BCHOME/genesis.json`
echo $GENJSON | jq '.app_options.accounts[0].pub_key.data='$GENKEY | jq ".chain_id=\"$CHAIN_ID\"" > $BCHOME/genesis.json
sed -ie "s/4665/$PREFIX/" $BCHOME/config.toml
basecoin start
```
Attach the client to the chain and confirm state. The first account should
have money, the second none:
**Client1**
```
basecli init --chain-id=${CHAIN_ID} --node=tcp://localhost:${PORT}
ME=`basecli keys get money -o=json | jq .address | tr -d '"'`
YOU=`basecli keys get gotnone -o=json | jq .address | tr -d '"'`
basecli query account $ME
basecli query account $YOU
```
### Setup Chain 2
This is the same as above, except in two new terminal windows with
different chain ids, ports, etc. Note that you need to make new accounts
on this chain, as the "cool" key only has money on chain 1.
**Client2**
```
export BCHOME=~/.ibcdemo/chain2/client
CHAIN_ID=test-chain-2
PORT=23457
basecli keys new moremoney
basecli keys new broke
```
Prepare the genesis block and start the server:
**Server2**
```
# set up the directory, chainid and port of this chain...
export BCHOME=~/.ibcdemo/chain2/server
CHAIN_ID=test-chain-2
PREFIX=2345
basecoin init
GENKEY=`basecli keys get moremoney -o json --home=$HOME/.ibcdemo/chain2/client | jq .pubkey.data`
GENJSON=`cat $BCHOME/genesis.json`
echo $GENJSON | jq '.app_options.accounts[0].pub_key.data='$GENKEY | jq ".chain_id=\"$CHAIN_ID\"" > $BCHOME/genesis.json
sed -ie "s/4665/$PREFIX/" $BCHOME/config.toml
basecoin start
```
Attach the client to the chain and confirm state. The first account should
have money, the second none:
**Client2**
```
basecli init --chain-id=${CHAIN_ID} --node=tcp://localhost:${PORT}
ME=`basecli keys get moremoney -o=json | jq .address | tr -d '"'`
YOU=`basecli keys get broke -o=json | jq .address | tr -d '"'`
basecli query account $ME
basecli query account $YOU
```
### Connect these chains
Great, so we have two chains running on your local machine, with different
keys on each. Now it is time to hook them up together. Let's start
a relay to forward the messages.
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.
**Client1**
```
# note that this key.json file is a hardcoded demo for all chains, this will
# be updated in a future release
RELAY_KEY=${BCHOME}/../server/key.json
RELAY_ADDR=$(cat $RELAY_KEY | jq .address | tr -d \")
basecli tx send --amount=100000mycoin --sequence=1 --to=$RELAY_ADDR --name=money
basecli query account $RELAY_ADDR
```
**Client2**
```
# note that this key.json file is a hardcoded demo for all chains, this will
# be updated in a future release
RELAY_KEY=${BCHOME}/../server/key.json
RELAY_ADDR=$(cat $RELAY_KEY | jq .address | tr -d \")
basecli tx send --amount=100000mycoin --sequence=1 --to=$RELAY_ADDR --name=moremoney
basecli query account $RELAY_ADDR
```
**Relay**
```
# lots of config...
SERVER_1=~/.ibcdemo/chain1/server
SERVER_2=~/.ibcdemo/chain2/server
CHAIN_ID_1=test-chain-1
CHAIN_ID_2=test-chain-2
PORT_1=12347
PORT_2=23457
RELAY_KEY=${SERVER_1}/key.json
basecoin relay init --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \
--chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \
--genesis1=${SERVER_1}/genesis.json --genesis2=${SERVER_2}/genesis.json \
--from=$RELAY_KEY
basecoin relay start --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \
--chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \
--from=$RELAY_KEY
```
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...
**Client2**
```
# this should be empty
basecli query account $YOU
# now, we get the key to copy to the other terminal
echo $YOU
```
**Client1**
```
# set TARGET to be $YOU from the other chain
basecli tx send --amount=12345mycoin --sequence=2 --to=test-chain-2/$TARGET --name=money
```
**Client2**
```
# give it time to arrive...
sleep 1
# now you should see 12345 coins!
basecli query account $YOU
```
Cool, huh? Now have fun exploring and sending coins across the chains. And
making more accounts as you want to.
## Conclusion ## Conclusion

View File

@ -157,13 +157,13 @@ startRelay() {
${SERVER_EXE} relay init --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \ ${SERVER_EXE} relay init --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \
--chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \ --chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \
--genesis1=${BASE_DIR_1}/server/genesis.json --genesis2=${BASE_DIR_2}/server/genesis.json \ --genesis1=${BASE_DIR_1}/server/genesis.json --genesis2=${BASE_DIR_2}/server/genesis.json \
--from=$RELAY_KEY > ${BASE_DIR_1}/../relay.log & --from=$RELAY_KEY > ${BASE_DIR_1}/../relay.log
if [ $? != 0 ]; then echo "can't initialize relays"; cat ${BASE_DIR_1}/../relay.log; return 1; fi if [ $? != 0 ]; then echo "can't initialize relays"; cat ${BASE_DIR_1}/../relay.log; return 1; fi
# now start the relay (constantly send packets) # now start the relay (constantly send packets)
${SERVER_EXE} relay start --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \ ${SERVER_EXE} relay start --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \
--chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \ --chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \
--from=$RELAY_KEY > ${BASE_DIR_1}/../relay.log & --from=$RELAY_KEY >> ${BASE_DIR_1}/../relay.log &
sleep 2 sleep 2
PID_RELAY=$! PID_RELAY=$!
disown disown