mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-24 11:41:22 +00:00
Merge branch 'develop' into sdk2
This commit is contained in:
commit
c38ac88d69
@ -1,14 +1,18 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 0.9.0 (TBD)
|
## 0.9.0 (December 28, 2017)
|
||||||
|
|
||||||
BREAKING CHANGES:
|
BREAKING CHANGES:
|
||||||
|
- [types] Id -> ID
|
||||||
- [types] ResponseEndBlock: renamed Diffs field to ValidatorUpdates
|
- [types] ResponseEndBlock: renamed Diffs field to ValidatorUpdates
|
||||||
- [types] changed protobuf field indices for Request and Response oneof types
|
- [types] changed protobuf field indices for Request and Response oneof types
|
||||||
|
|
||||||
FEATURES:
|
FEATURES:
|
||||||
- [types] ResponseEndBlock: added ConsensusParamUpdates
|
- [types] ResponseEndBlock: added ConsensusParamUpdates
|
||||||
|
|
||||||
|
BUG FIXES:
|
||||||
|
- [cmd] fix console and batch commands to use a single persistent connection
|
||||||
|
|
||||||
## 0.8.0 (December 6, 2017)
|
## 0.8.0 (December 6, 2017)
|
||||||
|
|
||||||
BREAKING CHANGES:
|
BREAKING CHANGES:
|
||||||
|
104
README.md
104
README.md
@ -13,7 +13,20 @@ The two guides to focus on are the `Application Development Guide` and `Using AB
|
|||||||
|
|
||||||
Previously, the ABCI was referred to as TMSP.
|
Previously, the ABCI was referred to as TMSP.
|
||||||
|
|
||||||
The community has provided a number of addtional implementations, see the `Tendermint Ecosystem` in [the documentation](http://tendermint.readthedocs.io/en/master/).
|
The community has provided a number of addtional implementations, see the [Tendermint Ecosystem](https://tendermint.com/ecosystem)
|
||||||
|
|
||||||
|
## Specification
|
||||||
|
|
||||||
|
See the [spec file](specification.rst) for more information.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
go get github.com/tendermint/abci
|
||||||
|
cd $GOPATH/src/github.com/tendermint/abci
|
||||||
|
make get_vendor_deps
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
|
||||||
## Implementation
|
## Implementation
|
||||||
|
|
||||||
@ -24,13 +37,15 @@ We provide three implementations of the ABCI in Go:
|
|||||||
- GRPC
|
- GRPC
|
||||||
|
|
||||||
Note the GRPC version is maintained primarily to simplify onboarding and prototyping and is not receiving the same
|
Note the GRPC version is maintained primarily to simplify onboarding and prototyping and is not receiving the same
|
||||||
attention to security and performance as the others.
|
attention to security and performance as the others
|
||||||
|
|
||||||
### In Process
|
### In Process
|
||||||
|
|
||||||
The simplest implementation just uses function calls within Go.
|
The simplest implementation just uses function calls within Go.
|
||||||
This means ABCI applications written in Golang can be compiled with TendermintCore and run as a single binary.
|
This means ABCI applications written in Golang can be compiled with TendermintCore and run as a single binary.
|
||||||
|
|
||||||
|
See the [examples](#examples) below for more information.
|
||||||
|
|
||||||
### Socket (TSP)
|
### Socket (TSP)
|
||||||
|
|
||||||
ABCI is best implemented as a streaming protocol.
|
ABCI is best implemented as a streaming protocol.
|
||||||
@ -48,36 +63,85 @@ the ordered, asynchronous socket protocol. The implementation has also not recei
|
|||||||
|
|
||||||
Note the length-prefixing used in the socket implementation does not apply for GRPC.
|
Note the length-prefixing used in the socket implementation does not apply for GRPC.
|
||||||
|
|
||||||
## Tools
|
## Usage
|
||||||
|
|
||||||
The `abci-cli` tool wraps an ABCI client and can be used for probing/testing an ABCI server.
|
The `abci-cli` tool wraps an ABCI client and can be used for probing/testing an ABCI server.
|
||||||
For instance, `abci-cli test` will run a test sequence against a listening server running the Counter application (see below).
|
For instance, `abci-cli test` will run a test sequence against a listening server running the Counter application (see below).
|
||||||
It can also be used to run some example applications.
|
It can also be used to run some example applications.
|
||||||
See [the documentation](http://tendermint.readthedocs.io/en/master/) for more details.
|
See [the documentation](http://tendermint.readthedocs.io/en/master/) for more details.
|
||||||
|
|
||||||
### Example Apps
|
### Examples
|
||||||
|
|
||||||
Multiple example apps are included:
|
Check out the variety of example applications in the [example directory](example/).
|
||||||
- the `abci-cli counter` application, which illustrates nonce checking in txs
|
It also contains the code refered to by the `counter` and `dummy` apps; these apps come
|
||||||
- the `abci-cli dummy` application, which illustrates a simple key-value Merkle tree
|
built into the `abci-cli` binary.
|
||||||
- the `abci-cli dummy --persistent` application, which augments the dummy with persistence and validator set changes
|
|
||||||
|
|
||||||
### Install
|
#### Counter
|
||||||
|
|
||||||
```
|
The `abci-cli counter` application illustrates nonce checking in transactions. It's code looks like:
|
||||||
go get github.com/tendermint/abci
|
|
||||||
cd $GOPATH/src/github.com/tendermint/abci
|
```golang
|
||||||
make get_vendor_deps
|
func cmdCounter(cmd *cobra.Command, args []string) error {
|
||||||
make install
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait forever
|
||||||
|
cmn.TrapSignal(func() {
|
||||||
|
// Cleanup
|
||||||
|
srv.Stop()
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Specification
|
and can be found in [this file](cmd/abci-cli/abci-cli.go).
|
||||||
|
|
||||||
The [primary specification](https://github.com/tendermint/abci/blob/master/types/types.proto) is made using Protocol Buffers.
|
#### Dummy
|
||||||
To build it, run
|
|
||||||
|
|
||||||
```
|
The `abci-cli dummy` application, which illustrates a simple key-value Merkle tree
|
||||||
make protoc
|
|
||||||
|
```golang
|
||||||
|
func cmdDummy(cmd *cobra.Command, args []string) error {
|
||||||
|
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
||||||
|
|
||||||
|
// Create the application - in memory or persisted to disk
|
||||||
|
var app types.Application
|
||||||
|
if flagPersist == "" {
|
||||||
|
app = dummy.NewDummyApplication()
|
||||||
|
} else {
|
||||||
|
app = dummy.NewPersistentDummyApplication(flagPersist)
|
||||||
|
app.(*dummy.PersistentDummyApplication).SetLogger(logger.With("module", "dummy"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the listener
|
||||||
|
srv, err := server.NewServer(flagAddrD, flagAbci, app)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srv.SetLogger(logger.With("module", "abci-server"))
|
||||||
|
if err := srv.Start(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait forever
|
||||||
|
cmn.TrapSignal(func() {
|
||||||
|
// Cleanup
|
||||||
|
srv.Stop()
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
See `protoc --help` and [the Protocol Buffers site](https://developers.google.com/protocol-buffers/) for details on compiling for other languages.
|
See `protoc --help` and [the Protocol Buffers site](https://developers.google.com/protocol-buffers/) for details on compiling for other languages.
|
||||||
@ -200,3 +264,5 @@ Here, we describe the requests and responses as function arguments and return va
|
|||||||
* `Log (string)`: Debug or error message
|
* `Log (string)`: Debug or error message
|
||||||
* __Usage__:<br/>
|
* __Usage__:<br/>
|
||||||
Return a Merkle root hash of the application state.
|
Return a Merkle root hash of the application state.
|
||||||
|
and can be found in [this file](cmd/abci-cli/abci-cli.go).
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ checkout:
|
|||||||
|
|
||||||
test:
|
test:
|
||||||
override:
|
override:
|
||||||
- cd $REPO && make get_tools check build test_integrations
|
- cd $REPO && make get_tools check get_vendor_deps install test_integrations
|
||||||
post:
|
post:
|
||||||
- cd "$REPO" && bash <(curl -s https://codecov.io/bash) -f coverage.txt
|
- cd "$REPO" && bash <(curl -s https://codecov.io/bash) -f coverage.txt
|
||||||
- cd "$REPO" && mv coverage.txt "${CIRCLE_ARTIFACTS}"
|
- cd "$REPO" && mv coverage.txt "${CIRCLE_ARTIFACTS}"
|
||||||
|
@ -54,8 +54,8 @@ var (
|
|||||||
|
|
||||||
var RootCmd = &cobra.Command{
|
var RootCmd = &cobra.Command{
|
||||||
Use: "abci-cli",
|
Use: "abci-cli",
|
||||||
Short: "",
|
Short: "the ABCI CLI tool wraps an ABCI client",
|
||||||
Long: "",
|
Long: "the ABCI CLI tool wraps an ABCI client and is used for testing ABCI servers",
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
switch cmd.Use {
|
switch cmd.Use {
|
||||||
@ -112,26 +112,26 @@ func Execute() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addGlobalFlags() {
|
func addGlobalFlags() {
|
||||||
RootCmd.PersistentFlags().StringVarP(&flagAddress, "address", "", "tcp://0.0.0.0:46658", "Address of application socket")
|
RootCmd.PersistentFlags().StringVarP(&flagAddress, "address", "", "tcp://0.0.0.0:46658", "address of application socket")
|
||||||
RootCmd.PersistentFlags().StringVarP(&flagAbci, "abci", "", "socket", "Either socket or grpc")
|
RootCmd.PersistentFlags().StringVarP(&flagAbci, "abci", "", "socket", "either socket or grpc")
|
||||||
RootCmd.PersistentFlags().BoolVarP(&flagVerbose, "verbose", "v", false, "Print the command and results as if it were a console session")
|
RootCmd.PersistentFlags().BoolVarP(&flagVerbose, "verbose", "v", false, "print the command and results as if it were a console session")
|
||||||
RootCmd.PersistentFlags().StringVarP(&flagLogLevel, "log_level", "", "debug", "Set the logger level")
|
RootCmd.PersistentFlags().StringVarP(&flagLogLevel, "log_level", "", "debug", "set the logger level")
|
||||||
}
|
}
|
||||||
|
|
||||||
func addQueryFlags() {
|
func addQueryFlags() {
|
||||||
queryCmd.PersistentFlags().StringVarP(&flagPath, "path", "", "/store", "Path to prefix query with")
|
queryCmd.PersistentFlags().StringVarP(&flagPath, "path", "", "/store", "path to prefix query with")
|
||||||
queryCmd.PersistentFlags().IntVarP(&flagHeight, "height", "", 0, "Height to query the blockchain at")
|
queryCmd.PersistentFlags().IntVarP(&flagHeight, "height", "", 0, "height to query the blockchain at")
|
||||||
queryCmd.PersistentFlags().BoolVarP(&flagProve, "prove", "", false, "Whether or not to return a merkle proof of the query result")
|
queryCmd.PersistentFlags().BoolVarP(&flagProve, "prove", "", false, "whether or not to return a merkle proof of the query result")
|
||||||
}
|
}
|
||||||
|
|
||||||
func addCounterFlags() {
|
func addCounterFlags() {
|
||||||
counterCmd.PersistentFlags().StringVarP(&flagAddrC, "addr", "", "tcp://0.0.0.0:46658", "Listen address")
|
counterCmd.PersistentFlags().StringVarP(&flagAddrC, "addr", "", "tcp://0.0.0.0:46658", "listen address")
|
||||||
counterCmd.PersistentFlags().BoolVarP(&flagSerial, "serial", "", false, "Enforce incrementing (serial) transactions")
|
counterCmd.PersistentFlags().BoolVarP(&flagSerial, "serial", "", false, "enforce incrementing (serial) transactions")
|
||||||
}
|
}
|
||||||
|
|
||||||
func addDummyFlags() {
|
func addDummyFlags() {
|
||||||
dummyCmd.PersistentFlags().StringVarP(&flagAddrD, "addr", "", "tcp://0.0.0.0:46658", "Listen address")
|
dummyCmd.PersistentFlags().StringVarP(&flagAddrD, "addr", "", "tcp://0.0.0.0:46658", "listen address")
|
||||||
dummyCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "Directory to use for a database")
|
dummyCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "directory to use for a database")
|
||||||
}
|
}
|
||||||
func addCommands() {
|
func addCommands() {
|
||||||
RootCmd.AddCommand(batchCmd)
|
RootCmd.AddCommand(batchCmd)
|
||||||
@ -156,8 +156,25 @@ func addCommands() {
|
|||||||
|
|
||||||
var batchCmd = &cobra.Command{
|
var batchCmd = &cobra.Command{
|
||||||
Use: "batch",
|
Use: "batch",
|
||||||
Short: "Run a batch of abci commands against an application",
|
Short: "run a batch of abci commands against an application",
|
||||||
Long: "",
|
Long: `run a batch of abci commands against an application
|
||||||
|
|
||||||
|
This command is run by piping in a file containing a series of commands
|
||||||
|
you'd like to run:
|
||||||
|
|
||||||
|
abci-cli batch < example.file
|
||||||
|
|
||||||
|
where example.file looks something like:
|
||||||
|
|
||||||
|
set_option serial on
|
||||||
|
check_tx 0x00
|
||||||
|
check_tx 0xff
|
||||||
|
deliver_tx 0x00
|
||||||
|
check_tx 0x00
|
||||||
|
deliver_tx 0x01
|
||||||
|
deliver_tx 0x04
|
||||||
|
info
|
||||||
|
`,
|
||||||
Args: cobra.ExactArgs(0),
|
Args: cobra.ExactArgs(0),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdBatch(cmd, args)
|
return cmdBatch(cmd, args)
|
||||||
@ -166,8 +183,12 @@ var batchCmd = &cobra.Command{
|
|||||||
|
|
||||||
var consoleCmd = &cobra.Command{
|
var consoleCmd = &cobra.Command{
|
||||||
Use: "console",
|
Use: "console",
|
||||||
Short: "Start an interactive abci console for multiple commands",
|
Short: "start an interactive ABCI console for multiple commands",
|
||||||
Long: "",
|
Long: `start an interactive ABCI console for multiple commands
|
||||||
|
|
||||||
|
This command opens an interactive console for running any of the other commands
|
||||||
|
without opening a new connection each time
|
||||||
|
`,
|
||||||
Args: cobra.ExactArgs(0),
|
Args: cobra.ExactArgs(0),
|
||||||
ValidArgs: []string{"echo", "info", "set_option", "deliver_tx", "check_tx", "commit", "query"},
|
ValidArgs: []string{"echo", "info", "set_option", "deliver_tx", "check_tx", "commit", "query"},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@ -177,8 +198,8 @@ var consoleCmd = &cobra.Command{
|
|||||||
|
|
||||||
var echoCmd = &cobra.Command{
|
var echoCmd = &cobra.Command{
|
||||||
Use: "echo",
|
Use: "echo",
|
||||||
Short: "Have the application echo a message",
|
Short: "have the application echo a message",
|
||||||
Long: "",
|
Long: "have the application echo a message",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdEcho(cmd, args)
|
return cmdEcho(cmd, args)
|
||||||
@ -186,8 +207,8 @@ var echoCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
var infoCmd = &cobra.Command{
|
var infoCmd = &cobra.Command{
|
||||||
Use: "info",
|
Use: "info",
|
||||||
Short: "Get some info about the application",
|
Short: "get some info about the application",
|
||||||
Long: "",
|
Long: "get some info about the application",
|
||||||
Args: cobra.ExactArgs(0),
|
Args: cobra.ExactArgs(0),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdInfo(cmd, args)
|
return cmdInfo(cmd, args)
|
||||||
@ -195,8 +216,8 @@ var infoCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
var setOptionCmd = &cobra.Command{
|
var setOptionCmd = &cobra.Command{
|
||||||
Use: "set_option",
|
Use: "set_option",
|
||||||
Short: "Set an option on the application",
|
Short: "set an option on the application",
|
||||||
Long: "",
|
Long: "set an option on the application",
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdSetOption(cmd, args)
|
return cmdSetOption(cmd, args)
|
||||||
@ -205,8 +226,8 @@ var setOptionCmd = &cobra.Command{
|
|||||||
|
|
||||||
var deliverTxCmd = &cobra.Command{
|
var deliverTxCmd = &cobra.Command{
|
||||||
Use: "deliver_tx",
|
Use: "deliver_tx",
|
||||||
Short: "Deliver a new transaction to the application",
|
Short: "deliver a new transaction to the application",
|
||||||
Long: "",
|
Long: "deliver a new transaction to the application",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdDeliverTx(cmd, args)
|
return cmdDeliverTx(cmd, args)
|
||||||
@ -215,8 +236,8 @@ var deliverTxCmd = &cobra.Command{
|
|||||||
|
|
||||||
var checkTxCmd = &cobra.Command{
|
var checkTxCmd = &cobra.Command{
|
||||||
Use: "check_tx",
|
Use: "check_tx",
|
||||||
Short: "Validate a transaction",
|
Short: "validate a transaction",
|
||||||
Long: "",
|
Long: "validate a transaction",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdCheckTx(cmd, args)
|
return cmdCheckTx(cmd, args)
|
||||||
@ -225,8 +246,8 @@ var checkTxCmd = &cobra.Command{
|
|||||||
|
|
||||||
var commitCmd = &cobra.Command{
|
var commitCmd = &cobra.Command{
|
||||||
Use: "commit",
|
Use: "commit",
|
||||||
Short: "Commit the application state and return the Merkle root hash",
|
Short: "commit the application state and return the Merkle root hash",
|
||||||
Long: "",
|
Long: "commit the application state and return the Merkle root hash",
|
||||||
Args: cobra.ExactArgs(0),
|
Args: cobra.ExactArgs(0),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdCommit(cmd, args)
|
return cmdCommit(cmd, args)
|
||||||
@ -235,8 +256,8 @@ var commitCmd = &cobra.Command{
|
|||||||
|
|
||||||
var versionCmd = &cobra.Command{
|
var versionCmd = &cobra.Command{
|
||||||
Use: "version",
|
Use: "version",
|
||||||
Short: "Print abci console version",
|
Short: "print ABCI console version",
|
||||||
Long: "",
|
Long: "print ABCI console version",
|
||||||
Args: cobra.ExactArgs(0),
|
Args: cobra.ExactArgs(0),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
fmt.Println(version.Version)
|
fmt.Println(version.Version)
|
||||||
@ -246,8 +267,8 @@ var versionCmd = &cobra.Command{
|
|||||||
|
|
||||||
var queryCmd = &cobra.Command{
|
var queryCmd = &cobra.Command{
|
||||||
Use: "query",
|
Use: "query",
|
||||||
Short: "Query the application state",
|
Short: "query the application state",
|
||||||
Long: "",
|
Long: "query the application state",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdQuery(cmd, args)
|
return cmdQuery(cmd, args)
|
||||||
@ -257,7 +278,7 @@ var queryCmd = &cobra.Command{
|
|||||||
var counterCmd = &cobra.Command{
|
var counterCmd = &cobra.Command{
|
||||||
Use: "counter",
|
Use: "counter",
|
||||||
Short: "ABCI demo example",
|
Short: "ABCI demo example",
|
||||||
Long: "",
|
Long: "ABCI demo example",
|
||||||
Args: cobra.ExactArgs(0),
|
Args: cobra.ExactArgs(0),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdCounter(cmd, args)
|
return cmdCounter(cmd, args)
|
||||||
@ -267,7 +288,7 @@ var counterCmd = &cobra.Command{
|
|||||||
var dummyCmd = &cobra.Command{
|
var dummyCmd = &cobra.Command{
|
||||||
Use: "dummy",
|
Use: "dummy",
|
||||||
Short: "ABCI demo example",
|
Short: "ABCI demo example",
|
||||||
Long: "",
|
Long: "ABCI demo example",
|
||||||
Args: cobra.ExactArgs(0),
|
Args: cobra.ExactArgs(0),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdDummy(cmd, args)
|
return cmdDummy(cmd, args)
|
||||||
@ -276,8 +297,8 @@ var dummyCmd = &cobra.Command{
|
|||||||
|
|
||||||
var testCmd = &cobra.Command{
|
var testCmd = &cobra.Command{
|
||||||
Use: "test",
|
Use: "test",
|
||||||
Short: "Run integration tests",
|
Short: "run integration tests",
|
||||||
Long: "",
|
Long: "run integration tests",
|
||||||
Args: cobra.ExactArgs(0),
|
Args: cobra.ExactArgs(0),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return cmdTest(cmd, args)
|
return cmdTest(cmd, args)
|
||||||
@ -300,49 +321,39 @@ func persistentArgs(line []byte) []string {
|
|||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
func or(err1 error, err2 error) error {
|
func compose(fs []func() error) error {
|
||||||
if err1 == nil {
|
if len(fs) == 0 {
|
||||||
return err2
|
return nil
|
||||||
} else {
|
} else {
|
||||||
return err1
|
err := fs[0]()
|
||||||
|
if err == nil {
|
||||||
|
return compose(fs[1:])
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdTest(cmd *cobra.Command, args []string) error {
|
func cmdTest(cmd *cobra.Command, args []string) error {
|
||||||
fmt.Println("Running tests")
|
return compose(
|
||||||
|
[]func() error{
|
||||||
err := servertest.InitChain(client)
|
func() error { return servertest.InitChain(client) },
|
||||||
fmt.Println("")
|
func() error { return servertest.SetOption(client, "serial", "on") },
|
||||||
err = or(err, servertest.SetOption(client, "serial", "on"))
|
func() error { return servertest.Commit(client, nil) },
|
||||||
fmt.Println("")
|
func() error { return servertest.DeliverTx(client, []byte("abc"), code.CodeTypeBadNonce, nil) },
|
||||||
err = or(err, servertest.Commit(client, nil))
|
func() error { return servertest.Commit(client, nil) },
|
||||||
fmt.Println("")
|
func() error { return servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeOK, nil) },
|
||||||
err = or(err, servertest.DeliverTx(client, []byte("abc"), code.CodeTypeBadNonce, nil))
|
func() error { return servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) },
|
||||||
fmt.Println("")
|
func() error { return servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeBadNonce, nil) },
|
||||||
err = or(err, servertest.Commit(client, nil))
|
func() error { return servertest.DeliverTx(client, []byte{0x01}, code.CodeTypeOK, nil) },
|
||||||
fmt.Println("")
|
func() error { return servertest.DeliverTx(client, []byte{0x00, 0x02}, code.CodeTypeOK, nil) },
|
||||||
err = or(err, servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeOK, nil))
|
func() error { return servertest.DeliverTx(client, []byte{0x00, 0x03}, code.CodeTypeOK, nil) },
|
||||||
fmt.Println("")
|
func() error { return servertest.DeliverTx(client, []byte{0x00, 0x00, 0x04}, code.CodeTypeOK, nil) },
|
||||||
err = or(err, servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}))
|
func() error {
|
||||||
fmt.Println("")
|
return servertest.DeliverTx(client, []byte{0x00, 0x00, 0x06}, code.CodeTypeBadNonce, nil)
|
||||||
err = or(err, servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeBadNonce, nil))
|
},
|
||||||
fmt.Println("")
|
func() error { return servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5}) },
|
||||||
err = or(err, servertest.DeliverTx(client, []byte{0x01}, code.CodeTypeOK, nil))
|
})
|
||||||
fmt.Println("")
|
|
||||||
err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x02}, code.CodeTypeOK, nil))
|
|
||||||
fmt.Println("")
|
|
||||||
err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x03}, code.CodeTypeOK, nil))
|
|
||||||
fmt.Println("")
|
|
||||||
err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x00, 0x04}, code.CodeTypeOK, nil))
|
|
||||||
fmt.Println("")
|
|
||||||
err = or(err, servertest.DeliverTx(client, []byte{0x00, 0x00, 0x06}, code.CodeTypeBadNonce, nil))
|
|
||||||
fmt.Println("")
|
|
||||||
err = or(err, servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5}))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return errors.New("Some checks didn't pass, please inspect stdout to see the exact failures.")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdBatch(cmd *cobra.Command, args []string) error {
|
func cmdBatch(cmd *cobra.Command, args []string) error {
|
||||||
|
221
specification.rst
Normal file
221
specification.rst
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
Specification
|
||||||
|
=============
|
||||||
|
|
||||||
|
The `primary
|
||||||
|
specification <https://github.com/tendermint/abci/blob/master/types/types.proto>`__
|
||||||
|
is made using Protocol Buffers. To build it, run
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
make protoc
|
||||||
|
|
||||||
|
See ``protoc --help`` and `the Protocol Buffers
|
||||||
|
site <https://developers.google.com/protocol-buffers/>`__ for details on
|
||||||
|
compiling for other languages. Note we also include a
|
||||||
|
`GRPC <http://www.grpc.io/docs>`__ service definition.
|
||||||
|
|
||||||
|
For the specification as an interface in Go, see the
|
||||||
|
`types/application.go
|
||||||
|
file <https://github.com/tendermint/abci/blob/master/types/application.go>`__.
|
||||||
|
|
||||||
|
Message Types
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
ABCI requests/responses are defined as simple Protobuf messages in `this
|
||||||
|
schema
|
||||||
|
file <https://github.com/tendermint/abci/blob/master/types/types.proto>`__.
|
||||||
|
TendermintCore sends the requests, and the ABCI application sends the
|
||||||
|
responses. Here, we describe the requests and responses as function
|
||||||
|
arguments and return values, and make some notes about usage:
|
||||||
|
|
||||||
|
Echo
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
- **Arguments**:
|
||||||
|
|
||||||
|
- ``Message (string)``: A string to echo back
|
||||||
|
|
||||||
|
- **Returns**:
|
||||||
|
|
||||||
|
- ``Message (string)``: The input string
|
||||||
|
|
||||||
|
- **Usage**:
|
||||||
|
|
||||||
|
- Echo a string to test an abci client/server implementation
|
||||||
|
|
||||||
|
Flush
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
- **Usage**:
|
||||||
|
|
||||||
|
- Signals that messages queued on the client should be flushed to
|
||||||
|
the server. It is called periodically by the client implementation
|
||||||
|
to ensure asynchronous requests are actually sent, and is called
|
||||||
|
immediately to make a synchronous request, which returns when the
|
||||||
|
Flush response comes back.
|
||||||
|
|
||||||
|
Info
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
- **Returns**:
|
||||||
|
|
||||||
|
- ``Data (string)``: Some arbitrary information
|
||||||
|
- ``Version (Version)``: Version information
|
||||||
|
- ``LastBlockHeight (int64)``: Latest block for which the app has
|
||||||
|
called Commit
|
||||||
|
- ``LastBlockAppHash ([]byte)``: Latest result of Commit
|
||||||
|
|
||||||
|
- **Usage**: Return information about the application state. Used to
|
||||||
|
sync the app with Tendermint on crash/restart.
|
||||||
|
|
||||||
|
SetOption
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
- **Arguments**:
|
||||||
|
|
||||||
|
- ``Key (string)``: Key to set
|
||||||
|
- ``Value (string)``: Value to set for key
|
||||||
|
|
||||||
|
- **Returns**:
|
||||||
|
|
||||||
|
- ``Code (uint32)``: Response code
|
||||||
|
- ``Log (string)``: Debug or error message
|
||||||
|
|
||||||
|
- **Usage**: Set application options. E.g. Key="mode", Value="mempool"
|
||||||
|
for a mempool connection, or Key="mode", Value="consensus" for a
|
||||||
|
consensus connection. Other options are application specific.
|
||||||
|
|
||||||
|
InitChain
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
- **Arguments**:
|
||||||
|
|
||||||
|
- ``Validators ([]Validator)``: Initial genesis validators
|
||||||
|
|
||||||
|
- **Usage**: Called once upon genesis
|
||||||
|
|
||||||
|
Query
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
- **Arguments**:
|
||||||
|
|
||||||
|
- ``Data ([]byte)``: Raw query bytes. Can be used with or in lieu of
|
||||||
|
Path.
|
||||||
|
- ``Path (string)``: Path of request, like an HTTP GET path. Can be
|
||||||
|
used with or in liue of Data.
|
||||||
|
- Apps MUST interpret '/store' as a query by key on the underlying
|
||||||
|
store. The key SHOULD be specified in the Data field.
|
||||||
|
- Apps SHOULD allow queries over specific types like '/accounts/...'
|
||||||
|
or '/votes/...'
|
||||||
|
- ``Height (int64)``: The block height for which you want the query
|
||||||
|
(default=0 returns data for the latest committed block). Note that
|
||||||
|
this is the height of the block containing the application's
|
||||||
|
Merkle root hash, which represents the state as it was after
|
||||||
|
committing the block at Height-1
|
||||||
|
- ``Prove (bool)``: Return Merkle proof with response if possible
|
||||||
|
|
||||||
|
- **Returns**:
|
||||||
|
|
||||||
|
- ``Code (uint32)``: Response code
|
||||||
|
- ``Key ([]byte)``: The key of the matching data
|
||||||
|
- ``Value ([]byte)``: The value of the matching data
|
||||||
|
- ``Proof ([]byte)``: Proof for the data, if requested
|
||||||
|
- ``Height (int64)``: The block height from which data was derived.
|
||||||
|
Note that this is the height of the block containing the
|
||||||
|
application's Merkle root hash, which represents the state as it
|
||||||
|
was after committing the block at Height-1
|
||||||
|
- ``Log (string)``: Debug or error message
|
||||||
|
|
||||||
|
BeginBlock
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
- **Arguments**:
|
||||||
|
|
||||||
|
- ``Hash ([]byte)``: The block's hash. This can be derived from the
|
||||||
|
block header.
|
||||||
|
- ``Header (struct{})``: The block header
|
||||||
|
- ``AbsentValidators ([]int32)``: List of indices of validators not
|
||||||
|
included in the LastCommit
|
||||||
|
- ``ByzantineValidators ([]Evidence)``: List of evidence of
|
||||||
|
validators that acted maliciously
|
||||||
|
|
||||||
|
- **Usage**: Signals the beginning of a new block. Called prior to any
|
||||||
|
DeliverTxs. The header is expected to at least contain the Height.
|
||||||
|
The ``AbsentValidators`` and ``ByzantineValidators`` can be used to
|
||||||
|
determine rewards and punishments for the validators.
|
||||||
|
|
||||||
|
CheckTx
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
- **Arguments**:
|
||||||
|
|
||||||
|
- ``Data ([]byte)``: The request transaction bytes
|
||||||
|
|
||||||
|
- **Returns**:
|
||||||
|
|
||||||
|
- ``Code (uint32)``: Response code
|
||||||
|
- ``Data ([]byte)``: Result bytes, if any
|
||||||
|
- ``Log (string)``: Debug or error message
|
||||||
|
- ``Gas (int64)``: Amount of gas consumed by transaction
|
||||||
|
- ``Fee (int64)``: Fee paid by transaction
|
||||||
|
|
||||||
|
- **Usage**: Validate a mempool transaction, prior to broadcasting or
|
||||||
|
proposing. This message should not mutate the main state, but
|
||||||
|
application developers may want to keep a separate CheckTx state that
|
||||||
|
gets reset upon Commit.
|
||||||
|
|
||||||
|
CheckTx can happen interspersed with DeliverTx, but they happen on
|
||||||
|
different ABCI connections - CheckTx from the mempool connection, and
|
||||||
|
DeliverTx from the consensus connection. During Commit, the mempool
|
||||||
|
is locked, so you can reset the mempool state to the latest state
|
||||||
|
after running all those DeliverTxs, and then the mempool will re-run
|
||||||
|
whatever txs it has against that latest mempool state.
|
||||||
|
|
||||||
|
Transactions are first run through CheckTx before broadcast to peers
|
||||||
|
in the mempool layer. You can make CheckTx semi-stateful and clear
|
||||||
|
the state upon ``Commit`` or ``BeginBlock``, to allow for dependent
|
||||||
|
sequences of transactions in the same block.
|
||||||
|
|
||||||
|
DeliverTx
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
- **Arguments**:
|
||||||
|
|
||||||
|
- ``Data ([]byte)``: The request transaction bytes
|
||||||
|
|
||||||
|
- **Returns**:
|
||||||
|
|
||||||
|
- ``Code (uint32)``: Response code
|
||||||
|
- ``Data ([]byte)``: Result bytes, if any
|
||||||
|
- ``Log (string)``: Debug or error message
|
||||||
|
- ``Tags ([]*KVPair)``: Optional tags for indexing
|
||||||
|
|
||||||
|
- **Usage**: Append and run a transaction. If the transaction is valid,
|
||||||
|
returns CodeType.OK
|
||||||
|
|
||||||
|
EndBlock
|
||||||
|
^^^^^^^^
|
||||||
|
|
||||||
|
- **Arguments**:
|
||||||
|
|
||||||
|
- ``Height (int64)``: The block height that ended
|
||||||
|
|
||||||
|
- **Returns**:
|
||||||
|
|
||||||
|
- ``ValidatorUpdates ([]Validator)``: Changes to validator set (set
|
||||||
|
voting power to 0 to remove)
|
||||||
|
- ``ConsensusParamUpdates (ConsensusParams)``: Changes to
|
||||||
|
consensus-critical time/size parameters
|
||||||
|
|
||||||
|
- **Usage**: Signals the end of a block. Called prior to each Commit
|
||||||
|
after all transactions. Validator set is updated with the result.
|
||||||
|
|
||||||
|
Commit
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
- **Returns**:
|
||||||
|
|
||||||
|
- ``Data ([]byte)``: The Merkle root hash
|
||||||
|
- ``Log (string)``: Debug or error message
|
||||||
|
|
||||||
|
- **Usage**: Return a Merkle root hash of the application state.
|
@ -20,8 +20,8 @@ function testExample() {
|
|||||||
abci-cli --log_level=error --verbose batch < "$INPUT" > "${INPUT}.out.new"
|
abci-cli --log_level=error --verbose batch < "$INPUT" > "${INPUT}.out.new"
|
||||||
killall "$3"
|
killall "$3"
|
||||||
|
|
||||||
pre=$(shasum < "${INPUT}.out")
|
pre=$(sha256sum < "${INPUT}.out")
|
||||||
post=$(shasum < "${INPUT}.out.new")
|
post=$(sha256sum < "${INPUT}.out.new")
|
||||||
|
|
||||||
if [[ "$pre" != "$post" ]]; then
|
if [[ "$pre" != "$post" ]]; then
|
||||||
echo "You broke the tutorial"
|
echo "You broke the tutorial"
|
||||||
|
@ -3,7 +3,7 @@ package version
|
|||||||
// NOTE: we should probably be versioning the ABCI and the abci-cli separately
|
// NOTE: we should probably be versioning the ABCI and the abci-cli separately
|
||||||
|
|
||||||
const Maj = "0"
|
const Maj = "0"
|
||||||
const Min = "8"
|
const Min = "9"
|
||||||
const Fix = "0"
|
const Fix = "0"
|
||||||
|
|
||||||
const Version = "0.8.0"
|
const Version = "0.9.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user