From e356fc1edb4077fc6f09aa45e41a51f32714764b Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Thu, 15 Jun 2017 15:11:47 -0400 Subject: [PATCH 01/20] makefile cleanup --- Makefile | 34 +++++++++++++------------------ {clitest => tests/cli}/basictx.sh | 0 {clitest => tests/cli}/ibc.sh | 0 3 files changed, 14 insertions(+), 20 deletions(-) rename {clitest => tests/cli}/basictx.sh (100%) rename {clitest => tests/cli}/ibc.sh (100%) diff --git a/Makefile b/Makefile index c336e05e2c0..18fcbbb2509 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,8 @@ -GOTOOLS = \ - github.com/mitchellh/gox \ - github.com/Masterminds/glide +GOTOOLS = github.com/mitchellh/gox \ + github.com/Masterminds/glide PACKAGES=$(shell go list ./... | grep -v '/vendor/') -all: get_vendor_deps test install +all: get_vendor_deps install test build: go build ./cmd/... @@ -15,30 +14,25 @@ dist: @bash scripts/dist.sh @bash scripts/publish.sh -clitest/shunit2: - wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ - -q -O clitest/shunit2 - -test_cli: clitest/shunit2 - # sudo apt-get install jq - @./clitest/basictx.sh - # @./clitest/ibc.sh +test: test_unit test_cli -test: +test_unit: go test $(PACKAGES) #go run tests/tendermint/*.go -# get_deps: -# go get -d ./... - -# update_deps: -# go get -d -u ./... +test_cli: + wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ + -q -O tests/cli/shunit2 + # sudo apt-get install jq + @./tests/cli/basictx.sh + # @./clitest/ibc.sh get_vendor_deps: tools glide install build-docker: - docker run -it --rm -v "$(PWD):/go/src/github.com/tendermint/basecoin" -w "/go/src/github.com/tendermint/basecoin" -e "CGO_ENABLED=0" golang:alpine go build ./cmd/basecoin + docker run -it --rm -v "$(PWD):/go/src/github.com/tendermint/basecoin" -w \ + "/go/src/github.com/tendermint/basecoin" -e "CGO_ENABLED=0" golang:alpine go build ./cmd/basecoin docker build -t "tendermint/basecoin" . tools: @@ -47,4 +41,4 @@ tools: clean: @rm -f ./basecoin -.PHONY: all build install test get_deps update_deps get_vendor_deps build-docker clean +.PHONY: all build install test test_cli test_unit get_vendor_deps build-docker clean diff --git a/clitest/basictx.sh b/tests/cli/basictx.sh similarity index 100% rename from clitest/basictx.sh rename to tests/cli/basictx.sh diff --git a/clitest/ibc.sh b/tests/cli/ibc.sh similarity index 100% rename from clitest/ibc.sh rename to tests/cli/ibc.sh From 226546e5582092e963864da7b5c640c8bb1d9454 Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Thu, 15 Jun 2017 15:25:08 -0400 Subject: [PATCH 02/20] circle bash integration --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 3e8710ca9e1..09093e34aeb 100644 --- a/circle.yml +++ b/circle.yml @@ -19,7 +19,7 @@ dependencies: test: override: - - "cd $REPO && glide install && go install ./cmd/basecoin" + - "cd $REPO && glide install && go install ./cmd/..." - ls $GOPATH/bin - "cd $REPO && make test" - "cd $REPO/demo && bash start.sh" From 789ebada42f44edf6504a7e4a3052967d473a217 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 15 Jun 2017 20:47:59 +0200 Subject: [PATCH 03/20] pulled out common helpers, prepare to support ibc --- clitest/common.sh | 67 +++++++++++++++++++++++++++++++++++++++++++ tests/cli/basictx.sh | 68 +++++++------------------------------------- 2 files changed, 77 insertions(+), 58 deletions(-) create mode 100644 clitest/common.sh diff --git a/clitest/common.sh b/clitest/common.sh new file mode 100644 index 00000000000..3294548a0d0 --- /dev/null +++ b/clitest/common.sh @@ -0,0 +1,67 @@ +# this is not executable, but helper functions for the other scripts + +prepareClient() { + echo "Preparing client keys..." + basecli reset_all + assertTrue $? + + for i in "${!ACCOUNTS[@]}"; do + newKey ${ACCOUNTS[$i]} + done +} + +# initServer takes two args - (root dir, chain_id) +# and optionally port prefix as a third arg (default is 4665{6,7,8}) +# it grabs the first account to give it the money +initServer() { + echo "Setting up genesis..." + SERVE_DIR=$1/server + assertNotNull "no chain" $2 + CHAIN=$2 + SERVER_LOG=$1/basecoin.log + basecoin init --home=$SERVE_DIR >>$SERVER_LOG + + #change the genesis to the first account + GENKEY=$(basecli keys get ${ACCOUNTS[0]} -o json | jq .pubkey.data) + GENJSON=$(cat $SERVE_DIR/genesis.json) + echo $GENJSON | jq '.app_options.accounts[0].pub_key.data='$GENKEY \ + | jq ".chain_id=\"$2\"" > $SERVE_DIR/genesis.json + + # optionally set the port + if [ -n "$3" ]; then + echo "setting port $3" + sed -ie "s/4665/$3/" $SERVE_DIR/config.toml + fi + + echo "Starting server..." + basecoin start --home=$SERVE_DIR >>$SERVER_LOG 2>&1 & + sleep 5 + PID_SERVER=$! +} + +# initClient requires chain_id arg, port is optional (default 4665{5,6,7}) +initClient() { + echo "Attaching client..." + PORT=${2:-4665} + # hard-code the expected validator hash + basecli init --chain-id=$1 --node=tcp://localhost:${PORT}7 --valhash=EB168E17E45BAEB194D4C79067FFECF345C64DE6 + assertTrue "initialized light-client" $? +} + +# newKeys makes a key for a given username, second arg optional password +newKey(){ + assertNotNull "keyname required" "$1" + KEYPASS=${2:-qwertyuiop} + (echo $KEYPASS; echo $KEYPASS) | basecli keys new $1 >/dev/null 2>/dev/null + assertTrue "created $1" $? + assertTrue "$1 doesn't exist" "basecli keys get $1" +} + +# getAddr gets the address for a key name +getAddr() { + assertNotNull "keyname required" "$1" + RAW=$(basecli keys get $1) + assertTrue "no key for $1" $? + # print the addr + echo $RAW | cut -d' ' -f2 +} diff --git a/tests/cli/basictx.sh b/tests/cli/basictx.sh index cbb15b4341e..8584535e56e 100755 --- a/tests/cli/basictx.sh +++ b/tests/cli/basictx.sh @@ -1,11 +1,11 @@ #!/bin/bash + oneTimeSetUp() { BASE_DIR=$HOME/.basecoin_test_basictx - LOG=$BASE_DIR/test.log - SERVER_LOG=$BASE_DIR/basecoin.log + CHAIN_ID=my-test-chain - rm -rf $BASE_DIR + rm -rf $BASE_DIR 2>/dev/null mkdir -p $BASE_DIR ACCOUNTS=(jae ethan bucky rigel igor) @@ -13,13 +13,14 @@ oneTimeSetUp() { POOR=${ACCOUNTS[1]} # set up client + export BC_HOME=${BASE_DIR}/client prepareClient # start basecoin server (with counter) - initServer + initServer $BASE_DIR $CHAIN_ID 3456 echo pid $PID_SERVER - initClient + initClient $CHAIN_ID 3456 echo "...Testing may begin!" echo @@ -35,59 +36,6 @@ oneTimeTearDown() { sleep 1 } -prepareClient() { - echo "Preparing client keys..." - export BC_HOME=$BASE_DIR/client - basecli reset_all - assertTrue $? - - for i in "${!ACCOUNTS[@]}"; do - newKey ${ACCOUNTS[$i]} - done -} - -initServer() { - echo "Setting up genesis..." - SERVE_DIR=$BASE_DIR/server - rm -rf $SERVE_DIR 2>/dev/null - basecoin init --home=$SERVE_DIR >>$SERVER_LOG - - #change the genesis to the first account - GENKEY=$(basecli keys get ${RICH} -o json | jq .pubkey.data) - GENJSON=$(cat $SERVE_DIR/genesis.json) - echo $GENJSON | jq '.app_options.accounts[0].pub_key.data='$GENKEY > $SERVE_DIR/genesis.json - - echo "Starting server..." - basecoin start --home=$SERVE_DIR >>$SERVER_LOG 2>&1 & - sleep 5 - PID_SERVER=$! -} - -initClient() { - echo "Attaching client..." - # hard-code the expected validator hash - basecli init --chain-id=test_chain_id --node=tcp://localhost:46657 --valhash=EB168E17E45BAEB194D4C79067FFECF345C64DE6 - assertTrue "initialized light-client" $? -} - -# newKeys makes a key for a given username, second arg optional password -newKey(){ - assertNotNull "keyname required" "$1" - KEYPASS=${2:-qwertyuiop} - (echo $KEYPASS; echo $KEYPASS) | basecli keys new $1 >>$LOG 2>/dev/null - assertTrue "created $1" $? - assertTrue "$1 doesn't exist" "basecli keys get $1" -} - -# getAddr gets the address for a key name -getAddr() { - assertNotNull "keyname required" "$1" - RAW=$(basecli keys get $1) - assertTrue "no key for $1" $? - # print the addr - echo $RAW | cut -d' ' -f2 -} - test00GetAccount() { SENDER=$(getAddr $RICH) RECV=$(getAddr $POOR) @@ -140,4 +88,8 @@ test01SendTx() { # load and run these tests with shunit2! DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory + +# load common helpers +. $DIR/common.sh + . $DIR/shunit2 From 9341b8be5d61d18c3a71c34efc93e4a56b868dcd Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 15 Jun 2017 20:56:59 +0200 Subject: [PATCH 04/20] Support other binaries --- clitest/common.sh | 27 ++++++++++++++++----------- tests/cli/basictx.sh | 30 ++++++++++++++++-------------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/clitest/common.sh b/clitest/common.sh index 3294548a0d0..07fe1a54b12 100644 --- a/clitest/common.sh +++ b/clitest/common.sh @@ -1,8 +1,13 @@ # this is not executable, but helper functions for the other scripts +# these are general accounts to be prepared +ACCOUNTS=(jae ethan bucky rigel igor) +RICH=${ACCOUNTS[0]} +POOR=${ACCOUNTS[4]} + prepareClient() { echo "Preparing client keys..." - basecli reset_all + ${CLIENT_EXE} reset_all assertTrue $? for i in "${!ACCOUNTS[@]}"; do @@ -18,11 +23,11 @@ initServer() { SERVE_DIR=$1/server assertNotNull "no chain" $2 CHAIN=$2 - SERVER_LOG=$1/basecoin.log - basecoin init --home=$SERVE_DIR >>$SERVER_LOG + SERVER_LOG=$1/${SERVER_EXE}.log + ${SERVER_EXE} init --home=$SERVE_DIR >>$SERVER_LOG #change the genesis to the first account - GENKEY=$(basecli keys get ${ACCOUNTS[0]} -o json | jq .pubkey.data) + GENKEY=$(${CLIENT_EXE} keys get ${RICH} -o json | jq .pubkey.data) GENJSON=$(cat $SERVE_DIR/genesis.json) echo $GENJSON | jq '.app_options.accounts[0].pub_key.data='$GENKEY \ | jq ".chain_id=\"$2\"" > $SERVE_DIR/genesis.json @@ -33,18 +38,18 @@ initServer() { sed -ie "s/4665/$3/" $SERVE_DIR/config.toml fi - echo "Starting server..." - basecoin start --home=$SERVE_DIR >>$SERVER_LOG 2>&1 & + echo "Starting ${SERVER_EXE} server..." + ${SERVER_EXE} start --home=$SERVE_DIR >>$SERVER_LOG 2>&1 & sleep 5 PID_SERVER=$! } # initClient requires chain_id arg, port is optional (default 4665{5,6,7}) initClient() { - echo "Attaching client..." + echo "Attaching ${CLIENT_EXE} client..." PORT=${2:-4665} # hard-code the expected validator hash - basecli init --chain-id=$1 --node=tcp://localhost:${PORT}7 --valhash=EB168E17E45BAEB194D4C79067FFECF345C64DE6 + ${CLIENT_EXE} init --chain-id=$1 --node=tcp://localhost:${PORT}7 --valhash=EB168E17E45BAEB194D4C79067FFECF345C64DE6 assertTrue "initialized light-client" $? } @@ -52,15 +57,15 @@ initClient() { newKey(){ assertNotNull "keyname required" "$1" KEYPASS=${2:-qwertyuiop} - (echo $KEYPASS; echo $KEYPASS) | basecli keys new $1 >/dev/null 2>/dev/null + (echo $KEYPASS; echo $KEYPASS) | ${CLIENT_EXE} keys new $1 >/dev/null 2>/dev/null assertTrue "created $1" $? - assertTrue "$1 doesn't exist" "basecli keys get $1" + assertTrue "$1 doesn't exist" "${CLIENT_EXE} keys get $1" } # getAddr gets the address for a key name getAddr() { assertNotNull "keyname required" "$1" - RAW=$(basecli keys get $1) + RAW=$(${CLIENT_EXE} keys get $1) assertTrue "no key for $1" $? # print the addr echo $RAW | cut -d' ' -f2 diff --git a/tests/cli/basictx.sh b/tests/cli/basictx.sh index 8584535e56e..e9a6b0e5fbf 100755 --- a/tests/cli/basictx.sh +++ b/tests/cli/basictx.sh @@ -1,18 +1,20 @@ #!/bin/bash +# these are two globals to control all scripts (can use eg. counter instead) +SERVER_EXE=basecoin +CLIENT_EXE=basecli oneTimeSetUp() { + # these are passed in as args BASE_DIR=$HOME/.basecoin_test_basictx CHAIN_ID=my-test-chain rm -rf $BASE_DIR 2>/dev/null mkdir -p $BASE_DIR - ACCOUNTS=(jae ethan bucky rigel igor) - RICH=${ACCOUNTS[0]} - POOR=${ACCOUNTS[1]} - # set up client + # set up client - make sure you use the proper prefix if you set + # a custom CLIENT_EXE export BC_HOME=${BASE_DIR}/client prepareClient @@ -31,7 +33,7 @@ oneTimeSetUp() { oneTimeTearDown() { echo echo - echo "stopping basecoin test server..." + echo "stopping $SERVER_EXE test server..." kill -9 $PID_SERVER >/dev/null 2>&1 sleep 1 } @@ -40,13 +42,13 @@ test00GetAccount() { SENDER=$(getAddr $RICH) RECV=$(getAddr $POOR) - assertFalse "requires arg" "basecli query account" - ACCT=$(basecli query account $SENDER) + assertFalse "requires arg" "${CLIENT_EXE} query account" + ACCT=$(${CLIENT_EXE} query account $SENDER) assertTrue "must have proper genesis account" $? assertEquals "no tx" "0" $(echo $ACCT | jq .data.sequence) assertEquals "has money" "9007199254740992" $(echo $ACCT | jq .data.coins[0].amount) - ACCT2=$(basecli query account $RECV) + ACCT2=$(${CLIENT_EXE} query account $RECV) assertFalse "has no genesis account" $? } @@ -54,10 +56,10 @@ test01SendTx() { SENDER=$(getAddr $RICH) RECV=$(getAddr $POOR) - assertFalse "missing dest" "basecli tx send --amount=992mycoin --sequence=1 2>/dev/null" - assertFalse "bad password" "echo foo | basecli tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null" + assertFalse "missing dest" "${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 2>/dev/null" + assertFalse "bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null" # we have to remove the password request from stdout, to just get the json - RES=$(echo qwertyuiop | basecli tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null | tail -n +2) + RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null | tail -n +2) assertTrue "sent tx" $? HASH=$(echo $RES | jq .hash | tr -d \") TX_HEIGHT=$(echo $RES | jq .height) @@ -65,19 +67,19 @@ test01SendTx() { assertEquals "good deliver" "0" $(echo $RES | jq .deliver_tx.code) # make sure sender goes down - ACCT=$(basecli query account $SENDER) + ACCT=$(${CLIENT_EXE} query account $SENDER) assertTrue "must have genesis account" $? assertEquals "one tx" "1" $(echo $ACCT | jq .data.sequence) assertEquals "has money" "9007199254740000" $(echo $ACCT | jq .data.coins[0].amount) # make sure recipient goes up - ACCT2=$(basecli query account $RECV) + ACCT2=$(${CLIENT_EXE} query account $RECV) assertTrue "must have new account" $? assertEquals "no tx" "0" $(echo $ACCT2 | jq .data.sequence) assertEquals "has money" "992" $(echo $ACCT2 | jq .data.coins[0].amount) # make sure tx is indexed - TX=$(basecli query tx $HASH) + TX=$(${CLIENT_EXE} query tx $HASH) assertTrue "found tx" $? assertEquals "proper height" $TX_HEIGHT $(echo $TX | jq .height) assertEquals "type=send" '"send"' $(echo $TX | jq .data.type) From 81d6d2425f7628559f7b76234751982dbd4137c6 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Thu, 15 Jun 2017 21:13:56 +0200 Subject: [PATCH 05/20] Added counter tests as well --- Makefile | 10 +++ {clitest => tests/cli}/common.sh | 0 tests/cli/counter.sh | 137 +++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) rename {clitest => tests/cli}/common.sh (100%) create mode 100755 tests/cli/counter.sh diff --git a/Makefile b/Makefile index 18fcbbb2509..358a569e579 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,16 @@ dist: test: test_unit test_cli +clitest/shunit2: + wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ + -q -O clitest/shunit2 + +test_cli: clitest/shunit2 + # sudo apt-get install jq + @./clitest/basictx.sh + @./clitest/counter.sh + # @./clitest/ibc.sh + test_unit: go test $(PACKAGES) #go run tests/tendermint/*.go diff --git a/clitest/common.sh b/tests/cli/common.sh similarity index 100% rename from clitest/common.sh rename to tests/cli/common.sh diff --git a/tests/cli/counter.sh b/tests/cli/counter.sh new file mode 100755 index 00000000000..ea3069a2bb3 --- /dev/null +++ b/tests/cli/counter.sh @@ -0,0 +1,137 @@ +#!/bin/bash + +# these are two globals to control all scripts (can use eg. counter instead) +SERVER_EXE=counter +CLIENT_EXE=basecli # TODO: move to countercli + +oneTimeSetUp() { + # these are passed in as args + BASE_DIR=$HOME/.basecoin_test_counter + CHAIN_ID="counter-chain" + + rm -rf $BASE_DIR 2>/dev/null + mkdir -p $BASE_DIR + + # set up client - make sure you use the proper prefix if you set + # a custom CLIENT_EXE + export BC_HOME=${BASE_DIR}/client + prepareClient + + # start basecoin server (with counter) + initServer $BASE_DIR $CHAIN_ID 1234 + echo pid $PID_SERVER + + initClient $CHAIN_ID 1234 + + echo "...Testing may begin!" + echo + echo + echo +} + +oneTimeTearDown() { + echo + echo + echo "stopping $SERVER_EXE test server..." + kill -9 $PID_SERVER >/dev/null 2>&1 + sleep 1 +} + +# blatently copied to make sure it works with counter as well +test00GetAccount() { + SENDER=$(getAddr $RICH) + RECV=$(getAddr $POOR) + + assertFalse "requires arg" "${CLIENT_EXE} query account" + ACCT=$(${CLIENT_EXE} query account $SENDER) + assertTrue "must have proper genesis account" $? + assertEquals "no tx" "0" $(echo $ACCT | jq .data.sequence) + assertEquals "has money" "9007199254740992" $(echo $ACCT | jq .data.coins[0].amount) + + ACCT2=$(${CLIENT_EXE} query account $RECV) + assertFalse "has no genesis account" $? +} + +# blatently copied to make sure it works with counter as well +test01SendTx() { + SENDER=$(getAddr $RICH) + RECV=$(getAddr $POOR) + + assertFalse "missing dest" "${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 2>/dev/null" + assertFalse "bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null" + # we have to remove the password request from stdout, to just get the json + RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null | tail -n +2) + assertTrue "sent tx" $? + HASH=$(echo $RES | jq .hash | tr -d \") + TX_HEIGHT=$(echo $RES | jq .height) + assertEquals "good check" "0" $(echo $RES | jq .check_tx.code) + assertEquals "good deliver" "0" $(echo $RES | jq .deliver_tx.code) + + # make sure sender goes down + ACCT=$(${CLIENT_EXE} query account $SENDER) + assertTrue "must have genesis account" $? + assertEquals "one tx" "1" $(echo $ACCT | jq .data.sequence) + assertEquals "has money" "9007199254740000" $(echo $ACCT | jq .data.coins[0].amount) + + # make sure recipient goes up + ACCT2=$(${CLIENT_EXE} query account $RECV) + assertTrue "must have new account" $? + assertEquals "no tx" "0" $(echo $ACCT2 | jq .data.sequence) + assertEquals "has money" "992" $(echo $ACCT2 | jq .data.coins[0].amount) + + # make sure tx is indexed + TX=$(${CLIENT_EXE} query tx $HASH) + assertTrue "found tx" $? + assertEquals "proper height" $TX_HEIGHT $(echo $TX | jq .height) + assertEquals "type=send" '"send"' $(echo $TX | jq .data.type) + assertEquals "proper sender" "\"$SENDER\"" $(echo $TX | jq .data.data.inputs[0].address) + assertEquals "proper out amount" "992" $(echo $TX | jq .data.data.outputs[0].coins[0].amount) +} + +test02GetCounter() { + COUNT=$(${CLIENT_EXE} query counter) + assertFalse "no default count" $? +} + +test02AddCount() { + SENDER=$(getAddr $RICH) + assertFalse "bad password" "echo hi | ${CLIENT_EXE} tx counter --amount=1000mycoin --sequence=2 --name=${RICH} 2>/dev/null" + + # we have to remove the password request from stdout, to just get the json + RES=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --amount=10mycoin --sequence=2 --name=${RICH} --valid --countfee=5mycoin 2>/dev/null | tail -n +2) + assertTrue "sent tx" $? + HASH=$(echo $RES | jq .hash | tr -d \") + TX_HEIGHT=$(echo $RES | jq .height) + assertEquals "good check" "0" $(echo $RES | jq .check_tx.code) + assertEquals "good deliver" "0" $(echo $RES | jq .deliver_tx.code) + + # check new state + COUNT=$(${CLIENT_EXE} query counter) + assertTrue "count now set" $? + assertEquals "one tx" "1" $(echo $COUNT | jq .data.Counter) + assertEquals "has money" "5" $(echo $COUNT | jq .data.TotalFees[0].amount) + + # FIXME: cannot load apptx properly. + # Look at the stack trace + # This cannot be fixed with the current ugly apptx structure... + # Leave for refactoring + + # make sure tx is indexed + # echo hash $HASH + # TX=$(${CLIENT_EXE} query tx $HASH --trace) + # echo tx $TX + # if [-z assertTrue "found tx" $?]; then + # assertEquals "proper height" $TX_HEIGHT $(echo $TX | jq .height) + # assertEquals "type=app" '"app"' $(echo $TX | jq .data.type) + # assertEquals "proper sender" "\"$SENDER\"" $(echo $TX | jq .data.data.input.address) + # fi + # echo $TX +} + +# load and run these tests with shunit2! +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory + +# load common helpers +. $DIR/common.sh + +. $DIR/shunit2 From ad17fcf347fd1ab4a9a721c856767dac652ebb3a Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Thu, 15 Jun 2017 15:43:09 -0400 Subject: [PATCH 06/20] makefile cleanup int --- Makefile | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 358a569e579..ef3a3e6849b 100644 --- a/Makefile +++ b/Makefile @@ -16,16 +16,6 @@ dist: test: test_unit test_cli -clitest/shunit2: - wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ - -q -O clitest/shunit2 - -test_cli: clitest/shunit2 - # sudo apt-get install jq - @./clitest/basictx.sh - @./clitest/counter.sh - # @./clitest/ibc.sh - test_unit: go test $(PACKAGES) #go run tests/tendermint/*.go @@ -35,6 +25,7 @@ test_cli: -q -O tests/cli/shunit2 # sudo apt-get install jq @./tests/cli/basictx.sh + @./tests/cli/counter.sh # @./clitest/ibc.sh get_vendor_deps: tools From 9c8ccefd353ae072843ff67fa3a736dee68a07dc Mon Sep 17 00:00:00 2001 From: rigel rozanski Date: Fri, 16 Jun 2017 04:57:45 -0400 Subject: [PATCH 07/20] reorganize basecli appTx commands int --- cmd/basecli/commands/cmds.go | 120 +++++++++++++++++---------------- cmd/basecli/counter/counter.go | 56 ++++++++------- cmd/basecli/counter/query.go | 20 +----- cmd/basecli/main.go | 9 ++- 4 files changed, 99 insertions(+), 106 deletions(-) diff --git a/cmd/basecli/commands/cmds.go b/cmd/basecli/commands/cmds.go index 50a39024b4f..faf54c22799 100644 --- a/cmd/basecli/commands/cmds.go +++ b/cmd/basecli/commands/cmds.go @@ -10,41 +10,48 @@ import ( "github.com/tendermint/light-client/commands" txcmd "github.com/tendermint/light-client/commands/txs" + ctypes "github.com/tendermint/tendermint/rpc/core/types" + cmn "github.com/tendermint/tmlibs/common" btypes "github.com/tendermint/basecoin/types" ) -/*** Here is the sendtx command ***/ +/******** SendTx *********/ +// SendTxCmd is CLI command to send tokens between basecoin accounts var SendTxCmd = &cobra.Command{ Use: "send", Short: "send tokens from one account to another", RunE: doSendTx, } +//nolint const ( - ToFlag = "to" - AmountFlag = "amount" - FeeFlag = "fee" - GasFlag = "gas" - SequenceFlag = "sequence" + FlagTo = "to" + FlagAmount = "amount" + FlagFee = "fee" + FlagGas = "gas" + FlagSequence = "sequence" ) func init() { flags := SendTxCmd.Flags() - flags.String(ToFlag, "", "Destination address for the bits") - flags.String(AmountFlag, "", "Coins to send in the format ,...") - flags.String(FeeFlag, "0mycoin", "Coins for the transaction fee of the format ") - flags.Int64(GasFlag, 0, "Amount of gas for this transaction") - flags.Int(SequenceFlag, -1, "Sequence number for this transaction") + flags.String(FlagTo, "", "Destination address for the bits") + flags.String(FlagAmount, "", "Coins to send in the format ,...") + flags.String(FlagFee, "0mycoin", "Coins for the transaction fee of the format ") + flags.Int64(FlagGas, 0, "Amount of gas for this transaction") + flags.Int(FlagSequence, -1, "Sequence number for this transaction") } // runDemo is an example of how to make a tx func doSendTx(cmd *cobra.Command, args []string) error { - tx := new(btypes.SendTx) // load data from json or flags + tx := new(btypes.SendTx) found, err := txcmd.LoadJSON(tx) + if err != nil { + return err + } if !found { err = readSendTxFlags(tx) } @@ -52,6 +59,7 @@ func doSendTx(cmd *cobra.Command, args []string) error { return err } + // Wrap and add signer send := &SendTx{ chainID: commands.GetChainID(), Tx: tx, @@ -64,34 +72,34 @@ func doSendTx(cmd *cobra.Command, args []string) error { return err } - // output result + // Output result return txcmd.OutputTx(bres) } func readSendTxFlags(tx *btypes.SendTx) error { // parse to address - to, err := ParseHexFlag(ToFlag) + to, err := ParseHexFlag(FlagTo) if err != nil { return errors.Errorf("To address is invalid hex: %v\n", err) } //parse the fee and amounts into coin types - tx.Fee, err = btypes.ParseCoin(viper.GetString(FeeFlag)) + tx.Fee, err = btypes.ParseCoin(viper.GetString(FlagFee)) if err != nil { return err } - amountCoins, err := btypes.ParseCoins(viper.GetString(AmountFlag)) + amountCoins, err := btypes.ParseCoins(viper.GetString(FlagAmount)) if err != nil { return err } // set the gas - tx.Gas = viper.GetInt64(GasFlag) + tx.Gas = viper.GetInt64(FlagGas) // craft the inputs and outputs tx.Inputs = []btypes.TxInput{{ Coins: amountCoins, - Sequence: viper.GetInt(SequenceFlag), + Sequence: viper.GetInt(FlagSequence), }} tx.Outputs = []btypes.TxOutput{{ Address: to, @@ -103,39 +111,53 @@ func readSendTxFlags(tx *btypes.SendTx) error { /******** AppTx *********/ +// BroadcastAppTx wraps, signs, and executes an app tx basecoin transaction +func BroadcastAppTx(tx *btypes.AppTx) (*ctypes.ResultBroadcastTxCommit, error) { + + // Generate app transaction to be broadcast + appTx := WrapAppTx(tx) + appTx.AddSigner(txcmd.GetSigner()) + + // Sign if needed and post to the node. This it the work-horse + return txcmd.SignAndPostTx(appTx) +} + +// AddAppTxFlags adds flags required by apptx func AddAppTxFlags(fs *flag.FlagSet) { - fs.String(AmountFlag, "", "Coins to send in the format ,...") - fs.String(FeeFlag, "0mycoin", "Coins for the transaction fee of the format ") - fs.Int64(GasFlag, 0, "Amount of gas for this transaction") - fs.Int(SequenceFlag, -1, "Sequence number for this transaction") + fs.String(FlagAmount, "", "Coins to send in the format ,...") + fs.String(FlagFee, "0mycoin", "Coins for the transaction fee of the format ") + fs.Int64(FlagGas, 0, "Amount of gas for this transaction") + fs.Int(FlagSequence, -1, "Sequence number for this transaction") } // ReadAppTxFlags reads in the standard flags // your command should parse info to set tx.Name and tx.Data -func ReadAppTxFlags(tx *btypes.AppTx) error { - //parse the fee and amounts into coin types - var err error - tx.Fee, err = btypes.ParseCoin(viper.GetString(FeeFlag)) +func ReadAppTxFlags() (gas int64, fee btypes.Coin, txInput btypes.TxInput, err error) { + + // Set the gas + gas = viper.GetInt64(FlagGas) + + // Parse the fee and amounts into coin types + fee, err = btypes.ParseCoin(viper.GetString(FlagFee)) if err != nil { - return err + return } - amountCoins, err := btypes.ParseCoins(viper.GetString(AmountFlag)) + + // craft the inputs + var amount btypes.Coins + amount, err = btypes.ParseCoins(viper.GetString(FlagAmount)) if err != nil { - return err + return } - - // set the gas - tx.Gas = viper.GetInt64(GasFlag) - - // craft the inputs and outputs - tx.Input = btypes.TxInput{ - Coins: amountCoins, - Sequence: viper.GetInt(SequenceFlag), + txInput = btypes.TxInput{ + Coins: amount, + Sequence: viper.GetInt(FlagSequence), } - return nil + return } +// WrapAppTx wraps the transaction with chain id func WrapAppTx(tx *btypes.AppTx) *AppTx { return &AppTx{ chainID: commands.GetChainID(), @@ -145,25 +167,7 @@ func WrapAppTx(tx *btypes.AppTx) *AppTx { /** TODO copied from basecoin cli - put in common somewhere? **/ +// ParseHexFlag parses a flag string to byte array func ParseHexFlag(flag string) ([]byte, error) { - return hex.DecodeString(StripHex(viper.GetString(flag))) -} - -// Returns true for non-empty hex-string prefixed with "0x" -func isHex(s string) bool { - if len(s) > 2 && s[:2] == "0x" { - _, err := hex.DecodeString(s[2:]) - if err != nil { - return false - } - return true - } - return false -} - -func StripHex(s string) string { - if isHex(s) { - return s[2:] - } - return s + return hex.DecodeString(cmn.StripHex(viper.GetString(flag))) } diff --git a/cmd/basecli/counter/counter.go b/cmd/basecli/counter/counter.go index b39792e2cee..60f949fce2f 100644 --- a/cmd/basecli/counter/counter.go +++ b/cmd/basecli/counter/counter.go @@ -12,68 +12,72 @@ import ( btypes "github.com/tendermint/basecoin/types" ) +//CounterTxCmd is the CLI command to execute the counter +// through the appTx Command var CounterTxCmd = &cobra.Command{ Use: "counter", Short: "add a vote to the counter", Long: `Add a vote to the counter. You must pass --valid for it to count and the countfee will be added to the counter.`, - RunE: doCounterTx, + RunE: counterTxCmd, } const ( - CountFeeFlag = "countfee" - ValidFlag = "valid" + flagCountFee = "countfee" + flagValid = "valid" ) func init() { fs := CounterTxCmd.Flags() bcmd.AddAppTxFlags(fs) - fs.String(CountFeeFlag, "", "Coins to send in the format ,...") - fs.Bool(ValidFlag, false, "Is count valid?") + fs.String(flagCountFee, "", "Coins to send in the format ,...") + fs.Bool(flagValid, false, "Is count valid?") } -func doCounterTx(cmd *cobra.Command, args []string) error { - tx := new(btypes.AppTx) +func counterTxCmd(cmd *cobra.Command, args []string) error { // Note: we don't support loading apptx from json currently, so skip that - // read the standard flags - err := bcmd.ReadAppTxFlags(tx) + // Read the app-specific flags + name, data, err := getAppData() if err != nil { return err } - // now read the app-specific flags - err = readCounterFlags(tx) + // Read the standard app-tx flags + gas, fee, txInput, err := bcmd.ReadAppTxFlags() if err != nil { return err } - app := bcmd.WrapAppTx(tx) - app.AddSigner(txcmd.GetSigner()) - - // Sign if needed and post. This it the work-horse - bres, err := txcmd.SignAndPostTx(app) + // Create AppTx and broadcast + tx := &btypes.AppTx{ + Gas: gas, + Fee: fee, + Name: name, + Input: txInput, + Data: data, + } + res, err := bcmd.BroadcastAppTx(tx) if err != nil { return err } - // output result - return txcmd.OutputTx(bres) + // Output result + return txcmd.OutputTx(res) } -// readCounterFlags sets the app-specific data in the AppTx -func readCounterFlags(tx *btypes.AppTx) error { - countFee, err := btypes.ParseCoins(viper.GetString(CountFeeFlag)) +func getAppData() (name string, data []byte, err error) { + countFee, err := btypes.ParseCoins(viper.GetString(flagCountFee)) if err != nil { - return err + return } ctx := counter.CounterTx{ - Valid: viper.GetBool(ValidFlag), + Valid: viper.GetBool(flagValid), Fee: countFee, } - tx.Name = counter.New().Name() - tx.Data = wire.BinaryBytes(ctx) - return nil + name = counter.New().Name() + data = wire.BinaryBytes(ctx) + return } diff --git a/cmd/basecli/counter/query.go b/cmd/basecli/counter/query.go index a1c6aeb9b59..9a86df62574 100644 --- a/cmd/basecli/counter/query.go +++ b/cmd/basecli/counter/query.go @@ -8,13 +8,14 @@ import ( "github.com/tendermint/basecoin/plugins/counter" ) +//CounterQueryCmd CLI command to query the counter state var CounterQueryCmd = &cobra.Command{ Use: "counter", Short: "Query counter state, with proof", - RunE: doCounterQuery, + RunE: counterQueryCmd, } -func doCounterQuery(cmd *cobra.Command, args []string) error { +func counterQueryCmd(cmd *cobra.Command, args []string) error { key := counter.New().StateKey() var cp counter.CounterPluginState @@ -25,18 +26,3 @@ func doCounterQuery(cmd *cobra.Command, args []string) error { return proofcmd.OutputProof(cp, proof.BlockHeight()) } - -/*** doesn't seem to be needed anymore??? ***/ - -// type CounterPresenter struct{} - -// func (_ CounterPresenter) MakeKey(str string) ([]byte, error) { -// key := counter.New().StateKey() -// return key, nil -// } - -// func (_ CounterPresenter) ParseData(raw []byte) (interface{}, error) { -// var cp counter.CounterPluginState -// err := wire.ReadBinaryBytes(raw, &cp) -// return cp, err -// } diff --git a/cmd/basecli/main.go b/cmd/basecli/main.go index d5116d1600c..753e149fd4a 100644 --- a/cmd/basecli/main.go +++ b/cmd/basecli/main.go @@ -32,26 +32,25 @@ tmcli to work for any custom abci app. func main() { commands.AddBasicFlags(BaseCli) - // prepare queries + // Prepare queries pr := proofs.RootCmd - // these are default parsers, but you optional in your app + // These are default parsers, but you optional in your app pr.AddCommand(proofs.TxCmd) pr.AddCommand(proofs.KeyCmd) pr.AddCommand(bcmd.AccountQueryCmd) pr.AddCommand(bcount.CounterQueryCmd) - // here is how you would add the custom txs... but don't really add demo in your app + // Here is how you add custom txs... but don't really add counter in your app proofs.TxPresenters.Register("base", bcmd.BaseTxPresenter{}) tr := txs.RootCmd tr.AddCommand(bcmd.SendTxCmd) tr.AddCommand(bcount.CounterTxCmd) // TODO - // txs.Register("send", bcmd.SendTxMaker{}) // txs.Register("counter", bcount.CounterTxMaker{}) - // set up the various commands to use + // Set up the various commands to use BaseCli.AddCommand( commands.InitCmd, commands.ResetCmd, From 75425b9bc134da0e9dc4290ae035438a02cc767a Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 13:51:48 +0200 Subject: [PATCH 08/20] Update CHANGELOG for some of the 0.6 enhancements --- CHANGELOG.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6205a7e94b..62e45d6edfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## 0.6.0 (???) + +BREAKING CHANGES: +- basecli + - `basecli proof state get` -> `basecli query key` + - `basecli proof tx get` -> `basecli query tx` + - `basecli proof state get --app=account` -> `basecli query account` + - use `--chain-id` not `--chainid` for consistency + - update to use `--trace` not `--debug` for stack traces on errors + - complete overhaul on how tx and query subcommands are added. (see counter or trackomatron for examples) + - no longer supports counter app (see new countercli) +- basecoin + - removed all client side functionality from it (use basecli now for proofs) + +ENHANCEMENTS: +- intergrates tendermint 0.10.0 (not the rc-2, but the real thing) +- commands return error code (1) on failure for easier script testing +- add `reset_all` to basecli, and never delete keys on `init` +- new shutil based unit tests, with better coverage of the cli actions + +BUG FIXES: +- no longer panics on missing app_options in genesis (thanks, anton) + + ## 0.5.2 (June 2, 2017) BUG FIXES: From 4d4137855d4af364d8eaa295787e185da82a40b1 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 13:56:12 +0200 Subject: [PATCH 09/20] Cache shunit2 in Makefile, so we don't wget everytime --- CHANGELOG.md | 3 +++ Makefile | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62e45d6edfb..a917a1c791e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 0.6.0 (???) +Make the basecli command the only way to use client-side, to enforce best +security practices. Lots of enhancements to get it up to production quality. + BREAKING CHANGES: - basecli - `basecli proof state get` -> `basecli query key` diff --git a/Makefile b/Makefile index ef3a3e6849b..b61cc2ffd5b 100644 --- a/Makefile +++ b/Makefile @@ -20,9 +20,7 @@ test_unit: go test $(PACKAGES) #go run tests/tendermint/*.go -test_cli: - wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ - -q -O tests/cli/shunit2 +test_cli: tests/cli/shunit2 # sudo apt-get install jq @./tests/cli/basictx.sh @./tests/cli/counter.sh @@ -36,6 +34,10 @@ build-docker: "/go/src/github.com/tendermint/basecoin" -e "CGO_ENABLED=0" golang:alpine go build ./cmd/basecoin docker build -t "tendermint/basecoin" . +tests/cli/shunit2: + wget "https://raw.githubusercontent.com/kward/shunit2/master/source/2.1/src/shunit2" \ + -q -O tests/cli/shunit2 + tools: go get -u -v $(GOTOOLS) From 2f3c7002fab7845ebf157d3f47f65dacf4914561 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 14:00:43 +0200 Subject: [PATCH 10/20] Create new command, countercli, removed counter from basecli --- cmd/basecli/main.go | 11 +--- .../commands}/counter.go | 2 +- .../counter => countercli/commands}/query.go | 2 +- cmd/countercli/main.go | 64 +++++++++++++++++++ 4 files changed, 68 insertions(+), 11 deletions(-) rename cmd/{basecli/counter => countercli/commands}/counter.go (99%) rename cmd/{basecli/counter => countercli/commands}/query.go (97%) create mode 100644 cmd/countercli/main.go diff --git a/cmd/basecli/main.go b/cmd/basecli/main.go index 753e149fd4a..0506882a279 100644 --- a/cmd/basecli/main.go +++ b/cmd/basecli/main.go @@ -14,7 +14,6 @@ import ( "github.com/tendermint/tmlibs/cli" bcmd "github.com/tendermint/basecoin/cmd/basecli/commands" - bcount "github.com/tendermint/basecoin/cmd/basecli/counter" ) // BaseCli represents the base command when called without any subcommands @@ -34,21 +33,15 @@ func main() { // Prepare queries pr := proofs.RootCmd - // These are default parsers, but you optional in your app + // These are default parsers, but optional in your app (you can remove key) pr.AddCommand(proofs.TxCmd) pr.AddCommand(proofs.KeyCmd) pr.AddCommand(bcmd.AccountQueryCmd) - pr.AddCommand(bcount.CounterQueryCmd) - // Here is how you add custom txs... but don't really add counter in your app + // you will always want this for the base send command proofs.TxPresenters.Register("base", bcmd.BaseTxPresenter{}) tr := txs.RootCmd tr.AddCommand(bcmd.SendTxCmd) - tr.AddCommand(bcount.CounterTxCmd) - - // TODO - // txs.Register("send", bcmd.SendTxMaker{}) - // txs.Register("counter", bcount.CounterTxMaker{}) // Set up the various commands to use BaseCli.AddCommand( diff --git a/cmd/basecli/counter/counter.go b/cmd/countercli/commands/counter.go similarity index 99% rename from cmd/basecli/counter/counter.go rename to cmd/countercli/commands/counter.go index 60f949fce2f..22064e08cba 100644 --- a/cmd/basecli/counter/counter.go +++ b/cmd/countercli/commands/counter.go @@ -1,4 +1,4 @@ -package counter +package commands import ( "github.com/spf13/cobra" diff --git a/cmd/basecli/counter/query.go b/cmd/countercli/commands/query.go similarity index 97% rename from cmd/basecli/counter/query.go rename to cmd/countercli/commands/query.go index 9a86df62574..751f7a11b03 100644 --- a/cmd/basecli/counter/query.go +++ b/cmd/countercli/commands/query.go @@ -1,4 +1,4 @@ -package counter +package commands import ( "github.com/spf13/cobra" diff --git a/cmd/countercli/main.go b/cmd/countercli/main.go new file mode 100644 index 00000000000..57204d3fb6b --- /dev/null +++ b/cmd/countercli/main.go @@ -0,0 +1,64 @@ +package main + +import ( + "os" + + "github.com/spf13/cobra" + + keycmd "github.com/tendermint/go-crypto/cmd" + "github.com/tendermint/light-client/commands" + "github.com/tendermint/light-client/commands/proofs" + "github.com/tendermint/light-client/commands/proxy" + "github.com/tendermint/light-client/commands/seeds" + "github.com/tendermint/light-client/commands/txs" + "github.com/tendermint/tmlibs/cli" + + bcmd "github.com/tendermint/basecoin/cmd/basecli/commands" + bcount "github.com/tendermint/basecoin/cmd/countercli/commands" +) + +// BaseCli represents the base command when called without any subcommands +var BaseCli = &cobra.Command{ + Use: "basecli", + Short: "Light client for tendermint", + Long: `Basecli is an version of tmcli including custom logic to +present a nice (not raw hex) interface to the basecoin blockchain structure. + +This is a useful tool, but also serves to demonstrate how one can configure +tmcli to work for any custom abci app. +`, +} + +func main() { + commands.AddBasicFlags(BaseCli) + + // Prepare queries + pr := proofs.RootCmd + // These are default parsers, but you optional in your app + pr.AddCommand(proofs.TxCmd) + pr.AddCommand(proofs.KeyCmd) + pr.AddCommand(bcmd.AccountQueryCmd) + + // IMPORTANT: here is how you add custom query commands in your app + pr.AddCommand(bcount.CounterQueryCmd) + + proofs.TxPresenters.Register("base", bcmd.BaseTxPresenter{}) + tr := txs.RootCmd + tr.AddCommand(bcmd.SendTxCmd) + + // IMPORTANT: here is how you add custom tx construction for your app + tr.AddCommand(bcount.CounterTxCmd) + + // Set up the various commands to use + BaseCli.AddCommand( + commands.InitCmd, + commands.ResetCmd, + keycmd.RootCmd, + seeds.RootCmd, + pr, + tr, + proxy.RootCmd) + + cmd := cli.PrepareMainCmd(BaseCli, "BC", os.ExpandEnv("$HOME/.basecli")) + cmd.Execute() +} From 526e2136e109d0cc1c2751233b37fabc7df5d3ba Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 14:01:37 +0200 Subject: [PATCH 11/20] Fix cli tests for new countercli app --- tests/cli/counter.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cli/counter.sh b/tests/cli/counter.sh index ea3069a2bb3..3b00adb8814 100755 --- a/tests/cli/counter.sh +++ b/tests/cli/counter.sh @@ -2,7 +2,7 @@ # these are two globals to control all scripts (can use eg. counter instead) SERVER_EXE=counter -CLIENT_EXE=basecli # TODO: move to countercli +CLIENT_EXE=countercli oneTimeSetUp() { # these are passed in as args From fb7fc78b2e636a012c5a963591a2cbdfc04706ea Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 14:26:35 +0200 Subject: [PATCH 12/20] clean up cli tests --- tests/cli/basictx.sh | 31 ++++++-------------------- tests/cli/common.sh | 31 ++++++++++++++++++++++++++ tests/cli/counter.sh | 53 ++++++++++++++++---------------------------- 3 files changed, 57 insertions(+), 58 deletions(-) diff --git a/tests/cli/basictx.sh b/tests/cli/basictx.sh index e9a6b0e5fbf..550bd2c4301 100755 --- a/tests/cli/basictx.sh +++ b/tests/cli/basictx.sh @@ -43,10 +43,8 @@ test00GetAccount() { RECV=$(getAddr $POOR) assertFalse "requires arg" "${CLIENT_EXE} query account" - ACCT=$(${CLIENT_EXE} query account $SENDER) - assertTrue "must have proper genesis account" $? - assertEquals "no tx" "0" $(echo $ACCT | jq .data.sequence) - assertEquals "has money" "9007199254740992" $(echo $ACCT | jq .data.coins[0].amount) + + checkAccount $SENDER "0" "9007199254740992" ACCT2=$(${CLIENT_EXE} query account $RECV) assertFalse "has no genesis account" $? @@ -60,31 +58,16 @@ test01SendTx() { assertFalse "bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null" # we have to remove the password request from stdout, to just get the json RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null | tail -n +2) - assertTrue "sent tx" $? + txSucceeded "$RES" + HASH=$(echo $RES | jq .hash | tr -d \") TX_HEIGHT=$(echo $RES | jq .height) - assertEquals "good check" "0" $(echo $RES | jq .check_tx.code) - assertEquals "good deliver" "0" $(echo $RES | jq .deliver_tx.code) - # make sure sender goes down - ACCT=$(${CLIENT_EXE} query account $SENDER) - assertTrue "must have genesis account" $? - assertEquals "one tx" "1" $(echo $ACCT | jq .data.sequence) - assertEquals "has money" "9007199254740000" $(echo $ACCT | jq .data.coins[0].amount) - - # make sure recipient goes up - ACCT2=$(${CLIENT_EXE} query account $RECV) - assertTrue "must have new account" $? - assertEquals "no tx" "0" $(echo $ACCT2 | jq .data.sequence) - assertEquals "has money" "992" $(echo $ACCT2 | jq .data.coins[0].amount) + checkAccount $SENDER "1" "9007199254740000" + checkAccount $RECV "0" "992" # make sure tx is indexed - TX=$(${CLIENT_EXE} query tx $HASH) - assertTrue "found tx" $? - assertEquals "proper height" $TX_HEIGHT $(echo $TX | jq .height) - assertEquals "type=send" '"send"' $(echo $TX | jq .data.type) - assertEquals "proper sender" "\"$SENDER\"" $(echo $TX | jq .data.data.inputs[0].address) - assertEquals "proper out amount" "992" $(echo $TX | jq .data.data.outputs[0].coins[0].amount) + checkSendTx $HASH $TX_HEIGHT $SENDER "992" } diff --git a/tests/cli/common.sh b/tests/cli/common.sh index 07fe1a54b12..4a601284449 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -70,3 +70,34 @@ getAddr() { # print the addr echo $RAW | cut -d' ' -f2 } + +# checkAccount $ADDR $SEQUENCE $BALANCE +# assumes just one coin, checks the balance of first coin in any case +checkAccount() { + # make sure sender goes down + ACCT=$(${CLIENT_EXE} query account $1) + assertTrue "must have genesis account" $? + assertEquals "proper sequence" "$2" $(echo $ACCT | jq .data.sequence) + assertEquals "proper money" "$3" $(echo $ACCT | jq .data.coins[0].amount) +} + +# txSucceeded $RES +# must be called right after the `tx` command, makes sure it got a success response +txSucceeded() { + assertTrue "sent tx" $? + assertEquals "good check" "0" $(echo $1 | jq .check_tx.code) + assertEquals "good deliver" "0" $(echo $1 | jq .deliver_tx.code) +} + +# checkSendTx $HASH $HEIGHT $SENDER $AMOUNT +# this looks up the tx by hash, and makes sure the height and type match +# and that the first input was from this sender for this amount +checkSendTx() { + TX=$(${CLIENT_EXE} query tx $1) + assertTrue "found tx" $? + assertEquals "proper height" $2 $(echo $TX | jq .height) + assertEquals "type=send" '"send"' $(echo $TX | jq .data.type) + assertEquals "proper sender" "\"$3\"" $(echo $TX | jq .data.data.inputs[0].address) + assertEquals "proper out amount" "$4" $(echo $TX | jq .data.data.outputs[0].coins[0].amount) +} + diff --git a/tests/cli/counter.sh b/tests/cli/counter.sh index 3b00adb8814..461fb410e52 100755 --- a/tests/cli/counter.sh +++ b/tests/cli/counter.sh @@ -37,22 +37,19 @@ oneTimeTearDown() { sleep 1 } -# blatently copied to make sure it works with counter as well + test00GetAccount() { SENDER=$(getAddr $RICH) RECV=$(getAddr $POOR) assertFalse "requires arg" "${CLIENT_EXE} query account" - ACCT=$(${CLIENT_EXE} query account $SENDER) - assertTrue "must have proper genesis account" $? - assertEquals "no tx" "0" $(echo $ACCT | jq .data.sequence) - assertEquals "has money" "9007199254740992" $(echo $ACCT | jq .data.coins[0].amount) + + checkAccount $SENDER "0" "9007199254740992" ACCT2=$(${CLIENT_EXE} query account $RECV) assertFalse "has no genesis account" $? } -# blatently copied to make sure it works with counter as well test01SendTx() { SENDER=$(getAddr $RICH) RECV=$(getAddr $POOR) @@ -61,31 +58,15 @@ test01SendTx() { assertFalse "bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null" # we have to remove the password request from stdout, to just get the json RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null | tail -n +2) - assertTrue "sent tx" $? + txSucceeded "$RES" HASH=$(echo $RES | jq .hash | tr -d \") TX_HEIGHT=$(echo $RES | jq .height) - assertEquals "good check" "0" $(echo $RES | jq .check_tx.code) - assertEquals "good deliver" "0" $(echo $RES | jq .deliver_tx.code) - # make sure sender goes down - ACCT=$(${CLIENT_EXE} query account $SENDER) - assertTrue "must have genesis account" $? - assertEquals "one tx" "1" $(echo $ACCT | jq .data.sequence) - assertEquals "has money" "9007199254740000" $(echo $ACCT | jq .data.coins[0].amount) - - # make sure recipient goes up - ACCT2=$(${CLIENT_EXE} query account $RECV) - assertTrue "must have new account" $? - assertEquals "no tx" "0" $(echo $ACCT2 | jq .data.sequence) - assertEquals "has money" "992" $(echo $ACCT2 | jq .data.coins[0].amount) + checkAccount $SENDER "1" "9007199254740000" + checkAccount $RECV "0" "992" # make sure tx is indexed - TX=$(${CLIENT_EXE} query tx $HASH) - assertTrue "found tx" $? - assertEquals "proper height" $TX_HEIGHT $(echo $TX | jq .height) - assertEquals "type=send" '"send"' $(echo $TX | jq .data.type) - assertEquals "proper sender" "\"$SENDER\"" $(echo $TX | jq .data.data.inputs[0].address) - assertEquals "proper out amount" "992" $(echo $TX | jq .data.data.outputs[0].coins[0].amount) + checkSendTx $HASH $TX_HEIGHT $SENDER "992" } test02GetCounter() { @@ -93,23 +74,27 @@ test02GetCounter() { assertFalse "no default count" $? } +# checkAccount $COUNT $BALANCE +# assumes just one coin, checks the balance of first coin in any case +checkCounter() { + # make sure sender goes down + ACCT=$(${CLIENT_EXE} query counter) + assertTrue "count is set" $? + assertEquals "proper count" "$1" $(echo $ACCT | jq .data.Counter) + assertEquals "proper money" "$2" $(echo $ACCT | jq .data.TotalFees[0].amount) +} + test02AddCount() { SENDER=$(getAddr $RICH) assertFalse "bad password" "echo hi | ${CLIENT_EXE} tx counter --amount=1000mycoin --sequence=2 --name=${RICH} 2>/dev/null" # we have to remove the password request from stdout, to just get the json RES=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --amount=10mycoin --sequence=2 --name=${RICH} --valid --countfee=5mycoin 2>/dev/null | tail -n +2) - assertTrue "sent tx" $? + txSucceeded "$RES" HASH=$(echo $RES | jq .hash | tr -d \") TX_HEIGHT=$(echo $RES | jq .height) - assertEquals "good check" "0" $(echo $RES | jq .check_tx.code) - assertEquals "good deliver" "0" $(echo $RES | jq .deliver_tx.code) - # check new state - COUNT=$(${CLIENT_EXE} query counter) - assertTrue "count now set" $? - assertEquals "one tx" "1" $(echo $COUNT | jq .data.Counter) - assertEquals "has money" "5" $(echo $COUNT | jq .data.TotalFees[0].amount) + checkCounter "1" "5" # FIXME: cannot load apptx properly. # Look at the stack trace From 4606fc84f7687d757009851dc4f20e82c9ad173d Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 14:43:54 +0200 Subject: [PATCH 13/20] Add ibc test scaffolding --- Makefile | 2 +- tests/cli/basictx.sh | 2 +- tests/cli/common.sh | 1 - tests/cli/counter.sh | 2 +- tests/cli/ibc.sh | 83 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 85 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index b61cc2ffd5b..dddf4fc2cec 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ test_cli: tests/cli/shunit2 # sudo apt-get install jq @./tests/cli/basictx.sh @./tests/cli/counter.sh - # @./clitest/ibc.sh + @./clitest/ibc.sh get_vendor_deps: tools glide install diff --git a/tests/cli/basictx.sh b/tests/cli/basictx.sh index 550bd2c4301..efb01f18529 100755 --- a/tests/cli/basictx.sh +++ b/tests/cli/basictx.sh @@ -20,7 +20,7 @@ oneTimeSetUp() { # start basecoin server (with counter) initServer $BASE_DIR $CHAIN_ID 3456 - echo pid $PID_SERVER + PID_SERVER=$! initClient $CHAIN_ID 3456 diff --git a/tests/cli/common.sh b/tests/cli/common.sh index 4a601284449..08acb71e014 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -41,7 +41,6 @@ initServer() { echo "Starting ${SERVER_EXE} server..." ${SERVER_EXE} start --home=$SERVE_DIR >>$SERVER_LOG 2>&1 & sleep 5 - PID_SERVER=$! } # initClient requires chain_id arg, port is optional (default 4665{5,6,7}) diff --git a/tests/cli/counter.sh b/tests/cli/counter.sh index 461fb410e52..fbc7699d3c7 100755 --- a/tests/cli/counter.sh +++ b/tests/cli/counter.sh @@ -19,7 +19,7 @@ oneTimeSetUp() { # start basecoin server (with counter) initServer $BASE_DIR $CHAIN_ID 1234 - echo pid $PID_SERVER + PID_SERVER=$! initClient $CHAIN_ID 1234 diff --git a/tests/cli/ibc.sh b/tests/cli/ibc.sh index 2b0c889a74c..662f91b1065 100755 --- a/tests/cli/ibc.sh +++ b/tests/cli/ibc.sh @@ -1,3 +1,84 @@ #!/bin/bash -echo "ibc test not implemented" +#!/bin/bash + +# these are two globals to control all scripts (can use eg. counter instead) +SERVER_EXE=basecoin +CLIENT_EXE=basecli + +oneTimeSetUp() { + # these are passed in as args + BASE_DIR_1=$HOME/.basecoin_test_ibc/chain1 + CHAIN_ID_1=test-chain-1 + CLIENT_1=${BASE_DIR_1}/client + + BASE_DIR_2=$HOME/.basecoin_test_ibc/chain2 + CHAIN_ID_2=test-chain-2 + CLIENT_2=${BASE_DIR_2}/client + + # clean up and create the test dirs + rm -rf $BASE_DIR_1 $BASE_DIR_2 2>/dev/null + mkdir -p $BASE_DIR_1 $BASE_DIR_2 + + # set up client for chain 1- make sure you use the proper prefix if you set + # a custom CLIENT_EXE + BC_HOME=${CLIENT_1} prepareClient + BC_HOME=${CLIENT_2} prepareClient + + # start basecoin server, giving money to the key in the first client + BC_HOME=${CLIENT_1} initServer $BASE_DIR_1 $CHAIN_ID_1 2345 + PID_SERVER_1=$! + + # start second basecoin server, giving money to the key in the second client + BC_HOME=${CLIENT_2} initServer $BASE_DIR_2 $CHAIN_ID_2 3456 + PID_SERVER_2=$! + + # connect both clients + BC_HOME=${CLIENT_1} initClient $CHAIN_ID_1 2345 + BC_HOME=${CLIENT_2} initClient $CHAIN_ID_2 3456 + + echo "...Testing may begin!" + echo + echo + echo +} + +oneTimeTearDown() { + echo + echo + echo "stopping both $SERVER_EXE test servers... $PID_SERVER_1 $PID_SERVER_2" + kill -9 $PID_SERVER_1 + kill -9 $PID_SERVER_2 + sleep 1 +} + +test00GetAccount() { + export BC_HOME=${CLIENT_1} + SENDER_1=$(getAddr $RICH) + RECV_1=$(getAddr $POOR) + + assertFalse "requires arg" "${CLIENT_EXE} query account" + assertFalse "has no genesis account" "${CLIENT_EXE} query account $RECV_1" + checkAccount $SENDER_1 "0" "9007199254740992" + + export BC_HOME=${CLIENT_2} + SENDER_2=$(getAddr $RICH) + RECV_2=$(getAddr $POOR) + + assertFalse "requires arg" "${CLIENT_EXE} query account" + assertFalse "has no genesis account" "${CLIENT_EXE} query account $RECV_2" + checkAccount $SENDER_2 "0" "9007199254740992" + + # make sure that they have different addresses on both chains (they are random keys) + assertNotEquals "sender keys must be different" "$SENDER_1" "$SENDER_2" + assertNotEquals "recipient keys must be different" "$RECV_1" "$RECV_2" +} + + +# load and run these tests with shunit2! +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory + +# load common helpers +. $DIR/common.sh + +. $DIR/shunit2 From cba5523ca5beece7a6803d0f3c6fdf45e2c9e617 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 15:33:37 +0200 Subject: [PATCH 14/20] Clear output of test failures in ibc --- tests/cli/basictx.sh | 11 +++++------ tests/cli/common.sh | 28 ++++++++++++++++++++++++---- tests/cli/counter.sh | 20 ++++++++++---------- tests/cli/ibc.sh | 44 ++++++++++++++++++++++++++++++++++++++------ 4 files changed, 77 insertions(+), 26 deletions(-) diff --git a/tests/cli/basictx.sh b/tests/cli/basictx.sh index efb01f18529..945665b521f 100755 --- a/tests/cli/basictx.sh +++ b/tests/cli/basictx.sh @@ -56,12 +56,11 @@ test01SendTx() { assertFalse "missing dest" "${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 2>/dev/null" assertFalse "bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null" - # we have to remove the password request from stdout, to just get the json - RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null | tail -n +2) - txSucceeded "$RES" - - HASH=$(echo $RES | jq .hash | tr -d \") - TX_HEIGHT=$(echo $RES | jq .height) + RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null) + txSucceeded $? "$RES" + TX=`echo $RES | cut -d: -f2-` + HASH=$(echo $TX | jq .hash | tr -d \") + TX_HEIGHT=$(echo $TX | jq .height) checkAccount $SENDER "1" "9007199254740000" checkAccount $RECV "0" "992" diff --git a/tests/cli/common.sh b/tests/cli/common.sh index 08acb71e014..faa9faa88b9 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -78,14 +78,19 @@ checkAccount() { assertTrue "must have genesis account" $? assertEquals "proper sequence" "$2" $(echo $ACCT | jq .data.sequence) assertEquals "proper money" "$3" $(echo $ACCT | jq .data.coins[0].amount) + return $? } -# txSucceeded $RES +# txSucceeded $? "$RES" # must be called right after the `tx` command, makes sure it got a success response txSucceeded() { - assertTrue "sent tx" $? - assertEquals "good check" "0" $(echo $1 | jq .check_tx.code) - assertEquals "good deliver" "0" $(echo $1 | jq .deliver_tx.code) + if (assertTrue "sent tx: $2" $1); then + TX=`echo $2 | cut -d: -f2-` # strip off first line asking for password + assertEquals "good check: $TX" "0" $(echo $TX | jq .check_tx.code) + assertEquals "good deliver: $TX" "0" $(echo $TX | jq .deliver_tx.code) + else + return 1 + fi } # checkSendTx $HASH $HEIGHT $SENDER $AMOUNT @@ -98,5 +103,20 @@ checkSendTx() { assertEquals "type=send" '"send"' $(echo $TX | jq .data.type) assertEquals "proper sender" "\"$3\"" $(echo $TX | jq .data.data.inputs[0].address) assertEquals "proper out amount" "$4" $(echo $TX | jq .data.data.outputs[0].coins[0].amount) + return $? } +# waitForBlock $port +# waits until the block height on that node increases by one +waitForBlock() { + addr=http://localhost:$1 + b1=`curl -s $addr/status | jq .result.latest_block_height` + b2=$b1 + while [ "$b2" == "$b1" ]; do + echo "Waiting for node $addr to commit a block ..." + sleep 1 + b2=`curl -s $addr/status | jq .result.latest_block_height` + done +} + + diff --git a/tests/cli/counter.sh b/tests/cli/counter.sh index fbc7699d3c7..6f83e33da58 100755 --- a/tests/cli/counter.sh +++ b/tests/cli/counter.sh @@ -56,11 +56,11 @@ test01SendTx() { assertFalse "missing dest" "${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 2>/dev/null" assertFalse "bad password" "echo foo | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null" - # we have to remove the password request from stdout, to just get the json - RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null | tail -n +2) - txSucceeded "$RES" - HASH=$(echo $RES | jq .hash | tr -d \") - TX_HEIGHT=$(echo $RES | jq .height) + RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=992mycoin --sequence=1 --to=$RECV --name=$RICH 2>/dev/null) + txSucceeded $? "$RES" + TX=`echo $RES | cut -d: -f2-` + HASH=$(echo $TX | jq .hash | tr -d \") + TX_HEIGHT=$(echo $TX | jq .height) checkAccount $SENDER "1" "9007199254740000" checkAccount $RECV "0" "992" @@ -88,11 +88,11 @@ test02AddCount() { SENDER=$(getAddr $RICH) assertFalse "bad password" "echo hi | ${CLIENT_EXE} tx counter --amount=1000mycoin --sequence=2 --name=${RICH} 2>/dev/null" - # we have to remove the password request from stdout, to just get the json - RES=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --amount=10mycoin --sequence=2 --name=${RICH} --valid --countfee=5mycoin 2>/dev/null | tail -n +2) - txSucceeded "$RES" - HASH=$(echo $RES | jq .hash | tr -d \") - TX_HEIGHT=$(echo $RES | jq .height) + RES=$(echo qwertyuiop | ${CLIENT_EXE} tx counter --amount=10mycoin --sequence=2 --name=${RICH} --valid --countfee=5mycoin 2>/dev/null) + txSucceeded $? "$RES" + TX=`echo $RES | cut -d: -f2-` + HASH=$(echo $TX | jq .hash | tr -d \") + TX_HEIGHT=$(echo $TX | jq .height) checkCounter "1" "5" diff --git a/tests/cli/ibc.sh b/tests/cli/ibc.sh index 662f91b1065..49c60783457 100755 --- a/tests/cli/ibc.sh +++ b/tests/cli/ibc.sh @@ -11,10 +11,12 @@ oneTimeSetUp() { BASE_DIR_1=$HOME/.basecoin_test_ibc/chain1 CHAIN_ID_1=test-chain-1 CLIENT_1=${BASE_DIR_1}/client + PORT_1=1234 BASE_DIR_2=$HOME/.basecoin_test_ibc/chain2 CHAIN_ID_2=test-chain-2 CLIENT_2=${BASE_DIR_2}/client + PORT_2=2345 # clean up and create the test dirs rm -rf $BASE_DIR_1 $BASE_DIR_2 2>/dev/null @@ -26,16 +28,16 @@ oneTimeSetUp() { BC_HOME=${CLIENT_2} prepareClient # start basecoin server, giving money to the key in the first client - BC_HOME=${CLIENT_1} initServer $BASE_DIR_1 $CHAIN_ID_1 2345 + BC_HOME=${CLIENT_1} initServer $BASE_DIR_1 $CHAIN_ID_1 $PORT_1 PID_SERVER_1=$! # start second basecoin server, giving money to the key in the second client - BC_HOME=${CLIENT_2} initServer $BASE_DIR_2 $CHAIN_ID_2 3456 + BC_HOME=${CLIENT_2} initServer $BASE_DIR_2 $CHAIN_ID_2 $PORT_2 PID_SERVER_2=$! # connect both clients - BC_HOME=${CLIENT_1} initClient $CHAIN_ID_1 2345 - BC_HOME=${CLIENT_2} initClient $CHAIN_ID_2 3456 + BC_HOME=${CLIENT_1} initClient $CHAIN_ID_1 $PORT_1 + BC_HOME=${CLIENT_2} initClient $CHAIN_ID_2 $PORT_2 echo "...Testing may begin!" echo @@ -53,9 +55,9 @@ 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 "requires arg" "${CLIENT_EXE} query account" assertFalse "has no genesis account" "${CLIENT_EXE} query account $RECV_1" @@ -74,6 +76,36 @@ test00GetAccount() { assertNotEquals "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) + + # we have to remove the password request from stdout, to just get the json + export BC_HOME=${CLIENT_1} + RES=$(echo qwertyuiop | ${CLIENT_EXE} tx send --amount=20002mycoin --sequence=1 --to=${CHAIN_ID_2}/${RECV} --name=$RICH 2>/dev/null) + txSucceeded $? "$RES" + # an example to quit early if there is no point in more tests + if [ $? != 0 ]; then echo "aborting!"; return 1; fi + + TX=`echo $RES | cut -d: -f2-` + 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}7 + assertFalse "no relay running" "BC_HOME=${CLIENT_2} ${CLIENT_EXE} query account $RECV" + + # start the relay and wait a few blocks... + + # then make sure the money arrived +} + # load and run these tests with shunit2! DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory From 33d4f930da8e582357d0dcb7d1c55125f7bde33b Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 15:42:18 +0200 Subject: [PATCH 15/20] basecli sendtx handles chain/addr format --- cmd/basecli/commands/cmds.go | 31 +++++++++++++++++++++++++++++-- cmd/basecli/commands/sendtx.go | 3 ++- tests/cli/ibc.sh | 2 ++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/cmd/basecli/commands/cmds.go b/cmd/basecli/commands/cmds.go index faf54c22799..d6d598590a8 100644 --- a/cmd/basecli/commands/cmds.go +++ b/cmd/basecli/commands/cmds.go @@ -2,6 +2,7 @@ package commands import ( "encoding/hex" + "strings" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -78,9 +79,9 @@ func doSendTx(cmd *cobra.Command, args []string) error { func readSendTxFlags(tx *btypes.SendTx) error { // parse to address - to, err := ParseHexFlag(FlagTo) + to, err := parseChainAddress(viper.GetString(FlagTo)) if err != nil { - return errors.Errorf("To address is invalid hex: %v\n", err) + return err } //parse the fee and amounts into coin types @@ -109,6 +110,32 @@ func readSendTxFlags(tx *btypes.SendTx) error { return nil } +func parseChainAddress(toFlag string) ([]byte, error) { + var toHex string + var chainPrefix string + spl := strings.Split(toFlag, "/") + switch len(spl) { + case 1: + toHex = spl[0] + case 2: + chainPrefix = spl[0] + toHex = spl[1] + default: + return nil, errors.Errorf("To address has too many slashes") + } + + // convert destination address to bytes + to, err := hex.DecodeString(cmn.StripHex(toHex)) + if err != nil { + return nil, errors.Errorf("To address is invalid hex: %v\n", err) + } + + if chainPrefix != "" { + to = []byte(chainPrefix + "/" + string(to)) + } + return to, nil +} + /******** AppTx *********/ // BroadcastAppTx wraps, signs, and executes an app tx basecoin transaction diff --git a/cmd/basecli/commands/sendtx.go b/cmd/basecli/commands/sendtx.go index ccf00c6ed1d..178e4e37d92 100644 --- a/cmd/basecli/commands/sendtx.go +++ b/cmd/basecli/commands/sendtx.go @@ -97,7 +97,8 @@ func (s *SendTx) ValidateBasic() error { } } for _, out := range s.Tx.Outputs { - if len(out.Address) != 20 { + // we now allow chain/addr, so it can be more than 20 bytes + if len(out.Address) < 20 { return errors.Errorf("Invalid output address length: %d", len(out.Address)) } if !out.Coins.IsValid() { diff --git a/tests/cli/ibc.sh b/tests/cli/ibc.sh index 49c60783457..dbe1ff4f954 100755 --- a/tests/cli/ibc.sh +++ b/tests/cli/ibc.sh @@ -5,6 +5,8 @@ # these are two globals to control all scripts (can use eg. counter instead) SERVER_EXE=basecoin CLIENT_EXE=basecli +# just uncomment this line for full stack traces in error output +# CLIENT_EXE="basecli --trace" oneTimeSetUp() { # these are passed in as args From 6eac364c4322497f6d2f38f7d675d86cd9b6ee16 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 16:59:23 +0200 Subject: [PATCH 16/20] Complete ibc tests with "basecoin ibc register" and "basecoin relay" --- tests/cli/basictx.sh | 3 +- tests/cli/common.sh | 6 ++-- tests/cli/counter.sh | 2 +- tests/cli/ibc.sh | 78 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 77 insertions(+), 12 deletions(-) diff --git a/tests/cli/basictx.sh b/tests/cli/basictx.sh index 945665b521f..0f2eb7803a1 100755 --- a/tests/cli/basictx.sh +++ b/tests/cli/basictx.sh @@ -12,7 +12,6 @@ oneTimeSetUp() { rm -rf $BASE_DIR 2>/dev/null mkdir -p $BASE_DIR - # set up client - make sure you use the proper prefix if you set # a custom CLIENT_EXE export BC_HOME=${BASE_DIR}/client @@ -22,7 +21,7 @@ oneTimeSetUp() { initServer $BASE_DIR $CHAIN_ID 3456 PID_SERVER=$! - initClient $CHAIN_ID 3456 + initClient $CHAIN_ID 34567 echo "...Testing may begin!" echo diff --git a/tests/cli/common.sh b/tests/cli/common.sh index faa9faa88b9..d39355fe054 100644 --- a/tests/cli/common.sh +++ b/tests/cli/common.sh @@ -43,12 +43,12 @@ initServer() { sleep 5 } -# initClient requires chain_id arg, port is optional (default 4665{5,6,7}) +# initClient requires chain_id arg, port is optional (default 46657) initClient() { echo "Attaching ${CLIENT_EXE} client..." - PORT=${2:-4665} + PORT=${2:-46657} # hard-code the expected validator hash - ${CLIENT_EXE} init --chain-id=$1 --node=tcp://localhost:${PORT}7 --valhash=EB168E17E45BAEB194D4C79067FFECF345C64DE6 + ${CLIENT_EXE} init --chain-id=$1 --node=tcp://localhost:${PORT} --valhash=EB168E17E45BAEB194D4C79067FFECF345C64DE6 assertTrue "initialized light-client" $? } diff --git a/tests/cli/counter.sh b/tests/cli/counter.sh index 6f83e33da58..599f511297d 100755 --- a/tests/cli/counter.sh +++ b/tests/cli/counter.sh @@ -21,7 +21,7 @@ oneTimeSetUp() { initServer $BASE_DIR $CHAIN_ID 1234 PID_SERVER=$! - initClient $CHAIN_ID 1234 + initClient $CHAIN_ID 12347 echo "...Testing may begin!" echo diff --git a/tests/cli/ibc.sh b/tests/cli/ibc.sh index dbe1ff4f954..bc9d76cd929 100755 --- a/tests/cli/ibc.sh +++ b/tests/cli/ibc.sh @@ -13,12 +13,14 @@ oneTimeSetUp() { BASE_DIR_1=$HOME/.basecoin_test_ibc/chain1 CHAIN_ID_1=test-chain-1 CLIENT_1=${BASE_DIR_1}/client - PORT_1=1234 + PREFIX_1=1234 + PORT_1=${PREFIX_1}7 BASE_DIR_2=$HOME/.basecoin_test_ibc/chain2 CHAIN_ID_2=test-chain-2 CLIENT_2=${BASE_DIR_2}/client - PORT_2=2345 + PREFIX_2=2345 + PORT_2=${PREFIX_2}7 # clean up and create the test dirs rm -rf $BASE_DIR_1 $BASE_DIR_2 2>/dev/null @@ -30,11 +32,11 @@ oneTimeSetUp() { BC_HOME=${CLIENT_2} prepareClient # start basecoin server, giving money to the key in the first client - BC_HOME=${CLIENT_1} initServer $BASE_DIR_1 $CHAIN_ID_1 $PORT_1 + BC_HOME=${CLIENT_1} initServer $BASE_DIR_1 $CHAIN_ID_1 $PREFIX_1 PID_SERVER_1=$! # start second basecoin server, giving money to the key in the second client - BC_HOME=${CLIENT_2} initServer $BASE_DIR_2 $CHAIN_ID_2 $PORT_2 + BC_HOME=${CLIENT_2} initServer $BASE_DIR_2 $CHAIN_ID_2 $PREFIX_2 PID_SERVER_2=$! # connect both clients @@ -100,14 +102,78 @@ test01SendIBCTx() { checkSendTx $HASH $TX_HEIGHT $SENDER "20002" # # make sure nothing arrived - yet - waitForBlock ${PORT_1}7 + waitForBlock ${PORT_1} assertFalse "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!"; return 1; fi - # then make sure the money arrived + # 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 + 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 \") + + # 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 2>/dev/null) + txSucceeded $? "$RES" + 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 2>/dev/null) + txSucceeded $? "$RES" + if [ $? != 0 ]; then echo "can't pay chain2!"; return 1; fi + + # now we need to register the chains + # TODO: do this with basecli!!!! + basecoin tx ibc --amount 10mycoin --from=$RELAY_KEY --chain_id=$CHAIN_ID_2 \ + --node=tcp://localhost:${PORT_2} \ + register --ibc_chain_id=$CHAIN_ID_1 --genesis=$BASE_DIR_1/server/genesis.json \ + >/dev/null + if [ $? != 0 ]; then echo "can't register chain1 on chain 2"; return 1; fi + + basecoin tx ibc --amount 10mycoin --from=$RELAY_KEY --chain_id=$CHAIN_ID_1 \ + --node=tcp://localhost:${PORT_1} \ + register --ibc_chain_id=$CHAIN_ID_2 --genesis=$BASE_DIR_2/server/genesis.json \ + >/dev/null + if [ $? != 0 ]; then echo "can't register chain2 on chain 1"; return 1; fi + + # now start the relay! (this remains a server command) + # TODO: bucky, why does this die if I don't provide home??? + # It doesn't use the --from flag???? + ${SERVER_EXE} relay --chain1-id=$CHAIN_ID_1 --chain2-id=$CHAIN_ID_2 \ + --chain1-addr=tcp://localhost:${PORT_1} --chain2-addr=tcp://localhost:${PORT_2} \ + --home=${BASE_DIR_1}/server --from=$RELAY_KEY > ${BASE_DIR_1}/../relay.log & + PID_RELAY=$! + echo starting relay $PID_RELAY ... + + # return an error if it dies in the first two seconds to make sure it is running + sleep 2 + ps $PID_RELAY >/dev/null + return $? +} # load and run these tests with shunit2! DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" #get this files directory From f75ebca3aeef3d38f4a6f5db7a25e20df7687102 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 17:10:45 +0200 Subject: [PATCH 17/20] Fix Makefile, remove no longer needed demo! --- Makefile | 2 +- circle.yml | 1 - demo/clean.sh | 10 -- demo/data/chain1/config.toml | 11 -- demo/data/chain1/genesis.json | 31 ----- demo/data/chain1/key.json | 12 -- demo/data/chain1/priv_validator.json | 1 - demo/data/chain2/config.toml | 11 -- demo/data/chain2/genesis.json | 31 ----- demo/data/chain2/key.json | 11 -- demo/data/chain2/priv_validator.json | 1 - demo/start.sh | 198 --------------------------- 12 files changed, 1 insertion(+), 319 deletions(-) delete mode 100644 demo/clean.sh delete mode 100644 demo/data/chain1/config.toml delete mode 100644 demo/data/chain1/genesis.json delete mode 100644 demo/data/chain1/key.json delete mode 100644 demo/data/chain1/priv_validator.json delete mode 100644 demo/data/chain2/config.toml delete mode 100644 demo/data/chain2/genesis.json delete mode 100644 demo/data/chain2/key.json delete mode 100644 demo/data/chain2/priv_validator.json delete mode 100644 demo/start.sh diff --git a/Makefile b/Makefile index dddf4fc2cec..159618cc9eb 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ test_cli: tests/cli/shunit2 # sudo apt-get install jq @./tests/cli/basictx.sh @./tests/cli/counter.sh - @./clitest/ibc.sh + @./tests/cli/ibc.sh get_vendor_deps: tools glide install diff --git a/circle.yml b/circle.yml index 09093e34aeb..ea4110e9da5 100644 --- a/circle.yml +++ b/circle.yml @@ -22,6 +22,5 @@ test: - "cd $REPO && glide install && go install ./cmd/..." - ls $GOPATH/bin - "cd $REPO && make test" - - "cd $REPO/demo && bash start.sh" diff --git a/demo/clean.sh b/demo/clean.sh deleted file mode 100644 index bffdefdb84f..00000000000 --- a/demo/clean.sh +++ /dev/null @@ -1,10 +0,0 @@ -#! /bin/bash - -killall -9 basecoin tendermint -TMHOME=./data/chain1 tendermint unsafe_reset_all -TMHOME=./data/chain2 tendermint unsafe_reset_all - -rm ./*.log - -rm ./data/chain1/*.bak -rm ./data/chain2/*.bak diff --git a/demo/data/chain1/config.toml b/demo/data/chain1/config.toml deleted file mode 100644 index e2bcb49fff8..00000000000 --- a/demo/data/chain1/config.toml +++ /dev/null @@ -1,11 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -proxy_app = "tcp://127.0.0.1:46658" -moniker = "anonymous" -node_laddr = "tcp://0.0.0.0:46656" -seeds = "" -fast_sync = true -db_backend = "leveldb" -log_level = "info" -rpc_laddr = "tcp://0.0.0.0:46657" diff --git a/demo/data/chain1/genesis.json b/demo/data/chain1/genesis.json deleted file mode 100644 index 284572eb374..00000000000 --- a/demo/data/chain1/genesis.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "app_hash": "", - "chain_id": "test_chain_1", - "genesis_time": "0001-01-01T00:00:00.000Z", - "validators": [ - { - "amount": 10, - "name": "", - "pub_key": { - "type": "ed25519", - "data":"D6EBB92440CF375054AA59BCF0C99D596DEEDFFB2543CAE1BA1908B72CF9676A" - } - } - ], - "app_options": { - "accounts": [ - { - "pub_key": { - "type": "ed25519", - "data": "B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF" - }, - "coins": [ - { - "denom": "mycoin", - "amount": 9007199254740992 - } - ] - } - ] - } -} diff --git a/demo/data/chain1/key.json b/demo/data/chain1/key.json deleted file mode 100644 index 751dc858f0d..00000000000 --- a/demo/data/chain1/key.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "address": "D397BC62B435F3CF50570FBAB4340FE52C60858F", - "priv_key": { - "type": "ed25519", - "data": "39E75AA1CF7BC710585977EFC375CD1730519186BD231478C339F2819C3C26E7B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF" - }, - "pub_key": { - "type": "ed25519", - "data": "B3588BDC92015ED3CDB6F57A86379E8C79A7111063610B7E625487C76496F4DF" - } -} - diff --git a/demo/data/chain1/priv_validator.json b/demo/data/chain1/priv_validator.json deleted file mode 100644 index 55db06f4bca..00000000000 --- a/demo/data/chain1/priv_validator.json +++ /dev/null @@ -1 +0,0 @@ -{"address":"EBB0B4A899973C524A6BB18A161056A55F590F41","pub_key":{"type":"ed25519","data":"D6EBB92440CF375054AA59BCF0C99D596DEEDFFB2543CAE1BA1908B72CF9676A"},"last_height":0,"last_round":0,"last_step":0,"last_signature":null,"priv_key":{"type":"ed25519","data":"5FFDC1EA5FA2CA4A0A5503C86D2D348C5B401AD80FAA1899508F1ED00D8982E8D6EBB92440CF375054AA59BCF0C99D596DEEDFFB2543CAE1BA1908B72CF9676A"}} \ No newline at end of file diff --git a/demo/data/chain2/config.toml b/demo/data/chain2/config.toml deleted file mode 100644 index e2bcb49fff8..00000000000 --- a/demo/data/chain2/config.toml +++ /dev/null @@ -1,11 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -proxy_app = "tcp://127.0.0.1:46658" -moniker = "anonymous" -node_laddr = "tcp://0.0.0.0:46656" -seeds = "" -fast_sync = true -db_backend = "leveldb" -log_level = "info" -rpc_laddr = "tcp://0.0.0.0:46657" diff --git a/demo/data/chain2/genesis.json b/demo/data/chain2/genesis.json deleted file mode 100644 index 3ff94b99332..00000000000 --- a/demo/data/chain2/genesis.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "app_hash": "", - "chain_id": "test_chain_2", - "genesis_time": "0001-01-01T00:00:00.000Z", - "validators": [ - { - "amount": 10, - "name": "", - "pub_key": { - "type": "ed25519", - "data": "9A76DDE4CA4EE660C073D288DBE4F8A128F23857881A95F18167682D47E7058F" - } - } - ], - "app_options": { - "accounts": [ - { - "pub_key": { - "type": "ed25519", - "data": "0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D" - }, - "coins": [ - { - "denom": "mycoin", - "amount": 9007199254740992 - } - ] - } - ] - } -} diff --git a/demo/data/chain2/key.json b/demo/data/chain2/key.json deleted file mode 100644 index 6aa8b7965f9..00000000000 --- a/demo/data/chain2/key.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "address": "053BA0F19616AFF975C8756A2CBFF04F408B4D47", - "priv_key": { - "type": "ed25519", - "data": "22920C428043D869987F253D7C9B2305E7010642C40CE88A52C9F6CE5ACC42080628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D" - }, - "pub_key": { - "type": "ed25519", - "data": "0628C8E6C2D50B15764B443394E06C6A64F3082CE966A2A8C1A55A4D63D0FC5D" - } -} diff --git a/demo/data/chain2/priv_validator.json b/demo/data/chain2/priv_validator.json deleted file mode 100644 index 12eb625259f..00000000000 --- a/demo/data/chain2/priv_validator.json +++ /dev/null @@ -1 +0,0 @@ -{"address":"D42CFCB9C42DF9A73143EEA89255D1DF027B6240","pub_key":{"type":"ed25519","data":"9A76DDE4CA4EE660C073D288DBE4F8A128F23857881A95F18167682D47E7058F"},"last_height":0,"last_round":0,"last_step":0,"last_signature":null,"priv_key":{"type":"ed25519","data":"6353FAF4ADEB03EA496A9EAE5BE56C4C6A851CB705401788184FDC9198413C2C9A76DDE4CA4EE660C073D288DBE4F8A128F23857881A95F18167682D47E7058F"}} \ No newline at end of file diff --git a/demo/start.sh b/demo/start.sh deleted file mode 100644 index abb1576be54..00000000000 --- a/demo/start.sh +++ /dev/null @@ -1,198 +0,0 @@ -#! /bin/bash -set -e - -cd $GOPATH/src/github.com/tendermint/basecoin/demo - -LOG_DIR="." -TM_VERSION="master" -#TM_VERSION="v0.10.0" - -if [[ "$CIRCLECI" == "true" ]]; then - # set log dir - LOG_DIR="${CIRCLE_ARTIFACTS}" - - # install tendermint - set +e - go get github.com/tendermint/tendermint - pushd $GOPATH/src/github.com/tendermint/tendermint - git checkout $TM_VERSION - glide install - go install ./cmd/tendermint - popd - set -e -fi - -set -u - -function ifExit() { - if [[ "$?" != 0 ]]; then - echo "FAIL" - exit 1 - fi -} - -function removeQuotes() { - temp="${1%\"}" - temp="${temp#\"}" - echo "$temp" -} - -function waitForNode() { - addr=$1 - set +e - curl -s $addr/status > /dev/null - ERR=$? - i=0 - while [ "$ERR" != 0 ]; do - if [[ "$i" == 10 ]]; then - echo "waited too long for chain to start" - exit 1 - fi - echo "...... still waiting on $addr" - sleep 1 - curl -s $addr/status > /dev/null - ERR=$? - i=$((i+1)) - done - set -e - echo "... node $addr is up" -} - -function waitForBlock() { - addr=$1 - b1=`curl -s $addr/status | jq .result.latest_block_height` - b2=$b1 - while [ "$b2" == "$b1" ]; do - echo "Waiting for node $addr to commit a block ..." - sleep 1 - b2=`curl -s $addr/status | jq .result.latest_block_height` - done -} - -# make basecoin root vars -export BCHOME="." -BCHOME1="./data/chain1" -BCHOME2="./data/chain2" - -# grab the chain ids -CHAIN_ID1=$(cat $BCHOME1/genesis.json | jq .chain_id) -CHAIN_ID1=$(removeQuotes $CHAIN_ID1) -CHAIN_ID2=$(cat $BCHOME2/genesis.json | jq .chain_id) -CHAIN_ID2=$(removeQuotes $CHAIN_ID2) -echo "CHAIN_ID1: $CHAIN_ID1" -echo "CHAIN_ID2: $CHAIN_ID2" - -# make reusable chain flags -CHAIN_FLAGS1="--chain_id $CHAIN_ID1 --from $BCHOME1/key.json" -CHAIN_FLAGS2="--chain_id $CHAIN_ID2 --from $BCHOME2/key.json --node tcp://localhost:36657" - - -echo "" -echo "... starting chains" -echo "" -# start the first node -TMHOME=$BCHOME1 tendermint node --p2p.skip_upnp --log_level=info &> $LOG_DIR/chain1_tendermint.log & -ifExit -BCHOME=$BCHOME1 basecoin start --without-tendermint &> $LOG_DIR/chain1_basecoin.log & -ifExit - -# start the second node -TMHOME=$BCHOME2 tendermint node --p2p.skip_upnp --log_level=info --p2p.laddr tcp://localhost:36656 --rpc.laddr tcp://localhost:36657 --proxy_app tcp://localhost:36658 &> $LOG_DIR/chain2_tendermint.log & -ifExit -BCHOME=$BCHOME2 basecoin start --address tcp://localhost:36658 --without-tendermint &> $LOG_DIR/chain2_basecoin.log & -ifExit - -echo "" -echo "... waiting for chains to start" -echo "" - -waitForNode localhost:46657 -waitForNode localhost:36657 - -# TODO: remove the sleep -# Without it we sometimes get "Account bytes are empty for address: 053BA0F19616AFF975C8756A2CBFF04F408B4D47" -sleep 3 - -echo "... registering chain1 on chain2" -echo "" -# register chain1 on chain2 -basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 register --ibc_chain_id $CHAIN_ID1 --genesis $BCHOME1/genesis.json -ifExit - -echo "" -echo "... creating egress packet on chain1" -echo "" -# send coins from chain1 to an address on chain2 -# TODO: dont hardcode the address -basecoin tx send --amount 10mycoin $CHAIN_FLAGS1 --to $CHAIN_ID2/053BA0F19616AFF975C8756A2CBFF04F408B4D47 -ifExit - -# alternative way to create packets (for testing) -# basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS1 packet create --ibc_from $CHAIN_ID1 --to $CHAIN_ID2 --type coin --payload $PAYLOAD --ibc_sequence 0 - -echo "" -echo "... querying for packet data" -echo "" -# query for the packet data and proof -# since we only sent one packet, the sequence number is 0 -QUERY_RESULT=$(basecoin query ibc,egress,$CHAIN_ID1,$CHAIN_ID2,0) -ifExit -HEIGHT=$(echo $QUERY_RESULT | jq .height) -PACKET=$(echo $QUERY_RESULT | jq .value) -PROOF=$(echo $QUERY_RESULT | jq .proof) -PACKET=$(removeQuotes $PACKET) -PROOF=$(removeQuotes $PROOF) -echo "" -echo "QUERY_RESULT: $QUERY_RESULT" -echo "HEIGHT: $HEIGHT" -echo "PACKET: $PACKET" -echo "PROOF: $PROOF" - - -# the query returns the height of the next block, which contains the app hash -# but which may not be committed yet, so we have to wait for it to query the commit -echo "" -echo "... waiting for a block to be committed" -echo "" - -waitForBlock localhost:46657 -waitForBlock localhost:36657 - -echo "" -echo "... querying for block data" -echo "" -# get the header and commit for the height -HEADER_AND_COMMIT=$(basecoin block $HEIGHT) -ifExit -HEADER=$(echo $HEADER_AND_COMMIT | jq .hex.header) -HEADER=$(removeQuotes $HEADER) -COMMIT=$(echo $HEADER_AND_COMMIT | jq .hex.commit) -COMMIT=$(removeQuotes $COMMIT) -echo "" -echo "HEADER_AND_COMMIT: $HEADER_AND_COMMIT" -echo "HEADER: $HEADER" -echo "COMMIT: $COMMIT" - -echo "" -echo "... updating state of chain1 on chain2" -echo "" -# update the state of chain1 on chain2 -basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 update --header 0x$HEADER --commit 0x$COMMIT -ifExit - -echo "" -echo "... posting packet from chain1 on chain2" -echo "" -# post the packet from chain1 to chain2 -basecoin tx ibc --amount 10mycoin $CHAIN_FLAGS2 packet post --ibc_from $CHAIN_ID1 --height $HEIGHT --packet 0x$PACKET --proof 0x$PROOF -ifExit - -echo "" -echo "... checking if the packet is present on chain2" -echo "" -# query for the packet on chain2 -basecoin query --node tcp://localhost:36657 ibc,ingress,test_chain_2,test_chain_1,0 -ifExit - -echo "" -echo "DONE!" From b15f882ff4f5358ec32926aec1ab2af1c1507c26 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 17:20:45 +0200 Subject: [PATCH 18/20] Ripped out query, tx send, account, keys, and more --- cmd/basecoin/main.go | 5 - cmd/commands/plugin_util.go | 5 - cmd/commands/query.go | 234 ------------------------------------ cmd/commands/tx.go | 118 ------------------ cmd/counter/main.go | 5 - 5 files changed, 367 deletions(-) delete mode 100644 cmd/commands/query.go diff --git a/cmd/basecoin/main.go b/cmd/basecoin/main.go index 5bc03e0fa66..f95eb93438f 100644 --- a/cmd/basecoin/main.go +++ b/cmd/basecoin/main.go @@ -20,11 +20,6 @@ func main() { commands.StartCmd, commands.RelayCmd, commands.TxCmd, - commands.QueryCmd, - commands.KeyCmd, - commands.VerifyCmd, - commands.BlockCmd, - commands.AccountCmd, commands.UnsafeResetAllCmd, commands.VersionCmd, ) diff --git a/cmd/commands/plugin_util.go b/cmd/commands/plugin_util.go index 082ff2669fc..43afd93c284 100644 --- a/cmd/commands/plugin_util.go +++ b/cmd/commands/plugin_util.go @@ -19,11 +19,6 @@ func RegisterStartPlugin(name string, newPlugin func() types.Plugin) { plugins = append(plugins, plugin{name: name, newPlugin: newPlugin}) } -// Register a subcommand of QueryCmd for plugin specific query functionality -func RegisterQuerySubcommand(cmd *cobra.Command) { - QueryCmd.AddCommand(cmd) -} - // Register a subcommand of TxCmd to craft transactions for plugins func RegisterTxSubcommand(cmd *cobra.Command) { TxCmd.AddCommand(cmd) diff --git a/cmd/commands/query.go b/cmd/commands/query.go deleted file mode 100644 index e31d6254919..00000000000 --- a/cmd/commands/query.go +++ /dev/null @@ -1,234 +0,0 @@ -package commands - -import ( - "encoding/hex" - "encoding/json" - "fmt" - "strconv" - - "github.com/pkg/errors" - "github.com/spf13/cobra" - - "github.com/tendermint/go-wire" - "github.com/tendermint/go-wire/data" - "github.com/tendermint/merkleeyes/iavl" - "github.com/tendermint/tendermint/rpc/client" - tmtypes "github.com/tendermint/tendermint/types" -) - -//commands -var ( - QueryCmd = &cobra.Command{ - Use: "query [key]", - Short: "Query the merkle tree", - RunE: queryCmd, - } - - AccountCmd = &cobra.Command{ - Use: "account [address]", - Short: "Get details of an account", - RunE: accountCmd, - } - - BlockCmd = &cobra.Command{ - Use: "block [height]", - Short: "Get the header and commit of a block", - RunE: blockCmd, - } - - VerifyCmd = &cobra.Command{ - Use: "verify", - Short: "Verify the IAVL proof", - RunE: verifyCmd, - } -) - -//flags -var ( - nodeFlag string - proofFlag string - keyFlag string - valueFlag string - rootFlag string -) - -func init() { - - commonFlags := []Flag2Register{ - {&nodeFlag, "node", "tcp://localhost:46657", "Tendermint RPC address"}, - } - - verifyFlags := []Flag2Register{ - {&proofFlag, "proof", "", "hex-encoded IAVL proof"}, - {&keyFlag, "key", "", "key to the IAVL tree"}, - {&valueFlag, "value", "", "value in the IAVL tree"}, - {&rootFlag, "root", "", "root hash of the IAVL tree"}, - } - - RegisterFlags(QueryCmd, commonFlags) - RegisterFlags(AccountCmd, commonFlags) - RegisterFlags(BlockCmd, commonFlags) - RegisterFlags(VerifyCmd, verifyFlags) -} - -func queryCmd(cmd *cobra.Command, args []string) error { - - if len(args) != 1 { - return fmt.Errorf("query command requires an argument ([key])") //never stack trace - } - - keyString := args[0] - key := []byte(keyString) - if isHex(keyString) { - // convert key to bytes - var err error - key, err = hex.DecodeString(StripHex(keyString)) - if err != nil { - return errors.Errorf("Query key (%v) is invalid hex: %v\n", keyString, err) - } - } - - resp, err := Query(nodeFlag, key) - if err != nil { - return errors.Errorf("Query returns error: %v\n", err) - } - - if !resp.Code.IsOK() { - return errors.Errorf("Query for key (%v) returned non-zero code (%v): %v", keyString, resp.Code, resp.Log) - } - - val := resp.Value - proof := resp.Proof - height := resp.Height - - out, err := json.Marshal(struct { - Value data.Bytes `json:"value"` - Proof data.Bytes `json:"proof"` - Height uint64 `json:"height"` - }{val, proof, height}) - if err != nil { - return err - } - - fmt.Println(string(out)) - return nil -} - -func accountCmd(cmd *cobra.Command, args []string) error { - - if len(args) != 1 { - return fmt.Errorf("account command requires an argument ([address])") //never stack trace - } - - addrHex := StripHex(args[0]) - - // convert destination address to bytes - addr, err := hex.DecodeString(addrHex) - if err != nil { - return errors.Errorf("Account address (%v) is invalid hex: %v\n", addrHex, err) - } - - httpClient := client.NewHTTP(nodeFlag, "/websocket") - acc, err := getAccWithClient(httpClient, addr) - if err != nil { - return err - } - out, err := json.Marshal(acc) - if err != nil { - return err - } - fmt.Println(string(out)) - return nil -} - -func blockCmd(cmd *cobra.Command, args []string) error { - - if len(args) != 1 { - return fmt.Errorf("block command requires an argument ([height])") //never stack trace - } - - heightString := args[0] - height, err := strconv.Atoi(heightString) - if err != nil { - return errors.Errorf("Height must be an int, got %v: %v\n", heightString, err) - } - - header, commit, err := getHeaderAndCommit(nodeFlag, height) - if err != nil { - return err - } - - out, err := json.Marshal(struct { - Hex BlockHex `json:"hex"` - JSON BlockJSON `json:"json"` - }{ - BlockHex{ - Header: wire.BinaryBytes(header), - Commit: wire.BinaryBytes(commit), - }, - BlockJSON{ - Header: header, - Commit: commit, - }, - }) - if err != nil { - return err - } - - fmt.Println(string(out)) - return nil -} - -type BlockHex struct { - Header data.Bytes `json:"header"` - Commit data.Bytes `json:"commit"` -} - -type BlockJSON struct { - Header *tmtypes.Header `json:"header"` - Commit *tmtypes.Commit `json:"commit"` -} - -func verifyCmd(cmd *cobra.Command, args []string) error { - - keyString, valueString := keyFlag, valueFlag - - var err error - key := []byte(keyString) - if isHex(keyString) { - key, err = hex.DecodeString(StripHex(keyString)) - if err != nil { - return errors.Errorf("Key (%v) is invalid hex: %v\n", keyString, err) - } - } - - value := []byte(valueString) - if isHex(valueString) { - value, err = hex.DecodeString(StripHex(valueString)) - if err != nil { - return errors.Errorf("Value (%v) is invalid hex: %v\n", valueString, err) - } - } - - root, err := hex.DecodeString(StripHex(rootFlag)) - if err != nil { - return errors.Errorf("Root (%v) is invalid hex: %v\n", rootFlag, err) - } - - proofBytes, err := hex.DecodeString(StripHex(proofFlag)) - if err != nil { - return errors.Errorf("Proof (%v) is invalid hex: %v\n", proofFlag, err) - } - - proof, err := iavl.ReadProof(proofBytes) - if err != nil { - return errors.Errorf("Error unmarshalling proof: %v\n", err) - } - - if proof.Verify(key, value, root) { - fmt.Println("OK") - } else { - return errors.New("Proof does not verify") - } - return nil -} diff --git a/cmd/commands/tx.go b/cmd/commands/tx.go index 70bc8e626b2..8c661568c5d 100644 --- a/cmd/commands/tx.go +++ b/cmd/commands/tx.go @@ -1,9 +1,7 @@ package commands import ( - "encoding/hex" "fmt" - "strings" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -20,18 +18,6 @@ var ( Use: "tx", Short: "Create, sign, and broadcast a transaction", } - - SendTxCmd = &cobra.Command{ - Use: "send", - Short: "A SendTx transaction, for sending tokens around", - RunE: sendTxCmd, - } - - AppTxCmd = &cobra.Command{ - Use: "app", - Short: "An AppTx transaction, for sending raw data to plugins", - RunE: appTxCmd, - } ) var ( @@ -43,11 +29,6 @@ var ( gasFlag int feeFlag string chainIDFlag string - - //non-persistent flags - toFlag string - dataFlag string - nameFlag string ) func init() { @@ -62,106 +43,7 @@ func init() { {&feeFlag, "fee", "0coin", "Coins for the transaction fee of the format "}, {&seqFlag, "sequence", -1, "Sequence number for the account (-1 to autocalculate)"}, } - - sendTxFlags := []Flag2Register{ - {&toFlag, "to", "", "Destination address for the transaction"}, - } - - appTxFlags := []Flag2Register{ - {&nameFlag, "name", "", "Plugin to send the transaction to"}, - {&dataFlag, "data", "", "Data to send with the transaction"}, - } - RegisterPersistentFlags(TxCmd, cmdTxFlags) - RegisterFlags(SendTxCmd, sendTxFlags) - RegisterFlags(AppTxCmd, appTxFlags) - - //register commands - TxCmd.AddCommand(SendTxCmd, AppTxCmd) -} - -func sendTxCmd(cmd *cobra.Command, args []string) error { - - var toHex string - var chainPrefix string - spl := strings.Split(toFlag, "/") - switch len(spl) { - case 1: - toHex = spl[0] - case 2: - chainPrefix = spl[0] - toHex = spl[1] - default: - return errors.Errorf("To address has too many slashes") - } - - // convert destination address to bytes - to, err := hex.DecodeString(StripHex(toHex)) - if err != nil { - return errors.Errorf("To address is invalid hex: %v\n", err) - } - - if chainPrefix != "" { - to = []byte(chainPrefix + "/" + string(to)) - } - - // load the priv key - privKey, err := LoadKey(fromFlag) - if err != nil { - return err - } - - // get the sequence number for the tx - sequence, err := getSeq(privKey.Address[:]) - if err != nil { - return err - } - - //parse the fee and amounts into coin types - feeCoin, err := types.ParseCoin(feeFlag) - if err != nil { - return err - } - amountCoins, err := types.ParseCoins(amountFlag) - if err != nil { - return err - } - - // craft the tx - input := types.NewTxInput(privKey.PubKey, amountCoins, sequence) - output := newOutput(to, amountCoins) - tx := &types.SendTx{ - Gas: int64(gasFlag), - Fee: feeCoin, - Inputs: []types.TxInput{input}, - Outputs: []types.TxOutput{output}, - } - - // sign that puppy - signBytes := tx.SignBytes(chainIDFlag) - tx.Inputs[0].Signature = privKey.Sign(signBytes) - - out := wire.BinaryBytes(tx) - fmt.Println("Signed SendTx:") - fmt.Printf("%X\n", out) - - // broadcast the transaction to tendermint - data, log, err := broadcastTx(tx) - if err != nil { - return err - } - fmt.Printf("Response: %X ; %s\n", data, log) - return nil -} - -func appTxCmd(cmd *cobra.Command, args []string) error { - // convert data to bytes - data := []byte(dataFlag) - if isHex(dataFlag) { - data, _ = hex.DecodeString(dataFlag) - } - name := nameFlag - return AppTx(name, data) } func AppTx(name string, data []byte) error { diff --git a/cmd/counter/main.go b/cmd/counter/main.go index 083535733f3..e9694002944 100644 --- a/cmd/counter/main.go +++ b/cmd/counter/main.go @@ -19,11 +19,6 @@ func main() { commands.InitCmd, commands.StartCmd, commands.TxCmd, - commands.QueryCmd, - commands.KeyCmd, - commands.VerifyCmd, - commands.BlockCmd, - commands.AccountCmd, commands.UnsafeResetAllCmd, commands.VersionCmd, ) From 9bf34cbac274ab25fbb4ce2f1e564c10df81502e Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 17:28:26 +0200 Subject: [PATCH 19/20] Removed many more unneeded commands --- cmd/commands/ibc.go | 209 +------------------------------------------- cmd/commands/key.go | 45 +--------- 2 files changed, 4 insertions(+), 250 deletions(-) diff --git a/cmd/commands/ibc.go b/cmd/commands/ibc.go index 8f1bdb4f56b..ddde46825e7 100644 --- a/cmd/commands/ibc.go +++ b/cmd/commands/ibc.go @@ -1,7 +1,6 @@ package commands import ( - "encoding/hex" "encoding/json" "fmt" "io/ioutil" @@ -12,8 +11,6 @@ import ( "github.com/tendermint/basecoin/plugins/ibc" "github.com/tendermint/go-wire" - "github.com/tendermint/merkleeyes/iavl" - tmtypes "github.com/tendermint/tendermint/types" ) // returns a new IBC plugin to be registered with Basecoin @@ -33,85 +30,25 @@ var ( Short: "Register a blockchain via IBC", RunE: ibcRegisterTxCmd, } - - IBCUpdateTxCmd = &cobra.Command{ - Use: "update", - Short: "Update the latest state of a blockchain via IBC", - RunE: ibcUpdateTxCmd, - } - - IBCPacketTxCmd = &cobra.Command{ - Use: "packet", - Short: "Send a new packet via IBC", - } - - IBCPacketCreateTxCmd = &cobra.Command{ - Use: "create", - Short: "Create an egress IBC packet", - RunE: ibcPacketCreateTxCmd, - } - - IBCPacketPostTxCmd = &cobra.Command{ - Use: "post", - Short: "Deliver an IBC packet to another chain", - RunE: ibcPacketPostTxCmd, - } ) //flags var ( - ibcChainIDFlag string - ibcGenesisFlag string - ibcHeaderFlag string - ibcCommitFlag string - ibcFromFlag string - ibcToFlag string - ibcTypeFlag string - ibcPayloadFlag string - ibcPacketFlag string - ibcProofFlag string - ibcSequenceFlag int - ibcHeightFlag int + ibcChainIDFlag string + ibcGenesisFlag string ) func init() { - // register flags registerFlags := []Flag2Register{ {&ibcChainIDFlag, "ibc_chain_id", "", "ChainID for the new blockchain"}, {&ibcGenesisFlag, "genesis", "", "Genesis file for the new blockchain"}, } - updateFlags := []Flag2Register{ - {&ibcHeaderFlag, "header", "", "Block header for an ibc update"}, - {&ibcCommitFlag, "commit", "", "Block commit for an ibc update"}, - } - - fromFlagReg := Flag2Register{&ibcFromFlag, "ibc_from", "", "Source ChainID"} - - packetCreateFlags := []Flag2Register{ - fromFlagReg, - {&ibcToFlag, "to", "", "Destination ChainID"}, - {&ibcTypeFlag, "type", "", "IBC packet type (eg. coin)"}, - {&ibcPayloadFlag, "payload", "", "IBC packet payload"}, - {&ibcSequenceFlag, "ibc_sequence", -1, "sequence number for IBC packet"}, - } - - packetPostFlags := []Flag2Register{ - fromFlagReg, - {&ibcHeightFlag, "height", 0, "Height the packet became egress in source chain"}, - {&ibcPacketFlag, "packet", "", "hex-encoded IBC packet"}, - {&ibcProofFlag, "proof", "", "hex-encoded proof of IBC packet from source chain"}, - } - RegisterFlags(IBCRegisterTxCmd, registerFlags) - RegisterFlags(IBCUpdateTxCmd, updateFlags) - RegisterFlags(IBCPacketCreateTxCmd, packetCreateFlags) - RegisterFlags(IBCPacketPostTxCmd, packetPostFlags) //register commands - IBCTxCmd.AddCommand(IBCRegisterTxCmd, IBCUpdateTxCmd, IBCPacketTxCmd) - IBCPacketTxCmd.AddCommand(IBCPacketCreateTxCmd, IBCPacketPostTxCmd) + IBCTxCmd.AddCommand(IBCRegisterTxCmd) RegisterTxSubcommand(IBCTxCmd) } @@ -148,143 +85,3 @@ func ibcRegisterTxCmd(cmd *cobra.Command, args []string) error { return AppTx(name, data) } - -func ibcUpdateTxCmd(cmd *cobra.Command, args []string) error { - headerBytes, err := hex.DecodeString(StripHex(ibcHeaderFlag)) - if err != nil { - return errors.Errorf("Header (%v) is invalid hex: %v\n", ibcHeaderFlag, err) - } - - commitBytes, err := hex.DecodeString(StripHex(ibcCommitFlag)) - if err != nil { - return errors.Errorf("Commit (%v) is invalid hex: %v\n", ibcCommitFlag, err) - } - - header := new(tmtypes.Header) - commit := new(tmtypes.Commit) - - err = wire.ReadBinaryBytes(headerBytes, &header) - if err != nil { - return errors.Errorf("Error unmarshalling header: %v\n", err) - } - - err = wire.ReadBinaryBytes(commitBytes, &commit) - if err != nil { - return errors.Errorf("Error unmarshalling commit: %v\n", err) - } - - ibcTx := ibc.IBCUpdateChainTx{ - Header: *header, - Commit: *commit, - } - - out, err := json.Marshal(ibcTx) - if err != nil { - return err - } - fmt.Printf("IBCTx: %s\n", string(out)) - - data := []byte(wire.BinaryBytes(struct { - ibc.IBCTx `json:"unwrap"` - }{ibcTx})) - name := "IBC" - - return AppTx(name, data) -} - -func ibcPacketCreateTxCmd(cmd *cobra.Command, args []string) error { - fromChain, toChain := ibcFromFlag, ibcToFlag - packetType := ibcTypeFlag - - payloadBytes, err := hex.DecodeString(StripHex(ibcPayloadFlag)) - if err != nil { - return errors.Errorf("Payload (%v) is invalid hex: %v\n", ibcPayloadFlag, err) - } - - sequence, err := ibcSequenceCmd() - if err != nil { - return err - } - - var payload ibc.Payload - if err := wire.ReadBinaryBytes(payloadBytes, &payload); err != nil { - return err - } - - ibcTx := ibc.IBCPacketCreateTx{ - Packet: ibc.Packet{ - SrcChainID: fromChain, - DstChainID: toChain, - Sequence: sequence, - Type: packetType, - Payload: payload, - }, - } - - out, err := json.Marshal(ibcTx) - if err != nil { - return err - } - fmt.Printf("IBCTx: %s\n", string(out)) - - data := []byte(wire.BinaryBytes(struct { - ibc.IBCTx `json:"unwrap"` - }{ibcTx})) - - return AppTx("IBC", data) -} - -func ibcPacketPostTxCmd(cmd *cobra.Command, args []string) error { - fromChain, fromHeight := ibcFromFlag, ibcHeightFlag - - packetBytes, err := hex.DecodeString(StripHex(ibcPacketFlag)) - if err != nil { - return errors.Errorf("Packet (%v) is invalid hex: %v\n", ibcPacketFlag, err) - } - - proofBytes, err := hex.DecodeString(StripHex(ibcProofFlag)) - if err != nil { - return errors.Errorf("Proof (%v) is invalid hex: %v\n", ibcProofFlag, err) - } - - var packet ibc.Packet - proof := new(iavl.IAVLProof) - - err = wire.ReadBinaryBytes(packetBytes, &packet) - if err != nil { - return errors.Errorf("Error unmarshalling packet: %v\n", err) - } - - err = wire.ReadBinaryBytes(proofBytes, &proof) - if err != nil { - return errors.Errorf("Error unmarshalling proof: %v\n", err) - } - - ibcTx := ibc.IBCPacketPostTx{ - FromChainID: fromChain, - FromChainHeight: uint64(fromHeight), - Packet: packet, - Proof: proof, - } - - out, err := json.Marshal(ibcTx) - if err != nil { - return err - } - fmt.Printf("IBCTx: %s\n", string(out)) - - data := []byte(wire.BinaryBytes(struct { - ibc.IBCTx `json:"unwrap"` - }{ibcTx})) - - return AppTx("IBC", data) -} - -func ibcSequenceCmd() (uint64, error) { - if ibcSequenceFlag >= 0 { - return uint64(ibcSequenceFlag), nil - } - - // TODO: get sequence - return 0, nil -} diff --git a/cmd/commands/key.go b/cmd/commands/key.go index 4f0b2538188..08f54e0a421 100644 --- a/cmd/commands/key.go +++ b/cmd/commands/key.go @@ -9,42 +9,13 @@ import ( "strings" //"github.com/pkg/errors" - "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/tendermint/go-crypto" "github.com/tendermint/tmlibs/cli" ) -//commands -var ( - KeyCmd = &cobra.Command{ - Use: "key", - Short: "Manage keys", - } - - NewKeyCmd = &cobra.Command{ - Use: "new", - Short: "Create a new private key", - RunE: newKeyCmd, - } -) - -func newKeyCmd(cmd *cobra.Command, args []string) error { - key := genKey() - keyJSON, err := json.MarshalIndent(key, "", "\t") - if err != nil { - return err - } - fmt.Println(string(keyJSON)) - return nil -} - -func init() { - //register commands - KeyCmd.AddCommand(NewKeyCmd) -} - //--------------------------------------------- // simple implementation of a key @@ -74,20 +45,6 @@ func (k *Key) Sign(msg []byte) crypto.Signature { return k.PrivKey.Sign(msg) } -// Generates a new validator with private key. -func genKey() *Key { - privKey := crypto.GenPrivKeyEd25519() - pubKey := privKey.PubKey() - addrBytes := pubKey.Address() - var addr Address - copy(addr[:], addrBytes) - return &Key{ - Address: addr, - PubKey: pubKey, - PrivKey: privKey.Wrap(), - } -} - func LoadKey(keyFile string) (*Key, error) { filePath := keyFile From 22918ba3d28a1220861ec2049dc95b079bce1665 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Fri, 16 Jun 2017 17:35:37 +0200 Subject: [PATCH 20/20] Remove example-plugin code, need to fix docs --- docs/guide/src/example-plugin/cmd.go | 62 ----------- docs/guide/src/example-plugin/main.go | 35 ------- docs/guide/src/example-plugin/plugin.go | 134 ------------------------ 3 files changed, 231 deletions(-) delete mode 100644 docs/guide/src/example-plugin/cmd.go delete mode 100644 docs/guide/src/example-plugin/main.go delete mode 100644 docs/guide/src/example-plugin/plugin.go diff --git a/docs/guide/src/example-plugin/cmd.go b/docs/guide/src/example-plugin/cmd.go deleted file mode 100644 index b439176266d..00000000000 --- a/docs/guide/src/example-plugin/cmd.go +++ /dev/null @@ -1,62 +0,0 @@ -package main - -import ( - "github.com/spf13/cobra" - - wire "github.com/tendermint/go-wire" - - "github.com/tendermint/basecoin/cmd/commands" - "github.com/tendermint/basecoin/types" -) - -var ( - //CLI Flags - validFlag bool - - //CLI Plugin Commands - ExamplePluginTxCmd = &cobra.Command{ - Use: "example", - Short: "Create, sign, and broadcast a transaction to the example plugin", - RunE: examplePluginTxCmd, - } -) - -//Called during CLI initialization -func init() { - - //Set the Plugin Flags - ExamplePluginTxCmd.Flags().BoolVar(&validFlag, "valid", false, "Set this to make transaction valid") - - //Register a plugin specific CLI command as a subcommand of the tx command - commands.RegisterTxSubcommand(ExamplePluginTxCmd) - - //Register the example with basecoin at start - commands.RegisterStartPlugin("example-plugin", func() types.Plugin { return NewExamplePlugin() }) -} - -//Send a transaction -func examplePluginTxCmd(cmd *cobra.Command, args []string) error { - - // Create a transaction using the flag. - // The tx passes on custom information to the plugin - exampleTx := ExamplePluginTx{validFlag} - - // The tx is passed to the plugin in the form of - // a byte array. This is achieved by serializing the object using go-wire. - // Once received in the plugin, these exampleTxBytes are decoded back - // into the original ExamplePluginTx struct - exampleTxBytes := wire.BinaryBytes(exampleTx) - - // Send the transaction and return any errors. - // Here exampleTxBytes is packaged in the `tx.Data` field of an AppTx, - // and passed on to the plugin through the following sequence: - // - passed as `data` to `commands.AppTx` (cmd/commands/tx.go) - // - set as the `tx.Data` field of an AppTx, which is then passed to commands.broadcastTx (cmd/commands/tx.go) - // - the tx is broadcast to Tendermint, which runs it through app.CheckTx (app/app.go) - // - after passing CheckTx, it will eventually be included in a block and run through app.DeliverTx (app/app.go) - // - DeliverTx receives txBytes, which is the serialization of the full AppTx (app/app.go) - // - Once deserialized, the tx is passed to `state.ExecTx` (state/execution.go) - // - If the tx passes various checks, the `tx.Data` is forwarded as `txBytes` to `plugin.RunTx` (docs/guide/src/example-plugin/plugin.go) - // - Finally, it deserialized back to the ExamplePluginTx - return commands.AppTx("example-plugin", exampleTxBytes) -} diff --git a/docs/guide/src/example-plugin/main.go b/docs/guide/src/example-plugin/main.go deleted file mode 100644 index 328e22025bd..00000000000 --- a/docs/guide/src/example-plugin/main.go +++ /dev/null @@ -1,35 +0,0 @@ -package main - -import ( - "os" - - "github.com/spf13/cobra" - - "github.com/tendermint/basecoin/cmd/commands" - "github.com/tendermint/tmlibs/cli" -) - -func main() { - - //Initialize example-plugin root command - var RootCmd = &cobra.Command{ - Use: "example-plugin", - Short: "example-plugin usage description", - } - - //Add the default basecoin commands to the root command - RootCmd.AddCommand( - commands.InitCmd, - commands.StartCmd, - commands.TxCmd, - commands.QueryCmd, - commands.KeyCmd, - commands.VerifyCmd, - commands.BlockCmd, - commands.AccountCmd, - commands.UnsafeResetAllCmd, - ) - - cmd := cli.PrepareMainCmd(RootCmd, "BC", os.ExpandEnv("$HOME/.basecoin-example-plugin")) - cmd.Execute() -} diff --git a/docs/guide/src/example-plugin/plugin.go b/docs/guide/src/example-plugin/plugin.go deleted file mode 100644 index 97e80520a4c..00000000000 --- a/docs/guide/src/example-plugin/plugin.go +++ /dev/null @@ -1,134 +0,0 @@ -package main - -import ( - abci "github.com/tendermint/abci/types" - "github.com/tendermint/basecoin/types" - "github.com/tendermint/go-wire" -) - -//----------------------------------------- -// Structs -// * Note the fields in each struct may be expanded/modified - -// Plugin State Struct -// * Intended to store the current state of the plugin -// * This example contains a field which holds the execution count -// * Serialized (by go-wire) and stored within the KVStore using the key retrieved -// from the ExamplePlugin.StateKey() function/ -// * All fields must be exposed for serialization by external libs (here go-wire) -type ExamplePluginState struct { - Counter int -} - -// Transaction Struct -// * Stores transaction-specific plugin-customized information -// * This example contains a dummy field 'Valid' intended to specify -// if the transaction is a valid and should proceed -// * Deserialized (by go-wire) from txBytes in ExamplePlugin.RunTx -// * All fields must be exposed for serialization by external libs (here go-wire) -type ExamplePluginTx struct { - Valid bool -} - -// Plugin Struct -// * Struct which satisfies the basecoin Plugin interface -// * Stores global plugin settings, in this example just the plugin name -type ExamplePlugin struct { - name string -} - -//----------------------------------------- -// Non-Mandatory Functions - -// Return a new ExamplePlugin pointer with a hard-coded name -func NewExamplePlugin() *ExamplePlugin { - return &ExamplePlugin{ - name: "example-plugin", - } -} - -// Return a byte array unique to this plugin which is used as the key -// to store the plugin state (ExamplePluginState) -func (ep *ExamplePlugin) StateKey() []byte { - return []byte("ExamplePlugin.State") -} - -//----------------------------------------- -// Basecoin Plugin Interface Functions - -//Return the name of the plugin -func (ep *ExamplePlugin) Name() string { - return ep.name -} - -// SetOption may be called during genesis of basecoin and can be used to set -// initial plugin parameters. Within genesis.json file entries are made in -// the format: "/", "" Where is the plugin name, -// in this file ExamplePlugin.name, and and are the strings passed -// into the plugin SetOption function. This function is intended to be used to -// set plugin specific information such as the plugin state. Within this example -// SetOption is left unimplemented. -func (ep *ExamplePlugin) SetOption(store types.KVStore, key string, value string) (log string) { - return "" -} - -// The core tx logic of the app is containted within the RunTx function -// Input fields: -// - store types.KVStore -// - This term provides read/write capabilities to the merkelized data store -// which holds the basecoin state and is accessible to all plugins -// - ctx types.CallContext -// - The ctx contains the callers address, a pointer to the callers account, -// and an amount of coins sent with the transaction -// - txBytes []byte -// - Used to send customized information to your plugin -// -// Other more complex plugins may have a variant on the process order within this -// example including loading and saving multiple or variable states, or not -// including a state stored in the KVStore whatsoever. -func (ep *ExamplePlugin) RunTx(store types.KVStore, ctx types.CallContext, txBytes []byte) (res abci.Result) { - - // Decode txBytes using go-wire. Attempt to write the txBytes to the variable - // tx, if the txBytes have not been properly encoded from a ExamplePluginTx - // struct wire will produce an error. - var tx ExamplePluginTx - err := wire.ReadBinaryBytes(txBytes, &tx) - if err != nil { - return abci.ErrBaseEncodingError.AppendLog("Error decoding tx: " + err.Error()) - } - - // Perform Transaction Validation - if !tx.Valid { - return abci.ErrInternalError.AppendLog("Valid must be true") - } - - // Load PluginState - var pluginState ExamplePluginState - stateBytes := store.Get(ep.StateKey()) - // If the state does not exist, stateBytes will be initialized - // as an empty byte array with length of zero - if len(stateBytes) > 0 { - err = wire.ReadBinaryBytes(stateBytes, &pluginState) //decode using go-wire - if err != nil { - return abci.ErrInternalError.AppendLog("Error decoding state: " + err.Error()) - } - } - - //App Logic - pluginState.Counter += 1 - - // Save PluginState - store.Set(ep.StateKey(), wire.BinaryBytes(pluginState)) - - return abci.OK -} - -func (ep *ExamplePlugin) InitChain(store types.KVStore, vals []*abci.Validator) { -} - -func (ep *ExamplePlugin) BeginBlock(store types.KVStore, hash []byte, header *abci.Header) { -} - -func (ep *ExamplePlugin) EndBlock(store types.KVStore, height uint64) abci.ResponseEndBlock { - return abci.ResponseEndBlock{} -}