Browse Source

abci: remove counter app (#6684)

* remove counter app

* remove unneeeded ci

* lint fix

* modify tx sizes

* cleanup docs

* Update abci/cmd/abci-cli/abci-cli.go

Co-authored-by: Callum Waters <cmwaters19@gmail.com>

* Update docs/app-dev/getting-started.md

Co-authored-by: Callum Waters <cmwaters19@gmail.com>

* Update docs/app-dev/getting-started.md

Co-authored-by: Callum Waters <cmwaters19@gmail.com>

* bring back comment

* migrate to kvstore and not persistent

* remove unused func

* test persistent

Co-authored-by: Callum Waters <cmwaters19@gmail.com>
pull/6696/head
Marko 3 years ago
committed by GitHub
parent
commit
363ea56680
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 35 additions and 664 deletions
  1. +0
    -32
      .github/workflows/tests.yml
  2. +1
    -0
      CHANGELOG_PENDING.md
  3. +1
    -47
      abci/cmd/abci-cli/abci-cli.go
  4. +0
    -86
      abci/example/counter/counter.go
  5. +0
    -55
      abci/tests/test_app/app.go
  6. +0
    -93
      abci/tests/test_app/main.go
  7. +0
    -28
      abci/tests/test_app/test.sh
  8. +0
    -1
      abci/tests/test_cli/test.sh
  9. +1
    -3
      cmd/tendermint/commands/run_node.go
  10. +1
    -130
      docs/app-dev/abci-cli.md
  11. +2
    -88
      docs/app-dev/getting-started.md
  12. +1
    -1
      internal/consensus/byzantine_test.go
  13. +5
    -6
      internal/consensus/common_test.go
  14. +3
    -1
      internal/consensus/invalid_test.go
  15. +8
    -4
      internal/consensus/reactor_test.go
  16. +4
    -4
      internal/consensus/state_test.go
  17. +7
    -8
      internal/mempool/v0/clist_mempool_test.go
  18. +1
    -6
      proxy/client.go
  19. +0
    -2
      test/README.md
  20. +0
    -69
      test/app/test.sh

+ 0
- 32
.github/workflows/tests.yml View File

@ -42,38 +42,6 @@ jobs:
key: ${{ runner.os }}-${{ github.sha }}-tm-binary key: ${{ runner.os }}-${{ github.sha }}-tm-binary
if: env.GIT_DIFF if: env.GIT_DIFF
test_abci_apps:
runs-on: ubuntu-latest
needs: build
timeout-minutes: 5
steps:
- uses: actions/setup-go@v2
with:
go-version: "1.16"
- uses: actions/checkout@v2.3.4
- uses: technote-space/get-diff-action@v4
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- uses: actions/cache@v2.1.6
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
if: env.GIT_DIFF
- uses: actions/cache@v2.1.6
with:
path: ~/go/bin
key: ${{ runner.os }}-${{ github.sha }}-tm-binary
if: env.GIT_DIFF
- name: test_abci_apps
run: abci/tests/test_app/test.sh
shell: bash
if: env.GIT_DIFF
test_abci_cli: test_abci_cli:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build


+ 1
- 0
CHANGELOG_PENDING.md View File

@ -31,6 +31,7 @@ Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermi
- [ABCI] \#5818 Use protoio for msg length delimitation. Migrates from int64 to uint64 length delimiters. - [ABCI] \#5818 Use protoio for msg length delimitation. Migrates from int64 to uint64 length delimiters.
- [Version] \#6494 `TMCoreSemVer` has been renamed to `TMVersion`. - [Version] \#6494 `TMCoreSemVer` has been renamed to `TMVersion`.
- It is not required any longer to set ldflags to set version strings - It is not required any longer to set ldflags to set version strings
- [abci/counter] \#6684 Delete counter example app
- P2P Protocol - P2P Protocol


+ 1
- 47
abci/cmd/abci-cli/abci-cli.go View File

@ -17,7 +17,6 @@ import (
abcicli "github.com/tendermint/tendermint/abci/client" abcicli "github.com/tendermint/tendermint/abci/client"
"github.com/tendermint/tendermint/abci/example/code" "github.com/tendermint/tendermint/abci/example/code"
"github.com/tendermint/tendermint/abci/example/counter"
"github.com/tendermint/tendermint/abci/example/kvstore" "github.com/tendermint/tendermint/abci/example/kvstore"
"github.com/tendermint/tendermint/abci/server" "github.com/tendermint/tendermint/abci/server"
servertest "github.com/tendermint/tendermint/abci/tests/server" servertest "github.com/tendermint/tendermint/abci/tests/server"
@ -47,9 +46,6 @@ var (
flagHeight int flagHeight int
flagProve bool flagProve bool
// counter
flagSerial bool
// kvstore // kvstore
flagPersist string flagPersist string
) )
@ -61,9 +57,7 @@ var RootCmd = &cobra.Command{
PersistentPreRunE: func(cmd *cobra.Command, args []string) error { PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
switch cmd.Use { switch cmd.Use {
case "counter", "kvstore": // for the examples apps, don't pre-run
return nil
case "version": // skip running for version command
case "kvstore", "version":
return nil return nil
} }
@ -135,10 +129,6 @@ func addQueryFlags() {
"whether or not to return a merkle proof of the query result") "whether or not to return a merkle proof of the query result")
} }
func addCounterFlags() {
counterCmd.PersistentFlags().BoolVarP(&flagSerial, "serial", "", false, "enforce incrementing (serial) transactions")
}
func addKVStoreFlags() { func addKVStoreFlags() {
kvstoreCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "directory to use for a database") kvstoreCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "directory to use for a database")
} }
@ -157,8 +147,6 @@ func addCommands() {
RootCmd.AddCommand(queryCmd) RootCmd.AddCommand(queryCmd)
// examples // examples
addCounterFlags()
RootCmd.AddCommand(counterCmd)
addKVStoreFlags() addKVStoreFlags()
RootCmd.AddCommand(kvstoreCmd) RootCmd.AddCommand(kvstoreCmd)
} }
@ -258,14 +246,6 @@ var queryCmd = &cobra.Command{
RunE: cmdQuery, RunE: cmdQuery,
} }
var counterCmd = &cobra.Command{
Use: "counter",
Short: "ABCI demo example",
Long: "ABCI demo example",
Args: cobra.ExactArgs(0),
RunE: cmdCounter,
}
var kvstoreCmd = &cobra.Command{ var kvstoreCmd = &cobra.Command{
Use: "kvstore", Use: "kvstore",
Short: "ABCI demo example", Short: "ABCI demo example",
@ -593,32 +573,6 @@ func cmdQuery(cmd *cobra.Command, args []string) error {
return nil return nil
} }
func cmdCounter(cmd *cobra.Command, args []string) error {
app := counter.NewApplication(flagSerial)
logger := log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)
// Start the listener
srv, err := server.NewServer(flagAddress, flagAbci, app)
if err != nil {
return err
}
srv.SetLogger(logger.With("module", "abci-server"))
if err := srv.Start(); err != nil {
return err
}
// Stop upon receiving SIGTERM or CTRL-C.
tmos.TrapSignal(logger, func() {
// Cleanup
if err := srv.Stop(); err != nil {
logger.Error("Error while stopping server", "err", err)
}
})
// Run forever.
select {}
}
func cmdKVStore(cmd *cobra.Command, args []string) error { func cmdKVStore(cmd *cobra.Command, args []string) error {
logger := log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false) logger := log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)


