mirror of
https://github.com/fluencelabs/tendermint
synced 2025-05-12 06:47:12 +00:00
Merge pull request #218 from tendermint/release/v0.10.1
Release/v0.10.1
This commit is contained in:
commit
f3f9f792a5
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,5 +1,18 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.10.1 (March 22, 2018)
|
||||||
|
|
||||||
|
FEATURES:
|
||||||
|
|
||||||
|
- [types] ResponseCheckTx and ResponseDeliverTx are now the same.
|
||||||
|
- [example] `dummy` is duplicated as `kvstore`.
|
||||||
|
|
||||||
|
IMPROVEMENTS:
|
||||||
|
|
||||||
|
- glide -> Godep
|
||||||
|
- remove pkg/errors
|
||||||
|
- improve specification.rst
|
||||||
|
|
||||||
## 0.10.0 (February 20, 2018)
|
## 0.10.0 (February 20, 2018)
|
||||||
|
|
||||||
BREAKING CHANGES:
|
BREAKING CHANGES:
|
||||||
|
@ -6,16 +6,18 @@ WORKDIR /go/src/github.com/tendermint/abci
|
|||||||
COPY Makefile /go/src/github.com/tendermint/abci/
|
COPY Makefile /go/src/github.com/tendermint/abci/
|
||||||
|
|
||||||
# see make protoc for details on ldconfig
|
# see make protoc for details on ldconfig
|
||||||
RUN make install_protoc && ldconfig
|
RUN make get_protoc && ldconfig
|
||||||
|
|
||||||
# killall is used in tests
|
# killall is used in tests
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
psmisc \
|
psmisc \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY glide.yaml /go/src/github.com/tendermint/abci/
|
COPY Gopkg.toml /go/src/github.com/tendermint/abci/
|
||||||
COPY glide.lock /go/src/github.com/tendermint/abci/
|
COPY Gopkg.lock /go/src/github.com/tendermint/abci/
|
||||||
|
RUN make get_tools
|
||||||
|
|
||||||
RUN make get_vendor_deps
|
# see https://github.com/golang/dep/issues/1312
|
||||||
|
RUN dep ensure -vendor-only
|
||||||
|
|
||||||
COPY . /go/src/github.com/tendermint/abci
|
COPY . /go/src/github.com/tendermint/abci
|
||||||
|
213
Gopkg.lock
generated
Normal file
213
Gopkg.lock
generated
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||||
|
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/davecgh/go-spew"
|
||||||
|
packages = ["spew"]
|
||||||
|
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||||
|
version = "v1.1.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/go-kit/kit"
|
||||||
|
packages = [
|
||||||
|
"log",
|
||||||
|
"log/level",
|
||||||
|
"log/term"
|
||||||
|
]
|
||||||
|
revision = "4dc7be5d2d12881735283bcab7352178e190fc71"
|
||||||
|
version = "v0.6.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/go-logfmt/logfmt"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5"
|
||||||
|
version = "v0.3.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/go-stack/stack"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "259ab82a6cad3992b4e21ff5cac294ccb06474bc"
|
||||||
|
version = "v1.7.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/gogo/protobuf"
|
||||||
|
packages = [
|
||||||
|
"gogoproto",
|
||||||
|
"jsonpb",
|
||||||
|
"proto",
|
||||||
|
"protoc-gen-gogo/descriptor",
|
||||||
|
"sortkeys",
|
||||||
|
"types"
|
||||||
|
]
|
||||||
|
revision = "1adfc126b41513cc696b209667c8656ea7aac67c"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/golang/protobuf"
|
||||||
|
packages = [
|
||||||
|
"proto",
|
||||||
|
"ptypes",
|
||||||
|
"ptypes/any",
|
||||||
|
"ptypes/duration",
|
||||||
|
"ptypes/timestamp"
|
||||||
|
]
|
||||||
|
revision = "925541529c1fa6821df4e44ce2723319eb2be768"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/golang/snappy"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "553a641470496b2327abcac10b36396bd98e45c9"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/inconshreveable/mousetrap"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
|
||||||
|
version = "v1.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/jmhodges/levigo"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/kr/logfmt"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/pkg/errors"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||||
|
version = "v0.8.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/pmezard/go-difflib"
|
||||||
|
packages = ["difflib"]
|
||||||
|
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/spf13/cobra"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b"
|
||||||
|
version = "v0.0.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/spf13/pflag"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/stretchr/testify"
|
||||||
|
packages = [
|
||||||
|
"assert",
|
||||||
|
"require"
|
||||||
|
]
|
||||||
|
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
|
||||||
|
version = "v1.2.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/syndtr/goleveldb"
|
||||||
|
packages = [
|
||||||
|
"leveldb",
|
||||||
|
"leveldb/cache",
|
||||||
|
"leveldb/comparer",
|
||||||
|
"leveldb/errors",
|
||||||
|
"leveldb/filter",
|
||||||
|
"leveldb/iterator",
|
||||||
|
"leveldb/journal",
|
||||||
|
"leveldb/memdb",
|
||||||
|
"leveldb/opt",
|
||||||
|
"leveldb/storage",
|
||||||
|
"leveldb/table",
|
||||||
|
"leveldb/util"
|
||||||
|
]
|
||||||
|
revision = "169b1b37be738edb2813dab48c97a549bcf99bb5"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/tendermint/tmlibs"
|
||||||
|
packages = [
|
||||||
|
"common",
|
||||||
|
"db",
|
||||||
|
"log"
|
||||||
|
]
|
||||||
|
revision = "24da7009c3d8c019b40ba4287495749e3160caca"
|
||||||
|
version = "v0.7.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/net"
|
||||||
|
packages = [
|
||||||
|
"context",
|
||||||
|
"http2",
|
||||||
|
"http2/hpack",
|
||||||
|
"idna",
|
||||||
|
"internal/timeseries",
|
||||||
|
"lex/httplex",
|
||||||
|
"trace"
|
||||||
|
]
|
||||||
|
revision = "6078986fec03a1dcc236c34816c71b0e05018fda"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "golang.org/x/text"
|
||||||
|
packages = [
|
||||||
|
"collate",
|
||||||
|
"collate/build",
|
||||||
|
"internal/colltab",
|
||||||
|
"internal/gen",
|
||||||
|
"internal/tag",
|
||||||
|
"internal/triegen",
|
||||||
|
"internal/ucd",
|
||||||
|
"language",
|
||||||
|
"secure/bidirule",
|
||||||
|
"transform",
|
||||||
|
"unicode/bidi",
|
||||||
|
"unicode/cldr",
|
||||||
|
"unicode/norm",
|
||||||
|
"unicode/rangetable"
|
||||||
|
]
|
||||||
|
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||||
|
version = "v0.3.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "google.golang.org/genproto"
|
||||||
|
packages = ["googleapis/rpc/status"]
|
||||||
|
revision = "f8c8703595236ae70fdf8789ecb656ea0bcdcf46"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "google.golang.org/grpc"
|
||||||
|
packages = [
|
||||||
|
".",
|
||||||
|
"balancer",
|
||||||
|
"codes",
|
||||||
|
"connectivity",
|
||||||
|
"credentials",
|
||||||
|
"grpclb/grpc_lb_v1/messages",
|
||||||
|
"grpclog",
|
||||||
|
"internal",
|
||||||
|
"keepalive",
|
||||||
|
"metadata",
|
||||||
|
"naming",
|
||||||
|
"peer",
|
||||||
|
"resolver",
|
||||||
|
"stats",
|
||||||
|
"status",
|
||||||
|
"tap",
|
||||||
|
"transport"
|
||||||
|
]
|
||||||
|
revision = "5b3c4e850e90a4cf6a20ebd46c8b32a0a3afcb9e"
|
||||||
|
version = "v1.7.5"
|
||||||
|
|
||||||
|
[solve-meta]
|
||||||
|
analyzer-name = "dep"
|
||||||
|
analyzer-version = 1
|
||||||
|
inputs-digest = "e0c31538af2916be2aed38bae72f9040d93aa9a4b86a1839df7a83545a2442f1"
|
||||||
|
solver-name = "gps-cdcl"
|
||||||
|
solver-version = 1
|
56
Gopkg.toml
Normal file
56
Gopkg.toml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# Gopkg.toml example
|
||||||
|
#
|
||||||
|
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||||
|
# for detailed Gopkg.toml documentation.
|
||||||
|
#
|
||||||
|
# required = ["github.com/user/thing/cmd/thing"]
|
||||||
|
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project"
|
||||||
|
# version = "1.0.0"
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project2"
|
||||||
|
# branch = "dev"
|
||||||
|
# source = "github.com/myfork/project2"
|
||||||
|
#
|
||||||
|
# [[override]]
|
||||||
|
# name = "github.com/x/y"
|
||||||
|
# version = "2.4.0"
|
||||||
|
#
|
||||||
|
# [prune]
|
||||||
|
# non-go = false
|
||||||
|
# go-tests = true
|
||||||
|
# unused-packages = true
|
||||||
|
|
||||||
|
# NOTE if not specified, dep automatically adds `^` to each version,
|
||||||
|
# meaning it will accept up to the next version for the first non-zero
|
||||||
|
# element in the version.
|
||||||
|
#
|
||||||
|
# So `version = "1.3.2"` means `1.3.2 <= version < 2.0.0`.
|
||||||
|
# Use `~` for only minor version bumps.
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/gogo/protobuf"
|
||||||
|
version = "~1.0.0"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/spf13/cobra"
|
||||||
|
version = "~0.0.1"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "github.com/stretchr/testify"
|
||||||
|
version = "~1.2.1"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
version = "~0.7.1"
|
||||||
|
name = "github.com/tendermint/tmlibs"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
name = "google.golang.org/grpc"
|
||||||
|
version = "~1.7.3"
|
||||||
|
|
||||||
|
[prune]
|
||||||
|
go-tests = true
|
||||||
|
unused-packages = true
|
8
Makefile
8
Makefile
@ -1,10 +1,10 @@
|
|||||||
GOTOOLS = \
|
GOTOOLS = \
|
||||||
github.com/mitchellh/gox \
|
github.com/mitchellh/gox \
|
||||||
github.com/Masterminds/glide \
|
github.com/golang/dep/cmd/dep \
|
||||||
gopkg.in/alecthomas/gometalinter.v2 \
|
gopkg.in/alecthomas/gometalinter.v2 \
|
||||||
github.com/gogo/protobuf/protoc-gen-gogo \
|
github.com/gogo/protobuf/protoc-gen-gogo \
|
||||||
github.com/gogo/protobuf/gogoproto
|
github.com/gogo/protobuf/gogoproto
|
||||||
GOTOOLS_CHECK = gox glide gometalinter.v2 protoc protoc-gen-gogo
|
GOTOOLS_CHECK = gox dep gometalinter.v2 protoc protoc-gen-gogo
|
||||||
PACKAGES=$(shell go list ./... | grep -v '/vendor/')
|
PACKAGES=$(shell go list ./... | grep -v '/vendor/')
|
||||||
INCLUDE = -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf
|
INCLUDE = -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf
|
||||||
|
|
||||||
@ -65,8 +65,8 @@ update_tools:
|
|||||||
|
|
||||||
get_vendor_deps:
|
get_vendor_deps:
|
||||||
@rm -rf vendor/
|
@rm -rf vendor/
|
||||||
@echo "--> Running glide install"
|
@echo "--> Running dep ensure"
|
||||||
@glide install
|
@dep ensure
|
||||||
|
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
|
15
README.md
15
README.md
@ -90,7 +90,7 @@ See [the documentation](http://tendermint.readthedocs.io/en/master/) for more de
|
|||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
Check out the variety of example applications in the [example directory](example/).
|
Check out the variety of example applications in the [example directory](example/).
|
||||||
It also contains the code refered to by the `counter` and `dummy` apps; these apps come
|
It also contains the code refered to by the `counter` and `kvstore` apps; these apps come
|
||||||
built into the `abci-cli` binary.
|
built into the `abci-cli` binary.
|
||||||
|
|
||||||
#### Counter
|
#### Counter
|
||||||
@ -125,21 +125,21 @@ func cmdCounter(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
and can be found in [this file](cmd/abci-cli/abci-cli.go).
|
and can be found in [this file](cmd/abci-cli/abci-cli.go).
|
||||||
|
|
||||||
#### Dummy
|
#### kvstore
|
||||||
|
|
||||||
The `abci-cli dummy` application, which illustrates a simple key-value Merkle tree
|
The `abci-cli kvstore` application, which illustrates a simple key-value Merkle tree
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
func cmdDummy(cmd *cobra.Command, args []string) error {
|
func cmdKVStore(cmd *cobra.Command, args []string) error {
|
||||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
||||||
|
|
||||||
// Create the application - in memory or persisted to disk
|
// Create the application - in memory or persisted to disk
|
||||||
var app types.Application
|
var app types.Application
|
||||||
if flagPersist == "" {
|
if flagPersist == "" {
|
||||||
app = dummy.NewDummyApplication()
|
app = kvstore.NewKVStoreApplication()
|
||||||
} else {
|
} else {
|
||||||
app = dummy.NewPersistentDummyApplication(flagPersist)
|
app = kvstore.NewPersistentKVStoreApplication(flagPersist)
|
||||||
app.(*dummy.PersistentDummyApplication).SetLogger(logger.With("module", "dummy"))
|
app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the listener
|
// Start the listener
|
||||||
@ -160,4 +160,3 @@ func cmdDummy(cmd *cobra.Command, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
context "golang.org/x/net/context"
|
context "golang.org/x/net/context"
|
||||||
grpc "google.golang.org/grpc"
|
grpc "google.golang.org/grpc"
|
||||||
|
|
||||||
@ -105,7 +104,7 @@ func (cli *grpcClient) StopForError(err error) {
|
|||||||
func (cli *grpcClient) Error() error {
|
func (cli *grpcClient) Error() error {
|
||||||
cli.mtx.Lock()
|
cli.mtx.Lock()
|
||||||
defer cli.mtx.Unlock()
|
defer cli.mtx.Unlock()
|
||||||
return errors.Wrap(cli.err, "grpc client error")
|
return cli.err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set listener for all responses
|
// Set listener for all responses
|
||||||
|
@ -3,13 +3,13 @@ package abcicli
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"container/list"
|
"container/list"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/tendermint/abci/types"
|
"github.com/tendermint/abci/types"
|
||||||
cmn "github.com/tendermint/tmlibs/common"
|
cmn "github.com/tendermint/tmlibs/common"
|
||||||
)
|
)
|
||||||
@ -111,7 +111,7 @@ func (cli *socketClient) StopForError(err error) {
|
|||||||
func (cli *socketClient) Error() error {
|
func (cli *socketClient) Error() error {
|
||||||
cli.mtx.Lock()
|
cli.mtx.Lock()
|
||||||
defer cli.mtx.Unlock()
|
defer cli.mtx.Unlock()
|
||||||
return errors.Wrap(cli.err, "socket client error")
|
return cli.err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set listener for all responses
|
// Set listener for all responses
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
abcicli "github.com/tendermint/abci/client"
|
abcicli "github.com/tendermint/abci/client"
|
||||||
"github.com/tendermint/abci/example/code"
|
"github.com/tendermint/abci/example/code"
|
||||||
"github.com/tendermint/abci/example/counter"
|
"github.com/tendermint/abci/example/counter"
|
||||||
"github.com/tendermint/abci/example/dummy"
|
"github.com/tendermint/abci/example/kvstore"
|
||||||
"github.com/tendermint/abci/server"
|
"github.com/tendermint/abci/server"
|
||||||
servertest "github.com/tendermint/abci/tests/server"
|
servertest "github.com/tendermint/abci/tests/server"
|
||||||
"github.com/tendermint/abci/types"
|
"github.com/tendermint/abci/types"
|
||||||
@ -47,7 +47,7 @@ var (
|
|||||||
flagAddrC string
|
flagAddrC string
|
||||||
flagSerial bool
|
flagSerial bool
|
||||||
|
|
||||||
// dummy
|
// kvstore
|
||||||
flagAddrD string
|
flagAddrD string
|
||||||
flagPersist string
|
flagPersist string
|
||||||
)
|
)
|
||||||
@ -59,7 +59,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", "dummy": // for the examples apps, don't pre-run
|
case "counter", "kvstore", "dummy": // for the examples apps, don't pre-run
|
||||||
return nil
|
return nil
|
||||||
case "version": // skip running for version command
|
case "version": // skip running for version command
|
||||||
return nil
|
return nil
|
||||||
@ -133,6 +133,12 @@ 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 addKVStoreFlags() {
|
||||||
|
kvstoreCmd.PersistentFlags().StringVarP(&flagAddrD, "addr", "", "tcp://0.0.0.0:46658", "listen address")
|
||||||
|
kvstoreCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "directory to use for a database")
|
||||||
|
}
|
||||||
|
|
||||||
func addCommands() {
|
func addCommands() {
|
||||||
RootCmd.AddCommand(batchCmd)
|
RootCmd.AddCommand(batchCmd)
|
||||||
RootCmd.AddCommand(consoleCmd)
|
RootCmd.AddCommand(consoleCmd)
|
||||||
@ -150,8 +156,12 @@ func addCommands() {
|
|||||||
// examples
|
// examples
|
||||||
addCounterFlags()
|
addCounterFlags()
|
||||||
RootCmd.AddCommand(counterCmd)
|
RootCmd.AddCommand(counterCmd)
|
||||||
|
// deprecated, left for backwards compatibility
|
||||||
addDummyFlags()
|
addDummyFlags()
|
||||||
RootCmd.AddCommand(dummyCmd)
|
RootCmd.AddCommand(dummyCmd)
|
||||||
|
// replaces dummy, see issue #196
|
||||||
|
addKVStoreFlags()
|
||||||
|
RootCmd.AddCommand(kvstoreCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
var batchCmd = &cobra.Command{
|
var batchCmd = &cobra.Command{
|
||||||
@ -285,13 +295,25 @@ var counterCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deprecated, left for backwards compatibility
|
||||||
var dummyCmd = &cobra.Command{
|
var dummyCmd = &cobra.Command{
|
||||||
Use: "dummy",
|
Use: "dummy",
|
||||||
|
Deprecated: "use: [abci-cli kvstore] instead",
|
||||||
|
Short: "ABCI demo example",
|
||||||
|
Long: "ABCI demo example",
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return cmdKVStore(cmd, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var kvstoreCmd = &cobra.Command{
|
||||||
|
Use: "kvstore",
|
||||||
Short: "ABCI demo example",
|
Short: "ABCI demo example",
|
||||||
Long: "ABCI demo example",
|
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 cmdKVStore(cmd, args)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -654,16 +676,16 @@ func cmdCounter(cmd *cobra.Command, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdDummy(cmd *cobra.Command, args []string) error {
|
func cmdKVStore(cmd *cobra.Command, args []string) error {
|
||||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
||||||
|
|
||||||
// Create the application - in memory or persisted to disk
|
// Create the application - in memory or persisted to disk
|
||||||
var app types.Application
|
var app types.Application
|
||||||
if flagPersist == "" {
|
if flagPersist == "" {
|
||||||
app = dummy.NewDummyApplication()
|
app = kvstore.NewKVStoreApplication()
|
||||||
} else {
|
} else {
|
||||||
app = dummy.NewPersistentDummyApplication(flagPersist)
|
app = kvstore.NewPersistentKVStoreApplication(flagPersist)
|
||||||
app.(*dummy.PersistentDummyApplication).SetLogger(logger.With("module", "dummy"))
|
app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the listener
|
// Start the listener
|
||||||
|
@ -1,31 +1,4 @@
|
|||||||
# Dummy
|
# Dummy
|
||||||
|
|
||||||
There are two app's here: the DummyApplication and the PersistentDummyApplication.
|
DEPRECATED. See KVStore
|
||||||
|
|
||||||
## DummyApplication
|
|
||||||
|
|
||||||
The DummyApplication is a simple merkle key-value store.
|
|
||||||
Transactions of the form `key=value` are stored as key-value pairs in the tree.
|
|
||||||
Transactions without an `=` sign set the value to the key.
|
|
||||||
The app has no replay protection (other than what the mempool provides).
|
|
||||||
|
|
||||||
## PersistentDummyApplication
|
|
||||||
|
|
||||||
The PersistentDummyApplication wraps the DummyApplication
|
|
||||||
and provides two additional features:
|
|
||||||
|
|
||||||
1) persistence of state across app restarts (using Tendermint's ABCI-Handshake mechanism)
|
|
||||||
2) validator set changes
|
|
||||||
|
|
||||||
The state is persisted in leveldb along with the last block committed,
|
|
||||||
and the Handshake allows any necessary blocks to be replayed.
|
|
||||||
Validator set changes are effected using the following transaction format:
|
|
||||||
|
|
||||||
```
|
|
||||||
val:pubkey1/power1,addr2/power2,addr3/power3"
|
|
||||||
```
|
|
||||||
|
|
||||||
where `power1` is the new voting power for the validator with `pubkey1` (possibly a new one).
|
|
||||||
There is no sybil protection against new validators joining.
|
|
||||||
Validators can be removed by setting their power to `0`.
|
|
||||||
|
|
||||||
|
@ -16,14 +16,14 @@ import (
|
|||||||
|
|
||||||
abcicli "github.com/tendermint/abci/client"
|
abcicli "github.com/tendermint/abci/client"
|
||||||
"github.com/tendermint/abci/example/code"
|
"github.com/tendermint/abci/example/code"
|
||||||
"github.com/tendermint/abci/example/dummy"
|
"github.com/tendermint/abci/example/kvstore"
|
||||||
abciserver "github.com/tendermint/abci/server"
|
abciserver "github.com/tendermint/abci/server"
|
||||||
"github.com/tendermint/abci/types"
|
"github.com/tendermint/abci/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDummy(t *testing.T) {
|
func TestKVStore(t *testing.T) {
|
||||||
fmt.Println("### Testing Dummy")
|
fmt.Println("### Testing KVStore")
|
||||||
testStream(t, dummy.NewDummyApplication())
|
testStream(t, kvstore.NewKVStoreApplication())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBaseApp(t *testing.T) {
|
func TestBaseApp(t *testing.T) {
|
||||||
|
31
example/kvstore/README.md
Normal file
31
example/kvstore/README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# KVStore
|
||||||
|
|
||||||
|
There are two app's here: the KVStoreApplication and the PersistentKVStoreApplication.
|
||||||
|
|
||||||
|
## KVStoreApplication
|
||||||
|
|
||||||
|
The KVStoreApplication is a simple merkle key-value store.
|
||||||
|
Transactions of the form `key=value` are stored as key-value pairs in the tree.
|
||||||
|
Transactions without an `=` sign set the value to the key.
|
||||||
|
The app has no replay protection (other than what the mempool provides).
|
||||||
|
|
||||||
|
## PersistentKVStoreApplication
|
||||||
|
|
||||||
|
The PersistentKVStoreApplication wraps the KVStoreApplication
|
||||||
|
and provides two additional features:
|
||||||
|
|
||||||
|
1) persistence of state across app restarts (using Tendermint's ABCI-Handshake mechanism)
|
||||||
|
2) validator set changes
|
||||||
|
|
||||||
|
The state is persisted in leveldb along with the last block committed,
|
||||||
|
and the Handshake allows any necessary blocks to be replayed.
|
||||||
|
Validator set changes are effected using the following transaction format:
|
||||||
|
|
||||||
|
```
|
||||||
|
val:pubkey1/power1,addr2/power2,addr3/power3"
|
||||||
|
```
|
||||||
|
|
||||||
|
where `power1` is the new voting power for the validator with `pubkey1` (possibly a new one).
|
||||||
|
There is no sybil protection against new validators joining.
|
||||||
|
Validators can be removed by setting their power to `0`.
|
||||||
|
|
36
example/kvstore/helpers.go
Normal file
36
example/kvstore/helpers.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package kvstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tendermint/abci/types"
|
||||||
|
cmn "github.com/tendermint/tmlibs/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RandVal creates one random validator, with a key derived
|
||||||
|
// from the input value
|
||||||
|
func RandVal(i int) types.Validator {
|
||||||
|
pubkey := cmn.RandBytes(33)
|
||||||
|
power := cmn.RandUint16() + 1
|
||||||
|
return types.Validator{pubkey, int64(power)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandVals returns a list of cnt validators for initializing
|
||||||
|
// the application. Note that the keys are deterministically
|
||||||
|
// derived from the index in the array, while the power is
|
||||||
|
// random (Change this if not desired)
|
||||||
|
func RandVals(cnt int) []types.Validator {
|
||||||
|
res := make([]types.Validator, cnt)
|
||||||
|
for i := 0; i < cnt; i++ {
|
||||||
|
res[i] = RandVal(i)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitKVStore initializes the kvstore app with some data,
|
||||||
|
// which allows tests to pass and is fine as long as you
|
||||||
|
// don't make any tx that modify the validator state
|
||||||
|
func InitKVStore(app *PersistentKVStoreApplication) {
|
||||||
|
app.InitChain(types.RequestInitChain{
|
||||||
|
Validators: RandVals(1),
|
||||||
|
AppStateBytes: []byte("[]"),
|
||||||
|
})
|
||||||
|
}
|
126
example/kvstore/kvstore.go
Normal file
126
example/kvstore/kvstore.go
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package kvstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/tendermint/abci/example/code"
|
||||||
|
"github.com/tendermint/abci/types"
|
||||||
|
cmn "github.com/tendermint/tmlibs/common"
|
||||||
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
stateKey = []byte("stateKey")
|
||||||
|
kvPairPrefixKey = []byte("kvPairKey:")
|
||||||
|
)
|
||||||
|
|
||||||
|
type State struct {
|
||||||
|
db dbm.DB
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
Height int64 `json:"height"`
|
||||||
|
AppHash []byte `json:"app_hash"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadState(db dbm.DB) State {
|
||||||
|
stateBytes := db.Get(stateKey)
|
||||||
|
var state State
|
||||||
|
if len(stateBytes) != 0 {
|
||||||
|
err := json.Unmarshal(stateBytes, &state)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
state.db = db
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveState(state State) {
|
||||||
|
stateBytes, err := json.Marshal(state)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
state.db.Set(stateKey, stateBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prefixKey(key []byte) []byte {
|
||||||
|
return append(kvPairPrefixKey, key...)
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------
|
||||||
|
|
||||||
|
var _ types.Application = (*KVStoreApplication)(nil)
|
||||||
|
|
||||||
|
type KVStoreApplication struct {
|
||||||
|
types.BaseApplication
|
||||||
|
|
||||||
|
state State
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewKVStoreApplication() *KVStoreApplication {
|
||||||
|
state := loadState(dbm.NewMemDB())
|
||||||
|
return &KVStoreApplication{state: state}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) {
|
||||||
|
return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tx is either "key=value" or just arbitrary bytes
|
||||||
|
func (app *KVStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx {
|
||||||
|
var key, value []byte
|
||||||
|
parts := bytes.Split(tx, []byte("="))
|
||||||
|
if len(parts) == 2 {
|
||||||
|
key, value = parts[0], parts[1]
|
||||||
|
} else {
|
||||||
|
key, value = tx, tx
|
||||||
|
}
|
||||||
|
app.state.db.Set(prefixKey(key), value)
|
||||||
|
app.state.Size += 1
|
||||||
|
|
||||||
|
tags := []cmn.KVPair{
|
||||||
|
{[]byte("app.creator"), []byte("jae")},
|
||||||
|
{[]byte("app.key"), key},
|
||||||
|
}
|
||||||
|
return types.ResponseDeliverTx{Code: code.CodeTypeOK, Tags: tags}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *KVStoreApplication) CheckTx(tx []byte) types.ResponseCheckTx {
|
||||||
|
return types.ResponseCheckTx{Code: code.CodeTypeOK}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *KVStoreApplication) Commit() types.ResponseCommit {
|
||||||
|
// Using a memdb - just return the big endian size of the db
|
||||||
|
appHash := make([]byte, 8)
|
||||||
|
binary.PutVarint(appHash, app.state.Size)
|
||||||
|
app.state.AppHash = appHash
|
||||||
|
app.state.Height += 1
|
||||||
|
saveState(app.state)
|
||||||
|
return types.ResponseCommit{Data: appHash}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *KVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
|
||||||
|
if reqQuery.Prove {
|
||||||
|
value := app.state.db.Get(prefixKey(reqQuery.Data))
|
||||||
|
resQuery.Index = -1 // TODO make Proof return index
|
||||||
|
resQuery.Key = reqQuery.Data
|
||||||
|
resQuery.Value = value
|
||||||
|
if value != nil {
|
||||||
|
resQuery.Log = "exists"
|
||||||
|
} else {
|
||||||
|
resQuery.Log = "does not exist"
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
value := app.state.db.Get(prefixKey(reqQuery.Data))
|
||||||
|
resQuery.Value = value
|
||||||
|
if value != nil {
|
||||||
|
resQuery.Log = "exists"
|
||||||
|
} else {
|
||||||
|
resQuery.Log = "does not exist"
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
310
example/kvstore/kvstore_test.go
Normal file
310
example/kvstore/kvstore_test.go
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
package kvstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
cmn "github.com/tendermint/tmlibs/common"
|
||||||
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
|
||||||
|
abcicli "github.com/tendermint/abci/client"
|
||||||
|
"github.com/tendermint/abci/example/code"
|
||||||
|
abciserver "github.com/tendermint/abci/server"
|
||||||
|
"github.com/tendermint/abci/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testKVStore(t *testing.T, app types.Application, tx []byte, key, value string) {
|
||||||
|
ar := app.DeliverTx(tx)
|
||||||
|
require.False(t, ar.IsErr(), ar)
|
||||||
|
// repeating tx doesn't raise error
|
||||||
|
ar = app.DeliverTx(tx)
|
||||||
|
require.False(t, ar.IsErr(), ar)
|
||||||
|
|
||||||
|
// make sure query is fine
|
||||||
|
resQuery := app.Query(types.RequestQuery{
|
||||||
|
Path: "/store",
|
||||||
|
Data: []byte(key),
|
||||||
|
})
|
||||||
|
require.Equal(t, code.CodeTypeOK, resQuery.Code)
|
||||||
|
require.Equal(t, value, string(resQuery.Value))
|
||||||
|
|
||||||
|
// make sure proof is fine
|
||||||
|
resQuery = app.Query(types.RequestQuery{
|
||||||
|
Path: "/store",
|
||||||
|
Data: []byte(key),
|
||||||
|
Prove: true,
|
||||||
|
})
|
||||||
|
require.EqualValues(t, code.CodeTypeOK, resQuery.Code)
|
||||||
|
require.Equal(t, value, string(resQuery.Value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKVStoreKV(t *testing.T) {
|
||||||
|
kvstore := NewKVStoreApplication()
|
||||||
|
key := "abc"
|
||||||
|
value := key
|
||||||
|
tx := []byte(key)
|
||||||
|
testKVStore(t, kvstore, tx, key, value)
|
||||||
|
|
||||||
|
value = "def"
|
||||||
|
tx = []byte(key + "=" + value)
|
||||||
|
testKVStore(t, kvstore, tx, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPersistentKVStoreKV(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test") // TODO
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
kvstore := NewPersistentKVStoreApplication(dir)
|
||||||
|
key := "abc"
|
||||||
|
value := key
|
||||||
|
tx := []byte(key)
|
||||||
|
testKVStore(t, kvstore, tx, key, value)
|
||||||
|
|
||||||
|
value = "def"
|
||||||
|
tx = []byte(key + "=" + value)
|
||||||
|
testKVStore(t, kvstore, tx, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPersistentKVStoreInfo(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test") // TODO
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
kvstore := NewPersistentKVStoreApplication(dir)
|
||||||
|
InitKVStore(kvstore)
|
||||||
|
height := int64(0)
|
||||||
|
|
||||||
|
resInfo := kvstore.Info(types.RequestInfo{})
|
||||||
|
if resInfo.LastBlockHeight != height {
|
||||||
|
t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// make and apply block
|
||||||
|
height = int64(1)
|
||||||
|
hash := []byte("foo")
|
||||||
|
header := types.Header{
|
||||||
|
Height: int64(height),
|
||||||
|
}
|
||||||
|
kvstore.BeginBlock(types.RequestBeginBlock{hash, header, nil, nil})
|
||||||
|
kvstore.EndBlock(types.RequestEndBlock{header.Height})
|
||||||
|
kvstore.Commit()
|
||||||
|
|
||||||
|
resInfo = kvstore.Info(types.RequestInfo{})
|
||||||
|
if resInfo.LastBlockHeight != height {
|
||||||
|
t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a validator, remove a validator, update a validator
|
||||||
|
func TestValUpdates(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test") // TODO
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
kvstore := NewPersistentKVStoreApplication(dir)
|
||||||
|
|
||||||
|
// init with some validators
|
||||||
|
total := 10
|
||||||
|
nInit := 5
|
||||||
|
vals := RandVals(total)
|
||||||
|
// iniitalize with the first nInit
|
||||||
|
kvstore.InitChain(types.RequestInitChain{
|
||||||
|
Validators: vals[:nInit],
|
||||||
|
})
|
||||||
|
|
||||||
|
vals1, vals2 := vals[:nInit], kvstore.Validators()
|
||||||
|
valsEqual(t, vals1, vals2)
|
||||||
|
|
||||||
|
var v1, v2, v3 types.Validator
|
||||||
|
|
||||||
|
// add some validators
|
||||||
|
v1, v2 = vals[nInit], vals[nInit+1]
|
||||||
|
diff := []types.Validator{v1, v2}
|
||||||
|
tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power)
|
||||||
|
tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power)
|
||||||
|
|
||||||
|
makeApplyBlock(t, kvstore, 1, diff, tx1, tx2)
|
||||||
|
|
||||||
|
vals1, vals2 = vals[:nInit+2], kvstore.Validators()
|
||||||
|
valsEqual(t, vals1, vals2)
|
||||||
|
|
||||||
|
// remove some validators
|
||||||
|
v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit]
|
||||||
|
v1.Power = 0
|
||||||
|
v2.Power = 0
|
||||||
|
v3.Power = 0
|
||||||
|
diff = []types.Validator{v1, v2, v3}
|
||||||
|
tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
|
||||||
|
tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power)
|
||||||
|
tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power)
|
||||||
|
|
||||||
|
makeApplyBlock(t, kvstore, 2, diff, tx1, tx2, tx3)
|
||||||
|
|
||||||
|
vals1 = append(vals[:nInit-2], vals[nInit+1])
|
||||||
|
vals2 = kvstore.Validators()
|
||||||
|
valsEqual(t, vals1, vals2)
|
||||||
|
|
||||||
|
// update some validators
|
||||||
|
v1 = vals[0]
|
||||||
|
if v1.Power == 5 {
|
||||||
|
v1.Power = 6
|
||||||
|
} else {
|
||||||
|
v1.Power = 5
|
||||||
|
}
|
||||||
|
diff = []types.Validator{v1}
|
||||||
|
tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
|
||||||
|
|
||||||
|
makeApplyBlock(t, kvstore, 3, diff, tx1)
|
||||||
|
|
||||||
|
vals1 = append([]types.Validator{v1}, vals1[1:]...)
|
||||||
|
vals2 = kvstore.Validators()
|
||||||
|
valsEqual(t, vals1, vals2)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeApplyBlock(t *testing.T, kvstore types.Application, heightInt int, diff []types.Validator, txs ...[]byte) {
|
||||||
|
// make and apply block
|
||||||
|
height := int64(heightInt)
|
||||||
|
hash := []byte("foo")
|
||||||
|
header := types.Header{
|
||||||
|
Height: height,
|
||||||
|
}
|
||||||
|
|
||||||
|
kvstore.BeginBlock(types.RequestBeginBlock{hash, header, nil, nil})
|
||||||
|
for _, tx := range txs {
|
||||||
|
if r := kvstore.DeliverTx(tx); r.IsErr() {
|
||||||
|
t.Fatal(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resEndBlock := kvstore.EndBlock(types.RequestEndBlock{header.Height})
|
||||||
|
kvstore.Commit()
|
||||||
|
|
||||||
|
valsEqual(t, diff, resEndBlock.ValidatorUpdates)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// order doesn't matter
|
||||||
|
func valsEqual(t *testing.T, vals1, vals2 []types.Validator) {
|
||||||
|
if len(vals1) != len(vals2) {
|
||||||
|
t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1))
|
||||||
|
}
|
||||||
|
sort.Sort(types.Validators(vals1))
|
||||||
|
sort.Sort(types.Validators(vals2))
|
||||||
|
for i, v1 := range vals1 {
|
||||||
|
v2 := vals2[i]
|
||||||
|
if !bytes.Equal(v1.PubKey, v2.PubKey) ||
|
||||||
|
v1.Power != v2.Power {
|
||||||
|
t.Fatalf("vals dont match at index %d. got %X/%d , expected %X/%d", i, v2.PubKey, v2.Power, v1.PubKey, v1.Power)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeSocketClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) {
|
||||||
|
// Start the listener
|
||||||
|
socket := cmn.Fmt("unix://%s.sock", name)
|
||||||
|
logger := log.TestingLogger()
|
||||||
|
|
||||||
|
server := abciserver.NewSocketServer(socket, app)
|
||||||
|
server.SetLogger(logger.With("module", "abci-server"))
|
||||||
|
if err := server.Start(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to the socket
|
||||||
|
client := abcicli.NewSocketClient(socket, false)
|
||||||
|
client.SetLogger(logger.With("module", "abci-client"))
|
||||||
|
if err := client.Start(); err != nil {
|
||||||
|
server.Stop()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return client, server, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) {
|
||||||
|
// Start the listener
|
||||||
|
socket := cmn.Fmt("unix://%s.sock", name)
|
||||||
|
logger := log.TestingLogger()
|
||||||
|
|
||||||
|
gapp := types.NewGRPCApplication(app)
|
||||||
|
server := abciserver.NewGRPCServer(socket, gapp)
|
||||||
|
server.SetLogger(logger.With("module", "abci-server"))
|
||||||
|
if err := server.Start(); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := abcicli.NewGRPCClient(socket, true)
|
||||||
|
client.SetLogger(logger.With("module", "abci-client"))
|
||||||
|
if err := client.Start(); err != nil {
|
||||||
|
server.Stop()
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return client, server, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientServer(t *testing.T) {
|
||||||
|
// set up socket app
|
||||||
|
kvstore := NewKVStoreApplication()
|
||||||
|
client, server, err := makeSocketClientServer(kvstore, "kvstore-socket")
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Stop()
|
||||||
|
|
||||||
|
runClientTests(t, client)
|
||||||
|
|
||||||
|
// set up grpc app
|
||||||
|
kvstore = NewKVStoreApplication()
|
||||||
|
gclient, gserver, err := makeGRPCClientServer(kvstore, "kvstore-grpc")
|
||||||
|
require.Nil(t, err)
|
||||||
|
defer gserver.Stop()
|
||||||
|
defer gclient.Stop()
|
||||||
|
|
||||||
|
runClientTests(t, gclient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runClientTests(t *testing.T, client abcicli.Client) {
|
||||||
|
// run some tests....
|
||||||
|
key := "abc"
|
||||||
|
value := key
|
||||||
|
tx := []byte(key)
|
||||||
|
testClient(t, client, tx, key, value)
|
||||||
|
|
||||||
|
value = "def"
|
||||||
|
tx = []byte(key + "=" + value)
|
||||||
|
testClient(t, client, tx, key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) {
|
||||||
|
ar, err := app.DeliverTxSync(tx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, ar.IsErr(), ar)
|
||||||
|
// repeating tx doesn't raise error
|
||||||
|
ar, err = app.DeliverTxSync(tx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, ar.IsErr(), ar)
|
||||||
|
|
||||||
|
// make sure query is fine
|
||||||
|
resQuery, err := app.QuerySync(types.RequestQuery{
|
||||||
|
Path: "/store",
|
||||||
|
Data: []byte(key),
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, code.CodeTypeOK, resQuery.Code)
|
||||||
|
require.Equal(t, value, string(resQuery.Value))
|
||||||
|
|
||||||
|
// make sure proof is fine
|
||||||
|
resQuery, err = app.QuerySync(types.RequestQuery{
|
||||||
|
Path: "/store",
|
||||||
|
Data: []byte(key),
|
||||||
|
Prove: true,
|
||||||
|
})
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, code.CodeTypeOK, resQuery.Code)
|
||||||
|
require.Equal(t, value, string(resQuery.Value))
|
||||||
|
}
|
205
example/kvstore/persistent_kvstore.go
Normal file
205
example/kvstore/persistent_kvstore.go
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
package kvstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tendermint/abci/example/code"
|
||||||
|
"github.com/tendermint/abci/types"
|
||||||
|
cmn "github.com/tendermint/tmlibs/common"
|
||||||
|
dbm "github.com/tendermint/tmlibs/db"
|
||||||
|
"github.com/tendermint/tmlibs/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ValidatorSetChangePrefix string = "val:"
|
||||||
|
)
|
||||||
|
|
||||||
|
//-----------------------------------------
|
||||||
|
|
||||||
|
var _ types.Application = (*PersistentKVStoreApplication)(nil)
|
||||||
|
|
||||||
|
type PersistentKVStoreApplication struct {
|
||||||
|
app *KVStoreApplication
|
||||||
|
|
||||||
|
// validator set
|
||||||
|
ValUpdates []types.Validator
|
||||||
|
|
||||||
|
logger log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPersistentKVStoreApplication(dbDir string) *PersistentKVStoreApplication {
|
||||||
|
name := "kvstore"
|
||||||
|
db, err := dbm.NewGoLevelDB(name, dbDir)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
state := loadState(db)
|
||||||
|
|
||||||
|
return &PersistentKVStoreApplication{
|
||||||
|
app: &KVStoreApplication{state: state},
|
||||||
|
logger: log.NewNopLogger(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *PersistentKVStoreApplication) SetLogger(l log.Logger) {
|
||||||
|
app.logger = l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *PersistentKVStoreApplication) Info(req types.RequestInfo) types.ResponseInfo {
|
||||||
|
res := app.app.Info(req)
|
||||||
|
res.LastBlockHeight = app.app.state.Height
|
||||||
|
res.LastBlockAppHash = app.app.state.AppHash
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *PersistentKVStoreApplication) SetOption(req types.RequestSetOption) types.ResponseSetOption {
|
||||||
|
return app.app.SetOption(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tx is either "val:pubkey/power" or "key=value" or just arbitrary bytes
|
||||||
|
func (app *PersistentKVStoreApplication) DeliverTx(tx []byte) types.ResponseDeliverTx {
|
||||||
|
// if it starts with "val:", update the validator set
|
||||||
|
// format is "val:pubkey/power"
|
||||||
|
if isValidatorTx(tx) {
|
||||||
|
// update validators in the merkle tree
|
||||||
|
// and in app.ValUpdates
|
||||||
|
return app.execValidatorTx(tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, update the key-value store
|
||||||
|
return app.app.DeliverTx(tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *PersistentKVStoreApplication) CheckTx(tx []byte) types.ResponseCheckTx {
|
||||||
|
return app.app.CheckTx(tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit will panic if InitChain was not called
|
||||||
|
func (app *PersistentKVStoreApplication) Commit() types.ResponseCommit {
|
||||||
|
return app.app.Commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (app *PersistentKVStoreApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery {
|
||||||
|
return app.app.Query(reqQuery)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the validators in the merkle tree
|
||||||
|
func (app *PersistentKVStoreApplication) InitChain(req types.RequestInitChain) types.ResponseInitChain {
|
||||||
|
for _, v := range req.Validators {
|
||||||
|
r := app.updateValidator(v)
|
||||||
|
if r.IsErr() {
|
||||||
|
app.logger.Error("Error updating validators", "r", r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return types.ResponseInitChain{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track the block hash and header information
|
||||||
|
func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
|
||||||
|
// reset valset changes
|
||||||
|
app.ValUpdates = make([]types.Validator, 0)
|
||||||
|
return types.ResponseBeginBlock{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the validator set
|
||||||
|
func (app *PersistentKVStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock {
|
||||||
|
return types.ResponseEndBlock{ValidatorUpdates: app.ValUpdates}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------
|
||||||
|
// update validators
|
||||||
|
|
||||||
|
func (app *PersistentKVStoreApplication) Validators() (validators []types.Validator) {
|
||||||
|
itr := app.app.state.db.Iterator(nil, nil)
|
||||||
|
for ; itr.Valid(); itr.Next() {
|
||||||
|
if isValidatorTx(itr.Key()) {
|
||||||
|
validator := new(types.Validator)
|
||||||
|
err := types.ReadMessage(bytes.NewBuffer(itr.Value()), validator)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
validators = append(validators, *validator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeValSetChangeTx(pubkey []byte, power int64) []byte {
|
||||||
|
return []byte(cmn.Fmt("val:%X/%d", pubkey, power))
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidatorTx(tx []byte) bool {
|
||||||
|
return strings.HasPrefix(string(tx), ValidatorSetChangePrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// format is "val:pubkey1/power1,addr2/power2,addr3/power3"tx
|
||||||
|
func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) types.ResponseDeliverTx {
|
||||||
|
tx = tx[len(ValidatorSetChangePrefix):]
|
||||||
|
|
||||||
|
//get the pubkey and power
|
||||||
|
pubKeyAndPower := strings.Split(string(tx), "/")
|
||||||
|
if len(pubKeyAndPower) != 2 {
|
||||||
|
return types.ResponseDeliverTx{
|
||||||
|
Code: code.CodeTypeEncodingError,
|
||||||
|
Log: fmt.Sprintf("Expected 'pubkey/power'. Got %v", pubKeyAndPower)}
|
||||||
|
}
|
||||||
|
pubkeyS, powerS := pubKeyAndPower[0], pubKeyAndPower[1]
|
||||||
|
|
||||||
|
// decode the pubkey, ensuring its go-crypto encoded
|
||||||
|
pubkey, err := hex.DecodeString(pubkeyS)
|
||||||
|
if err != nil {
|
||||||
|
return types.ResponseDeliverTx{
|
||||||
|
Code: code.CodeTypeEncodingError,
|
||||||
|
Log: fmt.Sprintf("Pubkey (%s) is invalid hex", pubkeyS)}
|
||||||
|
}
|
||||||
|
/*_, err = crypto.PubKeyFromBytes(pubkey)
|
||||||
|
if err != nil {
|
||||||
|
return types.ResponseDeliverTx{
|
||||||
|
Code: code.CodeTypeEncodingError,
|
||||||
|
Log: fmt.Sprintf("Pubkey (%X) is invalid go-crypto encoded", pubkey)}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// decode the power
|
||||||
|
power, err := strconv.ParseInt(powerS, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return types.ResponseDeliverTx{
|
||||||
|
Code: code.CodeTypeEncodingError,
|
||||||
|
Log: fmt.Sprintf("Power (%s) is not an int", powerS)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update
|
||||||
|
return app.updateValidator(types.Validator{pubkey, power})
|
||||||
|
}
|
||||||
|
|
||||||
|
// add, update, or remove a validator
|
||||||
|
func (app *PersistentKVStoreApplication) updateValidator(v types.Validator) types.ResponseDeliverTx {
|
||||||
|
key := []byte("val:" + string(v.PubKey))
|
||||||
|
if v.Power == 0 {
|
||||||
|
// remove validator
|
||||||
|
if !app.app.state.db.Has(key) {
|
||||||
|
return types.ResponseDeliverTx{
|
||||||
|
Code: code.CodeTypeUnauthorized,
|
||||||
|
Log: fmt.Sprintf("Cannot remove non-existent validator %X", key)}
|
||||||
|
}
|
||||||
|
app.app.state.db.Delete(key)
|
||||||
|
} else {
|
||||||
|
// add or update validator
|
||||||
|
value := bytes.NewBuffer(make([]byte, 0))
|
||||||
|
if err := types.WriteMessage(&v, value); err != nil {
|
||||||
|
return types.ResponseDeliverTx{
|
||||||
|
Code: code.CodeTypeEncodingError,
|
||||||
|
Log: fmt.Sprintf("Error encoding validator: %v", err)}
|
||||||
|
}
|
||||||
|
app.app.state.db.Set(key, value.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
// we only update the changes array if we successfully updated the tree
|
||||||
|
app.ValUpdates = append(app.ValUpdates, v)
|
||||||
|
|
||||||
|
return types.ResponseDeliverTx{Code: code.CodeTypeOK}
|
||||||
|
}
|
120
glide.lock
generated
120
glide.lock
generated
@ -1,120 +0,0 @@
|
|||||||
hash: cff2757779ef879f0c625c42af37fb3e486afd93ab9a91175c2458a719faac66
|
|
||||||
updated: 2018-02-20T22:02:37.638875125-05:00
|
|
||||||
imports:
|
|
||||||
- name: github.com/go-kit/kit
|
|
||||||
version: 4dc7be5d2d12881735283bcab7352178e190fc71
|
|
||||||
subpackages:
|
|
||||||
- log
|
|
||||||
- log/level
|
|
||||||
- log/term
|
|
||||||
- name: github.com/go-logfmt/logfmt
|
|
||||||
version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5
|
|
||||||
- name: github.com/go-stack/stack
|
|
||||||
version: 259ab82a6cad3992b4e21ff5cac294ccb06474bc
|
|
||||||
- name: github.com/gogo/protobuf
|
|
||||||
version: 1adfc126b41513cc696b209667c8656ea7aac67c
|
|
||||||
subpackages:
|
|
||||||
- gogoproto
|
|
||||||
- jsonpb
|
|
||||||
- proto
|
|
||||||
- protoc-gen-gogo/descriptor
|
|
||||||
- sortkeys
|
|
||||||
- types
|
|
||||||
- name: github.com/golang/protobuf
|
|
||||||
version: 925541529c1fa6821df4e44ce2723319eb2be768
|
|
||||||
subpackages:
|
|
||||||
- proto
|
|
||||||
- ptypes
|
|
||||||
- ptypes/any
|
|
||||||
- ptypes/duration
|
|
||||||
- ptypes/timestamp
|
|
||||||
- name: github.com/golang/snappy
|
|
||||||
version: 553a641470496b2327abcac10b36396bd98e45c9
|
|
||||||
- name: github.com/inconshreveable/mousetrap
|
|
||||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
|
||||||
- name: github.com/jmhodges/levigo
|
|
||||||
version: c42d9e0ca023e2198120196f842701bb4c55d7b9
|
|
||||||
- name: github.com/kr/logfmt
|
|
||||||
version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0
|
|
||||||
- name: github.com/pkg/errors
|
|
||||||
version: 645ef00459ed84a119197bfb8d8205042c6df63d
|
|
||||||
- name: github.com/spf13/cobra
|
|
||||||
version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b
|
|
||||||
- name: github.com/spf13/pflag
|
|
||||||
version: 4c012f6dcd9546820e378d0bdda4d8fc772cdfea
|
|
||||||
- name: github.com/syndtr/goleveldb
|
|
||||||
version: 211f780988068502fe874c44dae530528ebd840f
|
|
||||||
subpackages:
|
|
||||||
- leveldb
|
|
||||||
- leveldb/cache
|
|
||||||
- leveldb/comparer
|
|
||||||
- leveldb/errors
|
|
||||||
- leveldb/filter
|
|
||||||
- leveldb/iterator
|
|
||||||
- leveldb/journal
|
|
||||||
- leveldb/memdb
|
|
||||||
- leveldb/opt
|
|
||||||
- leveldb/storage
|
|
||||||
- leveldb/table
|
|
||||||
- leveldb/util
|
|
||||||
- name: github.com/tendermint/tmlibs
|
|
||||||
version: 1b9b5652a199ab0be2e781393fb275b66377309d
|
|
||||||
subpackages:
|
|
||||||
- common
|
|
||||||
- db
|
|
||||||
- log
|
|
||||||
- process
|
|
||||||
- name: golang.org/x/net
|
|
||||||
version: 2fb46b16b8dda405028c50f7c7f0f9dd1fa6bfb1
|
|
||||||
subpackages:
|
|
||||||
- context
|
|
||||||
- http2
|
|
||||||
- http2/hpack
|
|
||||||
- idna
|
|
||||||
- internal/timeseries
|
|
||||||
- lex/httplex
|
|
||||||
- trace
|
|
||||||
- name: golang.org/x/text
|
|
||||||
version: e19ae1496984b1c655b8044a65c0300a3c878dd3
|
|
||||||
subpackages:
|
|
||||||
- secure/bidirule
|
|
||||||
- transform
|
|
||||||
- unicode/bidi
|
|
||||||
- unicode/norm
|
|
||||||
- name: google.golang.org/genproto
|
|
||||||
version: 4eb30f4778eed4c258ba66527a0d4f9ec8a36c45
|
|
||||||
subpackages:
|
|
||||||
- googleapis/rpc/status
|
|
||||||
- name: google.golang.org/grpc
|
|
||||||
version: 401e0e00e4bb830a10496d64cd95e068c5bf50de
|
|
||||||
subpackages:
|
|
||||||
- balancer
|
|
||||||
- codes
|
|
||||||
- connectivity
|
|
||||||
- credentials
|
|
||||||
- grpclb/grpc_lb_v1/messages
|
|
||||||
- grpclog
|
|
||||||
- internal
|
|
||||||
- keepalive
|
|
||||||
- metadata
|
|
||||||
- naming
|
|
||||||
- peer
|
|
||||||
- resolver
|
|
||||||
- stats
|
|
||||||
- status
|
|
||||||
- tap
|
|
||||||
- transport
|
|
||||||
testImports:
|
|
||||||
- name: github.com/davecgh/go-spew
|
|
||||||
version: 346938d642f2ec3594ed81d874461961cd0faa76
|
|
||||||
subpackages:
|
|
||||||
- spew
|
|
||||||
- name: github.com/pmezard/go-difflib
|
|
||||||
version: 792786c7400a136282c1664665ae0a8db921c6c2
|
|
||||||
subpackages:
|
|
||||||
- difflib
|
|
||||||
- name: github.com/stretchr/testify
|
|
||||||
version: 12b6f73e6084dad08a7c6e575284b177ecafbc71
|
|
||||||
subpackages:
|
|
||||||
- assert
|
|
||||||
- require
|
|
28
glide.yaml
28
glide.yaml
@ -1,28 +0,0 @@
|
|||||||
package: github.com/tendermint/abci
|
|
||||||
import:
|
|
||||||
- package: github.com/gogo/protobuf
|
|
||||||
version: ^1.0.0
|
|
||||||
subpackages:
|
|
||||||
- proto
|
|
||||||
- package: github.com/pkg/errors
|
|
||||||
version: v0.8.0
|
|
||||||
- package: github.com/spf13/cobra
|
|
||||||
version: v0.0.1
|
|
||||||
- package: github.com/tendermint/tmlibs
|
|
||||||
version: v0.7.0
|
|
||||||
subpackages:
|
|
||||||
- common
|
|
||||||
- db
|
|
||||||
- log
|
|
||||||
- process
|
|
||||||
- package: golang.org/x/net
|
|
||||||
subpackages:
|
|
||||||
- context
|
|
||||||
- package: google.golang.org/grpc
|
|
||||||
version: v1.7.3
|
|
||||||
testImport:
|
|
||||||
- package: github.com/stretchr/testify
|
|
||||||
version: v1.2.1
|
|
||||||
subpackages:
|
|
||||||
- assert
|
|
||||||
- require
|
|
@ -8,8 +8,51 @@ ABCI requests/responses are defined as simple Protobuf messages in `this
|
|||||||
schema
|
schema
|
||||||
file <https://github.com/tendermint/abci/blob/master/types/types.proto>`__.
|
file <https://github.com/tendermint/abci/blob/master/types/types.proto>`__.
|
||||||
TendermintCore sends the requests, and the ABCI application sends the
|
TendermintCore sends the requests, and the ABCI application sends the
|
||||||
responses. Here, we describe the requests and responses as function
|
responses. Here, we provide an overview of the messages types and how they
|
||||||
arguments and return values, and make some notes about usage:
|
are used by Tendermint. Then we describe each request-response pair as a
|
||||||
|
function with arguments and return values, and add some notes on usage.
|
||||||
|
|
||||||
|
Some messages (``Echo, Info, InitChain, BeginBlock, EndBlock, Commit``), don't
|
||||||
|
return errors because an error would indicate a critical failure in the
|
||||||
|
application and there's nothing Tendermint can do. The problem should be
|
||||||
|
addressed and both Tendermint and the application restarted. All other
|
||||||
|
messages (``SetOption, Query, CheckTx, DeliverTx``) return an
|
||||||
|
application-specific response ``Code uint32``, where only ``0`` is reserved for
|
||||||
|
``OK``.
|
||||||
|
|
||||||
|
Some messages (``SetOption, Query, CheckTx, DeliverTx``) return
|
||||||
|
non-deterministic data in the form of ``Info`` and ``Log``. The ``Log`` is
|
||||||
|
intended for the literal output from the application's logger, while the
|
||||||
|
``Info`` is any additional info that should be returned.
|
||||||
|
|
||||||
|
The first time a new blockchain is started, Tendermint calls ``InitChain``.
|
||||||
|
From then on, the Block Execution Sequence that causes the committed state to
|
||||||
|
be updated is as follows:
|
||||||
|
|
||||||
|
``BeginBlock, [DeliverTx], EndBlock, Commit``
|
||||||
|
|
||||||
|
where one ``DeliverTx`` is called for each transaction in the block.
|
||||||
|
Cryptographic commitments to the results of DeliverTx, EndBlock, and
|
||||||
|
Commit are included in the header of the next block.
|
||||||
|
|
||||||
|
Tendermint opens three connections to the application to handle the different message
|
||||||
|
types:
|
||||||
|
|
||||||
|
- ``Consensus Connection - InitChain, BeginBlock, DeliverTx, EndBlock, Commit``
|
||||||
|
|
||||||
|
- ``Mempool Connection - CheckTx``
|
||||||
|
|
||||||
|
- ``Info Connection - Info, SetOption, Query``
|
||||||
|
|
||||||
|
The ``Flush`` message is used on every connection, and the ``Echo`` message
|
||||||
|
is only used for debugging.
|
||||||
|
|
||||||
|
Note that messages may be sent concurrently across all connections -
|
||||||
|
a typical application will thus maintain a distinct state for each
|
||||||
|
connection. They may be referred to as the ``DeliverTx state``, the
|
||||||
|
``CheckTx state``, and the ``Commit state`` respectively.
|
||||||
|
|
||||||
|
See below for more details on the message types and how they are used.
|
||||||
|
|
||||||
Echo
|
Echo
|
||||||
^^^^
|
^^^^
|
||||||
@ -55,7 +98,11 @@ Info
|
|||||||
- **Usage**:
|
- **Usage**:
|
||||||
|
|
||||||
- Return information about the application state.
|
- Return information about the application state.
|
||||||
- Used to sync the app with Tendermint on crash/restart.
|
- Used to sync Tendermint with the application during a handshake that
|
||||||
|
happens on startup.
|
||||||
|
- Tendermint expects ``LastBlockAppHash`` and ``LastBlockHeight`` to be
|
||||||
|
updated during ``Commit``, ensuring that ``Commit`` is never called twice
|
||||||
|
for the same block height.
|
||||||
|
|
||||||
SetOption
|
SetOption
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
@ -87,7 +134,7 @@ InitChain
|
|||||||
|
|
||||||
- **Usage**:
|
- **Usage**:
|
||||||
|
|
||||||
- Called once upon genesis
|
- Called once upon genesis.
|
||||||
|
|
||||||
Query
|
Query
|
||||||
^^^^^
|
^^^^^
|
||||||
@ -161,26 +208,26 @@ CheckTx
|
|||||||
- ``Data ([]byte)``: Result bytes, if any.
|
- ``Data ([]byte)``: Result bytes, if any.
|
||||||
- ``Log (string)``: The output of the application's logger. May be non-deterministic.
|
- ``Log (string)``: The output of the application's logger. May be non-deterministic.
|
||||||
- ``Info (string)``: Additional information. May be non-deterministic.
|
- ``Info (string)``: Additional information. May be non-deterministic.
|
||||||
- ``GasWanted (int64)``: Amount of gas consumed by transaction.
|
- ``GasWanted (int64)``: Amount of gas request for transaction.
|
||||||
|
- ``GasUsed (int64)``: Amount of gas consumed by transaction.
|
||||||
- ``Tags ([]cmn.KVPair)``: Key-Value tags for filtering and indexing transactions (eg. by account).
|
- ``Tags ([]cmn.KVPair)``: Key-Value tags for filtering and indexing transactions (eg. by account).
|
||||||
- ``Fee ([]cmn.KI64Pair)``: Fee paid for the transaction.
|
- ``Fee (cmn.KI64Pair)``: Fee paid for the transaction.
|
||||||
|
|
||||||
- **Usage**: Validate a mempool transaction, prior to broadcasting or
|
- **Usage**: Validate a mempool transaction, prior to broadcasting or
|
||||||
proposing. This message should not mutate the main state, but
|
proposing. CheckTx should perform stateful but light-weight checks
|
||||||
application developers may want to keep a separate CheckTx state that
|
of the validity of the transaction (like checking signatures and account balances),
|
||||||
gets reset upon Commit.
|
but need not execute in full (like running a smart contract).
|
||||||
|
|
||||||
CheckTx can happen interspersed with DeliverTx, but they happen on
|
Tendermint runs CheckTx and DeliverTx concurrently with eachother,
|
||||||
different ABCI connections - CheckTx from the mempool connection, and
|
though on distinct ABCI connections - the mempool connection and the consensus
|
||||||
DeliverTx from the consensus connection. During Commit, the mempool
|
connection, respectively.
|
||||||
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
|
The application should maintain a separate state to support CheckTx.
|
||||||
whatever txs it has against that latest mempool state.
|
This state can be reset to the latest committed state during ``Commit``,
|
||||||
|
where Tendermint ensures the mempool is locked and not sending new ``CheckTx``.
|
||||||
|
After ``Commit``, the mempool will rerun CheckTx on all remaining
|
||||||
|
transactions, throwing out any that are no longer valid.
|
||||||
|
|
||||||
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``, to allow for dependent sequences of transactions
|
|
||||||
in the same block.
|
|
||||||
|
|
||||||
DeliverTx
|
DeliverTx
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
@ -195,11 +242,13 @@ DeliverTx
|
|||||||
- ``Data ([]byte)``: Result bytes, if any.
|
- ``Data ([]byte)``: Result bytes, if any.
|
||||||
- ``Log (string)``: The output of the application's logger. May be non-deterministic.
|
- ``Log (string)``: The output of the application's logger. May be non-deterministic.
|
||||||
- ``Info (string)``: Additional information. May be non-deterministic.
|
- ``Info (string)``: Additional information. May be non-deterministic.
|
||||||
- ``GasWanted (int64)``: Amount of gas predicted to be consumed by transaction.
|
- ``GasWanted (int64)``: Amount of gas requested for transaction.
|
||||||
- ``GasUsed (int64)``: Amount of gas consumed by transaction.
|
- ``GasUsed (int64)``: Amount of gas consumed by transaction.
|
||||||
- ``Tags ([]cmn.KVPair)``: Key-Value tags for filtering and indexing transactions (eg. by account).
|
- ``Tags ([]cmn.KVPair)``: Key-Value tags for filtering and indexing transactions (eg. by account).
|
||||||
|
- ``Fee (cmn.KI64Pair)``: Fee paid for the transaction.
|
||||||
|
|
||||||
- **Usage**:
|
- **Usage**:
|
||||||
|
|
||||||
- Deliver a transaction to be executed in full by the application. If the transaction is valid,
|
- Deliver a transaction to be executed in full by the application. If the transaction is valid,
|
||||||
returns CodeType.OK.
|
returns CodeType.OK.
|
||||||
|
|
||||||
@ -222,6 +271,7 @@ EndBlock
|
|||||||
- Signals the end of a block.
|
- Signals the end of a block.
|
||||||
- Called prior to each Commit, after all transactions.
|
- Called prior to each Commit, after all transactions.
|
||||||
- Validator set and consensus params are updated with the result.
|
- Validator set and consensus params are updated with the result.
|
||||||
|
- Validator pubkeys are expected to be go-wire encoded.
|
||||||
|
|
||||||
Commit
|
Commit
|
||||||
^^^^^^
|
^^^^^^
|
||||||
|
@ -6,14 +6,14 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
abciclient "github.com/tendermint/abci/client"
|
abciclient "github.com/tendermint/abci/client"
|
||||||
"github.com/tendermint/abci/example/dummy"
|
"github.com/tendermint/abci/example/kvstore"
|
||||||
abciserver "github.com/tendermint/abci/server"
|
abciserver "github.com/tendermint/abci/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestClientServerNoAddrPrefix(t *testing.T) {
|
func TestClientServerNoAddrPrefix(t *testing.T) {
|
||||||
addr := "localhost:46658"
|
addr := "localhost:46658"
|
||||||
transport := "socket"
|
transport := "socket"
|
||||||
app := dummy.NewDummyApplication()
|
app := kvstore.NewKVStoreApplication()
|
||||||
|
|
||||||
server, err := abciserver.NewServer(addr, transport, app)
|
server, err := abciserver.NewServer(addr, transport, app)
|
||||||
assert.NoError(t, err, "expected no error on NewServer")
|
assert.NoError(t, err, "expected no error on NewServer")
|
||||||
|
@ -34,7 +34,7 @@ func SetOption(client abcicli.Client, key, value string) error {
|
|||||||
_, err := client.SetOptionSync(types.RequestSetOption{Key: key, Value: value})
|
_, err := client.SetOptionSync(types.RequestSetOption{Key: key, Value: value})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Failed test: SetOption")
|
fmt.Println("Failed test: SetOption")
|
||||||
fmt.Printf("error while setting %v=%v: \nerror: %v\n", key, value)
|
fmt.Printf("error while setting %v=%v: \nerror: %v\n", key, value, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("Passed test: SetOption")
|
fmt.Println("Passed test: SetOption")
|
||||||
|
@ -35,7 +35,7 @@ function testExample() {
|
|||||||
rm "${INPUT}".out.new
|
rm "${INPUT}".out.new
|
||||||
}
|
}
|
||||||
|
|
||||||
testExample 1 tests/test_cli/ex1.abci abci-cli dummy
|
testExample 1 tests/test_cli/ex1.abci abci-cli kvstore
|
||||||
testExample 2 tests/test_cli/ex2.abci abci-cli counter
|
testExample 2 tests/test_cli/ex2.abci abci-cli counter
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
@ -21,7 +21,9 @@ func TestMarshalJSON(t *testing.T) {
|
|||||||
Code: 1,
|
Code: 1,
|
||||||
Data: []byte("hello"),
|
Data: []byte("hello"),
|
||||||
GasWanted: 43,
|
GasWanted: 43,
|
||||||
Fee: cmn.KI64Pair{[]byte("pho"), 12},
|
Tags: []cmn.KVPair{
|
||||||
|
{[]byte("pho"), []byte("bo")},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
b, err = json.Marshal(&r1)
|
b, err = json.Marshal(&r1)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
@ -1327,14 +1327,14 @@ func (*ResponseBeginBlock) ProtoMessage() {}
|
|||||||
func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} }
|
func (*ResponseBeginBlock) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{20} }
|
||||||
|
|
||||||
type ResponseCheckTx struct {
|
type ResponseCheckTx struct {
|
||||||
Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
|
Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
|
||||||
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
||||||
Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
|
Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
|
||||||
Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
|
Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
|
||||||
GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"`
|
GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"`
|
||||||
// int64 gas_used = 6;
|
GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
|
||||||
Tags []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"`
|
Tags []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"`
|
||||||
Fee common.KI64Pair `protobuf:"bytes,8,opt,name=fee" json:"fee"`
|
Fee *common.KI64Pair `protobuf:"bytes,8,opt,name=fee" json:"fee,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} }
|
func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} }
|
||||||
@ -1377,6 +1377,13 @@ func (m *ResponseCheckTx) GetGasWanted() int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *ResponseCheckTx) GetGasUsed() int64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.GasUsed
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (m *ResponseCheckTx) GetTags() []common.KVPair {
|
func (m *ResponseCheckTx) GetTags() []common.KVPair {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Tags
|
return m.Tags
|
||||||
@ -1384,21 +1391,22 @@ func (m *ResponseCheckTx) GetTags() []common.KVPair {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ResponseCheckTx) GetFee() common.KI64Pair {
|
func (m *ResponseCheckTx) GetFee() *common.KI64Pair {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Fee
|
return m.Fee
|
||||||
}
|
}
|
||||||
return common.KI64Pair{}
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseDeliverTx struct {
|
type ResponseDeliverTx struct {
|
||||||
Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
|
Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
|
||||||
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
|
||||||
Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
|
Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"`
|
||||||
Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
|
Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"`
|
||||||
GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"`
|
GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,json=gasWanted,proto3" json:"gas_wanted,omitempty"`
|
||||||
GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
|
GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
|
||||||
Tags []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"`
|
Tags []common.KVPair `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"`
|
||||||
|
Fee *common.KI64Pair `protobuf:"bytes,8,opt,name=fee" json:"fee,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} }
|
func (m *ResponseDeliverTx) Reset() { *m = ResponseDeliverTx{} }
|
||||||
@ -1455,6 +1463,13 @@ func (m *ResponseDeliverTx) GetTags() []common.KVPair {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *ResponseDeliverTx) GetFee() *common.KI64Pair {
|
||||||
|
if m != nil {
|
||||||
|
return m.Fee
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type ResponseEndBlock struct {
|
type ResponseEndBlock struct {
|
||||||
ValidatorUpdates []Validator `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates" json:"validator_updates"`
|
ValidatorUpdates []Validator `protobuf:"bytes,1,rep,name=validator_updates,json=validatorUpdates" json:"validator_updates"`
|
||||||
ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates" json:"consensus_param_updates,omitempty"`
|
ConsensusParamUpdates *ConsensusParams `protobuf:"bytes,2,opt,name=consensus_param_updates,json=consensusParamUpdates" json:"consensus_param_updates,omitempty"`
|
||||||
@ -2225,115 +2240,115 @@ var _ABCIApplication_serviceDesc = grpc.ServiceDesc{
|
|||||||
func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) }
|
func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) }
|
||||||
|
|
||||||
var fileDescriptorTypes = []byte{
|
var fileDescriptorTypes = []byte{
|
||||||
// 1759 bytes of a gzipped FileDescriptorProto
|
// 1756 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xdd, 0x6e, 0x1b, 0xb9,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0xcd, 0x6e, 0x1b, 0xc9,
|
||||||
0x15, 0xb6, 0xfe, 0x35, 0x47, 0xb6, 0x64, 0xd3, 0x4e, 0xa2, 0x68, 0x51, 0xc4, 0x18, 0x14, 0x59,
|
0x11, 0x16, 0xff, 0x39, 0x45, 0x89, 0x94, 0x5a, 0xb2, 0x4d, 0x73, 0x11, 0x58, 0x18, 0x04, 0x5e,
|
||||||
0xa5, 0xc9, 0x5a, 0xad, 0xb7, 0x09, 0x92, 0x6c, 0xb1, 0x68, 0x64, 0xa7, 0x91, 0xb0, 0x6d, 0x37,
|
0x39, 0xf6, 0x8a, 0x89, 0x36, 0x36, 0x2c, 0x6f, 0xb0, 0x88, 0x28, 0x39, 0x26, 0xb1, 0x49, 0xd6,
|
||||||
0x9d, 0x64, 0x53, 0xa0, 0x37, 0x02, 0xa5, 0xa1, 0xa5, 0x41, 0x34, 0x3f, 0x3b, 0xa4, 0xbc, 0x72,
|
0x19, 0x7b, 0x1d, 0x20, 0x17, 0xa2, 0xc9, 0x69, 0x91, 0x03, 0x73, 0x7e, 0x76, 0xba, 0xa9, 0xa5,
|
||||||
0x9e, 0x61, 0xef, 0x7b, 0xdd, 0xab, 0x3e, 0x41, 0x5f, 0xa1, 0x68, 0xd1, 0x07, 0xe8, 0x9d, 0x2f,
|
0xfc, 0x0c, 0x7b, 0xcf, 0x39, 0xa7, 0x3c, 0x41, 0x5e, 0x21, 0x48, 0x90, 0x77, 0xd0, 0x61, 0x8f,
|
||||||
0x16, 0xbd, 0xea, 0x53, 0x14, 0x87, 0xe4, 0xfc, 0x7a, 0x66, 0xb1, 0x68, 0x81, 0xde, 0x48, 0x3c,
|
0x79, 0x83, 0x20, 0x97, 0xa0, 0xba, 0x7b, 0x7e, 0x35, 0xb3, 0x58, 0xe4, 0xba, 0x17, 0xb2, 0xab,
|
||||||
0x3c, 0xdf, 0x21, 0x79, 0xc8, 0xc3, 0xef, 0x9c, 0x21, 0x1c, 0x88, 0xab, 0x80, 0xf1, 0x91, 0xfc,
|
0xeb, 0xab, 0xee, 0xae, 0xee, 0xea, 0xaf, 0x6a, 0x1a, 0xf6, 0xc4, 0x75, 0xc0, 0xf8, 0x50, 0xfe,
|
||||||
0x3d, 0x09, 0x42, 0x5f, 0xf8, 0xa4, 0x21, 0x85, 0xc1, 0x27, 0x4b, 0x47, 0xac, 0x36, 0xf3, 0x93,
|
0x1e, 0x07, 0xa1, 0x2f, 0x7c, 0xd2, 0x90, 0xc2, 0xe0, 0x93, 0x85, 0x23, 0x96, 0xeb, 0xd9, 0xf1,
|
||||||
0x85, 0xef, 0x8e, 0x96, 0xfe, 0xd2, 0x1f, 0x49, 0xed, 0x7c, 0x73, 0x21, 0x25, 0x29, 0xc8, 0x96,
|
0xdc, 0x77, 0x87, 0x0b, 0x7f, 0xe1, 0x0f, 0xa5, 0x76, 0xb6, 0xbe, 0x94, 0x92, 0x14, 0x64, 0x4b,
|
||||||
0xb2, 0x1a, 0x8c, 0x52, 0x70, 0xc1, 0x3c, 0x9b, 0x85, 0xae, 0xe3, 0x89, 0x91, 0x70, 0xd7, 0xce,
|
0x59, 0x0d, 0x86, 0x29, 0xb8, 0x60, 0x9e, 0xcd, 0x42, 0xd7, 0xf1, 0xc4, 0x50, 0xb8, 0x2b, 0x67,
|
||||||
0x9c, 0x8f, 0x16, 0xbe, 0xeb, 0xfa, 0x5e, 0x7a, 0x1a, 0xf3, 0xaf, 0x75, 0x68, 0x59, 0xec, 0xeb,
|
0xc6, 0x87, 0x73, 0xdf, 0x75, 0x7d, 0x2f, 0x3d, 0x8d, 0xf9, 0xf7, 0x3a, 0xb4, 0x2c, 0xf6, 0xf5,
|
||||||
0x0d, 0xe3, 0x82, 0x0c, 0xa1, 0xce, 0x16, 0x2b, 0xbf, 0x5f, 0x3d, 0xae, 0x0c, 0x3b, 0xa7, 0xe4,
|
0x9a, 0x71, 0x41, 0x8e, 0xa0, 0xce, 0xe6, 0x4b, 0xbf, 0x5f, 0x3d, 0xac, 0x1c, 0x75, 0x4e, 0xc8,
|
||||||
0x44, 0xe1, 0xb4, 0xf6, 0xe5, 0x62, 0xe5, 0x4f, 0x76, 0x2c, 0x89, 0x20, 0x0f, 0xa1, 0x71, 0xb1,
|
0xb1, 0xc2, 0x69, 0xed, 0xcb, 0xf9, 0xd2, 0x1f, 0x6f, 0x59, 0x12, 0x41, 0x1e, 0x43, 0xe3, 0x72,
|
||||||
0xde, 0xf0, 0x55, 0xbf, 0x26, 0xa1, 0x87, 0x59, 0xe8, 0xaf, 0x50, 0x35, 0xd9, 0xb1, 0x14, 0x06,
|
0xb5, 0xe6, 0xcb, 0x7e, 0x4d, 0x42, 0xf7, 0xb3, 0xd0, 0xdf, 0xa0, 0x6a, 0xbc, 0x65, 0x29, 0x0c,
|
||||||
0x87, 0x75, 0xbc, 0x0b, 0xbf, 0x5f, 0x2f, 0x1a, 0x76, 0xea, 0x5d, 0xc8, 0x61, 0x11, 0x41, 0x9e,
|
0x0e, 0xeb, 0x78, 0x97, 0x7e, 0xbf, 0x5e, 0x34, 0xec, 0xc4, 0xbb, 0x94, 0xc3, 0x22, 0x82, 0x3c,
|
||||||
0x02, 0x70, 0x26, 0x66, 0x7e, 0x20, 0x1c, 0xdf, 0xeb, 0x37, 0x24, 0xfe, 0x4e, 0x16, 0xff, 0x86,
|
0x07, 0xe0, 0x4c, 0x4c, 0xfd, 0x40, 0x38, 0xbe, 0xd7, 0x6f, 0x48, 0xfc, 0xbd, 0x2c, 0xfe, 0x0d,
|
||||||
0x89, 0x2f, 0xa5, 0x7a, 0xb2, 0x63, 0x19, 0x3c, 0x12, 0xd0, 0xd2, 0xf1, 0x1c, 0x31, 0x5b, 0xac,
|
0x13, 0x5f, 0x4a, 0xf5, 0x78, 0xcb, 0x32, 0x78, 0x24, 0xa0, 0xa5, 0xe3, 0x39, 0x62, 0x3a, 0x5f,
|
||||||
0xa8, 0xe3, 0xf5, 0x9b, 0x45, 0x96, 0x53, 0xcf, 0x11, 0x67, 0xa8, 0x46, 0x4b, 0x27, 0x12, 0xd0,
|
0x52, 0xc7, 0xeb, 0x37, 0x8b, 0x2c, 0x27, 0x9e, 0x23, 0xce, 0x51, 0x8d, 0x96, 0x4e, 0x24, 0xa0,
|
||||||
0x95, 0xaf, 0x37, 0x2c, 0xbc, 0xea, 0xb7, 0x8a, 0x5c, 0xf9, 0x1d, 0xaa, 0xd0, 0x15, 0x89, 0x21,
|
0x2b, 0x5f, 0xaf, 0x59, 0x78, 0xdd, 0x6f, 0x15, 0xb9, 0xf2, 0x07, 0x54, 0xa1, 0x2b, 0x12, 0x43,
|
||||||
0x9f, 0x41, 0x67, 0xce, 0x96, 0x8e, 0x37, 0x9b, 0xaf, 0xfd, 0xc5, 0xfb, 0x7e, 0x5b, 0x9a, 0xf4,
|
0x3e, 0x83, 0xce, 0x8c, 0x2d, 0x1c, 0x6f, 0x3a, 0x5b, 0xf9, 0xf3, 0xf7, 0xfd, 0xb6, 0x34, 0xe9,
|
||||||
0xb3, 0x26, 0x63, 0x04, 0x8c, 0x51, 0x3f, 0xd9, 0xb1, 0x60, 0x1e, 0x4b, 0xe4, 0x14, 0xda, 0x8b,
|
0x67, 0x4d, 0x46, 0x08, 0x18, 0xa1, 0x7e, 0xbc, 0x65, 0xc1, 0x2c, 0x96, 0xc8, 0x09, 0xb4, 0xe7,
|
||||||
0x15, 0x5b, 0xbc, 0x9f, 0x89, 0x6d, 0xdf, 0x90, 0x96, 0xb7, 0xb2, 0x96, 0x67, 0xa8, 0x7d, 0xbb,
|
0x4b, 0x36, 0x7f, 0x3f, 0x15, 0x9b, 0xbe, 0x21, 0x2d, 0xef, 0x64, 0x2d, 0xcf, 0x51, 0xfb, 0x76,
|
||||||
0x9d, 0xec, 0x58, 0xad, 0x85, 0x6a, 0xa2, 0x5f, 0x36, 0x5b, 0x3b, 0x97, 0x2c, 0x44, 0xab, 0xc3,
|
0x33, 0xde, 0xb2, 0x5a, 0x73, 0xd5, 0x44, 0xbf, 0x6c, 0xb6, 0x72, 0xae, 0x58, 0x88, 0x56, 0xfb,
|
||||||
0x22, 0xbf, 0xce, 0x95, 0x5e, 0xda, 0x19, 0x76, 0x24, 0x90, 0xc7, 0x60, 0x30, 0xcf, 0xd6, 0x0b,
|
0x45, 0x7e, 0x5d, 0x28, 0xbd, 0xb4, 0x33, 0xec, 0x48, 0x20, 0x4f, 0xc1, 0x60, 0x9e, 0xad, 0x17,
|
||||||
0xed, 0x48, 0xc3, 0xdb, 0xb9, 0x13, 0xf5, 0xec, 0x68, 0x99, 0x6d, 0xa6, 0xdb, 0xe4, 0x04, 0x9a,
|
0xda, 0x91, 0x86, 0x77, 0x73, 0x27, 0xea, 0xd9, 0xd1, 0x32, 0xdb, 0x4c, 0xb7, 0xc9, 0x31, 0x34,
|
||||||
0x18, 0x25, 0x8e, 0xe8, 0xef, 0x4a, 0x9b, 0xa3, 0xdc, 0x12, 0xa5, 0x6e, 0xb2, 0x63, 0x69, 0xd4,
|
0x31, 0x4a, 0x1c, 0xd1, 0xdf, 0x96, 0x36, 0x07, 0xb9, 0x25, 0x4a, 0xdd, 0x78, 0xcb, 0xd2, 0xa8,
|
||||||
0xb8, 0x05, 0x8d, 0x4b, 0xba, 0xde, 0x30, 0xf3, 0x63, 0xe8, 0xa4, 0x22, 0x85, 0xf4, 0xa1, 0xe5,
|
0x51, 0x0b, 0x1a, 0x57, 0x74, 0xb5, 0x66, 0xe6, 0xc7, 0xd0, 0x49, 0x45, 0x0a, 0xe9, 0x43, 0xcb,
|
||||||
0x32, 0xce, 0xe9, 0x92, 0xf5, 0x2b, 0xc7, 0x95, 0xa1, 0x61, 0x45, 0xa2, 0xd9, 0x85, 0xdd, 0x74,
|
0x65, 0x9c, 0xd3, 0x05, 0xeb, 0x57, 0x0e, 0x2b, 0x47, 0x86, 0x15, 0x89, 0x66, 0x17, 0xb6, 0xd3,
|
||||||
0x9c, 0xa4, 0x0c, 0x31, 0x16, 0xd0, 0xf0, 0x92, 0x85, 0x1c, 0x03, 0x40, 0x1b, 0x6a, 0xd1, 0x7c,
|
0x71, 0x92, 0x32, 0xc4, 0x58, 0x40, 0xc3, 0x2b, 0x16, 0x72, 0x0c, 0x00, 0x6d, 0xa8, 0x45, 0xf3,
|
||||||
0x0e, 0xfb, 0xf9, 0x20, 0x20, 0xfb, 0x50, 0x7b, 0xcf, 0xae, 0x34, 0x12, 0x9b, 0xe4, 0x48, 0x2f,
|
0x05, 0xec, 0xe6, 0x83, 0x80, 0xec, 0x42, 0xed, 0x3d, 0xbb, 0xd6, 0x48, 0x6c, 0x92, 0x03, 0xbd,
|
||||||
0x48, 0x46, 0xb1, 0x61, 0xe9, 0xd5, 0x85, 0xb1, 0x6d, 0x1c, 0x06, 0xe4, 0x09, 0xc0, 0x25, 0x5d,
|
0x20, 0x19, 0xc5, 0x86, 0xa5, 0x57, 0x17, 0xc6, 0xb6, 0x71, 0x18, 0x90, 0x67, 0x00, 0x57, 0x74,
|
||||||
0x3b, 0x36, 0x15, 0x7e, 0xc8, 0xfb, 0x95, 0xe3, 0xda, 0xb0, 0x73, 0xba, 0xaf, 0xdd, 0x7d, 0x17,
|
0xe5, 0xd8, 0x54, 0xf8, 0x21, 0xef, 0x57, 0x0e, 0x6b, 0x47, 0x9d, 0x93, 0x5d, 0xed, 0xee, 0xbb,
|
||||||
0x29, 0xc6, 0xf5, 0xbf, 0x5d, 0xdf, 0xdb, 0xb1, 0x52, 0x48, 0x72, 0x1f, 0x7a, 0x34, 0x08, 0x66,
|
0x48, 0x31, 0xaa, 0xff, 0xe3, 0xe6, 0xc1, 0x96, 0x95, 0x42, 0x92, 0x87, 0xd0, 0xa3, 0x41, 0x30,
|
||||||
0x5c, 0x50, 0xc1, 0x66, 0xf3, 0x2b, 0xc1, 0xb8, 0x9c, 0x6b, 0xd7, 0xda, 0xa3, 0x41, 0xf0, 0x06,
|
0xe5, 0x82, 0x0a, 0x36, 0x9d, 0x5d, 0x0b, 0xc6, 0xe5, 0x5c, 0xdb, 0xd6, 0x0e, 0x0d, 0x82, 0x37,
|
||||||
0x7b, 0xc7, 0xd8, 0x69, 0xda, 0xb1, 0xa3, 0x32, 0x8a, 0x08, 0x81, 0xba, 0x4d, 0x05, 0x95, 0x8b,
|
0xd8, 0x3b, 0xc2, 0x4e, 0xd3, 0x8e, 0x1d, 0x95, 0x51, 0x44, 0x08, 0xd4, 0x6d, 0x2a, 0xa8, 0x5c,
|
||||||
0xdd, 0xb5, 0x64, 0x1b, 0xfb, 0x02, 0x2a, 0x56, 0x7a, 0xb1, 0xb2, 0x4d, 0x6e, 0x43, 0x73, 0xc5,
|
0xec, 0xb6, 0x25, 0xdb, 0xd8, 0x17, 0x50, 0xb1, 0xd4, 0x8b, 0x95, 0x6d, 0x72, 0x17, 0x9a, 0x4b,
|
||||||
0x9c, 0xe5, 0x4a, 0xc8, 0xdb, 0x55, 0xb3, 0xb4, 0x84, 0x9e, 0x05, 0xa1, 0x7f, 0xc9, 0xe4, 0x45,
|
0xe6, 0x2c, 0x96, 0x42, 0xde, 0xae, 0x9a, 0xa5, 0x25, 0xf4, 0x2c, 0x08, 0xfd, 0x2b, 0x26, 0x2f,
|
||||||
0x6a, 0x5b, 0x4a, 0x30, 0xff, 0x51, 0x81, 0x83, 0x1b, 0x91, 0x87, 0xe3, 0xae, 0x28, 0x5f, 0x45,
|
0x52, 0xdb, 0x52, 0x82, 0xf9, 0xaf, 0x0a, 0xec, 0xdd, 0x8a, 0x3c, 0x1c, 0x77, 0x49, 0xf9, 0x32,
|
||||||
0x73, 0x61, 0x9b, 0x3c, 0xc4, 0x71, 0xa9, 0xcd, 0x42, 0x7d, 0xc1, 0xf7, 0xb4, 0xaf, 0x13, 0xd9,
|
0x9a, 0x0b, 0xdb, 0xe4, 0x31, 0x8e, 0x4b, 0x6d, 0x16, 0xea, 0x0b, 0xbe, 0xa3, 0x7d, 0x1d, 0xcb,
|
||||||
0xa9, 0x1d, 0xd5, 0x10, 0xf2, 0x10, 0x0e, 0xe8, 0x9c, 0x33, 0x4f, 0xcc, 0x52, 0x7b, 0x54, 0x3b,
|
0x4e, 0xed, 0xa8, 0x86, 0x90, 0xc7, 0xb0, 0x47, 0x67, 0x9c, 0x79, 0x62, 0x9a, 0xda, 0xa3, 0xda,
|
||||||
0xae, 0x0d, 0x1b, 0xd6, 0xbe, 0x52, 0xbc, 0x4b, 0x76, 0x64, 0x02, 0x47, 0xf3, 0xab, 0x0f, 0xd4,
|
0x61, 0xed, 0xa8, 0x61, 0xed, 0x2a, 0xc5, 0xbb, 0x64, 0x47, 0xc6, 0x70, 0x30, 0xbb, 0xfe, 0x40,
|
||||||
0x13, 0x8e, 0xc7, 0xd2, 0xf8, 0xba, 0xdc, 0xd3, 0x9e, 0x9e, 0xe7, 0xe5, 0xa5, 0x63, 0x33, 0x6f,
|
0x3d, 0xe1, 0x78, 0x2c, 0x8d, 0xaf, 0xcb, 0x3d, 0xed, 0xe9, 0x79, 0x5e, 0x5e, 0x39, 0x36, 0xf3,
|
||||||
0xc1, 0xf4, 0x4c, 0x87, 0xb1, 0x49, 0x32, 0x92, 0x79, 0x0c, 0xdd, 0xec, 0x65, 0x20, 0x5d, 0xa8,
|
0xe6, 0x4c, 0xcf, 0xb4, 0x1f, 0x9b, 0x24, 0x23, 0x99, 0x87, 0xd0, 0xcd, 0x5e, 0x06, 0xd2, 0x85,
|
||||||
0x8a, 0xad, 0xf6, 0xa3, 0x2a, 0xb6, 0xa6, 0x19, 0x9f, 0x64, 0x1c, 0xf8, 0x37, 0x30, 0x0f, 0xa0,
|
0xaa, 0xd8, 0x68, 0x3f, 0xaa, 0x62, 0x63, 0x9a, 0xf1, 0x49, 0xc6, 0x81, 0x7f, 0x0b, 0xf3, 0x08,
|
||||||
0x97, 0x8b, 0xf1, 0xd4, 0xa6, 0x56, 0xd2, 0x9b, 0x6a, 0xf6, 0x60, 0x2f, 0x13, 0xda, 0xe6, 0xb7,
|
0x7a, 0xb9, 0x18, 0x4f, 0x6d, 0x6a, 0x25, 0xbd, 0xa9, 0x66, 0x0f, 0x76, 0x32, 0xa1, 0x6d, 0x7e,
|
||||||
0x0d, 0x68, 0x5b, 0x8c, 0x07, 0xbe, 0xc7, 0x19, 0x79, 0x0a, 0x06, 0xdb, 0x2e, 0x98, 0xe2, 0xa3,
|
0xdb, 0x80, 0xb6, 0xc5, 0x78, 0xe0, 0x7b, 0x9c, 0x91, 0xe7, 0x60, 0xb0, 0xcd, 0x9c, 0x29, 0x3e,
|
||||||
0x4a, 0xee, 0xb6, 0x2b, 0xcc, 0xcb, 0x48, 0x8f, 0xd7, 0x2f, 0x06, 0x93, 0x07, 0x19, 0x2e, 0x3d,
|
0xaa, 0xe4, 0x6e, 0xbb, 0xc2, 0xbc, 0x8c, 0xf4, 0x78, 0xfd, 0x62, 0x30, 0x79, 0x94, 0xe1, 0xd2,
|
||||||
0xcc, 0x1b, 0xa5, 0xc9, 0xf4, 0x51, 0x96, 0x4c, 0x8f, 0x72, 0xd8, 0x1c, 0x9b, 0x3e, 0xc8, 0xb0,
|
0xfd, 0xbc, 0x51, 0x9a, 0x4c, 0x9f, 0x64, 0xc9, 0xf4, 0x20, 0x87, 0xcd, 0xb1, 0xe9, 0xa3, 0x0c,
|
||||||
0x69, 0x7e, 0xe0, 0x0c, 0x9d, 0x3e, 0x2b, 0xa0, 0xd3, 0xfc, 0xf2, 0x4b, 0xf8, 0xf4, 0x59, 0x01,
|
0x9b, 0xe6, 0x07, 0xce, 0xd0, 0xe9, 0x69, 0x01, 0x9d, 0xe6, 0x97, 0x5f, 0xc2, 0xa7, 0xa7, 0x05,
|
||||||
0x9f, 0xf6, 0x6f, 0xcc, 0x55, 0x48, 0xa8, 0x8f, 0xb2, 0x84, 0x9a, 0x77, 0x27, 0xc7, 0xa8, 0xbf,
|
0x7c, 0xda, 0xbf, 0x35, 0x57, 0x21, 0xa1, 0x3e, 0xc9, 0x12, 0x6a, 0xde, 0x9d, 0x1c, 0xa3, 0xfe,
|
||||||
0x28, 0x62, 0xd4, 0xbb, 0x39, 0x9b, 0x52, 0x4a, 0xfd, 0xf4, 0x06, 0xa5, 0xde, 0xce, 0x99, 0x16,
|
0xaa, 0x88, 0x51, 0xef, 0xe7, 0x6c, 0x4a, 0x29, 0xf5, 0xd3, 0x5b, 0x94, 0x7a, 0x37, 0x67, 0x5a,
|
||||||
0x70, 0xea, 0xb3, 0x0c, 0xa7, 0x42, 0xa1, 0x6f, 0x25, 0xa4, 0xfa, 0xe4, 0x26, 0xa9, 0xde, 0xc9,
|
0xc0, 0xa9, 0xa7, 0x19, 0x4e, 0x85, 0x42, 0xdf, 0x4a, 0x48, 0xf5, 0xd9, 0x6d, 0x52, 0xbd, 0x97,
|
||||||
0x1f, 0x6d, 0x11, 0xab, 0x8e, 0x72, 0xac, 0x7a, 0x2b, 0xbf, 0xca, 0x52, 0x5a, 0x7d, 0x80, 0xb7,
|
0x3f, 0xda, 0x22, 0x56, 0x1d, 0xe6, 0x58, 0xf5, 0x4e, 0x7e, 0x95, 0xa5, 0xb4, 0xfa, 0x08, 0x6f,
|
||||||
0x3b, 0x17, 0x69, 0xc8, 0x04, 0x2c, 0x0c, 0xfd, 0x50, 0xf3, 0x9e, 0x12, 0xcc, 0x21, 0xf2, 0x4d,
|
0x77, 0x2e, 0xd2, 0x90, 0x09, 0x58, 0x18, 0xfa, 0xa1, 0xe6, 0x3d, 0x25, 0x98, 0x47, 0xc8, 0x37,
|
||||||
0x12, 0x5f, 0xdf, 0x43, 0xc1, 0x32, 0xe8, 0x53, 0xd1, 0x65, 0xfe, 0xb1, 0x92, 0xd8, 0x4a, 0x16,
|
0x49, 0x7c, 0x7d, 0x0f, 0x05, 0xcb, 0xa0, 0x4f, 0x45, 0x97, 0xf9, 0xe7, 0x4a, 0x62, 0x2b, 0x59,
|
||||||
0x4e, 0x73, 0x95, 0xa1, 0xb9, 0x2a, 0xc5, 0xcc, 0xd5, 0x0c, 0x33, 0x93, 0x9f, 0xc0, 0xc1, 0x9a,
|
0x38, 0xcd, 0x55, 0x86, 0xe6, 0xaa, 0x14, 0x33, 0x57, 0x33, 0xcc, 0x4c, 0x7e, 0x06, 0x7b, 0x2b,
|
||||||
0x72, 0xa1, 0xf6, 0x65, 0x96, 0x21, 0xaf, 0x1e, 0x2a, 0xd4, 0x86, 0x28, 0x16, 0xfb, 0x04, 0x0e,
|
0xca, 0x85, 0xda, 0x97, 0x69, 0x86, 0xbc, 0x7a, 0xa8, 0x50, 0x1b, 0xa2, 0x58, 0xec, 0x13, 0xd8,
|
||||||
0x53, 0x58, 0x24, 0x52, 0x49, 0x54, 0x75, 0x79, 0x79, 0xf7, 0x63, 0xf4, 0x8b, 0x20, 0x98, 0x50,
|
0x4f, 0x61, 0x91, 0x48, 0x25, 0x51, 0xd5, 0xe5, 0xe5, 0xdd, 0x8d, 0xd1, 0x67, 0x41, 0x30, 0xa6,
|
||||||
0xbe, 0x32, 0x7f, 0x93, 0xf8, 0x9f, 0xb0, 0x3e, 0x81, 0xfa, 0xc2, 0xb7, 0x95, 0x5b, 0x7b, 0x96,
|
0x7c, 0x69, 0xfe, 0x2e, 0xf1, 0x3f, 0x61, 0x7d, 0x02, 0xf5, 0xb9, 0x6f, 0x2b, 0xb7, 0x76, 0x2c,
|
||||||
0x6c, 0x63, 0x26, 0x58, 0xfb, 0x4b, 0x39, 0xab, 0x61, 0x61, 0x13, 0x51, 0xf1, 0x4d, 0x31, 0xd4,
|
0xd9, 0xc6, 0x4c, 0xb0, 0xf2, 0x17, 0x72, 0x56, 0xc3, 0xc2, 0x26, 0xa2, 0xe2, 0x9b, 0x62, 0xa8,
|
||||||
0x95, 0x30, 0x0f, 0x93, 0xe1, 0xe2, 0xf0, 0x35, 0xff, 0x52, 0x49, 0xf6, 0x23, 0xa6, 0xea, 0xff,
|
0x2b, 0x61, 0xee, 0x27, 0xc3, 0xc5, 0xe1, 0x6b, 0xfe, 0xad, 0x92, 0xec, 0x47, 0x4c, 0xd5, 0xff,
|
||||||
0x6e, 0x02, 0x3c, 0x1a, 0xc7, 0xb3, 0xd9, 0x56, 0x5e, 0xb7, 0x9a, 0xa5, 0x84, 0x28, 0x4d, 0x35,
|
0xdf, 0x04, 0x78, 0x34, 0x8e, 0x67, 0xb3, 0x8d, 0xbc, 0x6e, 0x35, 0x4b, 0x09, 0x51, 0x9a, 0x6a,
|
||||||
0xa5, 0x93, 0xd9, 0x34, 0xd5, 0x92, 0x7d, 0x4a, 0xd0, 0x14, 0xef, 0x5f, 0xc8, 0x7b, 0xb0, 0x6b,
|
0x4a, 0x27, 0xb3, 0x69, 0xaa, 0x25, 0xfb, 0x94, 0xa0, 0x29, 0xde, 0xbf, 0x94, 0xf7, 0x60, 0xdb,
|
||||||
0x29, 0x21, 0xc5, 0x5d, 0x46, 0x86, 0xbb, 0x8e, 0x80, 0xdc, 0xbc, 0x21, 0xe6, 0xbf, 0x2a, 0xc8,
|
0x52, 0x42, 0x8a, 0xbb, 0x8c, 0x0c, 0x77, 0x1d, 0x00, 0xb9, 0x7d, 0x43, 0xcc, 0xff, 0x54, 0x90,
|
||||||
0x7e, 0x99, 0xe8, 0x2f, 0xf4, 0x27, 0x3a, 0xe2, 0x6a, 0x2a, 0x1d, 0xfd, 0x30, 0x1f, 0x7f, 0x04,
|
0xfd, 0x32, 0xd1, 0x5f, 0xe8, 0x4f, 0x74, 0xc4, 0xd5, 0x54, 0x3a, 0xfa, 0x61, 0x3e, 0xfe, 0x04,
|
||||||
0xb0, 0xa4, 0x7c, 0xf6, 0x0d, 0xf5, 0x04, 0xb3, 0xb5, 0xa3, 0xc6, 0x92, 0xf2, 0xdf, 0xcb, 0x0e,
|
0x60, 0x41, 0xf9, 0xf4, 0x1b, 0xea, 0x09, 0x66, 0x6b, 0x47, 0x8d, 0x05, 0xe5, 0x7f, 0x94, 0x1d,
|
||||||
0xf2, 0x1c, 0xea, 0x82, 0x2e, 0x79, 0xbf, 0x25, 0xd9, 0xbf, 0x7b, 0xa2, 0xaa, 0xce, 0x93, 0x2f,
|
0xe4, 0x3e, 0xb4, 0x51, 0xbd, 0xe6, 0xcc, 0x96, 0x1e, 0xd7, 0xac, 0xd6, 0x82, 0xf2, 0xaf, 0x38,
|
||||||
0xde, 0xbd, 0xa6, 0x4e, 0x38, 0xbe, 0x8d, 0xe4, 0xff, 0xef, 0xeb, 0x7b, 0x5d, 0xc4, 0x3c, 0xf2,
|
0xb3, 0xc9, 0x0b, 0xa8, 0x0b, 0xba, 0xe0, 0xfd, 0x96, 0x4c, 0x0c, 0xdd, 0x63, 0x55, 0x90, 0x1e,
|
||||||
0x5d, 0x47, 0x30, 0x37, 0x10, 0x57, 0x96, 0xb4, 0x21, 0x43, 0xa8, 0x5d, 0x30, 0xa6, 0x69, 0x60,
|
0x7f, 0xf1, 0xee, 0x35, 0x75, 0xc2, 0xd1, 0x5d, 0xcc, 0x0b, 0xff, 0xbe, 0x79, 0xd0, 0x45, 0xcc,
|
||||||
0x3f, 0x36, 0x9d, 0x3e, 0xf9, 0xb9, 0x34, 0x56, 0x99, 0x03, 0x21, 0xe6, 0x3f, 0x2b, 0xc9, 0x51,
|
0x13, 0xdf, 0x75, 0x04, 0x73, 0x03, 0x71, 0x6d, 0x49, 0x1b, 0x62, 0x42, 0xed, 0x92, 0x31, 0xcd,
|
||||||
0x26, 0x99, 0xe0, 0xff, 0xea, 0xe8, 0x5d, 0x68, 0xa3, 0x7a, 0xc3, 0x99, 0x2d, 0x8f, 0xb6, 0x66,
|
0x10, 0xbb, 0xb1, 0xe9, 0xe4, 0xd9, 0x2f, 0xd1, 0xd8, 0x42, 0xa5, 0xf9, 0xdf, 0x4a, 0x72, 0xbe,
|
||||||
0xb5, 0x96, 0x94, 0x7f, 0xc5, 0xff, 0xb7, 0x3d, 0x30, 0xff, 0x5c, 0xc1, 0x14, 0x97, 0x65, 0x13,
|
0x49, 0x7a, 0xf8, 0xb1, 0x78, 0xff, 0xd7, 0x0a, 0xe6, 0xc6, 0x2c, 0x0d, 0x91, 0x73, 0xd8, 0x8b,
|
||||||
0x72, 0x06, 0x07, 0x71, 0x62, 0x9d, 0x6d, 0x02, 0x9b, 0x62, 0xd9, 0xf1, 0xfd, 0x35, 0xcb, 0x7e,
|
0x33, 0xf2, 0x74, 0x1d, 0xd8, 0x14, 0xeb, 0x95, 0xef, 0x2f, 0x76, 0x76, 0x63, 0x83, 0xaf, 0x14,
|
||||||
0x6c, 0xf0, 0x95, 0xc2, 0x93, 0xdf, 0xc2, 0x9d, 0x05, 0x8e, 0xea, 0xf1, 0x0d, 0x9f, 0x05, 0x34,
|
0x9e, 0xfc, 0x1e, 0xee, 0xcd, 0x71, 0x54, 0x8f, 0xaf, 0xf9, 0x34, 0xa0, 0x21, 0x75, 0xe3, 0xa1,
|
||||||
0xa4, 0x6e, 0x3c, 0x54, 0x35, 0xc3, 0x9e, 0x67, 0x11, 0xea, 0x35, 0x82, 0xb8, 0x75, 0x6b, 0x91,
|
0xaa, 0x19, 0xda, 0x3d, 0x8f, 0x50, 0xaf, 0x11, 0xc4, 0xad, 0x3b, 0xf3, 0x4c, 0x87, 0x1e, 0xcf,
|
||||||
0xe9, 0xd0, 0xe3, 0x99, 0x3f, 0xc6, 0x6c, 0x9d, 0x66, 0xb0, 0xa2, 0xbd, 0x36, 0xff, 0x54, 0x81,
|
0xfc, 0x29, 0xa6, 0xf9, 0x34, 0xf5, 0x15, 0x9d, 0x87, 0xf9, 0x97, 0x0a, 0xf4, 0x72, 0x03, 0x92,
|
||||||
0x5e, 0x6e, 0x40, 0x32, 0x02, 0x50, 0x04, 0xc0, 0x9d, 0x0f, 0x4c, 0x67, 0xd6, 0xc8, 0x0f, 0xe9,
|
0x21, 0x80, 0x62, 0x0e, 0xee, 0x7c, 0x60, 0x3a, 0x25, 0x47, 0x7e, 0x48, 0x87, 0xdf, 0x38, 0x1f,
|
||||||
0xf0, 0x1b, 0xe7, 0x03, 0xb3, 0x8c, 0x79, 0xd4, 0x24, 0xf7, 0xa1, 0x25, 0xb6, 0x0a, 0x9d, 0xad,
|
0x98, 0x65, 0xcc, 0xa2, 0x26, 0x79, 0x08, 0x2d, 0xb1, 0x51, 0xe8, 0x6c, 0xd9, 0xf3, 0x76, 0x23,
|
||||||
0x5e, 0xde, 0x6e, 0x25, 0xb4, 0x29, 0xe4, 0x3f, 0x79, 0x0c, 0xbb, 0x6a, 0xe0, 0xa5, 0xcf, 0xb9,
|
0xa1, 0x4d, 0x21, 0xff, 0xc9, 0x53, 0xd8, 0x56, 0x03, 0x2f, 0x7c, 0xce, 0x9d, 0x40, 0x27, 0x63,
|
||||||
0x13, 0xe8, 0x9c, 0x4a, 0xd2, 0x43, 0xbf, 0x92, 0x1a, 0xab, 0x33, 0x4f, 0x04, 0xf3, 0x0f, 0x60,
|
0x92, 0x1e, 0xfa, 0x95, 0xd4, 0x58, 0x9d, 0x59, 0x22, 0x98, 0x7f, 0x02, 0x23, 0x9e, 0x96, 0x7c,
|
||||||
0xc4, 0xd3, 0x92, 0x8f, 0xc0, 0x70, 0xe9, 0x56, 0x97, 0x76, 0xb8, 0xb6, 0x86, 0xd5, 0x76, 0xe9,
|
0x04, 0x86, 0x4b, 0x37, 0xba, 0x26, 0xc4, 0xb5, 0x35, 0xac, 0xb6, 0x4b, 0x37, 0xb2, 0x1c, 0x24,
|
||||||
0x56, 0x56, 0x75, 0xe4, 0x0e, 0xb4, 0x50, 0x29, 0xb6, 0x6a, 0xcf, 0x1a, 0x56, 0xd3, 0xa5, 0xdb,
|
0xf7, 0xa0, 0x85, 0x4a, 0xb1, 0x51, 0x7b, 0xd6, 0xb0, 0x9a, 0x2e, 0xdd, 0xbc, 0xdd, 0xc4, 0x8a,
|
||||||
0xb7, 0xdb, 0x58, 0xb1, 0xa4, 0x3c, 0xaa, 0xdb, 0x5c, 0xba, 0x7d, 0x45, 0xb9, 0xf9, 0x39, 0x34,
|
0x05, 0xe5, 0x51, 0xc1, 0xe7, 0xd2, 0xcd, 0x2b, 0xca, 0xcd, 0xcf, 0xa1, 0xa9, 0x16, 0xf9, 0x83,
|
||||||
0xd5, 0x22, 0x7f, 0xd0, 0xc0, 0x68, 0x5f, 0xcd, 0xd8, 0xff, 0x12, 0x3a, 0xa9, 0x75, 0x93, 0x9f,
|
0x06, 0x46, 0xfb, 0x6a, 0xc6, 0xfe, 0xd7, 0xd0, 0x49, 0xad, 0x9b, 0xfc, 0x02, 0xee, 0x28, 0x0f,
|
||||||
0xc1, 0x2d, 0xe5, 0x61, 0x40, 0x43, 0x21, 0x77, 0x24, 0x33, 0x20, 0x91, 0xca, 0xd7, 0x34, 0x14,
|
0x03, 0x1a, 0x0a, 0xb9, 0x23, 0x99, 0x01, 0x89, 0x54, 0xbe, 0xa6, 0xa1, 0xc0, 0x29, 0x55, 0x09,
|
||||||
0x38, 0xa5, 0xaa, 0x44, 0xff, 0x5e, 0x85, 0xa6, 0xaa, 0xf2, 0xc8, 0x7d, 0xcc, 0x98, 0xd4, 0xf1,
|
0xfb, 0xcf, 0x2a, 0x34, 0x55, 0x79, 0x48, 0x1e, 0x62, 0xaa, 0xa5, 0x8e, 0x37, 0x75, 0x6c, 0x95,
|
||||||
0x66, 0x8e, 0xad, 0xc8, 0x7d, 0xdc, 0xf9, 0xee, 0xfa, 0x5e, 0x4b, 0x12, 0xe1, 0xf4, 0x1c, 0x93,
|
0x15, 0x46, 0x9d, 0xef, 0x6e, 0x1e, 0xb4, 0x24, 0x83, 0x4e, 0x2e, 0x30, 0xbb, 0x62, 0xc3, 0x4e,
|
||||||
0x24, 0x36, 0xec, 0x14, 0xe7, 0x54, 0x33, 0x45, 0x28, 0x81, 0xba, 0x70, 0x5c, 0xa6, 0x5d, 0x94,
|
0x91, 0x55, 0x35, 0x53, 0xbd, 0x12, 0xa8, 0x0b, 0xc7, 0x65, 0xda, 0x45, 0xd9, 0xc6, 0x95, 0x7b,
|
||||||
0x6d, 0x5c, 0xb9, 0xb7, 0x71, 0xe5, 0x96, 0xd4, 0xd5, 0x96, 0x78, 0x1b, 0x17, 0xb7, 0xe4, 0x15,
|
0x6b, 0x57, 0x6e, 0x49, 0x5d, 0x6d, 0x89, 0xb7, 0x76, 0x71, 0x4b, 0x5e, 0xc1, 0x4e, 0x2a, 0x49,
|
||||||
0xec, 0xa5, 0xb8, 0xde, 0xb1, 0x75, 0x0d, 0xd2, 0x4d, 0x9f, 0xc6, 0xf4, 0x7c, 0x7c, 0x88, 0xe1,
|
0x38, 0xb6, 0x2e, 0x5e, 0xba, 0xe9, 0xd3, 0x98, 0x5c, 0x8c, 0xf6, 0x31, 0x5c, 0xbf, 0xbb, 0x79,
|
||||||
0xfa, 0xdd, 0xf5, 0xbd, 0xce, 0xaf, 0x23, 0xf6, 0x9f, 0x9e, 0x5b, 0x9d, 0x38, 0x15, 0x4c, 0x6d,
|
0xd0, 0xf9, 0x6d, 0x94, 0x36, 0x26, 0x17, 0x56, 0x27, 0xce, 0x21, 0x13, 0x9b, 0x1c, 0x81, 0x4c,
|
||||||
0x32, 0x04, 0x99, 0x19, 0x66, 0x2a, 0x3b, 0xaa, 0x8c, 0xa1, 0xc8, 0xb4, 0x8b, 0xfd, 0x3a, 0x7d,
|
0x29, 0x53, 0x95, 0x56, 0x55, 0xaa, 0x51, 0x2c, 0xdc, 0xc5, 0x7e, 0x9d, 0x77, 0xb1, 0x3a, 0xfe,
|
||||||
0x62, 0x91, 0xfb, 0x11, 0x18, 0x18, 0x74, 0x0a, 0xa2, 0xb8, 0xb5, 0x8d, 0x1d, 0x52, 0xf9, 0x31,
|
0x08, 0x0c, 0x0c, 0x3a, 0x05, 0x51, 0xa4, 0xdc, 0xc6, 0x0e, 0xa9, 0xfc, 0x18, 0x7a, 0x49, 0x59,
|
||||||
0xf4, 0x92, 0xea, 0x54, 0x41, 0x14, 0xd1, 0x76, 0x93, 0x6e, 0x09, 0xbc, 0x0b, 0xed, 0x38, 0x33,
|
0xab, 0x20, 0x8a, 0xa1, 0xbb, 0x49, 0xb7, 0x04, 0xde, 0x87, 0x76, 0x9c, 0xd2, 0x0c, 0x89, 0x68,
|
||||||
0x19, 0x12, 0xd1, 0xa2, 0x3a, 0x21, 0x7d, 0x09, 0x2d, 0xbd, 0xc4, 0xc2, 0x22, 0xfb, 0xa7, 0xd0,
|
0x51, 0x9d, 0xc9, 0xbe, 0x84, 0x96, 0x5e, 0x62, 0x61, 0x75, 0xfe, 0x73, 0x68, 0xe0, 0xb9, 0x44,
|
||||||
0xc0, 0x73, 0x89, 0x2e, 0x54, 0x54, 0xfd, 0xc8, 0xf3, 0x60, 0x22, 0x53, 0x6a, 0x2b, 0xa0, 0xf9,
|
0x17, 0x2a, 0x2a, 0x9b, 0xe4, 0x79, 0x30, 0x91, 0xa9, 0xd1, 0x15, 0xd0, 0x3c, 0x85, 0x9d, 0x8c,
|
||||||
0x0c, 0xf6, 0x32, 0x5a, 0x4c, 0x02, 0xc2, 0x17, 0x74, 0xad, 0x0f, 0x54, 0x09, 0xf1, 0x64, 0xd5,
|
0x16, 0xb3, 0x87, 0xf0, 0x05, 0x5d, 0xe9, 0x03, 0x55, 0x42, 0x3c, 0x59, 0x35, 0x99, 0xcc, 0x7c,
|
||||||
0x64, 0x32, 0xf3, 0x39, 0x18, 0xf1, 0xa5, 0xc7, 0x53, 0x08, 0x36, 0xf3, 0x59, 0xf4, 0x39, 0xb4,
|
0x01, 0x46, 0x7c, 0xe9, 0xf1, 0x14, 0x82, 0xf5, 0x6c, 0x1a, 0x7d, 0x47, 0x6d, 0x5b, 0xcd, 0x60,
|
||||||
0x6b, 0x35, 0x83, 0xcd, 0xfc, 0x0b, 0x95, 0x6a, 0x02, 0xff, 0x1b, 0x5d, 0xf6, 0xd7, 0x2c, 0x25,
|
0x3d, 0xfb, 0x42, 0xe5, 0xa8, 0xc0, 0xff, 0x46, 0x7f, 0x2f, 0xd4, 0x2c, 0x25, 0x98, 0x9f, 0x41,
|
||||||
0x98, 0x9f, 0x41, 0x3b, 0x2a, 0xc8, 0xcb, 0x4d, 0x4b, 0xa2, 0xe0, 0xf4, 0xdb, 0x06, 0xf4, 0x5e,
|
0x3b, 0xaa, 0xe4, 0xcb, 0x4d, 0x4b, 0xa2, 0xe0, 0xe4, 0xdb, 0x06, 0xf4, 0xce, 0x46, 0xe7, 0x93,
|
||||||
0x8c, 0xcf, 0xa6, 0x2f, 0x82, 0x60, 0xed, 0x2c, 0xa8, 0x4c, 0xca, 0x23, 0xa8, 0xcb, 0xb2, 0xa3,
|
0xb3, 0x20, 0x58, 0x39, 0x73, 0x2a, 0xb3, 0xf9, 0x10, 0xea, 0xb2, 0x5e, 0x29, 0x78, 0x70, 0x18,
|
||||||
0xe0, 0xdd, 0x60, 0x50, 0x54, 0xff, 0x92, 0x53, 0x68, 0xc8, 0xea, 0x83, 0x14, 0x3d, 0x1f, 0x0c,
|
0x14, 0x15, 0xce, 0xe4, 0x04, 0x1a, 0xb2, 0x6c, 0x21, 0x45, 0xef, 0x0e, 0x83, 0xc2, 0xfa, 0x19,
|
||||||
0x0a, 0xcb, 0x60, 0x9c, 0x44, 0xd5, 0x27, 0x37, 0x5f, 0x11, 0x06, 0x45, 0xb5, 0x30, 0xf9, 0x1c,
|
0x27, 0x51, 0x85, 0xcd, 0xed, 0xe7, 0x87, 0x41, 0x51, 0x11, 0x4d, 0x3e, 0x07, 0x23, 0x29, 0x38,
|
||||||
0x8c, 0xa4, 0x6e, 0x28, 0x7b, 0x4b, 0x18, 0x94, 0x56, 0xc5, 0x68, 0x9f, 0x64, 0x97, 0xb2, 0x2f,
|
0xca, 0x1e, 0x21, 0x06, 0xa5, 0xe5, 0x34, 0xda, 0x27, 0x19, 0xa8, 0xec, 0x93, 0x7d, 0x50, 0x5a,
|
||||||
0xef, 0x41, 0x69, 0xf9, 0x48, 0x9e, 0x42, 0x2b, 0x4a, 0xc2, 0xc5, 0x5f, 0xfb, 0x83, 0x92, 0x8a,
|
0x77, 0x92, 0xe7, 0xd0, 0x8a, 0xb2, 0x77, 0xf1, 0x33, 0xc1, 0xa0, 0xa4, 0xd4, 0xc5, 0xed, 0x51,
|
||||||
0x15, 0xb7, 0x47, 0x15, 0x23, 0x45, 0x4f, 0x12, 0x83, 0xc2, 0xb2, 0x9a, 0x3c, 0x86, 0xa6, 0x26,
|
0x55, 0x4c, 0xd1, 0x5b, 0xc6, 0xa0, 0xb0, 0x1e, 0x27, 0x4f, 0xa1, 0xa9, 0x89, 0xb8, 0xf0, 0x83,
|
||||||
0xe2, 0xc2, 0xef, 0xf6, 0x41, 0x71, 0xdd, 0x89, 0x4e, 0x26, 0x9f, 0xc5, 0x65, 0xcf, 0x26, 0x83,
|
0x7f, 0x50, 0x5c, 0xb0, 0xa2, 0x93, 0xc9, 0xf7, 0x74, 0xd9, 0x7b, 0xcb, 0xa0, 0xf4, 0xc3, 0x81,
|
||||||
0xd2, 0xfa, 0x9f, 0xbc, 0x00, 0x48, 0x7d, 0x7b, 0x96, 0xbe, 0x87, 0x0c, 0xca, 0xeb, 0x7a, 0x82,
|
0x9c, 0x01, 0xa4, 0x3e, 0x5a, 0x4b, 0x1f, 0x52, 0x06, 0xe5, 0x1f, 0x04, 0x04, 0xc3, 0x31, 0xfe,
|
||||||
0xe1, 0x18, 0x7f, 0xab, 0x15, 0xbf, 0x53, 0x0c, 0xca, 0x4a, 0xed, 0x79, 0x53, 0xbe, 0x65, 0x7d,
|
0xc8, 0x2b, 0x7e, 0xe0, 0x18, 0x94, 0xd5, 0xe8, 0xb3, 0xa6, 0x7c, 0x04, 0xfb, 0xf4, 0x7f, 0x01,
|
||||||
0xfa, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x11, 0xd7, 0x9f, 0xcd, 0x47, 0x13, 0x00, 0x00,
|
0x00, 0x00, 0xff, 0xff, 0x78, 0xcf, 0xcd, 0xb3, 0x80, 0x13, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
@ -151,9 +151,9 @@ message ResponseCheckTx {
|
|||||||
string log = 3; // nondeterministic
|
string log = 3; // nondeterministic
|
||||||
string info = 4; // nondeterministic
|
string info = 4; // nondeterministic
|
||||||
int64 gas_wanted = 5;
|
int64 gas_wanted = 5;
|
||||||
// int64 gas_used = 6;
|
int64 gas_used = 6;
|
||||||
repeated common.KVPair tags = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
|
repeated common.KVPair tags = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
|
||||||
common.KI64Pair fee = 8 [(gogoproto.nullable)=false];
|
common.KI64Pair fee = 8 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
|
||||||
}
|
}
|
||||||
|
|
||||||
message ResponseDeliverTx {
|
message ResponseDeliverTx {
|
||||||
@ -164,7 +164,7 @@ message ResponseDeliverTx {
|
|||||||
int64 gas_wanted = 5;
|
int64 gas_wanted = 5;
|
||||||
int64 gas_used = 6;
|
int64 gas_used = 6;
|
||||||
repeated common.KVPair tags = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
|
repeated common.KVPair tags = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
|
||||||
// common.KI64Pair fee = 8;
|
common.KI64Pair fee = 8 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
|
||||||
}
|
}
|
||||||
|
|
||||||
message ResponseEndBlock {
|
message ResponseEndBlock {
|
||||||
|
@ -4,6 +4,6 @@ package version
|
|||||||
|
|
||||||
const Maj = "0"
|
const Maj = "0"
|
||||||
const Min = "10"
|
const Min = "10"
|
||||||
const Fix = "0"
|
const Fix = "1"
|
||||||
|
|
||||||
const Version = "0.10.0"
|
const Version = "0.10.1"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user