From fd10387eb59393d72f8f95c6920338a7c313061a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 21 Jul 2017 18:25:30 +0200 Subject: [PATCH] Tested register and update ibc via cli --- app/app.go | 28 ---- app/app_test.go | 30 +++++ client/commands/seeds/export.go | 21 ++- cmd/basecoin/main.go | 40 +++++- tests/cli/ibc.sh | 226 +++++++++++++++++++++----------- 5 files changed, 235 insertions(+), 110 deletions(-) diff --git a/app/app.go b/app/app.go index d27ee26e3..ca62ea80f 100644 --- a/app/app.go +++ b/app/app.go @@ -10,12 +10,6 @@ import ( "github.com/tendermint/basecoin" "github.com/tendermint/basecoin/errors" - "github.com/tendermint/basecoin/modules/auth" - "github.com/tendermint/basecoin/modules/base" - "github.com/tendermint/basecoin/modules/coin" - "github.com/tendermint/basecoin/modules/fee" - "github.com/tendermint/basecoin/modules/nonce" - "github.com/tendermint/basecoin/modules/roles" "github.com/tendermint/basecoin/stack" sm "github.com/tendermint/basecoin/state" "github.com/tendermint/basecoin/version" @@ -50,28 +44,6 @@ func NewBasecoin(handler basecoin.Handler, store *Store, logger log.Logger) *Bas } } -// DefaultHandler - placeholder to just handle sendtx -func DefaultHandler(feeDenom string) basecoin.Handler { - // use the default stack - c := coin.NewHandler() - r := roles.NewHandler() - d := stack.NewDispatcher( - stack.WrapHandler(c), - stack.WrapHandler(r), - ) - return stack.New( - base.Logger{}, - stack.Recovery{}, - auth.Signatures{}, - base.Chain{}, - stack.Checkpoint{OnCheck: true}, - nonce.ReplayCheck{}, - roles.NewMiddleware(), - fee.NewSimpleFeeMiddleware(coin.Coin{feeDenom, 0}, fee.Bank), - stack.Checkpoint{OnDeliver: true}, - ).Use(d) -} - // GetChainID returns the currently stored chain func (app *Basecoin) GetChainID() string { return app.info.GetChainID(app.state.Committed()) diff --git a/app/app_test.go b/app/app_test.go index d09a69d23..5ea8cc59b 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -13,13 +13,43 @@ import ( "github.com/tendermint/basecoin/modules/base" "github.com/tendermint/basecoin/modules/coin" "github.com/tendermint/basecoin/modules/fee" + "github.com/tendermint/basecoin/modules/ibc" "github.com/tendermint/basecoin/modules/nonce" + "github.com/tendermint/basecoin/modules/roles" "github.com/tendermint/basecoin/stack" "github.com/tendermint/basecoin/state" wire "github.com/tendermint/go-wire" "github.com/tendermint/tmlibs/log" ) +// DefaultHandler for the tests (coin, roles, ibc) +func DefaultHandler(feeDenom string) basecoin.Handler { + // use the default stack + c := coin.NewHandler() + r := roles.NewHandler() + i := ibc.NewHandler() + + return stack.New( + base.Logger{}, + stack.Recovery{}, + auth.Signatures{}, + base.Chain{}, + stack.Checkpoint{OnCheck: true}, + nonce.ReplayCheck{}, + ). + IBC(ibc.NewMiddleware()). + Apps( + roles.NewMiddleware(), + fee.NewSimpleFeeMiddleware(coin.Coin{feeDenom, 0}, fee.Bank), + stack.Checkpoint{OnDeliver: true}, + ). + Dispatch( + stack.WrapHandler(c), + stack.WrapHandler(r), + stack.WrapHandler(i), + ) +} + //-------------------------------------------------------- // test environment is a list of input and output accounts diff --git a/client/commands/seeds/export.go b/client/commands/seeds/export.go index 1ac3ac42a..babd1748a 100644 --- a/client/commands/seeds/export.go +++ b/client/commands/seeds/export.go @@ -1,11 +1,15 @@ package seeds import ( + "encoding/json" + "os" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/tendermint/basecoin/client/commands" + "github.com/tendermint/light-client/certifiers" ) var exportCmd = &cobra.Command{ @@ -40,5 +44,20 @@ func exportSeed(cmd *cobra.Command, args []string) error { } // now get the output file and write it - return seed.Write(path) + return writeSeed(seed, path) +} + +func writeSeed(seed certifiers.Seed, path string) (err error) { + var f *os.File + f, err = os.Create(path) + if err == nil { + stream := json.NewEncoder(f) + err = stream.Encode(seed) + f.Close() + } + // we don't write, but this is not an error + if os.IsExist(err) { + return nil + } + return errors.WithStack(err) } diff --git a/cmd/basecoin/main.go b/cmd/basecoin/main.go index 33ba8c1d4..5f98b085d 100644 --- a/cmd/basecoin/main.go +++ b/cmd/basecoin/main.go @@ -5,15 +5,51 @@ import ( "github.com/tendermint/tmlibs/cli" - "github.com/tendermint/basecoin/app" + "github.com/tendermint/basecoin" "github.com/tendermint/basecoin/cmd/basecoin/commands" + "github.com/tendermint/basecoin/modules/auth" + "github.com/tendermint/basecoin/modules/base" + "github.com/tendermint/basecoin/modules/coin" + "github.com/tendermint/basecoin/modules/fee" + "github.com/tendermint/basecoin/modules/ibc" + "github.com/tendermint/basecoin/modules/nonce" + "github.com/tendermint/basecoin/modules/roles" + "github.com/tendermint/basecoin/stack" ) +// BuildApp constructs the stack we want to use for this app +func BuildApp(feeDenom string) basecoin.Handler { + // use the default stack + c := coin.NewHandler() + r := roles.NewHandler() + i := ibc.NewHandler() + + return stack.New( + base.Logger{}, + stack.Recovery{}, + auth.Signatures{}, + base.Chain{}, + stack.Checkpoint{OnCheck: true}, + nonce.ReplayCheck{}, + ). + IBC(ibc.NewMiddleware()). + Apps( + roles.NewMiddleware(), + fee.NewSimpleFeeMiddleware(coin.Coin{feeDenom, 0}, fee.Bank), + stack.Checkpoint{OnDeliver: true}, + ). + Dispatch( + stack.WrapHandler(c), + stack.WrapHandler(r), + stack.WrapHandler(i), + ) +} + func main() { rt := commands.RootCmd // require all fees in mycoin - change this in your app! - commands.Handler = app.DefaultHandler("mycoin") + commands.Handler = BuildApp("mycoin") rt.AddCommand( commands.InitCmd, diff --git a/tests/cli/ibc.sh b/tests/cli/ibc.sh index 36f380ded..5a5c91c0d 100755 --- a/tests/cli/ibc.sh +++ b/tests/cli/ibc.sh @@ -62,13 +62,13 @@ oneTimeTearDown() { } test00GetAccount() { - SENDER_1=$(BC_HOME=${CLIENT_1} getAddr $RICH) - RECV_1=$(BC_HOME=${CLIENT_1} getAddr $POOR) export BC_HOME=${CLIENT_1} + SENDER_1=$(getAddr $RICH) + RECV_1=$(getAddr $POOR) assertFalse "line=${LINENO}, requires arg" "${CLIENT_EXE} query account 2>/dev/null" assertFalse "line=${LINENO}, has no genesis account" "${CLIENT_EXE} query account $RECV_1 2>/dev/null" - checkAccount $SENDER_1 "0" "9007199254740992" + checkAccount $SENDER_1 "9007199254740992" export BC_HOME=${CLIENT_2} SENDER_2=$(getAddr $RICH) @@ -76,102 +76,170 @@ test00GetAccount() { assertFalse "line=${LINENO}, requires arg" "${CLIENT_EXE} query account 2>/dev/null" assertFalse "line=${LINENO}, has no genesis account" "${CLIENT_EXE} query account $RECV_2 2>/dev/null" - checkAccount $SENDER_2 "0" "9007199254740992" + checkAccount $SENDER_2 "9007199254740992" # Make sure that they have different addresses on both chains (they are random keys) assertNotEquals "line=${LINENO}, sender keys must be different" "$SENDER_1" "$SENDER_2" assertNotEquals "line=${LINENO}, recipient keys must be different" "$RECV_1" "$RECV_2" } -test01SendIBCTx() { - # Trigger a cross-chain sendTx... from RICH on chain1 to POOR on chain2 - # we make sure the money was reduced, but nothing arrived - SENDER=$(BC_HOME=${CLIENT_1} getAddr $RICH) - RECV=$(BC_HOME=${CLIENT_2} getAddr $POOR) +test01RegisterChains() { + # let's get the root seeds to cross-register them + ROOT_1="$BASE_DIR_1/root_seed.json" + ${CLIENT_EXE} seeds export $ROOT_1 --home=${CLIENT_1} + assertTrue "line=${LINENO}, export seed failed" $? - export BC_HOME=${CLIENT_1} - TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=20002mycoin \ - --sequence=1 --to=${CHAIN_ID_2}/${RECV} --name=$RICH) - txSucceeded $? "$TX" "${CHAIN_ID_2}/${RECV}" + ROOT_2="$BASE_DIR_2/root_seed.json" + ${CLIENT_EXE} seeds export $ROOT_2 --home=${CLIENT_2} + assertTrue "line=${LINENO}, export seed failed" $? + + # register chain2 on chain1 + TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-register \ + --sequence=1 --seed=${ROOT_2} --name=$POOR --home=${CLIENT_1}) + txSucceeded $? "$TX" "register chain2 on chain 1" # an example to quit early if there is no point in more tests if [ $? != 0 ]; then echo "aborting!"; return 1; fi - HASH=$(echo $TX | jq .hash | tr -d \") - TX_HEIGHT=$(echo $TX | jq .height) - - # Make sure balance went down and tx is indexed - checkAccount $SENDER "1" "9007199254720990" - checkSendTx $HASH $TX_HEIGHT $SENDER "20002" - - # Make sure nothing arrived - yet - waitForBlock ${PORT_1} - assertFalse "line=${LINENO}, no relay running" "BC_HOME=${CLIENT_2} ${CLIENT_EXE} query account $RECV" - - # Start the relay and wait a few blocks... - # (already sent a tx on chain1, so use higher sequence) - startRelay 2 1 - if [ $? != 0 ]; then echo "can't start relay"; cat ${BASE_DIR_1}/../relay.log; return 1; fi - - # Give it a little time, then make sure the money arrived - echo "waiting for relay..." - sleep 1 - waitForBlock ${PORT_1} - waitForBlock ${PORT_2} - - # Check the new account - echo "checking ibc recipient..." - BC_HOME=${CLIENT_2} checkAccount $RECV "0" "20002" - - # Stop relay - printf "stoping relay\n" - kill -9 $PID_RELAY + # register chain1 on chain2 (no money needed... yet) + TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-register \ + --sequence=1 --seed=${ROOT_1} --name=$POOR --home=${CLIENT_2}) + txSucceeded $? "$TX" "register chain1 on chain 2" + # an example to quit early if there is no point in more tests + if [ $? != 0 ]; then echo "aborting!"; return 1; fi } -# StartRelay $seq1 $seq2 -# startRelay hooks up a relay between chain1 and chain2 -# it needs the proper sequence number for $RICH on chain1 and chain2 as args -startRelay() { - # Send some cash to the default key, so it can send messages - RELAY_KEY=${BASE_DIR_1}/server/key.json - RELAY_ADDR=$(cat $RELAY_KEY | jq .address | tr -d \") - echo starting relay $PID_RELAY ... +test02UpdateChains() { + # let's get the root seeds to cross-register them + UPDATE_1="$BASE_DIR_1/seed_1.json" + ${CLIENT_EXE} seeds update --home=${CLIENT_1} > /dev/null + ${CLIENT_EXE} seeds export $UPDATE_1 --home=${CLIENT_1} + assertTrue "line=${LINENO}, export seed failed" $? + # make sure it is newer than the other.... + assertNewHeight "line=${LINENO}" $ROOT_1 $UPDATE_1 - # Get paid on chain1 - export BC_HOME=${CLIENT_1} - SENDER=$(getAddr $RICH) - RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=100000mycoin \ - --sequence=$1 --to=$RELAY_ADDR --name=$RICH) - txSucceeded $? "$RES" "$RELAY_ADDR" - if [ $? != 0 ]; then echo "can't pay chain1!"; return 1; fi + UPDATE_2="$BASE_DIR_2/seed_2.json" + ${CLIENT_EXE} seeds update --home=${CLIENT_2} > /dev/null + ${CLIENT_EXE} seeds export $UPDATE_2 --home=${CLIENT_2} + assertTrue "line=${LINENO}, export seed failed" $? + assertNewHeight "line=${LINENO}" $ROOT_2 $UPDATE_2 - # Get paid on chain2 - export BC_HOME=${CLIENT_2} - SENDER=$(getAddr $RICH) - RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=100000mycoin \ - --sequence=$2 --to=$RELAY_ADDR --name=$RICH) - txSucceeded $? "$RES" "$RELAY_ADDR" - if [ $? != 0 ]; then echo "can't pay chain2!"; return 1; fi + # update chain2 on chain1 + TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ + --sequence=2 --seed=${UPDATE_2} --name=$POOR --home=${CLIENT_1}) + txSucceeded $? "$TX" "update chain2 on chain 1" + # an example to quit early if there is no point in more tests + if [ $? != 0 ]; then echo "aborting!"; return 1; fi - # Initialize the relay (register both chains) - ${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} \ - --genesis1=${BASE_DIR_1}/server/genesis.json --genesis2=${BASE_DIR_2}/server/genesis.json \ - --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 + # update chain1 on chain2 (no money needed... yet) + TX=$(echo qwertyuiop | ${CLIENT_EXE} tx ibc-update \ + --sequence=2 --seed=${UPDATE_1} --name=$POOR --home=${CLIENT_2}) + txSucceeded $? "$TX" "update chain1 on chain 2" + # an example to quit early if there is no point in more tests + if [ $? != 0 ]; then echo "aborting!"; return 1; fi +} - # Now start the relay (constantly send packets) - ${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} \ - --from=$RELAY_KEY >> ${BASE_DIR_1}/../relay.log & - sleep 2 - PID_RELAY=$! - disown +test03QueryIBC() { - # Return an error if it dies in the first two seconds to make sure it is running - ps $PID_RELAY >/dev/null +} + +# XXX Ex Usage: assertNewHeight $MSG $SEED_1 $SEED_2 +# Desc: Asserts that seed2 has a higher block height than seed 1 +assertNewHeight() { + H1=$(cat $2 | jq .checkpoint.header.height) + H2=$(cat $3 | jq .checkpoint.header.height) + assertTrue "$MSG" "test $H2 -gt $H1" return $? } +# test01SendIBCTx() { +# # Trigger a cross-chain sendTx... from RICH on chain1 to POOR on chain2 +# # we make sure the money was reduced, but nothing arrived +# SENDER=$(BC_HOME=${CLIENT_1} getAddr $RICH) +# RECV=$(BC_HOME=${CLIENT_2} getAddr $POOR) + +# export BC_HOME=${CLIENT_1} +# TX=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=20002mycoin \ +# --sequence=1 --to=${CHAIN_ID_2}/${RECV} --name=$RICH) +# txSucceeded $? "$TX" "${CHAIN_ID_2}/${RECV}" +# # an example to quit early if there is no point in more tests +# if [ $? != 0 ]; then echo "aborting!"; return 1; fi + +# HASH=$(echo $TX | jq .hash | tr -d \") +# TX_HEIGHT=$(echo $TX | jq .height) + +# # Make sure balance went down and tx is indexed +# checkAccount $SENDER "1" "9007199254720990" +# checkSendTx $HASH $TX_HEIGHT $SENDER "20002" + +# # Make sure nothing arrived - yet +# waitForBlock ${PORT_1} +# assertFalse "line=${LINENO}, no relay running" "BC_HOME=${CLIENT_2} ${CLIENT_EXE} query account $RECV" + +# # Start the relay and wait a few blocks... +# # (already sent a tx on chain1, so use higher sequence) +# startRelay 2 1 +# if [ $? != 0 ]; then echo "can't start relay"; cat ${BASE_DIR_1}/../relay.log; return 1; fi + +# # Give it a little time, then make sure the money arrived +# echo "waiting for relay..." +# sleep 1 +# waitForBlock ${PORT_1} +# waitForBlock ${PORT_2} + +# # Check the new account +# echo "checking ibc recipient..." +# BC_HOME=${CLIENT_2} checkAccount $RECV "0" "20002" + +# # Stop relay +# printf "stoping relay\n" +# kill -9 $PID_RELAY +# } + +# # StartRelay $seq1 $seq2 +# # startRelay hooks up a relay between chain1 and chain2 +# # it needs the proper sequence number for $RICH on chain1 and chain2 as args +# startRelay() { +# # Send some cash to the default key, so it can send messages +# RELAY_KEY=${BASE_DIR_1}/server/key.json +# RELAY_ADDR=$(cat $RELAY_KEY | jq .address | tr -d \") +# echo starting relay $PID_RELAY ... + +# # Get paid on chain1 +# export BC_HOME=${CLIENT_1} +# SENDER=$(getAddr $RICH) +# RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=100000mycoin \ +# --sequence=$1 --to=$RELAY_ADDR --name=$RICH) +# txSucceeded $? "$RES" "$RELAY_ADDR" +# if [ $? != 0 ]; then echo "can't pay chain1!"; return 1; fi + +# # Get paid on chain2 +# export BC_HOME=${CLIENT_2} +# SENDER=$(getAddr $RICH) +# RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=100000mycoin \ +# --sequence=$2 --to=$RELAY_ADDR --name=$RICH) +# txSucceeded $? "$RES" "$RELAY_ADDR" +# if [ $? != 0 ]; then echo "can't pay chain2!"; return 1; fi + +# # Initialize the relay (register both chains) +# ${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} \ +# --genesis1=${BASE_DIR_1}/server/genesis.json --genesis2=${BASE_DIR_2}/server/genesis.json \ +# --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 + +# # Now start the relay (constantly send packets) +# ${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} \ +# --from=$RELAY_KEY >> ${BASE_DIR_1}/../relay.log & +# sleep 2 +# PID_RELAY=$! +# disown + +# # Return an error if it dies in the first two seconds to make sure it is running +# ps $PID_RELAY >/dev/null +# return $? +# } + # Load common then run these tests with shunit2! DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory . $DIR/common.sh