+ 0
- 86
abci/example/counter/counter.go View File

@ -1,86 +0,0 @@
package counter
import (
"encoding/binary"
"fmt"
"github.com/tendermint/tendermint/abci/example/code"
"github.com/tendermint/tendermint/abci/types"
)
type Application struct {
types.BaseApplication
hashCount int
txCount int
serial bool
}
func NewApplication(serial bool) *Application {
return &Application{serial: serial}
}
func (app *Application) Info(req types.RequestInfo) types.ResponseInfo {
return types.ResponseInfo{Data: fmt.Sprintf("{\"hashes\":%v,\"txs\":%v}", app.hashCount, app.txCount)}
}
func (app *Application) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx {
if app.serial {
if len(req.Tx) > 8 {
return types.ResponseDeliverTx{
Code: code.CodeTypeEncodingError,
Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(req.Tx))}
}
tx8 := make([]byte, 8)
copy(tx8[len(tx8)-len(req.Tx):], req.Tx)
txValue := binary.BigEndian.Uint64(tx8)
if txValue != uint64(app.txCount) {
return types.ResponseDeliverTx{
Code: code.CodeTypeBadNonce,
Log: fmt.Sprintf("Invalid nonce. Expected %v, got %v", app.txCount, txValue)}
}
}
app.txCount++
return types.ResponseDeliverTx{Code: code.CodeTypeOK}
}
func (app *Application) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx {
if app.serial {
if len(req.Tx) > 8 {
return types.ResponseCheckTx{
Code: code.CodeTypeEncodingError,
Log: fmt.Sprintf("Max tx size is 8 bytes, got %d", len(req.Tx))}
}
tx8 := make([]byte, 8)
copy(tx8[len(tx8)-len(req.Tx):], req.Tx)
txValue := binary.BigEndian.Uint64(tx8)
if txValue < uint64(app.txCount) {
return types.ResponseCheckTx{
Code: code.CodeTypeBadNonce,
Log: fmt.Sprintf("Invalid nonce. Expected >= %v, got %v", app.txCount, txValue)}
}
}
return types.ResponseCheckTx{Code: code.CodeTypeOK}
}
func (app *Application) Commit() (resp types.ResponseCommit) {
app.hashCount++
if app.txCount == 0 {
return types.ResponseCommit{}
}
hash := make([]byte, 8)
binary.BigEndian.PutUint64(hash, uint64(app.txCount))
return types.ResponseCommit{Data: hash}
}
func (app *Application) Query(reqQuery types.RequestQuery) types.ResponseQuery {
switch reqQuery.Path {
case "hash":
return types.ResponseQuery{Value: []byte(fmt.Sprintf("%v", app.hashCount))}
case "tx":
return types.ResponseQuery{Value: []byte(fmt.Sprintf("%v", app.txCount))}
default:
return types.ResponseQuery{Log: fmt.Sprintf("Invalid query path. Expected hash or tx, got %v", reqQuery.Path)}
}
}

+ 0
- 55
abci/tests/test_app/app.go View File

@ -1,55 +0,0 @@
package main
import (
"bytes"
"context"
"fmt"
abcicli "github.com/tendermint/tendermint/abci/client"
"github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
)
var ctx = context.Background()
func startClient(abciType string) abcicli.Client {
// Start client
client, err := abcicli.NewClient("tcp://127.0.0.1:26658", abciType, true)
if err != nil {
panic(err.Error())
}
logger := log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)
client.SetLogger(logger.With("module", "abcicli"))
if err := client.Start(); err != nil {
panicf("connecting to abci_app: %v", err.Error())
}
return client
}
func commit(client abcicli.Client, hashExp []byte) {
res, err := client.CommitSync(ctx)
if err != nil {
panicf("client error: %v", err)
}
if !bytes.Equal(res.Data, hashExp) {
panicf("Commit hash was unexpected. Got %X expected %X", res.Data, hashExp)
}
}
func deliverTx(client abcicli.Client, txBytes []byte, codeExp uint32, dataExp []byte) {
res, err := client.DeliverTxSync(ctx, types.RequestDeliverTx{Tx: txBytes})
if err != nil {
panicf("client error: %v", err)
}
if res.Code != codeExp {
panicf("DeliverTx response code was unexpected. Got %v expected %v. Log: %v", res.Code, codeExp, res.Log)
}
if !bytes.Equal(res.Data, dataExp) {
panicf("DeliverTx response data was unexpected. Got %X expected %X", res.Data, dataExp)
}
}
func panicf(format string, a ...interface{}) {
panic(fmt.Sprintf(format, a...))
}

+ 0
- 93
abci/tests/test_app/main.go View File

@ -1,93 +0,0 @@
package main
import (
"fmt"
"log"
"os"
"os/exec"
"time"
"github.com/tendermint/tendermint/abci/types"
)
var abciType string
func init() {
abciType = os.Getenv("ABCI")
if abciType == "" {
abciType = "socket"
}
}
func main() {
testCounter()
}
const (
maxABCIConnectTries = 10
)
func ensureABCIIsUp(typ string, n int) error {
var err error
cmdString := "abci-cli echo hello"
if typ == "grpc" {
cmdString = "abci-cli --abci grpc echo hello"
}
for i := 0; i < n; i++ {
cmd := exec.Command("bash", "-c", cmdString)
_, err = cmd.CombinedOutput()
if err == nil {
break
}
time.Sleep(500 * time.Millisecond)
}
return err
}
func testCounter() {
abciApp := os.Getenv("ABCI_APP")
if abciApp == "" {
panic("No ABCI_APP specified")
}
fmt.Printf("Running %s test with abci=%s\n", abciApp, abciType)
subCommand := fmt.Sprintf("abci-cli %s", abciApp)
cmd := exec.Command("bash", "-c", subCommand)
cmd.Stdout = os.Stdout
if err := cmd.Start(); err != nil {
log.Fatalf("starting %q err: %v", abciApp, err)
}
defer func() {
if err := cmd.Process.Kill(); err != nil {
log.Printf("error on process kill: %v", err)
}
if err := cmd.Wait(); err != nil {
log.Printf("error while waiting for cmd to exit: %v", err)
}
}()
if err := ensureABCIIsUp(abciType, maxABCIConnectTries); err != nil {
log.Fatalf("echo failed: %v", err) //nolint:gocritic
}
client := startClient(abciType)
defer func() {
if err := client.Stop(); err != nil {
log.Printf("error trying client stop: %v", err)
}
}()
// commit(client, nil)
// deliverTx(client, []byte("abc"), code.CodeTypeBadNonce, nil)
commit(client, nil)
deliverTx(client, []byte{0x00}, types.CodeTypeOK, nil)
commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1})
// deliverTx(client, []byte{0x00}, code.CodeTypeBadNonce, nil)
deliverTx(client, []byte{0x01}, types.CodeTypeOK, nil)
deliverTx(client, []byte{0x00, 0x02}, types.CodeTypeOK, nil)
deliverTx(client, []byte{0x00, 0x03}, types.CodeTypeOK, nil)
deliverTx(client, []byte{0x00, 0x00, 0x04}, types.CodeTypeOK, nil)
// deliverTx(client, []byte{0x00, 0x00, 0x06}, code.CodeTypeBadNonce, nil)
commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5})
}

+ 0
- 28
abci/tests/test_app/test.sh View File

@ -1,28 +0,0 @@
#! /bin/bash
set -e
# These tests spawn the counter app and server by execing the ABCI_APP command and run some simple client tests against it
# Get the directory of where this script is.
export PATH="$GOBIN:$PATH"
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
# Change into that dir because we expect that.
cd "$DIR"
echo "RUN COUNTER OVER SOCKET"
# test golang counter
ABCI_APP="counter" go run -mod=readonly ./*.go
echo "----------------------"
echo "RUN COUNTER OVER GRPC"
# test golang counter via grpc
ABCI_APP="counter --abci=grpc" ABCI="grpc" go run -mod=readonly ./*.go
echo "----------------------"
# test nodejs counter
# TODO: fix node app
#ABCI_APP="node $GOPATH/src/github.com/tendermint/js-abci/example/app.js" go test -test.run TestCounter

+ 0
- 1
abci/tests/test_cli/test.sh View File

@ -37,7 +37,6 @@ function testExample() {
} }
testExample 1 tests/test_cli/ex1.abci abci-cli kvstore testExample 1 tests/test_cli/ex1.abci abci-cli kvstore
testExample 2 tests/test_cli/ex2.abci abci-cli counter
echo "" echo ""
echo "PASS" echo "PASS"

+ 1
- 3
cmd/tendermint/commands/run_node.go View File

@ -48,9 +48,7 @@ func AddNodeFlags(cmd *cobra.Command) {
"proxy-app", "proxy-app",
config.ProxyApp, config.ProxyApp,
"proxy app address, or one of: 'kvstore',"+ "proxy app address, or one of: 'kvstore',"+
" 'persistent_kvstore',"+
" 'counter',"+
" 'counter_serial' or 'noop' for local testing.")
" 'persistent_kvstore' or 'noop' for local testing.")
cmd.Flags().String("abci", config.ABCI, "specify abci transport (socket | grpc)") cmd.Flags().String("abci", config.ABCI, "specify abci transport (socket | grpc)")
// rpc flags // rpc flags


+ 1
- 130
docs/app-dev/abci-cli.md View File

@ -31,7 +31,6 @@ Available Commands:
check_tx Validate a tx check_tx Validate a tx
commit Commit the application state and return the Merkle root hash commit Commit the application state and return the Merkle root hash
console Start an interactive abci console for multiple commands console Start an interactive abci console for multiple commands
counter ABCI demo example
deliver_tx Deliver a new tx to the application deliver_tx Deliver a new tx to the application
kvstore ABCI demo example kvstore ABCI demo example
echo Have the application echo a message echo Have the application echo a message
@ -214,137 +213,9 @@ we do `deliver_tx "abc=efg"` it will store `(abc, efg)`.
Similarly, you could put the commands in a file and run Similarly, you could put the commands in a file and run
`abci-cli --verbose batch < myfile`. `abci-cli --verbose batch < myfile`.
## Counter - Another Example
Now that we've got the hang of it, let's try another application, the
"counter" app.
Like the kvstore app, its code can be found
[here](https://github.com/tendermint/tendermint/blob/master/abci/cmd/abci-cli/abci-cli.go)
and looks like:
```go
func cmdCounter(cmd *cobra.Command, args []string) error {
app := counter.NewCounterApplication(flagSerial)
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
// Start the listener
srv, err := server.NewServer(flagAddrC, flagAbci, app)
if err != nil {
return err
}
srv.SetLogger(logger.With("module", "abci-server"))
if err := srv.Start(); err != nil {
return err
}
// Stop upon receiving SIGTERM or CTRL-C.
tmos.TrapSignal(logger, func() {
// Cleanup
srv.Stop()
})
// Run forever.
select {}
}
```
The counter app doesn't use a Merkle tree, it just counts how many times
we've sent a transaction, asked for a hash, or committed the state. The
result of `commit` is just the number of transactions sent.
This application has two modes: `serial=off` and `serial=on`.
When `serial=on`, transactions must be a big-endian encoded incrementing
integer, starting at 0.
If `serial=off`, there are no restrictions on transactions.
We can toggle the value of `serial` using the `set_option` ABCI message.
When `serial=on`, some transactions are invalid. In a live blockchain,
transactions collect in memory before they are committed into blocks. To
avoid wasting resources on invalid transactions, ABCI provides the
`check_tx` message, which application developers can use to accept or
reject transactions, before they are stored in memory or gossipped to
other peers.
In this instance of the counter app, `check_tx` only allows transactions
whose integer is greater than the last committed one.
Let's kill the console and the kvstore application, and start the
counter app:
```sh
abci-cli counter
```
In another window, start the `abci-cli console`:
```sh
> check_tx 0x00
-> code: OK
> check_tx 0xff
-> code: OK
> deliver_tx 0x00
-> code: OK
> check_tx 0x00
-> code: BadNonce
-> log: Invalid nonce. Expected >= 1, got 0
> deliver_tx 0x01
-> code: OK
> deliver_tx 0x04
-> code: BadNonce
-> log: Invalid nonce. Expected 2, got 4
> info
-> code: OK
-> data: {"hashes":0,"txs":2}
-> data.hex: 0x7B22686173686573223A302C22747873223A327D
```
This is a very simple application, but between `counter` and `kvstore`,
its easy to see how you can build out arbitrary application states on
top of the ABCI. [Hyperledger's
Burrow](https://github.com/hyperledger/burrow) also runs atop ABCI,
bringing with it Ethereum-like accounts, the Ethereum virtual-machine,
Monax's permissioning scheme, and native contracts extensions.
But the ultimate flexibility comes from being able to write the
application easily in any language.
We have implemented the counter in a number of languages [see the
example directory](https://github.com/tendermint/tendermint/tree/master/abci/example).
To run the Node.js version, fist download & install [the Javascript ABCI server](https://github.com/tendermint/js-abci):
```sh
git clone https://github.com/tendermint/js-abci.git
cd js-abci
npm install abci
```
Now you can start the app:
```sh
node example/counter.js
```
(you'll have to kill the other counter application process). In another
window, run the console and those previous ABCI commands. You should get
the same results as for the Go version.
## Bounties ## Bounties
Want to write the counter app in your favorite language?! We'd be happy
Want to write an app in your favorite language?! We'd be happy
to add you to our [ecosystem](https://github.com/tendermint/awesome#ecosystem)! to add you to our [ecosystem](https://github.com/tendermint/awesome#ecosystem)!
See [funding](https://github.com/interchainio/funding) opportunities from the See [funding](https://github.com/interchainio/funding) opportunities from the
[Interchain Foundation](https://interchain.io/) for implementations in new languages and more. [Interchain Foundation](https://interchain.io/) for implementations in new languages and more.


+ 2
- 88
docs/app-dev/getting-started.md View File

@ -37,8 +37,8 @@ cd $GOPATH/src/github.com/tendermint/tendermint
make install_abci make install_abci
``` ```
Now you should have the `abci-cli` installed; you'll see a couple of
commands (`counter` and `kvstore`) that are example applications written
Now you should have the `abci-cli` installed; you'll notice the `kvstore`
command, an example application written
in Go. See below for an application written in JavaScript. in Go. See below for an application written in JavaScript.
Now, let's run some apps! Now, let's run some apps!
@ -165,92 +165,6 @@ curl -s 'localhost:26657/abci_query?data="name"'
Try some other transactions and queries to make sure everything is Try some other transactions and queries to make sure everything is
working! working!
## Counter - Another Example
Now that we've got the hang of it, let's try another application, the
`counter` app.
The counter app doesn't use a Merkle tree, it just counts how many times
we've sent a transaction, or committed the state.
This application has two modes: `serial=off` and `serial=on`.
When `serial=on`, transactions must be a big-endian encoded incrementing
integer, starting at 0.
If `serial=off`, there are no restrictions on transactions.
In a live blockchain, transactions collect in memory before they are
committed into blocks. To avoid wasting resources on invalid
transactions, ABCI provides the `CheckTx` message, which application
developers can use to accept or reject transactions, before they are
stored in memory or gossipped to other peers.
In this instance of the counter app, with `serial=on`, `CheckTx` only
allows transactions whose integer is greater than the last committed
one.
Let's kill the previous instance of `tendermint` and the `kvstore`
application, and start the counter app. We can enable `serial=on` with a
flag:
```sh
abci-cli counter --serial
```
In another window, reset then start Tendermint:
```sh
tendermint unsafe_reset_all
tendermint start
```
Once again, you can see the blocks streaming by. Let's send some
transactions. Since we have set `serial=on`, the first transaction must
be the number `0`:
```sh
curl localhost:26657/broadcast_tx_commit?tx=0x00
```
Note the empty (hence successful) response. The next transaction must be
the number `1`. If instead, we try to send a `5`, we get an error:
```json
> curl localhost:26657/broadcast_tx_commit?tx=0x05
{
"jsonrpc": "2.0",
"id": "",
"result": {
"check_tx": {},
"deliver_tx": {
"code": 2,
"log": "Invalid nonce. Expected 1, got 5"
},
"hash": "33B93DFF98749B0D6996A70F64071347060DC19C",
"height": 34
}
}
```
But if we send a `1`, it works again:
```json
> curl localhost:26657/broadcast_tx_commit?tx=0x01
{
"jsonrpc": "2.0",
"id": "",
"result": {
"check_tx": {},
"deliver_tx": {},
"hash": "F17854A977F6FA7EEA1BD758E296710B86F72F3D",
"height": 60
}
}
```
For more details on the `broadcast_tx` API, see [the guide on using
Tendermint](../tendermint-core/using-tendermint.md).
## CounterJS - Example in Another Language ## CounterJS - Example in Another Language


+ 1
- 1
internal/consensus/byzantine_test.go View File

@ -35,7 +35,7 @@ func TestByzantinePrevoteEquivocation(t *testing.T) {
prevoteHeight := int64(2) prevoteHeight := int64(2)
testName := "consensus_byzantine_test" testName := "consensus_byzantine_test"
tickerFunc := newMockTickerFunc(true) tickerFunc := newMockTickerFunc(true)
appFunc := newCounter
appFunc := newKVStore
genDoc, privVals := factory.RandGenesisDoc(config, nValidators, false, 30) genDoc, privVals := factory.RandGenesisDoc(config, nValidators, false, 30)
states := make([]*State, nValidators) states := make([]*State, nValidators)


+ 5
- 6
internal/consensus/common_test.go View File

@ -19,7 +19,6 @@ import (
dbm "github.com/tendermint/tm-db" dbm "github.com/tendermint/tm-db"
abcicli "github.com/tendermint/tendermint/abci/client" abcicli "github.com/tendermint/tendermint/abci/client"
"github.com/tendermint/tendermint/abci/example/counter"
"github.com/tendermint/tendermint/abci/example/kvstore" "github.com/tendermint/tendermint/abci/example/kvstore"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
cfg "github.com/tendermint/tendermint/config" cfg "github.com/tendermint/tendermint/config"
@ -449,7 +448,7 @@ func randState(config *cfg.Config, nValidators int) (*State, []*validatorStub) {
vss := make([]*validatorStub, nValidators) vss := make([]*validatorStub, nValidators)
cs := newState(state, privVals[0], counter.NewApplication(true))
cs := newState(state, privVals[0], kvstore.NewApplication())
for i := 0; i < nValidators; i++ { for i := 0; i < nValidators; i++ {
vss[i] = newValidatorStub(privVals[i], int32(i)) vss[i] = newValidatorStub(privVals[i], int32(i))
@ -862,10 +861,6 @@ func (m *mockTicker) Chan() <-chan timeoutInfo {
func (*mockTicker) SetLogger(log.Logger) {} func (*mockTicker) SetLogger(log.Logger) {}
func newCounter() abci.Application {
return counter.NewApplication(true)
}
func newPersistentKVStore() abci.Application { func newPersistentKVStore() abci.Application {
dir, err := ioutil.TempDir("", "persistent-kvstore") dir, err := ioutil.TempDir("", "persistent-kvstore")
if err != nil { if err != nil {
@ -874,6 +869,10 @@ func newPersistentKVStore() abci.Application {
return kvstore.NewPersistentKVStoreApplication(dir) return kvstore.NewPersistentKVStoreApplication(dir)
} }
func newKVStore() abci.Application {
return kvstore.NewApplication()
}
func newPersistentKVStoreWithPath(dbDir string) abci.Application { func newPersistentKVStoreWithPath(dbDir string) abci.Application {
return kvstore.NewPersistentKVStoreApplication(dbDir) return kvstore.NewPersistentKVStoreApplication(dbDir)
} }

+ 3
- 1
internal/consensus/invalid_test.go View File

@ -18,7 +18,9 @@ func TestReactorInvalidPrecommit(t *testing.T) {
config := configSetup(t) config := configSetup(t)
n := 4 n := 4
states, cleanup := randConsensusState(t, config, n, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
states, cleanup := randConsensusState(t,
config, n, "consensus_reactor_test",
newMockTickerFunc(true), newKVStore)
t.Cleanup(cleanup) t.Cleanup(cleanup)
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {


+ 8
- 4
internal/consensus/reactor_test.go View File

@ -257,7 +257,9 @@ func TestReactorBasic(t *testing.T) {
config := configSetup(t) config := configSetup(t)
n := 4 n := 4
states, cleanup := randConsensusState(t, config, n, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
states, cleanup := randConsensusState(t,
config, n, "consensus_reactor_test",
newMockTickerFunc(true), newKVStore)
t.Cleanup(cleanup) t.Cleanup(cleanup)
rts := setup(t, n, states, 100) // buffer must be large enough to not deadlock rts := setup(t, n, states, 100) // buffer must be large enough to not deadlock
@ -287,7 +289,7 @@ func TestReactorWithEvidence(t *testing.T) {
n := 4 n := 4
testName := "consensus_reactor_test" testName := "consensus_reactor_test"
tickerFunc := newMockTickerFunc(true) tickerFunc := newMockTickerFunc(true)
appFunc := newCounter
appFunc := newKVStore
genDoc, privVals := factory.RandGenesisDoc(config, n, false, 30) genDoc, privVals := factory.RandGenesisDoc(config, n, false, 30)
states := make([]*State, n) states := make([]*State, n)
@ -387,7 +389,7 @@ func TestReactorCreatesBlockWhenEmptyBlocksFalse(t *testing.T) {
n, n,
"consensus_reactor_test", "consensus_reactor_test",
newMockTickerFunc(true), newMockTickerFunc(true),
newCounter,
newKVStore,
func(c *cfg.Config) { func(c *cfg.Config) {
c.Consensus.CreateEmptyBlocks = false c.Consensus.CreateEmptyBlocks = false
}, },
@ -431,7 +433,9 @@ func TestReactorRecordsVotesAndBlockParts(t *testing.T) {
config := configSetup(t) config := configSetup(t)
n := 4 n := 4
states, cleanup := randConsensusState(t, config, n, "consensus_reactor_test", newMockTickerFunc(true), newCounter)
states, cleanup := randConsensusState(t,
config, n, "consensus_reactor_test",
newMockTickerFunc(true), newKVStore)
t.Cleanup(cleanup) t.Cleanup(cleanup)
rts := setup(t, n, states, 100) // buffer must be large enough to not deadlock rts := setup(t, n, states, 100) // buffer must be large enough to not deadlock


+ 4
- 4
internal/consensus/state_test.go View File

@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/abci/example/counter"
"github.com/tendermint/tendermint/abci/example/kvstore"
"github.com/tendermint/tendermint/crypto/tmhash" "github.com/tendermint/tendermint/crypto/tmhash"
cstypes "github.com/tendermint/tendermint/internal/consensus/types" cstypes "github.com/tendermint/tendermint/internal/consensus/types"
p2pmock "github.com/tendermint/tendermint/internal/p2p/mock" p2pmock "github.com/tendermint/tendermint/internal/p2p/mock"
@ -654,7 +654,7 @@ func TestStateLockPOLRelock(t *testing.T) {
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4) signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
// before we timeout to the new round set the new proposal // before we timeout to the new round set the new proposal
cs2 := newState(cs1.state, vs2, counter.NewApplication(true))
cs2 := newState(cs1.state, vs2, kvstore.NewApplication())
prop, propBlock := decideProposal(cs2, vs2, vs2.Height, vs2.Round+1) prop, propBlock := decideProposal(cs2, vs2, vs2.Height, vs2.Round+1)
if prop == nil || propBlock == nil { if prop == nil || propBlock == nil {
t.Fatal("Failed to create proposal block with vs2") t.Fatal("Failed to create proposal block with vs2")
@ -843,7 +843,7 @@ func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) {
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4) signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
// before we timeout to the new round set the new proposal // before we timeout to the new round set the new proposal
cs2 := newState(cs1.state, vs2, counter.NewApplication(true))
cs2 := newState(cs1.state, vs2, kvstore.NewApplication())
prop, propBlock := decideProposal(cs2, vs2, vs2.Height, vs2.Round+1) prop, propBlock := decideProposal(cs2, vs2, vs2.Height, vs2.Round+1)
if prop == nil || propBlock == nil { if prop == nil || propBlock == nil {
t.Fatal("Failed to create proposal block with vs2") t.Fatal("Failed to create proposal block with vs2")
@ -887,7 +887,7 @@ func TestStateLockPOLUnlockOnUnknownBlock(t *testing.T) {
signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4) signAddVotes(config, cs1, tmproto.PrecommitType, nil, types.PartSetHeader{}, vs2, vs3, vs4)
// before we timeout to the new round set the new proposal // before we timeout to the new round set the new proposal
cs3 := newState(cs1.state, vs3, counter.NewApplication(true))
cs3 := newState(cs1.state, vs3, kvstore.NewApplication())
prop, propBlock = decideProposal(cs3, vs3, vs3.Height, vs3.Round+1) prop, propBlock = decideProposal(cs3, vs3, vs3.Height, vs3.Round+1)
if prop == nil || propBlock == nil { if prop == nil || propBlock == nil {
t.Fatal("Failed to create proposal block with vs2") t.Fatal("Failed to create proposal block with vs2")


+ 7
- 8
internal/mempool/v0/clist_mempool_test.go View File

@ -15,7 +15,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/abci/example/counter"
"github.com/tendermint/tendermint/abci/example/kvstore" "github.com/tendermint/tendermint/abci/example/kvstore"
abciserver "github.com/tendermint/tendermint/abci/server" abciserver "github.com/tendermint/tendermint/abci/server"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
@ -217,7 +216,7 @@ func TestMempoolUpdate(t *testing.T) {
} }
func TestMempool_KeepInvalidTxsInCache(t *testing.T) { func TestMempool_KeepInvalidTxsInCache(t *testing.T) {
app := counter.NewApplication(true)
app := kvstore.NewApplication()
cc := proxy.NewLocalClientCreator(app) cc := proxy.NewLocalClientCreator(app)
wcfg := cfg.DefaultConfig() wcfg := cfg.DefaultConfig()
wcfg.Mempool.KeepInvalidTxsInCache = true wcfg.Mempool.KeepInvalidTxsInCache = true
@ -309,7 +308,7 @@ func TestTxsAvailable(t *testing.T) {
} }
func TestSerialReap(t *testing.T) { func TestSerialReap(t *testing.T) {
app := counter.NewApplication(true)
app := kvstore.NewApplication()
cc := proxy.NewLocalClientCreator(app) cc := proxy.NewLocalClientCreator(app)
mp, cleanup := newMempoolWithApp(cc) mp, cleanup := newMempoolWithApp(cc)
@ -508,7 +507,7 @@ func TestMempoolTxsBytes(t *testing.T) {
} }
// 6. zero after tx is rechecked and removed due to not being valid anymore // 6. zero after tx is rechecked and removed due to not being valid anymore
app2 := counter.NewApplication(true)
app2 := kvstore.NewApplication()
cc = proxy.NewLocalClientCreator(app2) cc = proxy.NewLocalClientCreator(app2)
mp, cleanup = newMempoolWithApp(cc) mp, cleanup = newMempoolWithApp(cc)
defer cleanup() defer cleanup()
@ -540,16 +539,16 @@ func TestMempoolTxsBytes(t *testing.T) {
// Pretend like we committed nothing so txBytes gets rechecked and removed. // Pretend like we committed nothing so txBytes gets rechecked and removed.
err = mp.Update(1, []types.Tx{}, abciResponses(0, abci.CodeTypeOK), nil, nil) err = mp.Update(1, []types.Tx{}, abciResponses(0, abci.CodeTypeOK), nil, nil)
require.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, 0, mp.SizeBytes())
assert.EqualValues(t, 8, mp.SizeBytes())
// 7. Test RemoveTxByKey function // 7. Test RemoveTxByKey function
err = mp.CheckTx(context.Background(), []byte{0x06}, nil, mempool.TxInfo{}) err = mp.CheckTx(context.Background(), []byte{0x06}, nil, mempool.TxInfo{})
require.NoError(t, err) require.NoError(t, err)
assert.EqualValues(t, 1, mp.SizeBytes())
assert.EqualValues(t, 9, mp.SizeBytes())
mp.RemoveTxByKey(mempool.TxKey([]byte{0x07}), true) mp.RemoveTxByKey(mempool.TxKey([]byte{0x07}), true)
assert.EqualValues(t, 1, mp.SizeBytes())
assert.EqualValues(t, 9, mp.SizeBytes())
mp.RemoveTxByKey(mempool.TxKey([]byte{0x06}), true) mp.RemoveTxByKey(mempool.TxKey([]byte{0x06}), true)
assert.EqualValues(t, 0, mp.SizeBytes())
assert.EqualValues(t, 8, mp.SizeBytes())
} }


+ 1
- 6
proxy/client.go View File

@ -5,7 +5,6 @@ import (
"io" "io"
abcicli "github.com/tendermint/tendermint/abci/client" abcicli "github.com/tendermint/tendermint/abci/client"
"github.com/tendermint/tendermint/abci/example/counter"
"github.com/tendermint/tendermint/abci/example/kvstore" "github.com/tendermint/tendermint/abci/example/kvstore"
"github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/abci/types"
tmsync "github.com/tendermint/tendermint/internal/libs/sync" tmsync "github.com/tendermint/tendermint/internal/libs/sync"
@ -68,17 +67,13 @@ func (r *remoteClientCreator) NewABCIClient() (abcicli.Client, error) {
} }
// DefaultClientCreator returns a default ClientCreator, which will create a // DefaultClientCreator returns a default ClientCreator, which will create a
// local client if addr is one of: 'counter', 'counter_serial', 'kvstore',
// local client if addr is one of: 'kvstore',
// 'persistent_kvstore' or 'noop', otherwise - a remote client. // 'persistent_kvstore' or 'noop', otherwise - a remote client.
// //
// The Closer is a noop except for persistent_kvstore applications, // The Closer is a noop except for persistent_kvstore applications,
// which will clean up the store. // which will clean up the store.
func DefaultClientCreator(addr, transport, dbDir string) (ClientCreator, io.Closer) { func DefaultClientCreator(addr, transport, dbDir string) (ClientCreator, io.Closer) {
switch addr { switch addr {
case "counter":
return NewLocalClientCreator(counter.NewApplication(false)), noopCloser{}
case "counter_serial":
return NewLocalClientCreator(counter.NewApplication(true)), noopCloser{}
case "kvstore": case "kvstore":
return NewLocalClientCreator(kvstore.NewApplication()), noopCloser{} return NewLocalClientCreator(kvstore.NewApplication()), noopCloser{}
case "persistent_kvstore": case "persistent_kvstore":


+ 0
- 2
test/README.md View File

@ -10,8 +10,6 @@ and run the following tests in docker containers:
- includes test coverage - includes test coverage
- app tests - app tests
- kvstore app over socket - kvstore app over socket
- counter app over socket
- counter app over grpc
- persistence tests - persistence tests
- crash tendermint at each of many predefined points, restart, and ensure it syncs properly with the app - crash tendermint at each of many predefined points, restart, and ensure it syncs properly with the app


+ 0
- 69
test/app/test.sh View File

@ -2,9 +2,6 @@
set -ex set -ex
#- kvstore over socket, curl #- kvstore over socket, curl
#- counter over socket, curl
#- counter over grpc, curl
#- counter over grpc, grpc
# TODO: install everything # TODO: install everything
@ -45,57 +42,6 @@ function kvstore_over_socket_reorder(){
kill -9 $pid_kvstore $pid_tendermint kill -9 $pid_kvstore $pid_tendermint
} }
function counter_over_socket() {
rm -rf $TMHOME
tendermint init validator
echo "Starting counter_over_socket"
abci-cli counter --serial > /dev/null &
pid_counter=$!
tendermint start --mode validator > tendermint.log &
pid_tendermint=$!
sleep 5
echo "running test"
bash test/app/counter_test.sh "Counter over Socket"
kill -9 $pid_counter $pid_tendermint
}
function counter_over_grpc() {
rm -rf $TMHOME
tendermint init validator
echo "Starting counter_over_grpc"
abci-cli counter --serial --abci grpc > /dev/null &
pid_counter=$!
tendermint start --mode validator --abci grpc > tendermint.log &
pid_tendermint=$!
sleep 5
echo "running test"
bash test/app/counter_test.sh "Counter over GRPC"
kill -9 $pid_counter $pid_tendermint
}
function counter_over_grpc_grpc() {
rm -rf $TMHOME
tendermint init validator
echo "Starting counter_over_grpc_grpc (ie. with grpc broadcast_tx)"
abci-cli counter --serial --abci grpc > /dev/null &
pid_counter=$!
sleep 1
GRPC_PORT=36656
tendermint start --mode validator --abci grpc --rpc.grpc-laddr tcp://localhost:$GRPC_PORT > tendermint.log &
pid_tendermint=$!
sleep 5
echo "running test"
GRPC_BROADCAST_TX=true bash test/app/counter_test.sh "Counter over GRPC via GRPC BroadcastTx"
kill -9 $pid_counter $pid_tendermint
}
case "$1" in case "$1" in
"kvstore_over_socket") "kvstore_over_socket")
kvstore_over_socket kvstore_over_socket
@ -103,25 +49,10 @@ case "$1" in
"kvstore_over_socket_reorder") "kvstore_over_socket_reorder")
kvstore_over_socket_reorder kvstore_over_socket_reorder
;; ;;
"counter_over_socket")
counter_over_socket
;;
"counter_over_grpc")
counter_over_grpc
;;
"counter_over_grpc_grpc")
counter_over_grpc_grpc
;;
*) *)
echo "Running all" echo "Running all"
kvstore_over_socket kvstore_over_socket
echo "" echo ""
kvstore_over_socket_reorder kvstore_over_socket_reorder
echo "" echo ""
counter_over_socket
echo ""
counter_over_grpc
echo ""
counter_over_grpc_grpc
esac esac

Loading…
Cancel
Save