diff --git a/.circleci/config.yml b/.circleci/config.yml index 5a50a61c5..82ef52309 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,7 +16,7 @@ jobs: - checkout - restore_cache: keys: - - v2-pkg-cache + - v3-pkg-cache - run: name: tools command: | @@ -31,19 +31,18 @@ jobs: name: binaries command: | export PATH="$GOBIN:$PATH" - make install - cd abci && make install + make install install_abci - persist_to_workspace: root: /tmp/workspace paths: - bin - profiles - save_cache: - key: v2-pkg-cache + key: v3-pkg-cache paths: - /go/pkg - save_cache: - key: v2-tree-{{ .Environment.CIRCLE_SHA1 }} + key: v3-tree-{{ .Environment.CIRCLE_SHA1 }} paths: - /go/src/github.com/tendermint/tendermint @@ -53,9 +52,9 @@ jobs: - attach_workspace: at: /tmp/workspace - restore_cache: - key: v2-pkg-cache + key: v3-pkg-cache - restore_cache: - key: v2-tree-{{ .Environment.CIRCLE_SHA1 }} + key: v3-tree-{{ .Environment.CIRCLE_SHA1 }} - run: name: slate docs command: | @@ -69,9 +68,9 @@ jobs: - attach_workspace: at: /tmp/workspace - restore_cache: - key: v2-pkg-cache + key: v3-pkg-cache - restore_cache: - key: v2-tree-{{ .Environment.CIRCLE_SHA1 }} + key: v3-tree-{{ .Environment.CIRCLE_SHA1 }} - run: name: metalinter command: | @@ -85,9 +84,9 @@ jobs: - attach_workspace: at: /tmp/workspace - restore_cache: - key: v2-pkg-cache + key: v3-pkg-cache - restore_cache: - key: v2-tree-{{ .Environment.CIRCLE_SHA1 }} + key: v3-tree-{{ .Environment.CIRCLE_SHA1 }} - run: name: Run abci apps tests command: | @@ -102,9 +101,9 @@ jobs: - attach_workspace: at: /tmp/workspace - restore_cache: - key: v2-pkg-cache + key: v3-pkg-cache - restore_cache: - key: v2-tree-{{ .Environment.CIRCLE_SHA1 }} + key: v3-tree-{{ .Environment.CIRCLE_SHA1 }} - run: name: Run abci-cli tests command: | @@ -117,9 +116,9 @@ jobs: - attach_workspace: at: /tmp/workspace - restore_cache: - key: v2-pkg-cache + key: v3-pkg-cache - restore_cache: - key: v2-tree-{{ .Environment.CIRCLE_SHA1 }} + key: v3-tree-{{ .Environment.CIRCLE_SHA1 }} - run: sudo apt-get update && sudo apt-get install -y --no-install-recommends bsdmainutils - run: name: Run tests @@ -132,14 +131,14 @@ jobs: - attach_workspace: at: /tmp/workspace - restore_cache: - key: v2-pkg-cache + key: v3-pkg-cache - restore_cache: - key: v2-tree-{{ .Environment.CIRCLE_SHA1 }} + key: v3-tree-{{ .Environment.CIRCLE_SHA1 }} - run: mkdir -p /tmp/logs - run: name: Run tests command: | - for pkg in $(go list github.com/tendermint/tendermint/... | grep -v /vendor/ | circleci tests split --split-by=timings); do + for pkg in $(go list github.com/tendermint/tendermint/... | circleci tests split --split-by=timings); do id=$(basename "$pkg") GOCACHE=off go test -v -timeout 5m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic "$pkg" | tee "/tmp/logs/$id-$RANDOM.log" @@ -157,9 +156,9 @@ jobs: - attach_workspace: at: /tmp/workspace - restore_cache: - key: v2-pkg-cache + key: v3-pkg-cache - restore_cache: - key: v2-tree-{{ .Environment.CIRCLE_SHA1 }} + key: v3-tree-{{ .Environment.CIRCLE_SHA1 }} - run: name: Run tests command: bash test/persist/test_failure_indices.sh @@ -182,7 +181,7 @@ jobs: - attach_workspace: at: /tmp/workspace - restore_cache: - key: v2-tree-{{ .Environment.CIRCLE_SHA1 }} + key: v3-tree-{{ .Environment.CIRCLE_SHA1 }} - run: name: gather command: | diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 42f8f44ee..9586a8702 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,3 +2,6 @@ # Everything goes through Bucky, Anton, Alex. For now. * @ebuchman @melekes @xla + +# Precious documentation +/docs/ @zramsay @jolesbi diff --git a/.gitignore b/.gitignore index 9337de17b..21a77ad14 100644 --- a/.gitignore +++ b/.gitignore @@ -14,10 +14,9 @@ test/p2p/data/ test/logs coverage.txt docs/_build -docs/tools *.log abci-cli -abci/types/types.pb.go +docs/node_modules/ scripts/wal2json/wal2json scripts/cutWALUntil/cutWALUntil @@ -27,5 +26,13 @@ scripts/cutWALUntil/cutWALUntil libs/pubsub/query/fuzz_test/output shunit2 + .tendermint-lite addrbook.json + +*/vendor +*/.glide +.terraform +terraform.tfstate +terraform.tfstate.backup +terraform.tfstate.d diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e910e365..27d5656b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,98 @@ # Changelog -## 0.23.0 +## TBA + +## 0.22.5 + +*July 23th, 2018* + +BREAKING CHANGES: +- [crypto] Refactor `tendermint/crypto` into many subpackages +- [libs/common] remove exponentially distributed random numbers + +IMPROVEMENTS: +- [abci, libs/common] Generated gogoproto static marshaller methods +- [config] Increase default send/recv rates to 5 mB/s +- [p2p] allow persistent peers to be private + +BUG FIXES +- [mempool] fixed a race condition when `create_empty_blocks=false` where a + transaction is published at an old height. +- [p2p] dial external IP setup by `persistent_peers`, not internal NAT IP +- [rpc] make `/status` RPC endpoint resistant to consensus halt + +## 0.22.4 + +*July 14th, 2018* + +BREAKING CHANGES: +- [genesis] removed deprecated `app_options` field. +- [types] Genesis.AppStateJSON -> Genesis.AppState + +FEATURES: +- [tools] Merged in from github.com/tendermint/tools + +BUG FIXES: +- [tools/tm-bench] Various fixes +- [consensus] Wait for WAL to stop on shutdown +- [abci] Fix #1891, pending requests cannot hang when abci server dies. + Previously a crash in BeginBlock could leave tendermint in broken state. + +## 0.22.3 + +*July 10th, 2018* + +IMPROVEMENTS +- Update dependencies + * pin all values in Gopkg.toml to version or commit + * update golang/protobuf to v1.1.0 + +## 0.22.2 + +*July 10th, 2018* + +IMPROVEMENTS +- More cleanup post repo merge! +- [docs] Include `ecosystem.json` and `tendermint-bft.md` from deprecated `aib-data` repository. +- [config] Add `instrumentation.max_open_connections`, which limits the number + of requests in flight to Prometheus server (if enabled). Default: 3. + + +BUG FIXES +- [rpc] Allow unquoted integers in requests + - NOTE: this is only for URI requests. JSONRPC requests and all responses + will use quoted integers (the proto3 JSON standard). +- [consensus] Fix halt on shutdown + +## 0.22.1 + +*July 5th, 2018* + +IMPROVEMENTS + +* Cleanup post repo-merge. +* [docs] Various improvements. + +BUG FIXES + +* [state] Return error when EndBlock returns a 0-power validator that isn't + already in the validator set. +* [consensus] Shut down WAL properly. -*TBD* ## 0.22.0 *July 2nd, 2018* BREAKING CHANGES: -- [config] Rename `skip_upnp` to `upnp`, and turn it off by default. +- [config] + * Remove `max_block_size_txs` and `max_block_size_bytes` in favor of + consensus params from the genesis file. + * Rename `skip_upnp` to `upnp`, and turn it off by default. + * Change `max_packet_msg_size` back to `max_packet_msg_payload_size` +- [rpc] + * All integers are encoded as strings (part of the update for Amino v0.10.1) + * `syncing` is now called `catching_up` - [types] Update Amino to v0.10.1 * Amino is now fully proto3 compatible for the basic types * JSON-encoded types now use the type name instead of the prefix bytes @@ -20,7 +103,6 @@ BREAKING CHANGES: * `tmlibs/merkle` -> `crypto/merkle`. Uses SHA256 instead of RIPEMD160 - [tmlibs] Update to v0.9.0 and merge into `libs` * remove `merkle` package (moved to `crypto/merkle`) -- [rpc] `syncing` is now called `catching_up`. FEATURES - [cmd] Added metrics (served under `/metrics` using a Prometheus client; diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md new file mode 100644 index 000000000..c51a2ab6f --- /dev/null +++ b/CHANGELOG_PENDING.md @@ -0,0 +1,10 @@ +# Pending + +BREAKING CHANGES: +- [types] CanonicalTime uses nanoseconds instead of clipping to ms + - breaks serialization/signing of all messages with a timestamp + +IMPROVEMENTS: +- [blockchain] Improve fast-sync logic + - tweak params + - only process one block at a time to avoid starving diff --git a/abci/Dockerfile.develop b/DOCKER/Dockerfile.abci similarity index 100% rename from abci/Dockerfile.develop rename to DOCKER/Dockerfile.abci diff --git a/Gopkg.lock b/Gopkg.lock index 6f350c933..b70692a58 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -11,10 +11,10 @@ branch = "master" name = "github.com/btcsuite/btcd" packages = ["btcec"] - revision = "86fed781132ac890ee03e906e4ecd5d6fa180c64" + pruneopts = "UT" + revision = "f673a4b563b57b9a95832545c878669a7fa801d9" [[projects]] - branch = "master" name = "github.com/btcsuite/btcutil" packages = [ "base58", @@ -29,16 +29,15 @@ version = "v1.1.0" [[projects]] - branch = "master" name = "github.com/ebuchman/fail-test" packages = ["."] revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" [[projects]] - branch = "master" name = "github.com/fortytw2/leaktest" packages = ["."] - revision = "b008db64ef8daabb22ff6daa557f33b41d8f6ccd" + revision = "a5ef70473c97b71626b9abeda80ee92ba2a7de9e" + version = "v1.2.0" [[projects]] name = "github.com/fsnotify/fsnotify" @@ -82,8 +81,8 @@ "sortkeys", "types" ] - revision = "1adfc126b41513cc696b209667c8656ea7aac67c" - version = "v1.0.0" + revision = "7d68e886eac4f7e34d0d82241a6273d6c304c5cf" + version = "v1.1.0" [[projects]] name = "github.com/golang/protobuf" @@ -94,8 +93,8 @@ "ptypes/duration", "ptypes/timestamp" ] - revision = "925541529c1fa6821df4e44ce2723319eb2be768" - version = "v1.0.0" + revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" + version = "v1.1.0" [[projects]] branch = "master" @@ -132,7 +131,6 @@ version = "v1.0" [[projects]] - branch = "master" name = "github.com/jmhodges/levigo" packages = ["."] revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" @@ -157,9 +155,11 @@ [[projects]] branch = "master" + digest = "1:5ab79470a1d0fb19b041a624415612f8236b3c06070161a910562f2b2d064355" name = "github.com/mitchellh/mapstructure" packages = ["."] - revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b" + pruneopts = "UT" + revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac" [[projects]] name = "github.com/pelletier/go-toml" @@ -185,14 +185,15 @@ "prometheus", "prometheus/promhttp" ] - revision = "c5b7fccd204277076155f10851dad72b76a49317" - version = "v0.8.0" + revision = "ae27198cdd90bf12cd134ad79d1366a6cf49f632" [[projects]] branch = "master" + digest = "1:0f37e09b3e92aaeda5991581311f8dbf38944b36a3edec61cc2d1991f527554a" name = "github.com/prometheus/client_model" packages = ["go"] - revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" + pruneopts = "UT" + revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" [[projects]] branch = "master" @@ -213,10 +214,9 @@ "nfs", "xfs" ] - revision = "40f013a808ec4fa79def444a1a56de4d1727efcb" + revision = "ae68e2d4c00fed4943b5f6698d504a5fe083da8a" [[projects]] - branch = "master" name = "github.com/rcrowley/go-metrics" packages = ["."] revision = "e2704e165165ec55d062f5919b4b29494e9fa790" @@ -266,8 +266,8 @@ "assert", "require" ] - revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" - version = "v1.2.2" + revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" + version = "v1.2.1" [[projects]] branch = "master" @@ -286,7 +286,7 @@ "leveldb/table", "leveldb/util" ] - revision = "0d5a0ceb10cf9ab89fdd744cc8c50a83134f6697" + revision = "c4c61651e9e37fa117f53c5a906d3b63090d8445" [[projects]] branch = "master" @@ -333,10 +333,9 @@ "ripemd160", "salsa20/salsa" ] - revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" + revision = "a2144134853fc9a27a7b1e3eb4f19f1a76df13c9" [[projects]] - branch = "master" name = "golang.org/x/net" packages = [ "context", @@ -348,7 +347,7 @@ "netutil", "trace" ] - revision = "afe8f62b1d6bbd81f31868121a50b06d8188e1f9" + revision = "292b43bbf7cb8d35ddf40f8d5100ef3837cced3f" [[projects]] branch = "master" @@ -357,7 +356,8 @@ "cpu", "unix" ] - revision = "7138fd3d9dc8335c567ca206f4333fb75eb05d56" + pruneopts = "UT" + revision = "ac767d655b305d4e9612f5f6e33120b9176c4ad4" [[projects]] name = "golang.org/x/text" @@ -397,9 +397,11 @@ "credentials", "encoding", "encoding/proto", - "grpclb/grpc_lb_v1/messages", "grpclog", "internal", + "internal/backoff", + "internal/channelz", + "internal/grpcrand", "keepalive", "metadata", "naming", @@ -412,8 +414,8 @@ "tap", "transport" ] - revision = "d11072e7ca9811b1100b80ca0269ac831f06d024" - version = "v1.11.3" + revision = "168a6198bcb0ef175f7dacec0b8691fc141dc9b8" + version = "v1.13.0" [[projects]] name = "gopkg.in/yaml.v2" @@ -424,6 +426,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "304d47a4914b47a821cc79c2186e198a98321a52d5932a2df988f02849f1924d" + inputs-digest = "9beb2d27dc19e3f9e2c7f416f312f7129f5441b1b53def42503fc6f7d3a54b16" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 28394b8b3..3ddd36deb 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -23,73 +23,100 @@ # non-go = false # go-tests = true # unused-packages = true +# +########################################################### +# NOTE: All packages should be pinned to specific versions. +# Packages without releases must pin to a commit. -[[constraint]] - name = "github.com/ebuchman/fail-test" - branch = "master" - -[[constraint]] - name = "github.com/fortytw2/leaktest" - branch = "master" - [[constraint]] name = "github.com/go-kit/kit" - version = "=0.6.0" + version = "=0.7.0" [[constraint]] name = "github.com/gogo/protobuf" - version = "=1.0.0" + version = "=1.1.1" [[constraint]] name = "github.com/golang/protobuf" - version = "=1.0.0" + version = "=1.1.0" [[constraint]] name = "github.com/gorilla/websocket" - version = "~1.2.0" + version = "=1.2.0" [[constraint]] name = "github.com/pkg/errors" version = "=0.8.0" -[[constraint]] - name = "github.com/rcrowley/go-metrics" - branch = "master" - [[constraint]] name = "github.com/spf13/cobra" - version = "=0.0.1" + version = "=0.0.3" [[constraint]] name = "github.com/spf13/viper" - version = "=1.0.0" + version = "=1.0.2" [[constraint]] name = "github.com/stretchr/testify" - version = "~1.2.1" + version = "=1.2.2" [[constraint]] name = "github.com/tendermint/go-amino" - version = "~0.10.1" + version = "=v0.11.1" [[constraint]] name = "google.golang.org/grpc" - version = "~1.11.3" + version = "=1.13.0" + +[[constraint]] + name = "github.com/fortytw2/leaktest" + version = "=1.2.0" + +################################### +## Some repos dont have releases. +## Pin to revision -# this got updated and broke, so locked to an old working commit ... +## We can remove this one by updating protobuf to v1.1.0 +## but then the grpc tests break with +#--- FAIL: TestBroadcastTx (0.01s) +#panic: message/group field common.KVPair:bytes without pointer [recovered] +# panic: message/group field common.KVPair:bytes without pointer +# +# ... +# +# github.com/tendermint/tendermint/rpc/grpc_test.TestBroadcastTx(0xc420a5ab40) +# /go/src/github.com/tendermint/tendermint/rpc/grpc/grpc_test.go:29 +0x141 [[override]] name = "google.golang.org/genproto" revision = "7fd901a49ba6a7f87732eb344f6e3c5b19d1b200" -[prune] - go-tests = true - unused-packages = true +[[override]] + name = "github.com/jmhodges/levigo" + revision = "c42d9e0ca023e2198120196f842701bb4c55d7b9" + +[[constraint]] + name = "github.com/ebuchman/fail-test" + revision = "95f809107225be108efcf10a3509e4ea6ceef3c4" + +# last revision used by go-crypto +[[constraint]] + name = "github.com/btcsuite/btcutil" + revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" +# Haven't made a release since 2016. [[constraint]] name = "github.com/prometheus/client_golang" - version = "0.8.0" + revision = "ae27198cdd90bf12cd134ad79d1366a6cf49f632" + +[[constraint]] + name = "github.com/rcrowley/go-metrics" + revision = "e2704e165165ec55d062f5919b4b29494e9fa790" [[constraint]] - branch = "master" name = "golang.org/x/net" + revision = "292b43bbf7cb8d35ddf40f8d5100ef3837cced3f" + +[prune] + go-tests = true + unused-packages = true diff --git a/Makefile b/Makefile index 0f7578c0b..14e48ee0a 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,14 @@ GOTOOLS = \ + github.com/mitchellh/gox \ 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/gogoproto \ + github.com/square/certstrap PACKAGES=$(shell go list ./... | grep -v '/vendor/') -BUILD_TAGS?=tendermint + +INCLUDE = -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf +BUILD_TAGS?='tendermint' BUILD_FLAGS = -ldflags "-X github.com/tendermint/tendermint/version.GitCommit=`git rev-parse --short=8 HEAD`" all: check build test install @@ -11,23 +17,48 @@ check: check_tools ensure_deps ######################################## -### Build +### Build Tendermint build: - CGO_ENABLED=0 go build $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' -o build/tendermint ./cmd/tendermint/ + CGO_ENABLED=0 go build $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o build/tendermint ./cmd/tendermint/ build_race: - CGO_ENABLED=0 go build -race $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' -o build/tendermint ./cmd/tendermint + CGO_ENABLED=0 go build -race $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o build/tendermint ./cmd/tendermint install: - CGO_ENABLED=0 go install $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' ./cmd/tendermint + CGO_ENABLED=0 go install $(BUILD_FLAGS) -tags $(BUILD_TAGS) ./cmd/tendermint + +######################################## +### Protobuf + +protoc_all: protoc_libs protoc_abci protoc_grpc + +%.pb.go: %.proto + ## If you get the following error, + ## "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" + ## See https://stackoverflow.com/a/25518702 + protoc $(INCLUDE) $< --gogo_out=plugins=grpc:. + @echo "--> adding nolint declarations to protobuf generated files" + @awk -i inplace '/^\s*package \w+/ { print "//nolint" }1' $@ + +######################################## +### Build ABCI + +protoc_abci: abci/types/types.pb.go + +build_abci: + @go build -i ./abci/cmd/... + +install_abci: + @go install ./abci/cmd/... ######################################## ### Distribution # dist builds binaries for all platforms and packages them for distribution +# TODO add abci to these scripts dist: - @BUILD_TAGS='$(BUILD_TAGS)' sh -c "'$(CURDIR)/scripts/dist.sh'" + @BUILD_TAGS=$(BUILD_TAGS) sh -c "'$(CURDIR)/scripts/dist.sh'" ######################################## ### Tools & dependencies @@ -59,6 +90,17 @@ ensure_deps: @echo "--> Running dep" @dep ensure +#For ABCI and libs +get_protoc: + @# https://github.com/google/protobuf/releases + curl -L https://github.com/google/protobuf/releases/download/v3.4.1/protobuf-cpp-3.4.1.tar.gz | tar xvz && \ + cd protobuf-3.4.1 && \ + DIST_LANG=cpp ./configure && \ + make && \ + make install && \ + cd .. && \ + rm -rf protobuf-3.4.1 + draw_deps: @# requires brew install graphviz or apt-get install graphviz go get github.com/RobotsAndPencils/goviz @@ -66,10 +108,36 @@ draw_deps: get_deps_bin_size: @# Copy of build recipe with additional flags to perform binary size analysis - $(eval $(shell go build -work -a $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' -o build/tendermint ./cmd/tendermint/ 2>&1)) + $(eval $(shell go build -work -a $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o build/tendermint ./cmd/tendermint/ 2>&1)) @find $(WORK) -type f -name "*.a" | xargs -I{} du -hxs "{}" | sort -rh | sed -e s:${WORK}/::g > deps_bin_size.log @echo "Results can be found here: $(CURDIR)/deps_bin_size.log" +######################################## +### Libs + +protoc_libs: libs/common/types.pb.go + +gen_certs: clean_certs + ## Generating certificates for TLS testing... + certstrap init --common-name "tendermint.com" --passphrase "" + certstrap request-cert -ip "::" --passphrase "" + certstrap sign "::" --CA "tendermint.com" --passphrase "" + mv out/::.crt out/::.key db/remotedb + +clean_certs: + ## Cleaning TLS testing certificates... + rm -rf out + rm -f db/remotedb/::.crt db/remotedb/::.key + +test_libs: gen_certs + GOCACHE=off go test -tags gcc $(PACKAGES) + make clean_certs + +grpc_dbserver: + protoc -I db/remotedb/proto/ db/remotedb/proto/defs.proto --go_out=plugins=grpc:db/remotedb/proto + +protoc_grpc: rpc/grpc/types.pb.go + ######################################## ### Testing @@ -87,6 +155,15 @@ test_apps: # requires `abci-cli` and `tendermint` binaries installed bash test/app/test.sh +test_abci_apps: + bash abci/tests/test_app/test.sh + +test_abci_cli: + # test the cli against the examples in the tutorial at: + # ./docs/abci-cli.md + # if test fails, update the docs ^ + @ bash abci/tests/test_cli/test.sh + test_persistence: # run the persistence tests using bash # requires `abci-cli` installed @@ -105,17 +182,16 @@ test_p2p: # requires 'tester' the image from above bash test/p2p/test.sh tester -need_abci: - bash scripts/install_abci_apps.sh - test_integrations: make build_docker_test_image make get_tools make get_vendor_deps make install - make need_abci make test_cover make test_apps + make test_abci_apps + make test_abci_cli + make test_libs make test_persistence make test_p2p @@ -233,4 +309,4 @@ build-slate: # To avoid unintended conflicts with file names, always add to .PHONY # unless there is a reason not to. # https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONY: check build build_race dist install check_tools get_tools update_tools get_vendor_deps draw_deps test_cover test_apps test_persistence test_p2p test test_race test_integrations test_release test100 vagrant_test fmt build-linux localnet-start localnet-stop build-docker build-docker-localnode sentry-start sentry-config sentry-stop build-slate +.PHONY: check build build_race build_abci dist install install_abci check_tools get_tools update_tools get_vendor_deps draw_deps get_protoc protoc_abci protoc_libs gen_certs clean_certs grpc_dbserver test_cover test_apps test_persistence test_p2p test test_race test_integrations test_release test100 vagrant_test fmt build-linux localnet-start localnet-stop build-docker build-docker-localnode sentry-start sentry-config sentry-stop build-slate protoc_grpc protoc_all diff --git a/README.md b/README.md index 2f7d13cdd..6268e0547 100644 --- a/README.md +++ b/README.md @@ -50,13 +50,13 @@ Go version | Go1.9 or higher ## Install -See the [install instructions](/docs/install.md) +See the [install instructions](/docs/introduction/install.md) ## Quick Start - [Single node](/docs/using-tendermint.md) - [Local cluster using docker-compose](/networks/local) -- [Remote cluster using terraform and ansible](/docs/terraform-and-ansible.md) +- [Remote cluster using terraform and ansible](/docs/networks/terraform-and-ansible.md) - [Join the public testnet](https://cosmos.network/testnet) ## Resources diff --git a/abci/Makefile b/abci/Makefile deleted file mode 100644 index 7d1c4b2e5..000000000 --- a/abci/Makefile +++ /dev/null @@ -1,174 +0,0 @@ -GOTOOLS = \ - github.com/mitchellh/gox \ - github.com/golang/dep/cmd/dep \ - gopkg.in/alecthomas/gometalinter.v2 \ - github.com/gogo/protobuf/protoc-gen-gogo \ - github.com/gogo/protobuf/gogoproto -GOTOOLS_CHECK = gox dep gometalinter.v2 protoc protoc-gen-gogo -PACKAGES=$(shell go list ./... | grep -v '/vendor/') -INCLUDE = -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf - -all: check get_vendor_deps protoc build test install metalinter - -check: check_tools - - -######################################## -### Build - -protoc: - ## If you get the following error, - ## "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" - ## See https://stackoverflow.com/a/25518702 - protoc $(INCLUDE) --gogo_out=plugins=grpc:. types/*.proto - @echo "--> adding nolint declarations to protobuf generated files" - @awk '/package types/ { print "//nolint: gas"; print; next }1' types/types.pb.go > types/types.pb.go.new - @mv types/types.pb.go.new types/types.pb.go - -build: - @go build -i ./cmd/... - -dist: - @bash scripts/dist.sh - @bash scripts/publish.sh - -install: - @go install ./cmd/... - - -######################################## -### Tools & dependencies - -check_tools: - @# https://stackoverflow.com/a/25668869 - @echo "Found tools: $(foreach tool,$(GOTOOLS_CHECK),\ - $(if $(shell which $(tool)),$(tool),$(error "No $(tool) in PATH")))" - -get_tools: - @echo "--> Installing tools" - go get -u -v $(GOTOOLS) - @gometalinter.v2 --install - -get_protoc: - @# https://github.com/google/protobuf/releases - curl -L https://github.com/google/protobuf/releases/download/v3.4.1/protobuf-cpp-3.4.1.tar.gz | tar xvz && \ - cd protobuf-3.4.1 && \ - DIST_LANG=cpp ./configure && \ - make && \ - make install && \ - cd .. && \ - rm -rf protobuf-3.4.1 - -update_tools: - @echo "--> Updating tools" - @go get -u $(GOTOOLS) - -get_vendor_deps: - @rm -rf vendor/ - @echo "--> Running dep ensure" - @dep ensure - - -######################################## -### Testing - -test: - @find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; - @echo "==> Running go test" - @go test $(PACKAGES) - -test_race: - @find . -path ./vendor -prune -o -name "*.sock" -exec rm {} \; - @echo "==> Running go test --race" - @go test -v -race $(PACKAGES) - -### three tests tested by Jenkins -test_cover: - @ bash tests/test_cover.sh - -test_apps: - # test the counter using a go test script - @ bash tests/test_app/test.sh - -test_cli: - # test the cli against the examples in the tutorial at: - # http://tendermint.readthedocs.io/projects/tools/en/master/abci-cli.html - # - # XXX: if this test fails, fix it and update the docs at: - # https://github.com/tendermint/tendermint/blob/develop/docs/abci-cli.rst - @ bash tests/test_cli/test.sh - -######################################## -### Formatting, linting, and vetting - -fmt: - @go fmt ./... - -metalinter: - @echo "==> Running linter" - gometalinter.v2 --vendor --deadline=600s --disable-all \ - --enable=maligned \ - --enable=deadcode \ - --enable=goconst \ - --enable=goimports \ - --enable=gosimple \ - --enable=ineffassign \ - --enable=megacheck \ - --enable=misspell \ - --enable=staticcheck \ - --enable=safesql \ - --enable=structcheck \ - --enable=unconvert \ - --enable=unused \ - --enable=varcheck \ - --enable=vetshadow \ - ./... - #--enable=gas \ - #--enable=dupl \ - #--enable=errcheck \ - #--enable=gocyclo \ - #--enable=golint \ <== comments on anything exported - #--enable=gotype \ - #--enable=interfacer \ - #--enable=unparam \ - #--enable=vet \ - -metalinter_all: - protoc $(INCLUDE) --lint_out=. types/*.proto - gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./... - - -######################################## -### Docker - -DEVDOC_SAVE = docker commit `docker ps -a -n 1 -q` devdoc:local - -docker_build: - docker build -t "tendermint/abci-dev" -f Dockerfile.develop . - -docker_run: - docker run -it -v "$(CURDIR):/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" "tendermint/abci-dev" /bin/bash - -docker_run_rm: - docker run -it --rm -v "$(CURDIR):/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" "tendermint/abci-dev" /bin/bash - -devdoc_init: - docker run -it -v "$(CURDIR):/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" tendermint/devdoc echo - # TODO make this safer - $(call DEVDOC_SAVE) - -devdoc: - docker run -it -v "$(CURDIR):/go/src/github.com/tendermint/abci" -w "/go/src/github.com/tendermint/abci" devdoc:local bash - -devdoc_save: - # TODO make this safer - $(call DEVDOC_SAVE) - -devdoc_clean: - docker rmi $$(docker images -f "dangling=true" -q) - - -# To avoid unintended conflicts with file names, always add to .PHONY -# unless there is a reason not to. -# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONY: check protoc build dist install check_tools get_tools get_protoc update_tools get_vendor_deps test test_race fmt metalinter metalinter_all docker_build docker_run docker_run_rm devdoc_init devdoc devdoc_save devdoc_clean diff --git a/abci/client/socket_client.go b/abci/client/socket_client.go index c3f88725c..affea1a9e 100644 --- a/abci/client/socket_client.go +++ b/abci/client/socket_client.go @@ -357,6 +357,13 @@ func (cli *socketClient) queueRequest(req *types.Request) *ReqRes { } func (cli *socketClient) flushQueue() { + // mark all in-flight messages as resolved (they will get cli.Error()) + for req := cli.reqSent.Front(); req != nil; req = req.Next() { + reqres := req.Value.(*ReqRes) + reqres.Done() + } + + // mark all queued messages as resolved LOOP: for { select { diff --git a/abci/client/socket_client_test.go b/abci/client/socket_client_test.go index 5a9187fb4..49114afd5 100644 --- a/abci/client/socket_client_test.go +++ b/abci/client/socket_client_test.go @@ -2,10 +2,17 @@ package abcicli_test import ( "errors" + "fmt" "testing" "time" - "github.com/tendermint/tendermint/abci/client" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + abcicli "github.com/tendermint/tendermint/abci/client" + "github.com/tendermint/tendermint/abci/server" + "github.com/tendermint/tendermint/abci/types" + cmn "github.com/tendermint/tendermint/libs/common" ) func TestSocketClientStopForErrorDeadlock(t *testing.T) { @@ -26,3 +33,89 @@ func TestSocketClientStopForErrorDeadlock(t *testing.T) { t.Fatalf("Test took too long, potential deadlock still exists") } } + +func TestProperSyncCalls(t *testing.T) { + app := slowApp{} + + s, c := setupClientServer(t, app) + defer s.Stop() + defer c.Stop() + + resp := make(chan error, 1) + go func() { + // This is BeginBlockSync unrolled.... + reqres := c.BeginBlockAsync(types.RequestBeginBlock{}) + c.FlushSync() + res := reqres.Response.GetBeginBlock() + require.NotNil(t, res) + resp <- c.Error() + }() + + select { + case <-time.After(time.Second): + require.Fail(t, "No response arrived") + case err, ok := <-resp: + require.True(t, ok, "Must not close channel") + assert.NoError(t, err, "This should return success") + } +} + +func TestHangingSyncCalls(t *testing.T) { + app := slowApp{} + + s, c := setupClientServer(t, app) + defer s.Stop() + defer c.Stop() + + resp := make(chan error, 1) + go func() { + // Start BeginBlock and flush it + reqres := c.BeginBlockAsync(types.RequestBeginBlock{}) + flush := c.FlushAsync() + // wait 20 ms for all events to travel socket, but + // no response yet from server + time.Sleep(20 * time.Millisecond) + // kill the server, so the connections break + s.Stop() + + // wait for the response from BeginBlock + reqres.Wait() + flush.Wait() + resp <- c.Error() + }() + + select { + case <-time.After(time.Second): + require.Fail(t, "No response arrived") + case err, ok := <-resp: + require.True(t, ok, "Must not close channel") + assert.Error(t, err, "We should get EOF error") + } +} + +func setupClientServer(t *testing.T, app types.Application) ( + cmn.Service, abcicli.Client) { + // some port between 20k and 30k + port := 20000 + cmn.RandInt32()%10000 + addr := fmt.Sprintf("localhost:%d", port) + + s, err := server.NewServer(addr, "socket", app) + require.NoError(t, err) + err = s.Start() + require.NoError(t, err) + + c := abcicli.NewSocketClient(addr, true) + err = c.Start() + require.NoError(t, err) + + return s, c +} + +type slowApp struct { + types.BaseApplication +} + +func (slowApp) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock { + time.Sleep(200 * time.Millisecond) + return types.ResponseBeginBlock{} +} diff --git a/abci/scripts/abci-builder/Dockerfile b/abci/scripts/abci-builder/Dockerfile deleted file mode 100644 index 1182085b4..000000000 --- a/abci/scripts/abci-builder/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM golang:1.9.2 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - zip \ - && rm -rf /var/lib/apt/lists/* - -# We want to ensure that release builds never have any cgo dependencies so we -# switch that off at the highest level. -ENV CGO_ENABLED 0 - -RUN mkdir -p $GOPATH/src/github.com/tendermint/abci -WORKDIR $GOPATH/src/github.com/tendermint/abci diff --git a/abci/scripts/dist.sh b/abci/scripts/dist.sh deleted file mode 100755 index d94ce20f7..000000000 --- a/abci/scripts/dist.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash -set -e - -REPO_NAME="abci" - -# Get the version from the environment, or try to figure it out. -if [ -z $VERSION ]; then - VERSION=$(awk -F\" '/Version =/ { print $2; exit }' < version/version.go) -fi -if [ -z "$VERSION" ]; then - echo "Please specify a version." - exit 1 -fi -echo "==> Building version $VERSION..." - -# Get the parent directory of where this script is. -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done -DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" - -# Change into that dir because we expect that. -cd "$DIR" - -# Delete the old dir -echo "==> Removing old directory..." -rm -rf build/pkg -mkdir -p build/pkg - - -# Do a hermetic build inside a Docker container. -docker build -t tendermint/${REPO_NAME}-builder scripts/${REPO_NAME}-builder/ -docker run --rm -e "BUILD_TAGS=$BUILD_TAGS" -v "$(pwd)":/go/src/github.com/tendermint/${REPO_NAME} tendermint/${REPO_NAME}-builder ./scripts/dist_build.sh - -# Add $REPO_NAME and $VERSION prefix to package name. -rm -rf ./build/dist -mkdir -p ./build/dist -for FILENAME in $(find ./build/pkg -mindepth 1 -maxdepth 1 -type f); do - FILENAME=$(basename "$FILENAME") - cp "./build/pkg/${FILENAME}" "./build/dist/${REPO_NAME}_${VERSION}_${FILENAME}" -done - -# Make the checksums. -pushd ./build/dist -shasum -a256 ./* > "./${REPO_NAME}_${VERSION}_SHA256SUMS" -popd - -# Done -echo -echo "==> Results:" -ls -hl ./build/dist - -exit 0 diff --git a/abci/scripts/dist_build.sh b/abci/scripts/dist_build.sh deleted file mode 100755 index c45c752ef..000000000 --- a/abci/scripts/dist_build.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -set -e - -# Get the parent directory of where this script is. -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done -DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" - -# Change into that dir because we expect that. -cd "$DIR" - -# Get the git commit -GIT_COMMIT="$(git rev-parse --short HEAD)" -GIT_DESCRIBE="$(git describe --tags --always)" -GIT_IMPORT="github.com/tendermint/abci/version" - -# Determine the arch/os combos we're building for -XC_ARCH=${XC_ARCH:-"386 amd64 arm"} -XC_OS=${XC_OS:-"solaris darwin freebsd linux windows"} - -# Make sure build tools are available. -make get_tools - -# Get VENDORED dependencies -make get_vendor_deps - -BINARY="abci-cli" - -# Build! -echo "==> Building..." -"$(which gox)" \ - -os="${XC_OS}" \ - -arch="${XC_ARCH}" \ - -osarch="!darwin/arm !solaris/amd64 !freebsd/amd64" \ - -ldflags "-X ${GIT_IMPORT}.GitCommit='${GIT_COMMIT}' -X ${GIT_IMPORT}.GitDescribe='${GIT_DESCRIBE}'" \ - -output "build/pkg/{{.OS}}_{{.Arch}}/$BINARY" \ - -tags="${BUILD_TAGS}" \ - github.com/tendermint/abci/cmd/$BINARY - -# Zip all the files. -echo "==> Packaging..." -for PLATFORM in $(find ./build/pkg -mindepth 1 -maxdepth 1 -type d); do - OSARCH=$(basename "${PLATFORM}") - echo "--> ${OSARCH}" - - pushd "$PLATFORM" >/dev/null 2>&1 - zip "../${OSARCH}.zip" ./* - popd >/dev/null 2>&1 -done - - - -exit 0 diff --git a/abci/scripts/publish.sh b/abci/scripts/publish.sh deleted file mode 100644 index 715f6c11b..000000000 --- a/abci/scripts/publish.sh +++ /dev/null @@ -1,7 +0,0 @@ -#! /bin/bash - -# Get the version from the environment, or try to figure it out. -if [ -z $VERSION ]; then - VERSION=$(awk -F\" '/Version =/ { print $2; exit }' < version/version.go) -fi -aws s3 cp --recursive build/dist s3://tendermint/binaries/abci/v${VERSION} --acl public-read diff --git a/abci/specification.rst b/abci/specification.rst deleted file mode 100644 index 8d8530def..000000000 --- a/abci/specification.rst +++ /dev/null @@ -1,294 +0,0 @@ -ABCI Specification -================== - -NOTE: this file has moved to `specification.md <./specification.md>`__. It is left to prevent link breakages for the forseable future. It can safely be deleted in a few months. - -Message Types -~~~~~~~~~~~~~ - -ABCI requests/responses are defined as simple Protobuf messages in `this -schema -file `__. -TendermintCore sends the requests, and the ABCI application sends the -responses. Here, we provide an overview of the messages types and how they -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 -^^^^ - -- **Arguments**: - - - ``Message (string)``: A string to echo back - -- **Returns**: - - - ``Message (string)``: The input string - -- **Usage**: - - - Echo a string to test an abci client/server implementation - -Flush -^^^^^ - -- **Usage**: - - - Signals that messages queued on the client should be flushed to - the server. It is called periodically by the client implementation - to ensure asynchronous requests are actually sent, and is called - immediately to make a synchronous request, which returns when the - Flush response comes back. - -Info -^^^^ - -- **Arguments**: - - - ``Version (string)``: The Tendermint version - -- **Returns**: - - - ``Data (string)``: Some arbitrary information - - ``Version (Version)``: Version information - - ``LastBlockHeight (int64)``: Latest block for which the app has - called Commit - - ``LastBlockAppHash ([]byte)``: Latest result of Commit - -- **Usage**: - - - Return information about the application state. - - Used to sync 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 -^^^^^^^^^ - -- **Arguments**: - - - ``Key (string)``: Key to set - - ``Value (string)``: Value to set for key - -- **Returns**: - - - ``Code (uint32)``: Response code - - ``Log (string)``: The output of the application's logger. May be non-deterministic. - - ``Info (string)``: Additional information. May be non-deterministic. - -- **Usage**: - - - Set non-consensus critical application specific options. - - e.g. Key="min-fee", Value="100fermion" could set the minimum fee required for CheckTx - (but not DeliverTx - that would be consensus critical). - -InitChain -^^^^^^^^^ - -- **Arguments**: - - - ``Validators ([]Validator)``: Initial genesis validators - - ``AppStateBytes ([]byte)``: Serialized initial application state - -- **Usage**: - - - Called once upon genesis. - -Query -^^^^^ - -- **Arguments**: - - - ``Data ([]byte)``: Raw query bytes. Can be used with or in lieu of - Path. - - ``Path (string)``: Path of request, like an HTTP GET path. Can be - used with or in liue of Data. - - Apps MUST interpret '/store' as a query by key on the underlying - store. The key SHOULD be specified in the Data field. - - Apps SHOULD allow queries over specific types like '/accounts/...' - or '/votes/...' - - ``Height (int64)``: The block height for which you want the query - (default=0 returns data for the latest committed block). Note that - this is the height of the block containing the application's - Merkle root hash, which represents the state as it was after - committing the block at Height-1 - - ``Prove (bool)``: Return Merkle proof with response if possible - -- **Returns**: - - - ``Code (uint32)``: Response code. - - ``Log (string)``: The output of the application's logger. May be non-deterministic. - - ``Info (string)``: Additional information. May be non-deterministic. - - ``Index (int64)``: The index of the key in the tree. - - ``Key ([]byte)``: The key of the matching data. - - ``Value ([]byte)``: The value of the matching data. - - ``Proof ([]byte)``: Proof for the data, if requested. - - ``Height (int64)``: The block height from which data was derived. - Note that this is the height of the block containing the - application's Merkle root hash, which represents the state as it - was after committing the block at Height-1 - -- **Usage**: - - - Query for data from the application at current or past height. - - Optionally return Merkle proof. - -BeginBlock -^^^^^^^^^^ - -- **Arguments**: - - - ``Hash ([]byte)``: The block's hash. This can be derived from the - block header. - - ``Header (struct{})``: The block header - - ``AbsentValidators ([]int32)``: List of indices of validators not - included in the LastCommit - - ``ByzantineValidators ([]Evidence)``: List of evidence of - validators that acted maliciously - -- **Usage**: - - - Signals the beginning of a new block. Called prior to any DeliverTxs. - - The header is expected to at least contain the Height. - - The ``AbsentValidators`` and ``ByzantineValidators`` can be used to - determine rewards and punishments for the validators. - -CheckTx -^^^^^^^ - -- **Arguments**: - - - ``Tx ([]byte)``: The request transaction bytes - -- **Returns**: - - - ``Code (uint32)``: Response code - - ``Data ([]byte)``: Result bytes, if any. - - ``Log (string)``: The output of the application's logger. May be non-deterministic. - - ``Info (string)``: Additional information. May be non-deterministic. - - ``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). - - ``Fee (cmn.KI64Pair)``: Fee paid for the transaction. - -- **Usage**: Validate a mempool transaction, prior to broadcasting or - proposing. CheckTx should perform stateful but light-weight checks - of the validity of the transaction (like checking signatures and account balances), - but need not execute in full (like running a smart contract). - - Tendermint runs CheckTx and DeliverTx concurrently with eachother, - though on distinct ABCI connections - the mempool connection and the consensus - connection, respectively. - - The application should maintain a separate state to support CheckTx. - 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. - - Keys and values in Tags must be UTF-8 encoded strings (e.g. "account.owner": "Bob", "balance": "100.0", "date": "2018-01-02") - - -DeliverTx -^^^^^^^^^ - -- **Arguments**: - - - ``Tx ([]byte)``: The request transaction bytes. - -- **Returns**: - - - ``Code (uint32)``: Response code. - - ``Data ([]byte)``: Result bytes, if any. - - ``Log (string)``: The output of the application's logger. May be non-deterministic. - - ``Info (string)``: Additional information. May be non-deterministic. - - ``GasWanted (int64)``: Amount of gas requested for transaction. - - ``GasUsed (int64)``: Amount of gas consumed by transaction. - - ``Tags ([]cmn.KVPair)``: Key-Value tags for filtering and indexing transactions (eg. by account). - - ``Fee (cmn.KI64Pair)``: Fee paid for the transaction. - -- **Usage**: - - - Deliver a transaction to be executed in full by the application. If the transaction is valid, - returns CodeType.OK. - - Keys and values in Tags must be UTF-8 encoded strings (e.g. "account.owner": "Bob", "balance": "100.0", "time": "2018-01-02T12:30:00Z") - -EndBlock -^^^^^^^^ - -- **Arguments**: - - - ``Height (int64)``: Height of the block just executed. - -- **Returns**: - - - ``ValidatorUpdates ([]Validator)``: Changes to validator set (set - voting power to 0 to remove). - - ``ConsensusParamUpdates (ConsensusParams)``: Changes to - consensus-critical time, size, and other parameters. - -- **Usage**: - - - Signals the end of a block. - - Called prior to each Commit, after all transactions. - - Validator set and consensus params are updated with the result. - - Validator pubkeys are expected to be go-wire encoded. - -Commit -^^^^^^ - -- **Returns**: - - - ``Data ([]byte)``: The Merkle root hash - -- **Usage**: - - - Persist the application state. - - Return a Merkle root hash of the application state. - - It's critical that all application instances return the same hash. If not, - they will not be able to agree on the next block, because the hash is - included in the next block! diff --git a/abci/tests/test_cover.sh b/abci/tests/test_cover.sh deleted file mode 100755 index abbbbe563..000000000 --- a/abci/tests/test_cover.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -e -echo "" > coverage.txt - -echo "==> Running unit tests" -for d in $(go list ./... | grep -v vendor); do - go test -race -coverprofile=profile.out -covermode=atomic "$d" - if [ -f profile.out ]; then - cat profile.out >> coverage.txt - rm profile.out - fi -done diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index 8135db50f..57dd14393 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -1,62 +1,68 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: types/types.proto +// source: abci/types/types.proto /* -Package types is a generated protocol buffer package. - -It is generated from these files: - types/types.proto - -It has these top-level messages: - Request - RequestEcho - RequestFlush - RequestInfo - RequestSetOption - RequestInitChain - RequestQuery - RequestBeginBlock - RequestCheckTx - RequestDeliverTx - RequestEndBlock - RequestCommit - Response - ResponseException - ResponseEcho - ResponseFlush - ResponseInfo - ResponseSetOption - ResponseInitChain - ResponseQuery - ResponseBeginBlock - ResponseCheckTx - ResponseDeliverTx - ResponseEndBlock - ResponseCommit - ConsensusParams - BlockSize - TxSize - BlockGossip - Header - Validator - SigningValidator - PubKey - Evidence + Package types is a generated protocol buffer package. + + It is generated from these files: + abci/types/types.proto + + It has these top-level messages: + Request + RequestEcho + RequestFlush + RequestInfo + RequestSetOption + RequestInitChain + RequestQuery + RequestBeginBlock + RequestCheckTx + RequestDeliverTx + RequestEndBlock + RequestCommit + Response + ResponseException + ResponseEcho + ResponseFlush + ResponseInfo + ResponseSetOption + ResponseInitChain + ResponseQuery + ResponseBeginBlock + ResponseCheckTx + ResponseDeliverTx + ResponseEndBlock + ResponseCommit + ConsensusParams + BlockSize + TxSize + BlockGossip + Header + Validator + SigningValidator + PubKey + Evidence */ -//nolint: gas +//nolint package types import proto "github.com/gogo/protobuf/proto" +import golang_proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" import _ "github.com/gogo/protobuf/gogoproto" import common "github.com/tendermint/tendermint/libs/common" +import bytes "bytes" + import context "golang.org/x/net/context" import grpc "google.golang.org/grpc" +import io "io" + // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal +var _ = golang_proto.Marshal var _ = fmt.Errorf var _ = math.Inf @@ -89,6 +95,9 @@ func (*Request) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int type isRequest_Value interface { isRequest_Value() + Equal(interface{}) bool + MarshalTo([]byte) (int, error) + Size() int } type Request_Echo struct { @@ -739,6 +748,9 @@ func (*Response) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []in type isResponse_Value interface { isResponse_Value() + Equal(interface{}) bool + MarshalTo([]byte) (int, error) + Size() int } type Response_Exception struct { @@ -1895,280 +1907,1913 @@ func (m *Evidence) GetTotalVotingPower() int64 { func init() { proto.RegisterType((*Request)(nil), "types.Request") + golang_proto.RegisterType((*Request)(nil), "types.Request") proto.RegisterType((*RequestEcho)(nil), "types.RequestEcho") + golang_proto.RegisterType((*RequestEcho)(nil), "types.RequestEcho") proto.RegisterType((*RequestFlush)(nil), "types.RequestFlush") + golang_proto.RegisterType((*RequestFlush)(nil), "types.RequestFlush") proto.RegisterType((*RequestInfo)(nil), "types.RequestInfo") + golang_proto.RegisterType((*RequestInfo)(nil), "types.RequestInfo") proto.RegisterType((*RequestSetOption)(nil), "types.RequestSetOption") + golang_proto.RegisterType((*RequestSetOption)(nil), "types.RequestSetOption") proto.RegisterType((*RequestInitChain)(nil), "types.RequestInitChain") + golang_proto.RegisterType((*RequestInitChain)(nil), "types.RequestInitChain") proto.RegisterType((*RequestQuery)(nil), "types.RequestQuery") + golang_proto.RegisterType((*RequestQuery)(nil), "types.RequestQuery") proto.RegisterType((*RequestBeginBlock)(nil), "types.RequestBeginBlock") + golang_proto.RegisterType((*RequestBeginBlock)(nil), "types.RequestBeginBlock") proto.RegisterType((*RequestCheckTx)(nil), "types.RequestCheckTx") + golang_proto.RegisterType((*RequestCheckTx)(nil), "types.RequestCheckTx") proto.RegisterType((*RequestDeliverTx)(nil), "types.RequestDeliverTx") + golang_proto.RegisterType((*RequestDeliverTx)(nil), "types.RequestDeliverTx") proto.RegisterType((*RequestEndBlock)(nil), "types.RequestEndBlock") + golang_proto.RegisterType((*RequestEndBlock)(nil), "types.RequestEndBlock") proto.RegisterType((*RequestCommit)(nil), "types.RequestCommit") + golang_proto.RegisterType((*RequestCommit)(nil), "types.RequestCommit") proto.RegisterType((*Response)(nil), "types.Response") + golang_proto.RegisterType((*Response)(nil), "types.Response") proto.RegisterType((*ResponseException)(nil), "types.ResponseException") + golang_proto.RegisterType((*ResponseException)(nil), "types.ResponseException") proto.RegisterType((*ResponseEcho)(nil), "types.ResponseEcho") + golang_proto.RegisterType((*ResponseEcho)(nil), "types.ResponseEcho") proto.RegisterType((*ResponseFlush)(nil), "types.ResponseFlush") + golang_proto.RegisterType((*ResponseFlush)(nil), "types.ResponseFlush") proto.RegisterType((*ResponseInfo)(nil), "types.ResponseInfo") + golang_proto.RegisterType((*ResponseInfo)(nil), "types.ResponseInfo") proto.RegisterType((*ResponseSetOption)(nil), "types.ResponseSetOption") + golang_proto.RegisterType((*ResponseSetOption)(nil), "types.ResponseSetOption") proto.RegisterType((*ResponseInitChain)(nil), "types.ResponseInitChain") + golang_proto.RegisterType((*ResponseInitChain)(nil), "types.ResponseInitChain") proto.RegisterType((*ResponseQuery)(nil), "types.ResponseQuery") + golang_proto.RegisterType((*ResponseQuery)(nil), "types.ResponseQuery") proto.RegisterType((*ResponseBeginBlock)(nil), "types.ResponseBeginBlock") + golang_proto.RegisterType((*ResponseBeginBlock)(nil), "types.ResponseBeginBlock") proto.RegisterType((*ResponseCheckTx)(nil), "types.ResponseCheckTx") + golang_proto.RegisterType((*ResponseCheckTx)(nil), "types.ResponseCheckTx") proto.RegisterType((*ResponseDeliverTx)(nil), "types.ResponseDeliverTx") + golang_proto.RegisterType((*ResponseDeliverTx)(nil), "types.ResponseDeliverTx") proto.RegisterType((*ResponseEndBlock)(nil), "types.ResponseEndBlock") + golang_proto.RegisterType((*ResponseEndBlock)(nil), "types.ResponseEndBlock") proto.RegisterType((*ResponseCommit)(nil), "types.ResponseCommit") + golang_proto.RegisterType((*ResponseCommit)(nil), "types.ResponseCommit") proto.RegisterType((*ConsensusParams)(nil), "types.ConsensusParams") + golang_proto.RegisterType((*ConsensusParams)(nil), "types.ConsensusParams") proto.RegisterType((*BlockSize)(nil), "types.BlockSize") + golang_proto.RegisterType((*BlockSize)(nil), "types.BlockSize") proto.RegisterType((*TxSize)(nil), "types.TxSize") + golang_proto.RegisterType((*TxSize)(nil), "types.TxSize") proto.RegisterType((*BlockGossip)(nil), "types.BlockGossip") + golang_proto.RegisterType((*BlockGossip)(nil), "types.BlockGossip") proto.RegisterType((*Header)(nil), "types.Header") + golang_proto.RegisterType((*Header)(nil), "types.Header") proto.RegisterType((*Validator)(nil), "types.Validator") + golang_proto.RegisterType((*Validator)(nil), "types.Validator") proto.RegisterType((*SigningValidator)(nil), "types.SigningValidator") + golang_proto.RegisterType((*SigningValidator)(nil), "types.SigningValidator") proto.RegisterType((*PubKey)(nil), "types.PubKey") + golang_proto.RegisterType((*PubKey)(nil), "types.PubKey") proto.RegisterType((*Evidence)(nil), "types.Evidence") + golang_proto.RegisterType((*Evidence)(nil), "types.Evidence") } +func (this *Request) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// Client API for ABCIApplication service - -type ABCIApplicationClient interface { - Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) - Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) - Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) - SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) - DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) - CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) - Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) - Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) - InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) - BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) - EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) -} - -type aBCIApplicationClient struct { - cc *grpc.ClientConn + that1, ok := that.(*Request) + if !ok { + that2, ok := that.(Request) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if that1.Value == nil { + if this.Value != nil { + return false + } + } else if this.Value == nil { + return false + } else if !this.Value.Equal(that1.Value) { + return false + } + return true } +func (this *Request_Echo) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func NewABCIApplicationClient(cc *grpc.ClientConn) ABCIApplicationClient { - return &aBCIApplicationClient{cc} + that1, ok := that.(*Request_Echo) + if !ok { + that2, ok := that.(Request_Echo) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Echo.Equal(that1.Echo) { + return false + } + return true } +func (this *Request_Flush) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) { - out := new(ResponseEcho) - err := grpc.Invoke(ctx, "/types.ABCIApplication/Echo", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*Request_Flush) + if !ok { + that2, ok := that.(Request_Flush) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Flush.Equal(that1.Flush) { + return false + } + return true } +func (this *Request_Info) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) { - out := new(ResponseFlush) - err := grpc.Invoke(ctx, "/types.ABCIApplication/Flush", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*Request_Info) + if !ok { + that2, ok := that.(Request_Info) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Info.Equal(that1.Info) { + return false + } + return true } +func (this *Request_SetOption) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) { - out := new(ResponseInfo) - err := grpc.Invoke(ctx, "/types.ABCIApplication/Info", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*Request_SetOption) + if !ok { + that2, ok := that.(Request_SetOption) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.SetOption.Equal(that1.SetOption) { + return false + } + return true } +func (this *Request_InitChain) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) { - out := new(ResponseSetOption) - err := grpc.Invoke(ctx, "/types.ABCIApplication/SetOption", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*Request_InitChain) + if !ok { + that2, ok := that.(Request_InitChain) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.InitChain.Equal(that1.InitChain) { + return false + } + return true } +func (this *Request_Query) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) { - out := new(ResponseDeliverTx) - err := grpc.Invoke(ctx, "/types.ABCIApplication/DeliverTx", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*Request_Query) + if !ok { + that2, ok := that.(Request_Query) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Query.Equal(that1.Query) { + return false + } + return true } +func (this *Request_BeginBlock) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) { - out := new(ResponseCheckTx) - err := grpc.Invoke(ctx, "/types.ABCIApplication/CheckTx", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*Request_BeginBlock) + if !ok { + that2, ok := that.(Request_BeginBlock) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.BeginBlock.Equal(that1.BeginBlock) { + return false + } + return true } +func (this *Request_CheckTx) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) { - out := new(ResponseQuery) - err := grpc.Invoke(ctx, "/types.ABCIApplication/Query", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*Request_CheckTx) + if !ok { + that2, ok := that.(Request_CheckTx) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.CheckTx.Equal(that1.CheckTx) { + return false + } + return true } +func (this *Request_DeliverTx) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { - out := new(ResponseCommit) - err := grpc.Invoke(ctx, "/types.ABCIApplication/Commit", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*Request_DeliverTx) + if !ok { + that2, ok := that.(Request_DeliverTx) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.DeliverTx.Equal(that1.DeliverTx) { + return false + } + return true } +func (this *Request_EndBlock) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) { - out := new(ResponseInitChain) - err := grpc.Invoke(ctx, "/types.ABCIApplication/InitChain", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*Request_EndBlock) + if !ok { + that2, ok := that.(Request_EndBlock) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.EndBlock.Equal(that1.EndBlock) { + return false + } + return true } +func (this *Request_Commit) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) { - out := new(ResponseBeginBlock) - err := grpc.Invoke(ctx, "/types.ABCIApplication/BeginBlock", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*Request_Commit) + if !ok { + that2, ok := that.(Request_Commit) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Commit.Equal(that1.Commit) { + return false + } + return true } +func (this *RequestEcho) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func (c *aBCIApplicationClient) EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) { - out := new(ResponseEndBlock) - err := grpc.Invoke(ctx, "/types.ABCIApplication/EndBlock", in, out, c.cc, opts...) - if err != nil { - return nil, err + that1, ok := that.(*RequestEcho) + if !ok { + that2, ok := that.(RequestEcho) + if ok { + that1 = &that2 + } else { + return false + } } - return out, nil + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Message != that1.Message { + return false + } + return true } +func (this *RequestFlush) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -// Server API for ABCIApplication service - -type ABCIApplicationServer interface { - Echo(context.Context, *RequestEcho) (*ResponseEcho, error) - Flush(context.Context, *RequestFlush) (*ResponseFlush, error) - Info(context.Context, *RequestInfo) (*ResponseInfo, error) - SetOption(context.Context, *RequestSetOption) (*ResponseSetOption, error) - DeliverTx(context.Context, *RequestDeliverTx) (*ResponseDeliverTx, error) - CheckTx(context.Context, *RequestCheckTx) (*ResponseCheckTx, error) - Query(context.Context, *RequestQuery) (*ResponseQuery, error) - Commit(context.Context, *RequestCommit) (*ResponseCommit, error) - InitChain(context.Context, *RequestInitChain) (*ResponseInitChain, error) - BeginBlock(context.Context, *RequestBeginBlock) (*ResponseBeginBlock, error) - EndBlock(context.Context, *RequestEndBlock) (*ResponseEndBlock, error) + that1, ok := that.(*RequestFlush) + if !ok { + that2, ok := that.(RequestFlush) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true } +func (this *RequestInfo) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func RegisterABCIApplicationServer(s *grpc.Server, srv ABCIApplicationServer) { - s.RegisterService(&_ABCIApplication_serviceDesc, srv) + that1, ok := that.(*RequestInfo) + if !ok { + that2, ok := that.(RequestInfo) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Version != that1.Version { + return false + } + return true } +func (this *RequestSetOption) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func _ABCIApplication_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestEcho) - if err := dec(in); err != nil { - return nil, err + that1, ok := that.(*RequestSetOption) + if !ok { + that2, ok := that.(RequestSetOption) + if ok { + that1 = &that2 + } else { + return false + } } - if interceptor == nil { - return srv.(ABCIApplicationServer).Echo(ctx, in) + if that1 == nil { + return this == nil + } else if this == nil { + return false } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/Echo", + if this.Key != that1.Key { + return false } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).Echo(ctx, req.(*RequestEcho)) + if this.Value != that1.Value { + return false } - return interceptor(ctx, in, info, handler) + return true } +func (this *RequestInitChain) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func _ABCIApplication_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestFlush) - if err := dec(in); err != nil { - return nil, err + that1, ok := that.(*RequestInitChain) + if !ok { + that2, ok := that.(RequestInitChain) + if ok { + that1 = &that2 + } else { + return false + } } - if interceptor == nil { - return srv.(ABCIApplicationServer).Flush(ctx, in) + if that1 == nil { + return this == nil + } else if this == nil { + return false } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/Flush", + if this.Time != that1.Time { + return false } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).Flush(ctx, req.(*RequestFlush)) + if this.ChainId != that1.ChainId { + return false } - return interceptor(ctx, in, info, handler) -} - -func _ABCIApplication_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestInfo) - if err := dec(in); err != nil { - return nil, err + if !this.ConsensusParams.Equal(that1.ConsensusParams) { + return false } - if interceptor == nil { - return srv.(ABCIApplicationServer).Info(ctx, in) + if len(this.Validators) != len(that1.Validators) { + return false } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/Info", + for i := range this.Validators { + if !this.Validators[i].Equal(&that1.Validators[i]) { + return false + } } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).Info(ctx, req.(*RequestInfo)) + if !bytes.Equal(this.AppStateBytes, that1.AppStateBytes) { + return false } - return interceptor(ctx, in, info, handler) + return true } +func (this *RequestQuery) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func _ABCIApplication_SetOption_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestSetOption) - if err := dec(in); err != nil { - return nil, err + that1, ok := that.(*RequestQuery) + if !ok { + that2, ok := that.(RequestQuery) + if ok { + that1 = &that2 + } else { + return false + } } - if interceptor == nil { - return srv.(ABCIApplicationServer).SetOption(ctx, in) + if that1 == nil { + return this == nil + } else if this == nil { + return false } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/SetOption", + if !bytes.Equal(this.Data, that1.Data) { + return false } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).SetOption(ctx, req.(*RequestSetOption)) + if this.Path != that1.Path { + return false } - return interceptor(ctx, in, info, handler) + if this.Height != that1.Height { + return false + } + if this.Prove != that1.Prove { + return false + } + return true } +func (this *RequestBeginBlock) Equal(that interface{}) bool { + if that == nil { + return this == nil + } -func _ABCIApplication_DeliverTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestDeliverTx) - if err := dec(in); err != nil { - return nil, err + that1, ok := that.(*RequestBeginBlock) + if !ok { + that2, ok := that.(RequestBeginBlock) + if ok { + that1 = &that2 + } else { + return false + } } - if interceptor == nil { - return srv.(ABCIApplicationServer).DeliverTx(ctx, in) + if that1 == nil { + return this == nil + } else if this == nil { + return false } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/DeliverTx", + if !bytes.Equal(this.Hash, that1.Hash) { + return false } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).DeliverTx(ctx, req.(*RequestDeliverTx)) + if !this.Header.Equal(&that1.Header) { + return false } - return interceptor(ctx, in, info, handler) + if len(this.Validators) != len(that1.Validators) { + return false + } + for i := range this.Validators { + if !this.Validators[i].Equal(&that1.Validators[i]) { + return false + } + } + if len(this.ByzantineValidators) != len(that1.ByzantineValidators) { + return false + } + for i := range this.ByzantineValidators { + if !this.ByzantineValidators[i].Equal(&that1.ByzantineValidators[i]) { + return false + } + } + return true +} +func (this *RequestCheckTx) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*RequestCheckTx) + if !ok { + that2, ok := that.(RequestCheckTx) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Tx, that1.Tx) { + return false + } + return true +} +func (this *RequestDeliverTx) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*RequestDeliverTx) + if !ok { + that2, ok := that.(RequestDeliverTx) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Tx, that1.Tx) { + return false + } + return true +} +func (this *RequestEndBlock) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*RequestEndBlock) + if !ok { + that2, ok := that.(RequestEndBlock) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Height != that1.Height { + return false + } + return true +} +func (this *RequestCommit) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*RequestCommit) + if !ok { + that2, ok := that.(RequestCommit) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (this *Response) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response) + if !ok { + that2, ok := that.(Response) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if that1.Value == nil { + if this.Value != nil { + return false + } + } else if this.Value == nil { + return false + } else if !this.Value.Equal(that1.Value) { + return false + } + return true +} +func (this *Response_Exception) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_Exception) + if !ok { + that2, ok := that.(Response_Exception) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Exception.Equal(that1.Exception) { + return false + } + return true +} +func (this *Response_Echo) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_Echo) + if !ok { + that2, ok := that.(Response_Echo) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Echo.Equal(that1.Echo) { + return false + } + return true +} +func (this *Response_Flush) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_Flush) + if !ok { + that2, ok := that.(Response_Flush) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Flush.Equal(that1.Flush) { + return false + } + return true +} +func (this *Response_Info) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_Info) + if !ok { + that2, ok := that.(Response_Info) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Info.Equal(that1.Info) { + return false + } + return true +} +func (this *Response_SetOption) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_SetOption) + if !ok { + that2, ok := that.(Response_SetOption) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.SetOption.Equal(that1.SetOption) { + return false + } + return true +} +func (this *Response_InitChain) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_InitChain) + if !ok { + that2, ok := that.(Response_InitChain) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.InitChain.Equal(that1.InitChain) { + return false + } + return true +} +func (this *Response_Query) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_Query) + if !ok { + that2, ok := that.(Response_Query) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Query.Equal(that1.Query) { + return false + } + return true +} +func (this *Response_BeginBlock) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_BeginBlock) + if !ok { + that2, ok := that.(Response_BeginBlock) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.BeginBlock.Equal(that1.BeginBlock) { + return false + } + return true +} +func (this *Response_CheckTx) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_CheckTx) + if !ok { + that2, ok := that.(Response_CheckTx) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.CheckTx.Equal(that1.CheckTx) { + return false + } + return true +} +func (this *Response_DeliverTx) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_DeliverTx) + if !ok { + that2, ok := that.(Response_DeliverTx) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.DeliverTx.Equal(that1.DeliverTx) { + return false + } + return true +} +func (this *Response_EndBlock) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_EndBlock) + if !ok { + that2, ok := that.(Response_EndBlock) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.EndBlock.Equal(that1.EndBlock) { + return false + } + return true +} +func (this *Response_Commit) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Response_Commit) + if !ok { + that2, ok := that.(Response_Commit) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Commit.Equal(that1.Commit) { + return false + } + return true +} +func (this *ResponseException) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseException) + if !ok { + that2, ok := that.(ResponseException) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Error != that1.Error { + return false + } + return true +} +func (this *ResponseEcho) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseEcho) + if !ok { + that2, ok := that.(ResponseEcho) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Message != that1.Message { + return false + } + return true +} +func (this *ResponseFlush) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseFlush) + if !ok { + that2, ok := that.(ResponseFlush) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (this *ResponseInfo) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseInfo) + if !ok { + that2, ok := that.(ResponseInfo) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Data != that1.Data { + return false + } + if this.Version != that1.Version { + return false + } + if this.LastBlockHeight != that1.LastBlockHeight { + return false + } + if !bytes.Equal(this.LastBlockAppHash, that1.LastBlockAppHash) { + return false + } + return true +} +func (this *ResponseSetOption) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseSetOption) + if !ok { + that2, ok := that.(ResponseSetOption) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Code != that1.Code { + return false + } + if this.Log != that1.Log { + return false + } + if this.Info != that1.Info { + return false + } + return true +} +func (this *ResponseInitChain) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseInitChain) + if !ok { + that2, ok := that.(ResponseInitChain) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.ConsensusParams.Equal(that1.ConsensusParams) { + return false + } + if len(this.Validators) != len(that1.Validators) { + return false + } + for i := range this.Validators { + if !this.Validators[i].Equal(&that1.Validators[i]) { + return false + } + } + return true +} +func (this *ResponseQuery) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseQuery) + if !ok { + that2, ok := that.(ResponseQuery) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Code != that1.Code { + return false + } + if this.Log != that1.Log { + return false + } + if this.Info != that1.Info { + return false + } + if this.Index != that1.Index { + return false + } + if !bytes.Equal(this.Key, that1.Key) { + return false + } + if !bytes.Equal(this.Value, that1.Value) { + return false + } + if !bytes.Equal(this.Proof, that1.Proof) { + return false + } + if this.Height != that1.Height { + return false + } + return true +} +func (this *ResponseBeginBlock) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseBeginBlock) + if !ok { + that2, ok := that.(ResponseBeginBlock) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.Tags) != len(that1.Tags) { + return false + } + for i := range this.Tags { + if !this.Tags[i].Equal(&that1.Tags[i]) { + return false + } + } + return true +} +func (this *ResponseCheckTx) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseCheckTx) + if !ok { + that2, ok := that.(ResponseCheckTx) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Code != that1.Code { + return false + } + if !bytes.Equal(this.Data, that1.Data) { + return false + } + if this.Log != that1.Log { + return false + } + if this.Info != that1.Info { + return false + } + if this.GasWanted != that1.GasWanted { + return false + } + if this.GasUsed != that1.GasUsed { + return false + } + if len(this.Tags) != len(that1.Tags) { + return false + } + for i := range this.Tags { + if !this.Tags[i].Equal(&that1.Tags[i]) { + return false + } + } + if !this.Fee.Equal(&that1.Fee) { + return false + } + return true +} +func (this *ResponseDeliverTx) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseDeliverTx) + if !ok { + that2, ok := that.(ResponseDeliverTx) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Code != that1.Code { + return false + } + if !bytes.Equal(this.Data, that1.Data) { + return false + } + if this.Log != that1.Log { + return false + } + if this.Info != that1.Info { + return false + } + if this.GasWanted != that1.GasWanted { + return false + } + if this.GasUsed != that1.GasUsed { + return false + } + if len(this.Tags) != len(that1.Tags) { + return false + } + for i := range this.Tags { + if !this.Tags[i].Equal(&that1.Tags[i]) { + return false + } + } + if !this.Fee.Equal(&that1.Fee) { + return false + } + return true +} +func (this *ResponseEndBlock) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseEndBlock) + if !ok { + that2, ok := that.(ResponseEndBlock) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if len(this.ValidatorUpdates) != len(that1.ValidatorUpdates) { + return false + } + for i := range this.ValidatorUpdates { + if !this.ValidatorUpdates[i].Equal(&that1.ValidatorUpdates[i]) { + return false + } + } + if !this.ConsensusParamUpdates.Equal(that1.ConsensusParamUpdates) { + return false + } + if len(this.Tags) != len(that1.Tags) { + return false + } + for i := range this.Tags { + if !this.Tags[i].Equal(&that1.Tags[i]) { + return false + } + } + return true +} +func (this *ResponseCommit) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseCommit) + if !ok { + that2, ok := that.(ResponseCommit) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Data, that1.Data) { + return false + } + return true +} +func (this *ConsensusParams) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ConsensusParams) + if !ok { + that2, ok := that.(ConsensusParams) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.BlockSize.Equal(that1.BlockSize) { + return false + } + if !this.TxSize.Equal(that1.TxSize) { + return false + } + if !this.BlockGossip.Equal(that1.BlockGossip) { + return false + } + return true +} +func (this *BlockSize) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*BlockSize) + if !ok { + that2, ok := that.(BlockSize) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MaxBytes != that1.MaxBytes { + return false + } + if this.MaxTxs != that1.MaxTxs { + return false + } + if this.MaxGas != that1.MaxGas { + return false + } + return true +} +func (this *TxSize) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*TxSize) + if !ok { + that2, ok := that.(TxSize) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.MaxBytes != that1.MaxBytes { + return false + } + if this.MaxGas != that1.MaxGas { + return false + } + return true +} +func (this *BlockGossip) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*BlockGossip) + if !ok { + that2, ok := that.(BlockGossip) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.BlockPartSizeBytes != that1.BlockPartSizeBytes { + return false + } + return true +} +func (this *Header) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Header) + if !ok { + that2, ok := that.(Header) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.ChainID != that1.ChainID { + return false + } + if this.Height != that1.Height { + return false + } + if this.Time != that1.Time { + return false + } + if this.NumTxs != that1.NumTxs { + return false + } + if this.TotalTxs != that1.TotalTxs { + return false + } + if !bytes.Equal(this.LastBlockHash, that1.LastBlockHash) { + return false + } + if !bytes.Equal(this.ValidatorsHash, that1.ValidatorsHash) { + return false + } + if !bytes.Equal(this.AppHash, that1.AppHash) { + return false + } + if !this.Proposer.Equal(&that1.Proposer) { + return false + } + return true +} +func (this *Validator) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Validator) + if !ok { + that2, ok := that.(Validator) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Address, that1.Address) { + return false + } + if !this.PubKey.Equal(&that1.PubKey) { + return false + } + if this.Power != that1.Power { + return false + } + return true +} +func (this *SigningValidator) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*SigningValidator) + if !ok { + that2, ok := that.(SigningValidator) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.Validator.Equal(&that1.Validator) { + return false + } + if this.SignedLastBlock != that1.SignedLastBlock { + return false + } + return true +} +func (this *PubKey) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PubKey) + if !ok { + that2, ok := that.(PubKey) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Type != that1.Type { + return false + } + if !bytes.Equal(this.Data, that1.Data) { + return false + } + return true +} +func (this *Evidence) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*Evidence) + if !ok { + that2, ok := that.(Evidence) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Type != that1.Type { + return false + } + if !this.Validator.Equal(&that1.Validator) { + return false + } + if this.Height != that1.Height { + return false + } + if this.Time != that1.Time { + return false + } + if this.TotalVotingPower != that1.TotalVotingPower { + return false + } + return true +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for ABCIApplication service + +type ABCIApplicationClient interface { + Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) + Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) + Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) + SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) + DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) + CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) + Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) + Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) + InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) + BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) + EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) +} + +type aBCIApplicationClient struct { + cc *grpc.ClientConn +} + +func NewABCIApplicationClient(cc *grpc.ClientConn) ABCIApplicationClient { + return &aBCIApplicationClient{cc} +} + +func (c *aBCIApplicationClient) Echo(ctx context.Context, in *RequestEcho, opts ...grpc.CallOption) (*ResponseEcho, error) { + out := new(ResponseEcho) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Echo", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Flush(ctx context.Context, in *RequestFlush, opts ...grpc.CallOption) (*ResponseFlush, error) { + out := new(ResponseFlush) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Flush", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Info(ctx context.Context, in *RequestInfo, opts ...grpc.CallOption) (*ResponseInfo, error) { + out := new(ResponseInfo) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Info", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) SetOption(ctx context.Context, in *RequestSetOption, opts ...grpc.CallOption) (*ResponseSetOption, error) { + out := new(ResponseSetOption) + err := grpc.Invoke(ctx, "/types.ABCIApplication/SetOption", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) DeliverTx(ctx context.Context, in *RequestDeliverTx, opts ...grpc.CallOption) (*ResponseDeliverTx, error) { + out := new(ResponseDeliverTx) + err := grpc.Invoke(ctx, "/types.ABCIApplication/DeliverTx", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) CheckTx(ctx context.Context, in *RequestCheckTx, opts ...grpc.CallOption) (*ResponseCheckTx, error) { + out := new(ResponseCheckTx) + err := grpc.Invoke(ctx, "/types.ABCIApplication/CheckTx", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Query(ctx context.Context, in *RequestQuery, opts ...grpc.CallOption) (*ResponseQuery, error) { + out := new(ResponseQuery) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Query", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) Commit(ctx context.Context, in *RequestCommit, opts ...grpc.CallOption) (*ResponseCommit, error) { + out := new(ResponseCommit) + err := grpc.Invoke(ctx, "/types.ABCIApplication/Commit", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) InitChain(ctx context.Context, in *RequestInitChain, opts ...grpc.CallOption) (*ResponseInitChain, error) { + out := new(ResponseInitChain) + err := grpc.Invoke(ctx, "/types.ABCIApplication/InitChain", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) BeginBlock(ctx context.Context, in *RequestBeginBlock, opts ...grpc.CallOption) (*ResponseBeginBlock, error) { + out := new(ResponseBeginBlock) + err := grpc.Invoke(ctx, "/types.ABCIApplication/BeginBlock", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *aBCIApplicationClient) EndBlock(ctx context.Context, in *RequestEndBlock, opts ...grpc.CallOption) (*ResponseEndBlock, error) { + out := new(ResponseEndBlock) + err := grpc.Invoke(ctx, "/types.ABCIApplication/EndBlock", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for ABCIApplication service + +type ABCIApplicationServer interface { + Echo(context.Context, *RequestEcho) (*ResponseEcho, error) + Flush(context.Context, *RequestFlush) (*ResponseFlush, error) + Info(context.Context, *RequestInfo) (*ResponseInfo, error) + SetOption(context.Context, *RequestSetOption) (*ResponseSetOption, error) + DeliverTx(context.Context, *RequestDeliverTx) (*ResponseDeliverTx, error) + CheckTx(context.Context, *RequestCheckTx) (*ResponseCheckTx, error) + Query(context.Context, *RequestQuery) (*ResponseQuery, error) + Commit(context.Context, *RequestCommit) (*ResponseCommit, error) + InitChain(context.Context, *RequestInitChain) (*ResponseInitChain, error) + BeginBlock(context.Context, *RequestBeginBlock) (*ResponseBeginBlock, error) + EndBlock(context.Context, *RequestEndBlock) (*ResponseEndBlock, error) +} + +func RegisterABCIApplicationServer(s *grpc.Server, srv ABCIApplicationServer) { + s.RegisterService(&_ABCIApplication_serviceDesc, srv) +} + +func _ABCIApplication_Echo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestEcho) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Echo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/Echo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Echo(ctx, req.(*RequestEcho)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Flush_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestFlush) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Flush(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/Flush", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Flush(ctx, req.(*RequestFlush)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Info(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/Info", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Info(ctx, req.(*RequestInfo)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_SetOption_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestSetOption) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).SetOption(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/SetOption", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).SetOption(ctx, req.(*RequestSetOption)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_DeliverTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestDeliverTx) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).DeliverTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/DeliverTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).DeliverTx(ctx, req.(*RequestDeliverTx)) + } + return interceptor(ctx, in, info, handler) } func _ABCIApplication_CheckTx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { @@ -2176,280 +3821,8344 @@ func _ABCIApplication_CheckTx_Handler(srv interface{}, ctx context.Context, dec if err := dec(in); err != nil { return nil, err } - if interceptor == nil { - return srv.(ABCIApplicationServer).CheckTx(ctx, in) + if interceptor == nil { + return srv.(ABCIApplicationServer).CheckTx(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/CheckTx", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).CheckTx(ctx, req.(*RequestCheckTx)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestQuery) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Query(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/Query", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Query(ctx, req.(*RequestQuery)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestCommit) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).Commit(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/Commit", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).Commit(ctx, req.(*RequestCommit)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_InitChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestInitChain) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).InitChain(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/InitChain", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).InitChain(ctx, req.(*RequestInitChain)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_BeginBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestBeginBlock) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).BeginBlock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/BeginBlock", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).BeginBlock(ctx, req.(*RequestBeginBlock)) + } + return interceptor(ctx, in, info, handler) +} + +func _ABCIApplication_EndBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RequestEndBlock) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ABCIApplicationServer).EndBlock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/types.ABCIApplication/EndBlock", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ABCIApplicationServer).EndBlock(ctx, req.(*RequestEndBlock)) + } + return interceptor(ctx, in, info, handler) +} + +var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ + ServiceName: "types.ABCIApplication", + HandlerType: (*ABCIApplicationServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Echo", + Handler: _ABCIApplication_Echo_Handler, + }, + { + MethodName: "Flush", + Handler: _ABCIApplication_Flush_Handler, + }, + { + MethodName: "Info", + Handler: _ABCIApplication_Info_Handler, + }, + { + MethodName: "SetOption", + Handler: _ABCIApplication_SetOption_Handler, + }, + { + MethodName: "DeliverTx", + Handler: _ABCIApplication_DeliverTx_Handler, + }, + { + MethodName: "CheckTx", + Handler: _ABCIApplication_CheckTx_Handler, + }, + { + MethodName: "Query", + Handler: _ABCIApplication_Query_Handler, + }, + { + MethodName: "Commit", + Handler: _ABCIApplication_Commit_Handler, + }, + { + MethodName: "InitChain", + Handler: _ABCIApplication_InitChain_Handler, + }, + { + MethodName: "BeginBlock", + Handler: _ABCIApplication_BeginBlock_Handler, + }, + { + MethodName: "EndBlock", + Handler: _ABCIApplication_EndBlock_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "abci/types/types.proto", +} + +func (m *Request) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Request) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Value != nil { + nn1, err := m.Value.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += nn1 + } + return i, nil +} + +func (m *Request_Echo) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Echo != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Echo.Size())) + n2, err := m.Echo.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n2 + } + return i, nil +} +func (m *Request_Flush) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Flush != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Flush.Size())) + n3, err := m.Flush.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n3 + } + return i, nil +} +func (m *Request_Info) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Info != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Info.Size())) + n4, err := m.Info.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n4 + } + return i, nil +} +func (m *Request_SetOption) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.SetOption != nil { + dAtA[i] = 0x2a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.SetOption.Size())) + n5, err := m.SetOption.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n5 + } + return i, nil +} +func (m *Request_InitChain) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.InitChain != nil { + dAtA[i] = 0x32 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.InitChain.Size())) + n6, err := m.InitChain.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n6 + } + return i, nil +} +func (m *Request_Query) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Query != nil { + dAtA[i] = 0x3a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Query.Size())) + n7, err := m.Query.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n7 + } + return i, nil +} +func (m *Request_BeginBlock) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.BeginBlock != nil { + dAtA[i] = 0x42 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.BeginBlock.Size())) + n8, err := m.BeginBlock.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n8 + } + return i, nil +} +func (m *Request_CheckTx) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.CheckTx != nil { + dAtA[i] = 0x4a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.CheckTx.Size())) + n9, err := m.CheckTx.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n9 + } + return i, nil +} +func (m *Request_EndBlock) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.EndBlock != nil { + dAtA[i] = 0x5a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.EndBlock.Size())) + n10, err := m.EndBlock.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n10 + } + return i, nil +} +func (m *Request_Commit) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Commit != nil { + dAtA[i] = 0x62 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Commit.Size())) + n11, err := m.Commit.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n11 + } + return i, nil +} +func (m *Request_DeliverTx) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.DeliverTx != nil { + dAtA[i] = 0x9a + i++ + dAtA[i] = 0x1 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.DeliverTx.Size())) + n12, err := m.DeliverTx.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n12 + } + return i, nil +} +func (m *RequestEcho) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestEcho) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Message) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Message))) + i += copy(dAtA[i:], m.Message) + } + return i, nil +} + +func (m *RequestFlush) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestFlush) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func (m *RequestInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestInfo) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Version) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Version))) + i += copy(dAtA[i:], m.Version) + } + return i, nil +} + +func (m *RequestSetOption) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestSetOption) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Key) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Key))) + i += copy(dAtA[i:], m.Key) + } + if len(m.Value) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Value))) + i += copy(dAtA[i:], m.Value) + } + return i, nil +} + +func (m *RequestInitChain) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestInitChain) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Time != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Time)) + } + if len(m.ChainId) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainId))) + i += copy(dAtA[i:], m.ChainId) + } + if m.ConsensusParams != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.ConsensusParams.Size())) + n13, err := m.ConsensusParams.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n13 + } + if len(m.Validators) > 0 { + for _, msg := range m.Validators { + dAtA[i] = 0x22 + i++ + i = encodeVarintTypes(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.AppStateBytes) > 0 { + dAtA[i] = 0x2a + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppStateBytes))) + i += copy(dAtA[i:], m.AppStateBytes) + } + return i, nil +} + +func (m *RequestQuery) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestQuery) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Data) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i += copy(dAtA[i:], m.Data) + } + if len(m.Path) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Path))) + i += copy(dAtA[i:], m.Path) + } + if m.Height != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + } + if m.Prove { + dAtA[i] = 0x20 + i++ + if m.Prove { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } + return i, nil +} + +func (m *RequestBeginBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestBeginBlock) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Hash) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Hash))) + i += copy(dAtA[i:], m.Hash) + } + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Header.Size())) + n14, err := m.Header.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n14 + if len(m.Validators) > 0 { + for _, msg := range m.Validators { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if len(m.ByzantineValidators) > 0 { + for _, msg := range m.ByzantineValidators { + dAtA[i] = 0x22 + i++ + i = encodeVarintTypes(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *RequestCheckTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestCheckTx) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Tx) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx))) + i += copy(dAtA[i:], m.Tx) + } + return i, nil +} + +func (m *RequestDeliverTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestDeliverTx) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Tx) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx))) + i += copy(dAtA[i:], m.Tx) + } + return i, nil +} + +func (m *RequestEndBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestEndBlock) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Height != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + } + return i, nil +} + +func (m *RequestCommit) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestCommit) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func (m *Response) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Response) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Value != nil { + nn15, err := m.Value.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += nn15 + } + return i, nil +} + +func (m *Response_Exception) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Exception != nil { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Exception.Size())) + n16, err := m.Exception.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n16 + } + return i, nil +} +func (m *Response_Echo) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Echo != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Echo.Size())) + n17, err := m.Echo.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n17 + } + return i, nil +} +func (m *Response_Flush) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Flush != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Flush.Size())) + n18, err := m.Flush.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n18 + } + return i, nil +} +func (m *Response_Info) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Info != nil { + dAtA[i] = 0x22 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Info.Size())) + n19, err := m.Info.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n19 + } + return i, nil +} +func (m *Response_SetOption) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.SetOption != nil { + dAtA[i] = 0x2a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.SetOption.Size())) + n20, err := m.SetOption.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n20 + } + return i, nil +} +func (m *Response_InitChain) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.InitChain != nil { + dAtA[i] = 0x32 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.InitChain.Size())) + n21, err := m.InitChain.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n21 + } + return i, nil +} +func (m *Response_Query) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Query != nil { + dAtA[i] = 0x3a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Query.Size())) + n22, err := m.Query.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n22 + } + return i, nil +} +func (m *Response_BeginBlock) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.BeginBlock != nil { + dAtA[i] = 0x42 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.BeginBlock.Size())) + n23, err := m.BeginBlock.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n23 + } + return i, nil +} +func (m *Response_CheckTx) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.CheckTx != nil { + dAtA[i] = 0x4a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.CheckTx.Size())) + n24, err := m.CheckTx.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n24 + } + return i, nil +} +func (m *Response_DeliverTx) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.DeliverTx != nil { + dAtA[i] = 0x52 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.DeliverTx.Size())) + n25, err := m.DeliverTx.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n25 + } + return i, nil +} +func (m *Response_EndBlock) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.EndBlock != nil { + dAtA[i] = 0x5a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.EndBlock.Size())) + n26, err := m.EndBlock.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n26 + } + return i, nil +} +func (m *Response_Commit) MarshalTo(dAtA []byte) (int, error) { + i := 0 + if m.Commit != nil { + dAtA[i] = 0x62 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Commit.Size())) + n27, err := m.Commit.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n27 + } + return i, nil +} +func (m *ResponseException) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseException) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Error) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Error))) + i += copy(dAtA[i:], m.Error) + } + return i, nil +} + +func (m *ResponseEcho) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseEcho) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Message) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Message))) + i += copy(dAtA[i:], m.Message) + } + return i, nil +} + +func (m *ResponseFlush) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseFlush) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func (m *ResponseInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseInfo) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Data) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i += copy(dAtA[i:], m.Data) + } + if len(m.Version) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Version))) + i += copy(dAtA[i:], m.Version) + } + if m.LastBlockHeight != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.LastBlockHeight)) + } + if len(m.LastBlockAppHash) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.LastBlockAppHash))) + i += copy(dAtA[i:], m.LastBlockAppHash) + } + return i, nil +} + +func (m *ResponseSetOption) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseSetOption) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Code != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + } + if len(m.Log) > 0 { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i += copy(dAtA[i:], m.Log) + } + if len(m.Info) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i += copy(dAtA[i:], m.Info) + } + return i, nil +} + +func (m *ResponseInitChain) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseInitChain) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.ConsensusParams != nil { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.ConsensusParams.Size())) + n28, err := m.ConsensusParams.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n28 + } + if len(m.Validators) > 0 { + for _, msg := range m.Validators { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *ResponseQuery) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseQuery) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Code != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + } + if len(m.Log) > 0 { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i += copy(dAtA[i:], m.Log) + } + if len(m.Info) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i += copy(dAtA[i:], m.Info) + } + if m.Index != 0 { + dAtA[i] = 0x28 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Index)) + } + if len(m.Key) > 0 { + dAtA[i] = 0x32 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Key))) + i += copy(dAtA[i:], m.Key) + } + if len(m.Value) > 0 { + dAtA[i] = 0x3a + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Value))) + i += copy(dAtA[i:], m.Value) + } + if len(m.Proof) > 0 { + dAtA[i] = 0x42 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Proof))) + i += copy(dAtA[i:], m.Proof) + } + if m.Height != 0 { + dAtA[i] = 0x48 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + } + return i, nil +} + +func (m *ResponseBeginBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseBeginBlock) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Tags) > 0 { + for _, msg := range m.Tags { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *ResponseCheckTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseCheckTx) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Code != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + } + if len(m.Data) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i += copy(dAtA[i:], m.Data) + } + if len(m.Log) > 0 { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i += copy(dAtA[i:], m.Log) + } + if len(m.Info) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i += copy(dAtA[i:], m.Info) + } + if m.GasWanted != 0 { + dAtA[i] = 0x28 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + dAtA[i] = 0x30 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.GasUsed)) + } + if len(m.Tags) > 0 { + for _, msg := range m.Tags { + dAtA[i] = 0x3a + i++ + i = encodeVarintTypes(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + dAtA[i] = 0x42 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Fee.Size())) + n29, err := m.Fee.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n29 + return i, nil +} + +func (m *ResponseDeliverTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseDeliverTx) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.Code != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Code)) + } + if len(m.Data) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i += copy(dAtA[i:], m.Data) + } + if len(m.Log) > 0 { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Log))) + i += copy(dAtA[i:], m.Log) + } + if len(m.Info) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Info))) + i += copy(dAtA[i:], m.Info) + } + if m.GasWanted != 0 { + dAtA[i] = 0x28 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + dAtA[i] = 0x30 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.GasUsed)) + } + if len(m.Tags) > 0 { + for _, msg := range m.Tags { + dAtA[i] = 0x3a + i++ + i = encodeVarintTypes(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + dAtA[i] = 0x42 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Fee.Size())) + n30, err := m.Fee.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n30 + return i, nil +} + +func (m *ResponseEndBlock) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseEndBlock) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.ValidatorUpdates) > 0 { + for _, msg := range m.ValidatorUpdates { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + if m.ConsensusParamUpdates != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.ConsensusParamUpdates.Size())) + n31, err := m.ConsensusParamUpdates.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n31 + } + if len(m.Tags) > 0 { + for _, msg := range m.Tags { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(msg.Size())) + n, err := msg.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n + } + } + return i, nil +} + +func (m *ResponseCommit) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseCommit) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Data) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i += copy(dAtA[i:], m.Data) + } + return i, nil +} + +func (m *ConsensusParams) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConsensusParams) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.BlockSize != nil { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.BlockSize.Size())) + n32, err := m.BlockSize.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n32 + } + if m.TxSize != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.TxSize.Size())) + n33, err := m.TxSize.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n33 + } + if m.BlockGossip != nil { + dAtA[i] = 0x1a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.BlockGossip.Size())) + n34, err := m.BlockGossip.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n34 + } + return i, nil +} + +func (m *BlockSize) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockSize) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.MaxBytes != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.MaxBytes)) + } + if m.MaxTxs != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.MaxTxs)) + } + if m.MaxGas != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.MaxGas)) + } + return i, nil +} + +func (m *TxSize) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TxSize) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.MaxBytes != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.MaxBytes)) + } + if m.MaxGas != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.MaxGas)) + } + return i, nil +} + +func (m *BlockGossip) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *BlockGossip) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.BlockPartSizeBytes != 0 { + dAtA[i] = 0x8 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.BlockPartSizeBytes)) + } + return i, nil +} + +func (m *Header) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Header) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.ChainID) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.ChainID))) + i += copy(dAtA[i:], m.ChainID) + } + if m.Height != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + } + if m.Time != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Time)) + } + if m.NumTxs != 0 { + dAtA[i] = 0x20 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.NumTxs)) + } + if m.TotalTxs != 0 { + dAtA[i] = 0x28 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.TotalTxs)) + } + if len(m.LastBlockHash) > 0 { + dAtA[i] = 0x32 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.LastBlockHash))) + i += copy(dAtA[i:], m.LastBlockHash) + } + if len(m.ValidatorsHash) > 0 { + dAtA[i] = 0x3a + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.ValidatorsHash))) + i += copy(dAtA[i:], m.ValidatorsHash) + } + if len(m.AppHash) > 0 { + dAtA[i] = 0x42 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.AppHash))) + i += copy(dAtA[i:], m.AppHash) + } + dAtA[i] = 0x4a + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Proposer.Size())) + n35, err := m.Proposer.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n35 + return i, nil +} + +func (m *Validator) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Validator) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Address) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Address))) + i += copy(dAtA[i:], m.Address) + } + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.PubKey.Size())) + n36, err := m.PubKey.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n36 + if m.Power != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Power)) + } + return i, nil +} + +func (m *SigningValidator) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SigningValidator) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Validator.Size())) + n37, err := m.Validator.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n37 + if m.SignedLastBlock { + dAtA[i] = 0x10 + i++ + if m.SignedLastBlock { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i++ + } + return i, nil +} + +func (m *PubKey) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PubKey) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Type) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Type))) + i += copy(dAtA[i:], m.Type) + } + if len(m.Data) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Data))) + i += copy(dAtA[i:], m.Data) + } + return i, nil +} + +func (m *Evidence) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Evidence) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Type) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Type))) + i += copy(dAtA[i:], m.Type) + } + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Validator.Size())) + n38, err := m.Validator.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n38 + if m.Height != 0 { + dAtA[i] = 0x18 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Height)) + } + if m.Time != 0 { + dAtA[i] = 0x20 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Time)) + } + if m.TotalVotingPower != 0 { + dAtA[i] = 0x28 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.TotalVotingPower)) + } + return i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func NewPopulatedRequest(r randyTypes, easy bool) *Request { + this := &Request{} + oneofNumber_Value := []int32{2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 19}[r.Intn(11)] + switch oneofNumber_Value { + case 2: + this.Value = NewPopulatedRequest_Echo(r, easy) + case 3: + this.Value = NewPopulatedRequest_Flush(r, easy) + case 4: + this.Value = NewPopulatedRequest_Info(r, easy) + case 5: + this.Value = NewPopulatedRequest_SetOption(r, easy) + case 6: + this.Value = NewPopulatedRequest_InitChain(r, easy) + case 7: + this.Value = NewPopulatedRequest_Query(r, easy) + case 8: + this.Value = NewPopulatedRequest_BeginBlock(r, easy) + case 9: + this.Value = NewPopulatedRequest_CheckTx(r, easy) + case 11: + this.Value = NewPopulatedRequest_EndBlock(r, easy) + case 12: + this.Value = NewPopulatedRequest_Commit(r, easy) + case 19: + this.Value = NewPopulatedRequest_DeliverTx(r, easy) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequest_Echo(r randyTypes, easy bool) *Request_Echo { + this := &Request_Echo{} + this.Echo = NewPopulatedRequestEcho(r, easy) + return this +} +func NewPopulatedRequest_Flush(r randyTypes, easy bool) *Request_Flush { + this := &Request_Flush{} + this.Flush = NewPopulatedRequestFlush(r, easy) + return this +} +func NewPopulatedRequest_Info(r randyTypes, easy bool) *Request_Info { + this := &Request_Info{} + this.Info = NewPopulatedRequestInfo(r, easy) + return this +} +func NewPopulatedRequest_SetOption(r randyTypes, easy bool) *Request_SetOption { + this := &Request_SetOption{} + this.SetOption = NewPopulatedRequestSetOption(r, easy) + return this +} +func NewPopulatedRequest_InitChain(r randyTypes, easy bool) *Request_InitChain { + this := &Request_InitChain{} + this.InitChain = NewPopulatedRequestInitChain(r, easy) + return this +} +func NewPopulatedRequest_Query(r randyTypes, easy bool) *Request_Query { + this := &Request_Query{} + this.Query = NewPopulatedRequestQuery(r, easy) + return this +} +func NewPopulatedRequest_BeginBlock(r randyTypes, easy bool) *Request_BeginBlock { + this := &Request_BeginBlock{} + this.BeginBlock = NewPopulatedRequestBeginBlock(r, easy) + return this +} +func NewPopulatedRequest_CheckTx(r randyTypes, easy bool) *Request_CheckTx { + this := &Request_CheckTx{} + this.CheckTx = NewPopulatedRequestCheckTx(r, easy) + return this +} +func NewPopulatedRequest_EndBlock(r randyTypes, easy bool) *Request_EndBlock { + this := &Request_EndBlock{} + this.EndBlock = NewPopulatedRequestEndBlock(r, easy) + return this +} +func NewPopulatedRequest_Commit(r randyTypes, easy bool) *Request_Commit { + this := &Request_Commit{} + this.Commit = NewPopulatedRequestCommit(r, easy) + return this +} +func NewPopulatedRequest_DeliverTx(r randyTypes, easy bool) *Request_DeliverTx { + this := &Request_DeliverTx{} + this.DeliverTx = NewPopulatedRequestDeliverTx(r, easy) + return this +} +func NewPopulatedRequestEcho(r randyTypes, easy bool) *RequestEcho { + this := &RequestEcho{} + this.Message = string(randStringTypes(r)) + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestFlush(r randyTypes, easy bool) *RequestFlush { + this := &RequestFlush{} + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestInfo(r randyTypes, easy bool) *RequestInfo { + this := &RequestInfo{} + this.Version = string(randStringTypes(r)) + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestSetOption(r randyTypes, easy bool) *RequestSetOption { + this := &RequestSetOption{} + this.Key = string(randStringTypes(r)) + this.Value = string(randStringTypes(r)) + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestInitChain(r randyTypes, easy bool) *RequestInitChain { + this := &RequestInitChain{} + this.Time = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Time *= -1 + } + this.ChainId = string(randStringTypes(r)) + if r.Intn(10) != 0 { + this.ConsensusParams = NewPopulatedConsensusParams(r, easy) + } + if r.Intn(10) != 0 { + v1 := r.Intn(5) + this.Validators = make([]Validator, v1) + for i := 0; i < v1; i++ { + v2 := NewPopulatedValidator(r, easy) + this.Validators[i] = *v2 + } + } + v3 := r.Intn(100) + this.AppStateBytes = make([]byte, v3) + for i := 0; i < v3; i++ { + this.AppStateBytes[i] = byte(r.Intn(256)) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestQuery(r randyTypes, easy bool) *RequestQuery { + this := &RequestQuery{} + v4 := r.Intn(100) + this.Data = make([]byte, v4) + for i := 0; i < v4; i++ { + this.Data[i] = byte(r.Intn(256)) + } + this.Path = string(randStringTypes(r)) + this.Height = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Height *= -1 + } + this.Prove = bool(bool(r.Intn(2) == 0)) + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestBeginBlock(r randyTypes, easy bool) *RequestBeginBlock { + this := &RequestBeginBlock{} + v5 := r.Intn(100) + this.Hash = make([]byte, v5) + for i := 0; i < v5; i++ { + this.Hash[i] = byte(r.Intn(256)) + } + v6 := NewPopulatedHeader(r, easy) + this.Header = *v6 + if r.Intn(10) != 0 { + v7 := r.Intn(5) + this.Validators = make([]SigningValidator, v7) + for i := 0; i < v7; i++ { + v8 := NewPopulatedSigningValidator(r, easy) + this.Validators[i] = *v8 + } + } + if r.Intn(10) != 0 { + v9 := r.Intn(5) + this.ByzantineValidators = make([]Evidence, v9) + for i := 0; i < v9; i++ { + v10 := NewPopulatedEvidence(r, easy) + this.ByzantineValidators[i] = *v10 + } + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestCheckTx(r randyTypes, easy bool) *RequestCheckTx { + this := &RequestCheckTx{} + v11 := r.Intn(100) + this.Tx = make([]byte, v11) + for i := 0; i < v11; i++ { + this.Tx[i] = byte(r.Intn(256)) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestDeliverTx(r randyTypes, easy bool) *RequestDeliverTx { + this := &RequestDeliverTx{} + v12 := r.Intn(100) + this.Tx = make([]byte, v12) + for i := 0; i < v12; i++ { + this.Tx[i] = byte(r.Intn(256)) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestEndBlock(r randyTypes, easy bool) *RequestEndBlock { + this := &RequestEndBlock{} + this.Height = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Height *= -1 + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestCommit(r randyTypes, easy bool) *RequestCommit { + this := &RequestCommit{} + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponse(r randyTypes, easy bool) *Response { + this := &Response{} + oneofNumber_Value := []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}[r.Intn(12)] + switch oneofNumber_Value { + case 1: + this.Value = NewPopulatedResponse_Exception(r, easy) + case 2: + this.Value = NewPopulatedResponse_Echo(r, easy) + case 3: + this.Value = NewPopulatedResponse_Flush(r, easy) + case 4: + this.Value = NewPopulatedResponse_Info(r, easy) + case 5: + this.Value = NewPopulatedResponse_SetOption(r, easy) + case 6: + this.Value = NewPopulatedResponse_InitChain(r, easy) + case 7: + this.Value = NewPopulatedResponse_Query(r, easy) + case 8: + this.Value = NewPopulatedResponse_BeginBlock(r, easy) + case 9: + this.Value = NewPopulatedResponse_CheckTx(r, easy) + case 10: + this.Value = NewPopulatedResponse_DeliverTx(r, easy) + case 11: + this.Value = NewPopulatedResponse_EndBlock(r, easy) + case 12: + this.Value = NewPopulatedResponse_Commit(r, easy) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponse_Exception(r randyTypes, easy bool) *Response_Exception { + this := &Response_Exception{} + this.Exception = NewPopulatedResponseException(r, easy) + return this +} +func NewPopulatedResponse_Echo(r randyTypes, easy bool) *Response_Echo { + this := &Response_Echo{} + this.Echo = NewPopulatedResponseEcho(r, easy) + return this +} +func NewPopulatedResponse_Flush(r randyTypes, easy bool) *Response_Flush { + this := &Response_Flush{} + this.Flush = NewPopulatedResponseFlush(r, easy) + return this +} +func NewPopulatedResponse_Info(r randyTypes, easy bool) *Response_Info { + this := &Response_Info{} + this.Info = NewPopulatedResponseInfo(r, easy) + return this +} +func NewPopulatedResponse_SetOption(r randyTypes, easy bool) *Response_SetOption { + this := &Response_SetOption{} + this.SetOption = NewPopulatedResponseSetOption(r, easy) + return this +} +func NewPopulatedResponse_InitChain(r randyTypes, easy bool) *Response_InitChain { + this := &Response_InitChain{} + this.InitChain = NewPopulatedResponseInitChain(r, easy) + return this +} +func NewPopulatedResponse_Query(r randyTypes, easy bool) *Response_Query { + this := &Response_Query{} + this.Query = NewPopulatedResponseQuery(r, easy) + return this +} +func NewPopulatedResponse_BeginBlock(r randyTypes, easy bool) *Response_BeginBlock { + this := &Response_BeginBlock{} + this.BeginBlock = NewPopulatedResponseBeginBlock(r, easy) + return this +} +func NewPopulatedResponse_CheckTx(r randyTypes, easy bool) *Response_CheckTx { + this := &Response_CheckTx{} + this.CheckTx = NewPopulatedResponseCheckTx(r, easy) + return this +} +func NewPopulatedResponse_DeliverTx(r randyTypes, easy bool) *Response_DeliverTx { + this := &Response_DeliverTx{} + this.DeliverTx = NewPopulatedResponseDeliverTx(r, easy) + return this +} +func NewPopulatedResponse_EndBlock(r randyTypes, easy bool) *Response_EndBlock { + this := &Response_EndBlock{} + this.EndBlock = NewPopulatedResponseEndBlock(r, easy) + return this +} +func NewPopulatedResponse_Commit(r randyTypes, easy bool) *Response_Commit { + this := &Response_Commit{} + this.Commit = NewPopulatedResponseCommit(r, easy) + return this +} +func NewPopulatedResponseException(r randyTypes, easy bool) *ResponseException { + this := &ResponseException{} + this.Error = string(randStringTypes(r)) + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseEcho(r randyTypes, easy bool) *ResponseEcho { + this := &ResponseEcho{} + this.Message = string(randStringTypes(r)) + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseFlush(r randyTypes, easy bool) *ResponseFlush { + this := &ResponseFlush{} + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseInfo(r randyTypes, easy bool) *ResponseInfo { + this := &ResponseInfo{} + this.Data = string(randStringTypes(r)) + this.Version = string(randStringTypes(r)) + this.LastBlockHeight = int64(r.Int63()) + if r.Intn(2) == 0 { + this.LastBlockHeight *= -1 + } + v13 := r.Intn(100) + this.LastBlockAppHash = make([]byte, v13) + for i := 0; i < v13; i++ { + this.LastBlockAppHash[i] = byte(r.Intn(256)) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseSetOption(r randyTypes, easy bool) *ResponseSetOption { + this := &ResponseSetOption{} + this.Code = uint32(r.Uint32()) + this.Log = string(randStringTypes(r)) + this.Info = string(randStringTypes(r)) + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseInitChain(r randyTypes, easy bool) *ResponseInitChain { + this := &ResponseInitChain{} + if r.Intn(10) != 0 { + this.ConsensusParams = NewPopulatedConsensusParams(r, easy) + } + if r.Intn(10) != 0 { + v14 := r.Intn(5) + this.Validators = make([]Validator, v14) + for i := 0; i < v14; i++ { + v15 := NewPopulatedValidator(r, easy) + this.Validators[i] = *v15 + } + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseQuery(r randyTypes, easy bool) *ResponseQuery { + this := &ResponseQuery{} + this.Code = uint32(r.Uint32()) + this.Log = string(randStringTypes(r)) + this.Info = string(randStringTypes(r)) + this.Index = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Index *= -1 + } + v16 := r.Intn(100) + this.Key = make([]byte, v16) + for i := 0; i < v16; i++ { + this.Key[i] = byte(r.Intn(256)) + } + v17 := r.Intn(100) + this.Value = make([]byte, v17) + for i := 0; i < v17; i++ { + this.Value[i] = byte(r.Intn(256)) + } + v18 := r.Intn(100) + this.Proof = make([]byte, v18) + for i := 0; i < v18; i++ { + this.Proof[i] = byte(r.Intn(256)) + } + this.Height = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Height *= -1 + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseBeginBlock(r randyTypes, easy bool) *ResponseBeginBlock { + this := &ResponseBeginBlock{} + if r.Intn(10) != 0 { + v19 := r.Intn(5) + this.Tags = make([]common.KVPair, v19) + for i := 0; i < v19; i++ { + v20 := common.NewPopulatedKVPair(r, easy) + this.Tags[i] = *v20 + } + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseCheckTx(r randyTypes, easy bool) *ResponseCheckTx { + this := &ResponseCheckTx{} + this.Code = uint32(r.Uint32()) + v21 := r.Intn(100) + this.Data = make([]byte, v21) + for i := 0; i < v21; i++ { + this.Data[i] = byte(r.Intn(256)) + } + this.Log = string(randStringTypes(r)) + this.Info = string(randStringTypes(r)) + this.GasWanted = int64(r.Int63()) + if r.Intn(2) == 0 { + this.GasWanted *= -1 + } + this.GasUsed = int64(r.Int63()) + if r.Intn(2) == 0 { + this.GasUsed *= -1 + } + if r.Intn(10) != 0 { + v22 := r.Intn(5) + this.Tags = make([]common.KVPair, v22) + for i := 0; i < v22; i++ { + v23 := common.NewPopulatedKVPair(r, easy) + this.Tags[i] = *v23 + } + } + v24 := common.NewPopulatedKI64Pair(r, easy) + this.Fee = *v24 + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseDeliverTx(r randyTypes, easy bool) *ResponseDeliverTx { + this := &ResponseDeliverTx{} + this.Code = uint32(r.Uint32()) + v25 := r.Intn(100) + this.Data = make([]byte, v25) + for i := 0; i < v25; i++ { + this.Data[i] = byte(r.Intn(256)) + } + this.Log = string(randStringTypes(r)) + this.Info = string(randStringTypes(r)) + this.GasWanted = int64(r.Int63()) + if r.Intn(2) == 0 { + this.GasWanted *= -1 + } + this.GasUsed = int64(r.Int63()) + if r.Intn(2) == 0 { + this.GasUsed *= -1 + } + if r.Intn(10) != 0 { + v26 := r.Intn(5) + this.Tags = make([]common.KVPair, v26) + for i := 0; i < v26; i++ { + v27 := common.NewPopulatedKVPair(r, easy) + this.Tags[i] = *v27 + } + } + v28 := common.NewPopulatedKI64Pair(r, easy) + this.Fee = *v28 + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseEndBlock(r randyTypes, easy bool) *ResponseEndBlock { + this := &ResponseEndBlock{} + if r.Intn(10) != 0 { + v29 := r.Intn(5) + this.ValidatorUpdates = make([]Validator, v29) + for i := 0; i < v29; i++ { + v30 := NewPopulatedValidator(r, easy) + this.ValidatorUpdates[i] = *v30 + } + } + if r.Intn(10) != 0 { + this.ConsensusParamUpdates = NewPopulatedConsensusParams(r, easy) + } + if r.Intn(10) != 0 { + v31 := r.Intn(5) + this.Tags = make([]common.KVPair, v31) + for i := 0; i < v31; i++ { + v32 := common.NewPopulatedKVPair(r, easy) + this.Tags[i] = *v32 + } + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseCommit(r randyTypes, easy bool) *ResponseCommit { + this := &ResponseCommit{} + v33 := r.Intn(100) + this.Data = make([]byte, v33) + for i := 0; i < v33; i++ { + this.Data[i] = byte(r.Intn(256)) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedConsensusParams(r randyTypes, easy bool) *ConsensusParams { + this := &ConsensusParams{} + if r.Intn(10) != 0 { + this.BlockSize = NewPopulatedBlockSize(r, easy) + } + if r.Intn(10) != 0 { + this.TxSize = NewPopulatedTxSize(r, easy) + } + if r.Intn(10) != 0 { + this.BlockGossip = NewPopulatedBlockGossip(r, easy) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedBlockSize(r randyTypes, easy bool) *BlockSize { + this := &BlockSize{} + this.MaxBytes = int32(r.Int31()) + if r.Intn(2) == 0 { + this.MaxBytes *= -1 + } + this.MaxTxs = int32(r.Int31()) + if r.Intn(2) == 0 { + this.MaxTxs *= -1 + } + this.MaxGas = int64(r.Int63()) + if r.Intn(2) == 0 { + this.MaxGas *= -1 + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedTxSize(r randyTypes, easy bool) *TxSize { + this := &TxSize{} + this.MaxBytes = int32(r.Int31()) + if r.Intn(2) == 0 { + this.MaxBytes *= -1 + } + this.MaxGas = int64(r.Int63()) + if r.Intn(2) == 0 { + this.MaxGas *= -1 + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedBlockGossip(r randyTypes, easy bool) *BlockGossip { + this := &BlockGossip{} + this.BlockPartSizeBytes = int32(r.Int31()) + if r.Intn(2) == 0 { + this.BlockPartSizeBytes *= -1 + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedHeader(r randyTypes, easy bool) *Header { + this := &Header{} + this.ChainID = string(randStringTypes(r)) + this.Height = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Height *= -1 + } + this.Time = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Time *= -1 + } + this.NumTxs = int32(r.Int31()) + if r.Intn(2) == 0 { + this.NumTxs *= -1 + } + this.TotalTxs = int64(r.Int63()) + if r.Intn(2) == 0 { + this.TotalTxs *= -1 + } + v34 := r.Intn(100) + this.LastBlockHash = make([]byte, v34) + for i := 0; i < v34; i++ { + this.LastBlockHash[i] = byte(r.Intn(256)) + } + v35 := r.Intn(100) + this.ValidatorsHash = make([]byte, v35) + for i := 0; i < v35; i++ { + this.ValidatorsHash[i] = byte(r.Intn(256)) + } + v36 := r.Intn(100) + this.AppHash = make([]byte, v36) + for i := 0; i < v36; i++ { + this.AppHash[i] = byte(r.Intn(256)) + } + v37 := NewPopulatedValidator(r, easy) + this.Proposer = *v37 + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedValidator(r randyTypes, easy bool) *Validator { + this := &Validator{} + v38 := r.Intn(100) + this.Address = make([]byte, v38) + for i := 0; i < v38; i++ { + this.Address[i] = byte(r.Intn(256)) + } + v39 := NewPopulatedPubKey(r, easy) + this.PubKey = *v39 + this.Power = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Power *= -1 + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedSigningValidator(r randyTypes, easy bool) *SigningValidator { + this := &SigningValidator{} + v40 := NewPopulatedValidator(r, easy) + this.Validator = *v40 + this.SignedLastBlock = bool(bool(r.Intn(2) == 0)) + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedPubKey(r randyTypes, easy bool) *PubKey { + this := &PubKey{} + this.Type = string(randStringTypes(r)) + v41 := r.Intn(100) + this.Data = make([]byte, v41) + for i := 0; i < v41; i++ { + this.Data[i] = byte(r.Intn(256)) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedEvidence(r randyTypes, easy bool) *Evidence { + this := &Evidence{} + this.Type = string(randStringTypes(r)) + v42 := NewPopulatedValidator(r, easy) + this.Validator = *v42 + this.Height = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Height *= -1 + } + this.Time = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Time *= -1 + } + this.TotalVotingPower = int64(r.Int63()) + if r.Intn(2) == 0 { + this.TotalVotingPower *= -1 + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +type randyTypes interface { + Float32() float32 + Float64() float64 + Int63() int64 + Int31() int32 + Uint32() uint32 + Intn(n int) int +} + +func randUTF8RuneTypes(r randyTypes) rune { + ru := r.Intn(62) + if ru < 10 { + return rune(ru + 48) + } else if ru < 36 { + return rune(ru + 55) + } + return rune(ru + 61) +} +func randStringTypes(r randyTypes) string { + v43 := r.Intn(100) + tmps := make([]rune, v43) + for i := 0; i < v43; i++ { + tmps[i] = randUTF8RuneTypes(r) + } + return string(tmps) +} +func randUnrecognizedTypes(r randyTypes, maxFieldNumber int) (dAtA []byte) { + l := r.Intn(5) + for i := 0; i < l; i++ { + wire := r.Intn(4) + if wire == 3 { + wire = 5 + } + fieldNumber := maxFieldNumber + r.Intn(100) + dAtA = randFieldTypes(dAtA, r, fieldNumber, wire) + } + return dAtA +} +func randFieldTypes(dAtA []byte, r randyTypes, fieldNumber int, wire int) []byte { + key := uint32(fieldNumber)<<3 | uint32(wire) + switch wire { + case 0: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + v44 := r.Int63() + if r.Intn(2) == 0 { + v44 *= -1 + } + dAtA = encodeVarintPopulateTypes(dAtA, uint64(v44)) + case 1: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) + case 2: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + ll := r.Intn(100) + dAtA = encodeVarintPopulateTypes(dAtA, uint64(ll)) + for j := 0; j < ll; j++ { + dAtA = append(dAtA, byte(r.Intn(256))) + } + default: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) + } + return dAtA +} +func encodeVarintPopulateTypes(dAtA []byte, v uint64) []byte { + for v >= 1<<7 { + dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80)) + v >>= 7 + } + dAtA = append(dAtA, uint8(v)) + return dAtA +} +func (m *Request) Size() (n int) { + var l int + _ = l + if m.Value != nil { + n += m.Value.Size() + } + return n +} + +func (m *Request_Echo) Size() (n int) { + var l int + _ = l + if m.Echo != nil { + l = m.Echo.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Flush) Size() (n int) { + var l int + _ = l + if m.Flush != nil { + l = m.Flush.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Info) Size() (n int) { + var l int + _ = l + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_SetOption) Size() (n int) { + var l int + _ = l + if m.SetOption != nil { + l = m.SetOption.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_InitChain) Size() (n int) { + var l int + _ = l + if m.InitChain != nil { + l = m.InitChain.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Query) Size() (n int) { + var l int + _ = l + if m.Query != nil { + l = m.Query.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_BeginBlock) Size() (n int) { + var l int + _ = l + if m.BeginBlock != nil { + l = m.BeginBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_CheckTx) Size() (n int) { + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_EndBlock) Size() (n int) { + var l int + _ = l + if m.EndBlock != nil { + l = m.EndBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_Commit) Size() (n int) { + var l int + _ = l + if m.Commit != nil { + l = m.Commit.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Request_DeliverTx) Size() (n int) { + var l int + _ = l + if m.DeliverTx != nil { + l = m.DeliverTx.Size() + n += 2 + l + sovTypes(uint64(l)) + } + return n +} +func (m *RequestEcho) Size() (n int) { + var l int + _ = l + l = len(m.Message) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestFlush) Size() (n int) { + var l int + _ = l + return n +} + +func (m *RequestInfo) Size() (n int) { + var l int + _ = l + l = len(m.Version) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestSetOption) Size() (n int) { + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Value) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestInitChain) Size() (n int) { + var l int + _ = l + if m.Time != 0 { + n += 1 + sovTypes(uint64(m.Time)) + } + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.ConsensusParams != nil { + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = len(m.AppStateBytes) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestQuery) Size() (n int) { + var l int + _ = l + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Path) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Prove { + n += 2 + } + return n +} + +func (m *RequestBeginBlock) Size() (n int) { + var l int + _ = l + l = len(m.Hash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Header.Size() + n += 1 + l + sovTypes(uint64(l)) + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if len(m.ByzantineValidators) > 0 { + for _, e := range m.ByzantineValidators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *RequestCheckTx) Size() (n int) { + var l int + _ = l + l = len(m.Tx) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestDeliverTx) Size() (n int) { + var l int + _ = l + l = len(m.Tx) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *RequestEndBlock) Size() (n int) { + var l int + _ = l + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + return n +} + +func (m *RequestCommit) Size() (n int) { + var l int + _ = l + return n +} + +func (m *Response) Size() (n int) { + var l int + _ = l + if m.Value != nil { + n += m.Value.Size() + } + return n +} + +func (m *Response_Exception) Size() (n int) { + var l int + _ = l + if m.Exception != nil { + l = m.Exception.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Echo) Size() (n int) { + var l int + _ = l + if m.Echo != nil { + l = m.Echo.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Flush) Size() (n int) { + var l int + _ = l + if m.Flush != nil { + l = m.Flush.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Info) Size() (n int) { + var l int + _ = l + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_SetOption) Size() (n int) { + var l int + _ = l + if m.SetOption != nil { + l = m.SetOption.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_InitChain) Size() (n int) { + var l int + _ = l + if m.InitChain != nil { + l = m.InitChain.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Query) Size() (n int) { + var l int + _ = l + if m.Query != nil { + l = m.Query.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_BeginBlock) Size() (n int) { + var l int + _ = l + if m.BeginBlock != nil { + l = m.BeginBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_CheckTx) Size() (n int) { + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_DeliverTx) Size() (n int) { + var l int + _ = l + if m.DeliverTx != nil { + l = m.DeliverTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_EndBlock) Size() (n int) { + var l int + _ = l + if m.EndBlock != nil { + l = m.EndBlock.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *Response_Commit) Size() (n int) { + var l int + _ = l + if m.Commit != nil { + l = m.Commit.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} +func (m *ResponseException) Size() (n int) { + var l int + _ = l + l = len(m.Error) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseEcho) Size() (n int) { + var l int + _ = l + l = len(m.Message) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseFlush) Size() (n int) { + var l int + _ = l + return n +} + +func (m *ResponseInfo) Size() (n int) { + var l int + _ = l + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Version) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.LastBlockHeight != 0 { + n += 1 + sovTypes(uint64(m.LastBlockHeight)) + } + l = len(m.LastBlockAppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseSetOption) Size() (n int) { + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponseInitChain) Size() (n int) { + var l int + _ = l + if m.ConsensusParams != nil { + l = m.ConsensusParams.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Validators) > 0 { + for _, e := range m.Validators { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ResponseQuery) Size() (n int) { + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Index != 0 { + n += 1 + sovTypes(uint64(m.Index)) + } + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Value) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Proof) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + return n +} + +func (m *ResponseBeginBlock) Size() (n int) { + var l int + _ = l + if len(m.Tags) > 0 { + for _, e := range m.Tags { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ResponseCheckTx) Size() (n int) { + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.GasWanted != 0 { + n += 1 + sovTypes(uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + n += 1 + sovTypes(uint64(m.GasUsed)) + } + if len(m.Tags) > 0 { + for _, e := range m.Tags { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.Fee.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *ResponseDeliverTx) Size() (n int) { + var l int + _ = l + if m.Code != 0 { + n += 1 + sovTypes(uint64(m.Code)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Log) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Info) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.GasWanted != 0 { + n += 1 + sovTypes(uint64(m.GasWanted)) + } + if m.GasUsed != 0 { + n += 1 + sovTypes(uint64(m.GasUsed)) + } + if len(m.Tags) > 0 { + for _, e := range m.Tags { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.Fee.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *ResponseEndBlock) Size() (n int) { + var l int + _ = l + if len(m.ValidatorUpdates) > 0 { + for _, e := range m.ValidatorUpdates { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + if m.ConsensusParamUpdates != nil { + l = m.ConsensusParamUpdates.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Tags) > 0 { + for _, e := range m.Tags { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ResponseCommit) Size() (n int) { + var l int + _ = l + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ConsensusParams) Size() (n int) { + var l int + _ = l + if m.BlockSize != nil { + l = m.BlockSize.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.TxSize != nil { + l = m.TxSize.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.BlockGossip != nil { + l = m.BlockGossip.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *BlockSize) Size() (n int) { + var l int + _ = l + if m.MaxBytes != 0 { + n += 1 + sovTypes(uint64(m.MaxBytes)) + } + if m.MaxTxs != 0 { + n += 1 + sovTypes(uint64(m.MaxTxs)) + } + if m.MaxGas != 0 { + n += 1 + sovTypes(uint64(m.MaxGas)) + } + return n +} + +func (m *TxSize) Size() (n int) { + var l int + _ = l + if m.MaxBytes != 0 { + n += 1 + sovTypes(uint64(m.MaxBytes)) + } + if m.MaxGas != 0 { + n += 1 + sovTypes(uint64(m.MaxGas)) + } + return n +} + +func (m *BlockGossip) Size() (n int) { + var l int + _ = l + if m.BlockPartSizeBytes != 0 { + n += 1 + sovTypes(uint64(m.BlockPartSizeBytes)) + } + return n +} + +func (m *Header) Size() (n int) { + var l int + _ = l + l = len(m.ChainID) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Time != 0 { + n += 1 + sovTypes(uint64(m.Time)) + } + if m.NumTxs != 0 { + n += 1 + sovTypes(uint64(m.NumTxs)) + } + if m.TotalTxs != 0 { + n += 1 + sovTypes(uint64(m.TotalTxs)) + } + l = len(m.LastBlockHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.ValidatorsHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.AppHash) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Proposer.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *Validator) Size() (n int) { + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.PubKey.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Power != 0 { + n += 1 + sovTypes(uint64(m.Power)) + } + return n +} + +func (m *SigningValidator) Size() (n int) { + var l int + _ = l + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.SignedLastBlock { + n += 2 + } + return n +} + +func (m *PubKey) Size() (n int) { + var l int + _ = l + l = len(m.Type) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Data) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Evidence) Size() (n int) { + var l int + _ = l + l = len(m.Type) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Validator.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.Height != 0 { + n += 1 + sovTypes(uint64(m.Height)) + } + if m.Time != 0 { + n += 1 + sovTypes(uint64(m.Time)) + } + if m.TotalVotingPower != 0 { + n += 1 + sovTypes(uint64(m.TotalVotingPower)) + } + return n +} + +func sovTypes(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Request) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Request: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Request: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Echo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestEcho{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Echo{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Flush", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestFlush{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Flush{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestInfo{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Info{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SetOption", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestSetOption{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_SetOption{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitChain", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestInitChain{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_InitChain{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestQuery{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Query{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestBeginBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_BeginBlock{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestCheckTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_CheckTx{v} + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestEndBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_EndBlock{v} + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestCommit{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_Commit{v} + iNdEx = postIndex + case 19: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &RequestDeliverTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Request_DeliverTx{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestEcho) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestEcho: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestEcho: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Message = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestFlush) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestFlush: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestFlush: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Version = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestSetOption) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestSetOption: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestSetOption: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestInitChain) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestInitChain: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestInitChain: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + m.Time = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Time |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParams == nil { + m.ConsensusParams = &ConsensusParams{} + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, Validator{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppStateBytes", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppStateBytes = append(m.AppStateBytes[:0], dAtA[iNdEx:postIndex]...) + if m.AppStateBytes == nil { + m.AppStateBytes = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestQuery) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestQuery: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestQuery: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Path = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Prove", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.Prove = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestBeginBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestBeginBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestBeginBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...) + if m.Hash == nil { + m.Hash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, SigningValidator{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ByzantineValidators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ByzantineValidators = append(m.ByzantineValidators, Evidence{}) + if err := m.ByzantineValidators[len(m.ByzantineValidators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestCheckTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestCheckTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestCheckTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tx", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tx = append(m.Tx[:0], dAtA[iNdEx:postIndex]...) + if m.Tx == nil { + m.Tx = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestDeliverTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestDeliverTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestDeliverTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tx", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tx = append(m.Tx[:0], dAtA[iNdEx:postIndex]...) + if m.Tx == nil { + m.Tx = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestEndBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestEndBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestEndBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestCommit) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestCommit: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestCommit: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Response) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Response: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Response: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Exception", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseException{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Exception{v} + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Echo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseEcho{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Echo{v} + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Flush", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseFlush{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Flush{v} + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseInfo{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Info{v} + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SetOption", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseSetOption{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_SetOption{v} + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field InitChain", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseInitChain{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_InitChain{v} + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Query", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseQuery{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Query{v} + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BeginBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseBeginBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_BeginBlock{v} + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseCheckTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_CheckTx{v} + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseDeliverTx{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_DeliverTx{v} + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field EndBlock", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseEndBlock{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_EndBlock{v} + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Commit", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &ResponseCommit{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Value = &Response_Commit{v} + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseException) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseException: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseException: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Error", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Error = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseEcho) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseEcho: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseEcho: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Message = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseFlush) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseFlush: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseFlush: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/CheckTx", + return nil +} +func (m *ResponseInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Version = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockHeight", wireType) + } + m.LastBlockHeight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LastBlockHeight |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockAppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LastBlockAppHash = append(m.LastBlockAppHash[:0], dAtA[iNdEx:postIndex]...) + if m.LastBlockAppHash == nil { + m.LastBlockAppHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).CheckTx(ctx, req.(*RequestCheckTx)) + + if iNdEx > l { + return io.ErrUnexpectedEOF } - return interceptor(ctx, in, info, handler) + return nil } +func (m *ResponseSetOption) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseSetOption: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseSetOption: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } -func _ABCIApplication_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestQuery) - if err := dec(in); err != nil { - return nil, err + if iNdEx > l { + return io.ErrUnexpectedEOF } - if interceptor == nil { - return srv.(ABCIApplicationServer).Query(ctx, in) + return nil +} +func (m *ResponseInitChain) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseInitChain: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseInitChain: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParams", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParams == nil { + m.ConsensusParams = &ConsensusParams{} + } + if err := m.ConsensusParams.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validators", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Validators = append(m.Validators, Validator{}) + if err := m.Validators[len(m.Validators)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/Query", + + if iNdEx > l { + return io.ErrUnexpectedEOF } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).Query(ctx, req.(*RequestQuery)) + return nil +} +func (m *ResponseQuery) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseQuery: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseQuery: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) + if m.Key == nil { + m.Key = []byte{} + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...) + if m.Value == nil { + m.Value = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proof", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Proof = append(m.Proof[:0], dAtA[iNdEx:postIndex]...) + if m.Proof == nil { + m.Proof = []byte{} + } + iNdEx = postIndex + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - return interceptor(ctx, in, info, handler) + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil } +func (m *ResponseBeginBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseBeginBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseBeginBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tags", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tags = append(m.Tags, common.KVPair{}) + if err := m.Tags[len(m.Tags)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } -func _ABCIApplication_Commit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestCommit) - if err := dec(in); err != nil { - return nil, err + if iNdEx > l { + return io.ErrUnexpectedEOF } - if interceptor == nil { - return srv.(ABCIApplicationServer).Commit(ctx, in) + return nil +} +func (m *ResponseCheckTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseCheckTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseCheckTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasWanted", wireType) + } + m.GasWanted = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasWanted |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType) + } + m.GasUsed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasUsed |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tags", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tags = append(m.Tags, common.KVPair{}) + if err := m.Tags[len(m.Tags)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Fee", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Fee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/Commit", + + if iNdEx > l { + return io.ErrUnexpectedEOF } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).Commit(ctx, req.(*RequestCommit)) + return nil +} +func (m *ResponseDeliverTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseDeliverTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseDeliverTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType) + } + m.Code = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Code |= (uint32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Log", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Log = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Info = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasWanted", wireType) + } + m.GasWanted = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasWanted |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GasUsed", wireType) + } + m.GasUsed = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GasUsed |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tags", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tags = append(m.Tags, common.KVPair{}) + if err := m.Tags[len(m.Tags)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Fee", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Fee.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - return interceptor(ctx, in, info, handler) + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil } +func (m *ResponseEndBlock) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseEndBlock: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseEndBlock: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorUpdates = append(m.ValidatorUpdates, Validator{}) + if err := m.ValidatorUpdates[len(m.ValidatorUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusParamUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ConsensusParamUpdates == nil { + m.ConsensusParamUpdates = &ConsensusParams{} + } + if err := m.ConsensusParamUpdates.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tags", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tags = append(m.Tags, common.KVPair{}) + if err := m.Tags[len(m.Tags)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } -func _ABCIApplication_InitChain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestInitChain) - if err := dec(in); err != nil { - return nil, err + if iNdEx > l { + return io.ErrUnexpectedEOF } - if interceptor == nil { - return srv.(ABCIApplicationServer).InitChain(ctx, in) + return nil +} +func (m *ResponseCommit) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseCommit: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseCommit: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/InitChain", + + if iNdEx > l { + return io.ErrUnexpectedEOF } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).InitChain(ctx, req.(*RequestInitChain)) + return nil +} +func (m *ConsensusParams) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConsensusParams: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsensusParams: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockSize", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BlockSize == nil { + m.BlockSize = &BlockSize{} + } + if err := m.BlockSize.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxSize", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.TxSize == nil { + m.TxSize = &TxSize{} + } + if err := m.TxSize.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockGossip", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BlockGossip == nil { + m.BlockGossip = &BlockGossip{} + } + if err := m.BlockGossip.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - return interceptor(ctx, in, info, handler) + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil } +func (m *BlockSize) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockSize: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockSize: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxBytes", wireType) + } + m.MaxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxBytes |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxTxs", wireType) + } + m.MaxTxs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxTxs |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxGas", wireType) + } + m.MaxGas = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxGas |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } -func _ABCIApplication_BeginBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestBeginBlock) - if err := dec(in); err != nil { - return nil, err + if iNdEx > l { + return io.ErrUnexpectedEOF } - if interceptor == nil { - return srv.(ABCIApplicationServer).BeginBlock(ctx, in) + return nil +} +func (m *TxSize) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TxSize: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TxSize: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxBytes", wireType) + } + m.MaxBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxBytes |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxGas", wireType) + } + m.MaxGas = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxGas |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/BeginBlock", + + if iNdEx > l { + return io.ErrUnexpectedEOF } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).BeginBlock(ctx, req.(*RequestBeginBlock)) + return nil +} +func (m *BlockGossip) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: BlockGossip: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BlockGossip: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlockPartSizeBytes", wireType) + } + m.BlockPartSizeBytes = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.BlockPartSizeBytes |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - return interceptor(ctx, in, info, handler) + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil } +func (m *Header) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Header: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Header: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + m.Time = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Time |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NumTxs", wireType) + } + m.NumTxs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.NumTxs |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalTxs", wireType) + } + m.TotalTxs = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalTxs |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastBlockHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LastBlockHash = append(m.LastBlockHash[:0], dAtA[iNdEx:postIndex]...) + if m.LastBlockHash == nil { + m.LastBlockHash = []byte{} + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorsHash = append(m.ValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.ValidatorsHash == nil { + m.ValidatorsHash = []byte{} + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AppHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AppHash = append(m.AppHash[:0], dAtA[iNdEx:postIndex]...) + if m.AppHash == nil { + m.AppHash = []byte{} + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposer", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Proposer.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } -func _ABCIApplication_EndBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RequestEndBlock) - if err := dec(in); err != nil { - return nil, err + if iNdEx > l { + return io.ErrUnexpectedEOF } - if interceptor == nil { - return srv.(ABCIApplicationServer).EndBlock(ctx, in) + return nil +} +func (m *Validator) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Validator: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Validator: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...) + if m.Address == nil { + m.Address = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Power", wireType) + } + m.Power = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Power |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/types.ABCIApplication/EndBlock", + + if iNdEx > l { + return io.ErrUnexpectedEOF } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ABCIApplicationServer).EndBlock(ctx, req.(*RequestEndBlock)) + return nil +} +func (m *SigningValidator) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SigningValidator: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SigningValidator: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SignedLastBlock", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + m.SignedLastBlock = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } } - return interceptor(ctx, in, info, handler) + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil } +func (m *PubKey) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PubKey: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PubKey: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Type = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data[:0], dAtA[iNdEx:postIndex]...) + if m.Data == nil { + m.Data = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } -var _ABCIApplication_serviceDesc = grpc.ServiceDesc{ - ServiceName: "types.ABCIApplication", - HandlerType: (*ABCIApplicationServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Echo", - Handler: _ABCIApplication_Echo_Handler, - }, - { - MethodName: "Flush", - Handler: _ABCIApplication_Flush_Handler, - }, - { - MethodName: "Info", - Handler: _ABCIApplication_Info_Handler, - }, - { - MethodName: "SetOption", - Handler: _ABCIApplication_SetOption_Handler, - }, - { - MethodName: "DeliverTx", - Handler: _ABCIApplication_DeliverTx_Handler, - }, - { - MethodName: "CheckTx", - Handler: _ABCIApplication_CheckTx_Handler, - }, - { - MethodName: "Query", - Handler: _ABCIApplication_Query_Handler, - }, - { - MethodName: "Commit", - Handler: _ABCIApplication_Commit_Handler, - }, - { - MethodName: "InitChain", - Handler: _ABCIApplication_InitChain_Handler, - }, - { - MethodName: "BeginBlock", - Handler: _ABCIApplication_BeginBlock_Handler, - }, - { - MethodName: "EndBlock", - Handler: _ABCIApplication_EndBlock_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "types/types.proto", + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Evidence) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Evidence: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Evidence: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Type = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Validator", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Validator.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + m.Time = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Time |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalVotingPower", wireType) + } + m.TotalVotingPower = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TotalVotingPower |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthTypes + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipTypes(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") } -func init() { proto.RegisterFile("types/types.proto", fileDescriptorTypes) } +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("abci/types/types.proto", fileDescriptorTypes) } +func init() { golang_proto.RegisterFile("abci/types/types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 1846 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0xcd, 0x6e, 0x1b, 0xc9, - 0x11, 0x16, 0xff, 0x39, 0xa5, 0x1f, 0xd2, 0x2d, 0xdb, 0xa2, 0xb9, 0x08, 0x6c, 0x0c, 0x02, 0xaf, - 0x9c, 0xd5, 0x8a, 0x89, 0x76, 0x6d, 0xd8, 0xbb, 0xc9, 0x22, 0x92, 0xd6, 0x59, 0x0a, 0x9b, 0x1f, - 0x65, 0xec, 0x75, 0x80, 0x5c, 0x88, 0x26, 0xa7, 0x45, 0x0e, 0x4c, 0xce, 0xcc, 0x4e, 0x37, 0xb5, - 0x94, 0x6f, 0xb9, 0x2f, 0x72, 0xcd, 0x39, 0x2f, 0x90, 0x43, 0x80, 0xbc, 0x42, 0x90, 0x97, 0x88, - 0x0f, 0x49, 0x4e, 0x79, 0x89, 0x04, 0x55, 0xdd, 0xf3, 0xab, 0xa1, 0xe1, 0x38, 0xc7, 0xbd, 0x48, - 0x5d, 0x5d, 0x55, 0x3d, 0x5d, 0xc5, 0xaa, 0xaf, 0xaa, 0x1a, 0x6e, 0xa8, 0xab, 0x50, 0xc8, 0x01, - 0xfd, 0x3d, 0x0c, 0xa3, 0x40, 0x05, 0xac, 0x41, 0x44, 0xff, 0xc3, 0xa9, 0xa7, 0x66, 0xcb, 0xf1, - 0xe1, 0x24, 0x58, 0x0c, 0xa6, 0xc1, 0x34, 0x18, 0x10, 0x77, 0xbc, 0xbc, 0x20, 0x8a, 0x08, 0x5a, - 0x69, 0xad, 0xfe, 0x20, 0x23, 0xae, 0x84, 0xef, 0x8a, 0x68, 0xe1, 0xf9, 0x6a, 0xa0, 0x16, 0x73, - 0x6f, 0x2c, 0x07, 0x93, 0x60, 0xb1, 0x08, 0xfc, 0xec, 0x67, 0xec, 0xbf, 0xd6, 0xa1, 0xe5, 0x88, - 0xaf, 0x97, 0x42, 0x2a, 0xb6, 0x0f, 0x75, 0x31, 0x99, 0x05, 0xbd, 0xea, 0xbd, 0xca, 0xfe, 0xe6, - 0x11, 0x3b, 0xd4, 0x72, 0x86, 0xfb, 0x74, 0x32, 0x0b, 0x86, 0x1b, 0x0e, 0x49, 0xb0, 0x0f, 0xa0, - 0x71, 0x31, 0x5f, 0xca, 0x59, 0xaf, 0x46, 0xa2, 0xbb, 0x79, 0xd1, 0x9f, 0x21, 0x6b, 0xb8, 0xe1, - 0x68, 0x19, 0x3c, 0xd6, 0xf3, 0x2f, 0x82, 0x5e, 0xbd, 0xec, 0xd8, 0x33, 0xff, 0x82, 0x8e, 0x45, - 0x09, 0xf6, 0x18, 0x40, 0x0a, 0x35, 0x0a, 0x42, 0xe5, 0x05, 0x7e, 0xaf, 0x41, 0xf2, 0x7b, 0x79, - 0xf9, 0x67, 0x42, 0xfd, 0x8a, 0xd8, 0xc3, 0x0d, 0xc7, 0x92, 0x31, 0x81, 0x9a, 0x9e, 0xef, 0xa9, - 0xd1, 0x64, 0xc6, 0x3d, 0xbf, 0xd7, 0x2c, 0xd3, 0x3c, 0xf3, 0x3d, 0x75, 0x8a, 0x6c, 0xd4, 0xf4, - 0x62, 0x02, 0x4d, 0xf9, 0x7a, 0x29, 0xa2, 0xab, 0x5e, 0xab, 0xcc, 0x94, 0x5f, 0x23, 0x0b, 0x4d, - 0x21, 0x19, 0xf6, 0x29, 0x6c, 0x8e, 0xc5, 0xd4, 0xf3, 0x47, 0xe3, 0x79, 0x30, 0x79, 0xd9, 0x6b, - 0x93, 0x4a, 0x2f, 0xaf, 0x72, 0x82, 0x02, 0x27, 0xc8, 0x1f, 0x6e, 0x38, 0x30, 0x4e, 0x28, 0x76, - 0x04, 0xed, 0xc9, 0x4c, 0x4c, 0x5e, 0x8e, 0xd4, 0xaa, 0x67, 0x91, 0xe6, 0xad, 0xbc, 0xe6, 0x29, - 0x72, 0x9f, 0xaf, 0x86, 0x1b, 0x4e, 0x6b, 0xa2, 0x97, 0x68, 0x97, 0x2b, 0xe6, 0xde, 0xa5, 0x88, - 0x50, 0x6b, 0xb7, 0xcc, 0xae, 0xcf, 0x35, 0x9f, 0xf4, 0x2c, 0x37, 0x26, 0xd8, 0x43, 0xb0, 0x84, - 0xef, 0x9a, 0x8b, 0x6e, 0x92, 0xe2, 0xed, 0xc2, 0x2f, 0xea, 0xbb, 0xf1, 0x35, 0xdb, 0xc2, 0xac, - 0xd9, 0x21, 0x34, 0x31, 0x4a, 0x3c, 0xd5, 0xdb, 0x22, 0x9d, 0x9b, 0x85, 0x2b, 0x12, 0x6f, 0xb8, - 0xe1, 0x18, 0xa9, 0x93, 0x16, 0x34, 0x2e, 0xf9, 0x7c, 0x29, 0xec, 0xf7, 0x61, 0x33, 0x13, 0x29, - 0xac, 0x07, 0xad, 0x85, 0x90, 0x92, 0x4f, 0x45, 0xaf, 0x72, 0xaf, 0xb2, 0x6f, 0x39, 0x31, 0x69, - 0xef, 0xc0, 0x56, 0x36, 0x4e, 0x32, 0x8a, 0x18, 0x0b, 0xa8, 0x78, 0x29, 0x22, 0x89, 0x01, 0x60, - 0x14, 0x0d, 0x69, 0x7f, 0x02, 0xdd, 0x62, 0x10, 0xb0, 0x2e, 0xd4, 0x5e, 0x8a, 0x2b, 0x23, 0x89, - 0x4b, 0x76, 0xd3, 0x5c, 0x88, 0xa2, 0xd8, 0x72, 0xcc, 0xed, 0xfe, 0x55, 0x49, 0x94, 0x93, 0x38, - 0x60, 0x0c, 0xea, 0xca, 0x5b, 0xe8, 0x0b, 0xd6, 0x1c, 0x5a, 0xb3, 0x3b, 0xf8, 0x23, 0x71, 0xcf, - 0x1f, 0x79, 0xae, 0x39, 0xa1, 0x45, 0xf4, 0x99, 0xcb, 0x8e, 0xa1, 0x3b, 0x09, 0x7c, 0x29, 0x7c, - 0xb9, 0x94, 0xa3, 0x90, 0x47, 0x7c, 0x21, 0x4d, 0xfc, 0xc7, 0x8e, 0x3d, 0x8d, 0xd9, 0xe7, 0xc4, - 0x75, 0x3a, 0x93, 0xfc, 0x06, 0x7b, 0x04, 0x70, 0xc9, 0xe7, 0x9e, 0xcb, 0x55, 0x10, 0xc9, 0x5e, - 0xfd, 0x5e, 0x6d, 0x7f, 0xf3, 0xa8, 0x6b, 0x94, 0x5f, 0xc4, 0x8c, 0x93, 0xfa, 0xdf, 0x5e, 0xdf, - 0xdd, 0x70, 0x32, 0x92, 0xec, 0x3e, 0x74, 0x78, 0x18, 0x8e, 0xa4, 0xe2, 0x4a, 0x8c, 0xc6, 0x57, - 0x4a, 0x48, 0xca, 0x8e, 0x2d, 0x67, 0x9b, 0x87, 0xe1, 0x33, 0xdc, 0x3d, 0xc1, 0x4d, 0xdb, 0x4d, - 0x7c, 0x4b, 0x81, 0x8b, 0x16, 0xba, 0x5c, 0x71, 0xb2, 0x70, 0xcb, 0xa1, 0x35, 0xee, 0x85, 0x5c, - 0xcd, 0x8c, 0x75, 0xb4, 0x66, 0xb7, 0xa1, 0x39, 0x13, 0xde, 0x74, 0xa6, 0xc8, 0xa0, 0x9a, 0x63, - 0x28, 0x74, 0x66, 0x18, 0x05, 0x97, 0x82, 0x72, 0xb7, 0xed, 0x68, 0xc2, 0xfe, 0x7b, 0x05, 0x6e, - 0x5c, 0x0b, 0x76, 0x3c, 0x77, 0xc6, 0xe5, 0x2c, 0xfe, 0x16, 0xae, 0xd9, 0x07, 0x78, 0x2e, 0x77, - 0x45, 0x64, 0x30, 0x65, 0xdb, 0xd8, 0x3a, 0xa4, 0x4d, 0x63, 0xa8, 0x11, 0x61, 0x3f, 0xc9, 0x39, - 0xa7, 0x46, 0xce, 0x89, 0x63, 0xfd, 0x99, 0x37, 0xf5, 0x3d, 0x7f, 0xfa, 0x26, 0x1f, 0x0d, 0xe1, - 0xe6, 0xf8, 0xea, 0x15, 0xf7, 0x95, 0xe7, 0x8b, 0xd1, 0x35, 0x2f, 0x77, 0xcc, 0x41, 0x4f, 0x2f, - 0x3d, 0x57, 0xf8, 0x13, 0x61, 0x0e, 0xd8, 0x4d, 0x54, 0x92, 0xa3, 0xa5, 0x7d, 0x0f, 0x76, 0xf2, - 0x19, 0xc9, 0x76, 0xa0, 0xaa, 0x56, 0xc6, 0xb2, 0xaa, 0x5a, 0xd9, 0x76, 0x12, 0x4d, 0x49, 0xf6, - 0x5d, 0x93, 0x79, 0x00, 0x9d, 0x42, 0xa2, 0x65, 0xdc, 0x5c, 0xc9, 0xba, 0xd9, 0xee, 0xc0, 0x76, - 0x2e, 0xbf, 0xec, 0x6f, 0x1b, 0xd0, 0x76, 0x84, 0x0c, 0x31, 0x7c, 0xd8, 0x63, 0xb0, 0xc4, 0x6a, - 0x22, 0x34, 0x28, 0x56, 0x0a, 0x90, 0xa3, 0x65, 0x9e, 0xc6, 0x7c, 0xc4, 0x80, 0x44, 0x98, 0x3d, - 0xc8, 0x01, 0xfa, 0x6e, 0x51, 0x29, 0x8b, 0xe8, 0x07, 0x79, 0x44, 0xbf, 0x59, 0x90, 0x2d, 0x40, - 0xfa, 0x83, 0x1c, 0xa4, 0x17, 0x0f, 0xce, 0x61, 0xfa, 0x93, 0x12, 0x4c, 0x2f, 0x5e, 0x7f, 0x0d, - 0xa8, 0x3f, 0x29, 0x01, 0xf5, 0xde, 0xb5, 0x6f, 0x95, 0xa2, 0xfa, 0x41, 0x1e, 0xd5, 0x8b, 0xe6, - 0x14, 0x60, 0xfd, 0xc7, 0x65, 0xb0, 0x7e, 0xa7, 0xa0, 0xb3, 0x16, 0xd7, 0x3f, 0xba, 0x86, 0xeb, - 0xb7, 0x0b, 0xaa, 0x25, 0xc0, 0xfe, 0x24, 0x07, 0xec, 0x50, 0x6a, 0xdb, 0x1a, 0x64, 0x7f, 0x74, - 0x1d, 0xd9, 0xf7, 0x8a, 0x3f, 0x6d, 0x19, 0xb4, 0x0f, 0x0a, 0xd0, 0x7e, 0xab, 0x78, 0xcb, 0xb5, - 0xd8, 0xfe, 0x00, 0xf3, 0xbd, 0x10, 0x69, 0x88, 0x0d, 0x22, 0x8a, 0x82, 0xc8, 0x80, 0xaf, 0x26, - 0xec, 0x7d, 0x44, 0xa0, 0x34, 0xbe, 0xde, 0x50, 0x07, 0x28, 0xe8, 0x33, 0xd1, 0x65, 0xff, 0xa1, - 0x92, 0xea, 0x52, 0x29, 0xc8, 0xa2, 0x97, 0x65, 0xd0, 0x2b, 0x53, 0x1e, 0xaa, 0xb9, 0xf2, 0xc0, - 0x7e, 0x00, 0x37, 0xe6, 0x5c, 0x2a, 0xed, 0x97, 0x51, 0x0e, 0xce, 0x3a, 0xc8, 0xd0, 0x0e, 0xd1, - 0xb8, 0xf6, 0x21, 0xec, 0x66, 0x64, 0x11, 0x5a, 0x09, 0xba, 0xea, 0x94, 0xbc, 0xdd, 0x44, 0xfa, - 0x38, 0x0c, 0x87, 0x5c, 0xce, 0xec, 0x5f, 0xa4, 0xf6, 0xa7, 0xa5, 0x87, 0x41, 0x7d, 0x12, 0xb8, - 0xda, 0xac, 0x6d, 0x87, 0xd6, 0x58, 0x8e, 0xe6, 0xc1, 0x94, 0xbe, 0x6a, 0x39, 0xb8, 0x44, 0xa9, - 0x24, 0x53, 0x2c, 0x9d, 0x12, 0xf6, 0xef, 0x2b, 0xe9, 0x79, 0x69, 0x35, 0x2a, 0x2b, 0x2f, 0x95, - 0xff, 0xa7, 0xbc, 0x54, 0xdf, 0xb6, 0xbc, 0xd8, 0x7f, 0xa9, 0xa4, 0xbf, 0x45, 0x52, 0x38, 0xde, - 0xcd, 0x38, 0x0c, 0x0b, 0xcf, 0x77, 0xc5, 0x8a, 0x52, 0xbd, 0xe6, 0x68, 0x22, 0xae, 0xd3, 0x4d, - 0x72, 0x70, 0xbe, 0x4e, 0xb7, 0x68, 0x4f, 0x13, 0xa6, 0xe0, 0x04, 0x17, 0x94, 0x83, 0x5b, 0x8e, - 0x26, 0x32, 0xb8, 0x69, 0xe5, 0x70, 0xf3, 0x1c, 0xd8, 0xf5, 0xec, 0x64, 0x9f, 0x40, 0x5d, 0xf1, - 0x29, 0x3a, 0x0f, 0xed, 0xdf, 0x39, 0xd4, 0x5d, 0xef, 0xe1, 0x97, 0x2f, 0xce, 0xb9, 0x17, 0x9d, - 0xdc, 0x46, 0xeb, 0xff, 0xfd, 0xfa, 0xee, 0x0e, 0xca, 0x1c, 0x04, 0x0b, 0x4f, 0x89, 0x45, 0xa8, - 0xae, 0x1c, 0xd2, 0xb1, 0xff, 0x53, 0x41, 0xd4, 0xce, 0x65, 0x6d, 0xa9, 0x2f, 0xe2, 0xd0, 0xac, - 0x66, 0x0a, 0xeb, 0xdb, 0xf9, 0xe7, 0x7b, 0x00, 0x53, 0x2e, 0x47, 0xdf, 0x70, 0x5f, 0x09, 0xd7, - 0x38, 0xc9, 0x9a, 0x72, 0xf9, 0x1b, 0xda, 0xc0, 0xfe, 0x03, 0xd9, 0x4b, 0x29, 0x5c, 0xf2, 0x56, - 0xcd, 0x69, 0x4d, 0xb9, 0xfc, 0x4a, 0x0a, 0x37, 0xb1, 0xab, 0xf5, 0xbf, 0xdb, 0xc5, 0xf6, 0xa1, - 0x76, 0x21, 0x84, 0x41, 0xb6, 0x6e, 0xa2, 0x7a, 0xf6, 0xe8, 0x63, 0x52, 0xd6, 0x21, 0x81, 0x22, - 0xf6, 0xef, 0xaa, 0x69, 0x70, 0xa6, 0xc5, 0xed, 0xbb, 0xe5, 0x83, 0x7f, 0x52, 0xb7, 0x98, 0x87, - 0x52, 0x76, 0x0a, 0x37, 0x92, 0x94, 0x19, 0x2d, 0x43, 0x97, 0x63, 0x17, 0x56, 0x79, 0x63, 0x8e, - 0x75, 0x13, 0x85, 0xaf, 0xb4, 0x3c, 0xfb, 0x25, 0xec, 0x15, 0x92, 0x3c, 0x39, 0xaa, 0xfa, 0xc6, - 0x5c, 0xbf, 0x95, 0xcf, 0xf5, 0xf8, 0xbc, 0xd8, 0x1f, 0xb5, 0x77, 0x88, 0xf5, 0xef, 0x63, 0x9b, - 0x93, 0x85, 0xfe, 0xb2, 0x5f, 0xd4, 0xfe, 0x63, 0x05, 0x3a, 0x85, 0xcb, 0xb0, 0x01, 0x80, 0x46, - 0x4e, 0xe9, 0xbd, 0x12, 0x06, 0xa4, 0x62, 0x1f, 0x90, 0xb3, 0x9e, 0x79, 0xaf, 0x84, 0x63, 0x8d, - 0xe3, 0x25, 0xbb, 0x0f, 0x2d, 0xb5, 0xd2, 0xd2, 0xf9, 0x46, 0xf0, 0xf9, 0x8a, 0x44, 0x9b, 0x8a, - 0xfe, 0xb3, 0x87, 0xb0, 0xa5, 0x0f, 0x9e, 0x06, 0x52, 0x7a, 0xa1, 0x69, 0x46, 0x58, 0xf6, 0xe8, - 0x2f, 0x88, 0xe3, 0x6c, 0x8e, 0x53, 0xc2, 0xfe, 0x2d, 0x58, 0xc9, 0x67, 0xd9, 0x7b, 0x60, 0x2d, - 0xf8, 0xca, 0x74, 0xc9, 0x78, 0xb7, 0x86, 0xd3, 0x5e, 0xf0, 0x15, 0x35, 0xc8, 0x6c, 0x0f, 0x5a, - 0xc8, 0x54, 0x2b, 0xed, 0xef, 0x86, 0xd3, 0x5c, 0xf0, 0xd5, 0xf3, 0x55, 0xc2, 0x98, 0x72, 0x19, - 0xb7, 0xc0, 0x0b, 0xbe, 0xfa, 0x82, 0x4b, 0xfb, 0x33, 0x68, 0xea, 0x4b, 0xbe, 0xd5, 0xc1, 0xa8, - 0x5f, 0xcd, 0xe9, 0xff, 0x14, 0x36, 0x33, 0xf7, 0x66, 0x3f, 0x82, 0x5b, 0xda, 0xc2, 0x90, 0x47, - 0x8a, 0x3c, 0x92, 0x3b, 0x90, 0x11, 0xf3, 0x9c, 0x47, 0x0a, 0x3f, 0xa9, 0x9b, 0xfa, 0x3f, 0x57, - 0xa1, 0xa9, 0x1b, 0x66, 0x76, 0x3f, 0x33, 0x9d, 0x50, 0x55, 0x3c, 0xd9, 0xfc, 0xc7, 0xeb, 0xbb, - 0x2d, 0x2a, 0x20, 0x67, 0x9f, 0xa7, 0xa3, 0x4a, 0x0a, 0x98, 0xd5, 0x5c, 0x3f, 0x1f, 0x4f, 0x3c, - 0xb5, 0xcc, 0xc4, 0xb3, 0x07, 0x2d, 0x7f, 0xb9, 0x20, 0x97, 0xd4, 0xb5, 0x4b, 0xfc, 0xe5, 0x02, - 0x5d, 0xf2, 0x1e, 0x58, 0x2a, 0x50, 0x7c, 0x4e, 0x2c, 0x9d, 0xa4, 0x6d, 0xda, 0x40, 0xe6, 0x7d, - 0xe8, 0x64, 0xab, 0x2d, 0x56, 0x4f, 0x0d, 0xee, 0xdb, 0x69, 0xad, 0xc5, 0x09, 0xe0, 0x7d, 0xe8, - 0xa4, 0x85, 0x46, 0xcb, 0x69, 0xc0, 0xdf, 0x49, 0xb7, 0x49, 0xf0, 0x0e, 0xb4, 0x93, 0x3a, 0xac, - 0xc1, 0xbf, 0xc5, 0x75, 0xf9, 0xc5, 0xc1, 0x39, 0x8c, 0x82, 0x30, 0x90, 0x22, 0x32, 0x0d, 0xd6, - 0xba, 0x84, 0x4b, 0xe4, 0x6c, 0x0f, 0xac, 0x84, 0x89, 0x4d, 0x03, 0x77, 0xdd, 0x48, 0x48, 0x69, - 0xfa, 0xf3, 0x98, 0x64, 0x07, 0xd0, 0x0a, 0x97, 0xe3, 0x11, 0xd6, 0xa6, 0x7c, 0x60, 0x9e, 0x2f, - 0xc7, 0x5f, 0x8a, 0xab, 0x78, 0x42, 0x09, 0x89, 0xa2, 0xea, 0x14, 0x7c, 0x23, 0x22, 0xe3, 0x3f, - 0x4d, 0xd8, 0x0a, 0xba, 0xc5, 0xf1, 0x84, 0x7d, 0x0c, 0x56, 0x62, 0x5f, 0x21, 0x41, 0x8a, 0x77, - 0x4e, 0x05, 0xb1, 0x85, 0x91, 0xde, 0xd4, 0x17, 0xee, 0x28, 0xf5, 0x2d, 0xdd, 0xab, 0xed, 0x74, - 0x34, 0xe3, 0xe7, 0xb1, 0x73, 0xed, 0x1f, 0x42, 0x53, 0xdf, 0x91, 0x7e, 0xd4, 0xab, 0x30, 0xee, - 0xaf, 0x68, 0x5d, 0x9a, 0xc9, 0x7f, 0xaa, 0x40, 0x3b, 0x1e, 0x7f, 0x4a, 0x95, 0x72, 0x97, 0xae, - 0xbe, 0xed, 0xa5, 0xd7, 0xcd, 0x8e, 0x71, 0xac, 0xd5, 0x33, 0xb1, 0x76, 0x00, 0x4c, 0x87, 0xd4, - 0x65, 0xa0, 0x3c, 0x7f, 0x3a, 0xd2, 0xde, 0xd4, 0xb1, 0xd5, 0x25, 0xce, 0x0b, 0x62, 0x9c, 0xe3, - 0xfe, 0xd1, 0xb7, 0x0d, 0xe8, 0x1c, 0x9f, 0x9c, 0x9e, 0x1d, 0x87, 0xe1, 0xdc, 0x9b, 0x70, 0xea, - 0xba, 0x06, 0x50, 0xa7, 0xbe, 0xb2, 0xe4, 0x75, 0xaa, 0x5f, 0x36, 0xe0, 0xb0, 0x23, 0x68, 0x50, - 0x7b, 0xc9, 0xca, 0x1e, 0xa9, 0xfa, 0xa5, 0x73, 0x0e, 0x7e, 0x44, 0x37, 0xa0, 0xd7, 0xdf, 0xaa, - 0xfa, 0x65, 0xc3, 0x0e, 0xfb, 0x0c, 0xac, 0xb4, 0x31, 0x5c, 0xf7, 0x62, 0xd5, 0x5f, 0x3b, 0xf6, - 0xa0, 0x7e, 0x5a, 0x6b, 0xd7, 0xbd, 0xef, 0xf4, 0xd7, 0xce, 0x07, 0xec, 0x31, 0xb4, 0xe2, 0x6e, - 0xa5, 0xfc, 0x4d, 0xa9, 0xbf, 0x66, 0x24, 0x41, 0xf7, 0xe8, 0x8e, 0xaf, 0xec, 0xe1, 0xab, 0x5f, - 0x3a, 0x37, 0xb1, 0x87, 0xd0, 0x34, 0x05, 0xa3, 0xf4, 0x75, 0xa8, 0x5f, 0x3e, 0x58, 0xa0, 0x91, - 0x69, 0xb7, 0xbb, 0xee, 0x71, 0xae, 0xbf, 0x76, 0xc0, 0x63, 0xc7, 0x00, 0x99, 0x2e, 0x6f, 0xed, - 0xab, 0x5b, 0x7f, 0xfd, 0xe0, 0xc6, 0x3e, 0x85, 0x76, 0x3a, 0x8c, 0x97, 0xbf, 0x86, 0xf5, 0xd7, - 0xcd, 0x52, 0xe3, 0x26, 0xbd, 0x98, 0x7e, 0xf4, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe5, 0xf3, - 0xb2, 0x34, 0xad, 0x15, 0x00, 0x00, + // 1892 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x58, 0x4b, 0x73, 0x1c, 0x49, + 0x11, 0x56, 0xcf, 0xbb, 0x53, 0x8f, 0x19, 0x97, 0x6c, 0x69, 0x3c, 0x0b, 0xb2, 0xa3, 0x83, 0xf0, + 0xca, 0xac, 0x56, 0x02, 0xed, 0xda, 0x61, 0xef, 0xc2, 0x06, 0x1a, 0xad, 0xd9, 0x51, 0x2c, 0x0f, + 0xd1, 0xf6, 0x9a, 0x08, 0x2e, 0x13, 0x35, 0xd3, 0xa5, 0x9e, 0x0e, 0xcf, 0x74, 0xf7, 0x76, 0xd5, + 0x68, 0x47, 0xbe, 0x71, 0xdf, 0xe0, 0xca, 0x99, 0x1b, 0x27, 0x0e, 0x44, 0x10, 0xc1, 0x91, 0x13, + 0xb1, 0x47, 0xfe, 0x00, 0x0e, 0xd0, 0x72, 0xe2, 0x17, 0x70, 0x83, 0xa8, 0xac, 0xea, 0xa7, 0x7a, + 0x1c, 0xc2, 0x1c, 0xb9, 0x48, 0x95, 0x9d, 0x99, 0x55, 0x95, 0x39, 0x99, 0x5f, 0x66, 0x16, 0x6c, + 0xd1, 0xd1, 0xd8, 0x3b, 0x10, 0x17, 0x21, 0xe3, 0xea, 0xef, 0x7e, 0x18, 0x05, 0x22, 0x20, 0x75, + 0x24, 0x7a, 0xef, 0xba, 0x9e, 0x98, 0xcc, 0x47, 0xfb, 0xe3, 0x60, 0x76, 0xe0, 0x06, 0x6e, 0x70, + 0x80, 0xdc, 0xd1, 0xfc, 0x0c, 0x29, 0x24, 0x70, 0xa5, 0xb4, 0x7a, 0x8f, 0x32, 0xe2, 0x82, 0xf9, + 0x0e, 0x8b, 0x66, 0x9e, 0x2f, 0xb2, 0xcb, 0xa9, 0x37, 0xe2, 0x07, 0xe3, 0x60, 0x36, 0x0b, 0xfc, + 0xec, 0x79, 0xd6, 0x9f, 0x6b, 0xd0, 0xb4, 0xd9, 0xe7, 0x73, 0xc6, 0x05, 0xd9, 0x85, 0x1a, 0x1b, + 0x4f, 0x82, 0x6e, 0xe5, 0xae, 0xb1, 0xbb, 0x7a, 0x48, 0xf6, 0x95, 0x9c, 0xe6, 0x3e, 0x19, 0x4f, + 0x82, 0xc1, 0x8a, 0x8d, 0x12, 0xe4, 0x1d, 0xa8, 0x9f, 0x4d, 0xe7, 0x7c, 0xd2, 0xad, 0xa2, 0xe8, + 0x66, 0x5e, 0xf4, 0x87, 0x92, 0x35, 0x58, 0xb1, 0x95, 0x8c, 0xdc, 0xd6, 0xf3, 0xcf, 0x82, 0x6e, + 0xad, 0x6c, 0xdb, 0x13, 0xff, 0x0c, 0xb7, 0x95, 0x12, 0xe4, 0x11, 0x00, 0x67, 0x62, 0x18, 0x84, + 0xc2, 0x0b, 0xfc, 0x6e, 0x1d, 0xe5, 0xb7, 0xf3, 0xf2, 0x4f, 0x99, 0xf8, 0x29, 0xb2, 0x07, 0x2b, + 0xb6, 0xc9, 0x63, 0x42, 0x6a, 0x7a, 0xbe, 0x27, 0x86, 0xe3, 0x09, 0xf5, 0xfc, 0x6e, 0xa3, 0x4c, + 0xf3, 0xc4, 0xf7, 0xc4, 0xb1, 0x64, 0x4b, 0x4d, 0x2f, 0x26, 0xa4, 0x29, 0x9f, 0xcf, 0x59, 0x74, + 0xd1, 0x6d, 0x96, 0x99, 0xf2, 0x33, 0xc9, 0x92, 0xa6, 0xa0, 0x0c, 0xf9, 0x10, 0x56, 0x47, 0xcc, + 0xf5, 0xfc, 0xe1, 0x68, 0x1a, 0x8c, 0x5f, 0x74, 0x5b, 0xa8, 0xd2, 0xcd, 0xab, 0xf4, 0xa5, 0x40, + 0x5f, 0xf2, 0x07, 0x2b, 0x36, 0x8c, 0x12, 0x8a, 0x1c, 0x42, 0x6b, 0x3c, 0x61, 0xe3, 0x17, 0x43, + 0xb1, 0xe8, 0x9a, 0xa8, 0x79, 0x2b, 0xaf, 0x79, 0x2c, 0xb9, 0xcf, 0x16, 0x83, 0x15, 0xbb, 0x39, + 0x56, 0x4b, 0xf2, 0x00, 0x4c, 0xe6, 0x3b, 0xfa, 0xb8, 0x55, 0x54, 0xda, 0x2a, 0xfc, 0x2e, 0xbe, + 0x13, 0x1f, 0xd6, 0x62, 0x7a, 0x4d, 0xf6, 0xa1, 0x21, 0x7f, 0x6b, 0x4f, 0x74, 0xd7, 0x50, 0xe7, + 0x66, 0xe1, 0x20, 0xe4, 0x0d, 0x56, 0x6c, 0x2d, 0x25, 0xdd, 0xe7, 0xb0, 0xa9, 0x77, 0xce, 0x22, + 0x79, 0xb9, 0xcd, 0x32, 0xf7, 0x7d, 0xac, 0xf8, 0x78, 0x3d, 0xd3, 0x89, 0x89, 0x7e, 0x13, 0xea, + 0xe7, 0x74, 0x3a, 0x67, 0xd6, 0xdb, 0xb0, 0x9a, 0x89, 0x14, 0xd2, 0x85, 0xe6, 0x8c, 0x71, 0x4e, + 0x5d, 0xd6, 0x35, 0xee, 0x1a, 0xbb, 0xa6, 0x1d, 0x93, 0xd6, 0x06, 0xac, 0x65, 0xe3, 0x24, 0xa3, + 0x28, 0x63, 0x41, 0x2a, 0x9e, 0xb3, 0x88, 0xcb, 0x00, 0xd0, 0x8a, 0x9a, 0xb4, 0x3e, 0x80, 0x4e, + 0x31, 0x08, 0x48, 0x07, 0xaa, 0x2f, 0xd8, 0x85, 0x96, 0x94, 0x4b, 0x72, 0x53, 0x5f, 0x08, 0xa3, + 0xd8, 0xb4, 0xf5, 0xed, 0xfe, 0x61, 0x24, 0xca, 0x49, 0x1c, 0x10, 0x02, 0x35, 0xe1, 0xcd, 0xd4, + 0x05, 0xab, 0x36, 0xae, 0xc9, 0x6d, 0xf9, 0x23, 0x51, 0xcf, 0x1f, 0x7a, 0x8e, 0xde, 0xa1, 0x89, + 0xf4, 0x89, 0x43, 0x8e, 0xa0, 0x33, 0x0e, 0x7c, 0xce, 0x7c, 0x3e, 0xe7, 0xc3, 0x90, 0x46, 0x74, + 0xc6, 0x75, 0xfc, 0xc7, 0x3f, 0xc9, 0x71, 0xcc, 0x3e, 0x45, 0xae, 0xdd, 0x1e, 0xe7, 0x3f, 0x90, + 0x87, 0x00, 0xe7, 0x74, 0xea, 0x39, 0x54, 0x04, 0x11, 0xef, 0xd6, 0xee, 0x56, 0x77, 0x57, 0x0f, + 0x3b, 0x5a, 0xf9, 0x79, 0xcc, 0xe8, 0xd7, 0xbe, 0x7a, 0x75, 0x67, 0xc5, 0xce, 0x48, 0x92, 0x7b, + 0xd0, 0xa6, 0x61, 0x38, 0xe4, 0x82, 0x0a, 0x36, 0x1c, 0x5d, 0x08, 0xc6, 0x31, 0x3b, 0xd6, 0xec, + 0x75, 0x1a, 0x86, 0x4f, 0xe5, 0xd7, 0xbe, 0xfc, 0x68, 0x39, 0x89, 0x6f, 0x31, 0x70, 0xa5, 0x85, + 0x0e, 0x15, 0x14, 0x2d, 0x5c, 0xb3, 0x71, 0x2d, 0xbf, 0x85, 0x54, 0x4c, 0xb4, 0x75, 0xb8, 0x26, + 0x5b, 0xd0, 0x98, 0x30, 0xcf, 0x9d, 0x08, 0x34, 0xa8, 0x6a, 0x6b, 0x4a, 0x3a, 0x33, 0x8c, 0x82, + 0x73, 0x86, 0xb9, 0xdb, 0xb2, 0x15, 0x61, 0xfd, 0xd5, 0x80, 0x1b, 0x57, 0x82, 0x5d, 0xee, 0x3b, + 0xa1, 0x7c, 0x12, 0x9f, 0x25, 0xd7, 0xe4, 0x1d, 0xb9, 0x2f, 0x75, 0x58, 0xa4, 0x31, 0x65, 0x5d, + 0xdb, 0x3a, 0xc0, 0x8f, 0xda, 0x50, 0x2d, 0x42, 0xbe, 0x9f, 0x73, 0x4e, 0x15, 0x9d, 0x13, 0x07, + 0xe1, 0x53, 0xcf, 0xf5, 0x3d, 0xdf, 0x7d, 0x9d, 0x8f, 0x06, 0x70, 0x73, 0x74, 0xf1, 0x92, 0xfa, + 0xc2, 0xf3, 0xd9, 0xf0, 0x8a, 0x97, 0xdb, 0x7a, 0xa3, 0x27, 0xe7, 0x9e, 0xc3, 0xfc, 0x31, 0xd3, + 0x1b, 0x6c, 0x26, 0x2a, 0xc9, 0xd6, 0xdc, 0xba, 0x0b, 0x1b, 0xf9, 0x8c, 0x24, 0x1b, 0x50, 0x11, + 0x0b, 0x6d, 0x59, 0x45, 0x2c, 0x2c, 0x2b, 0x89, 0xa6, 0x24, 0x2d, 0xae, 0xc8, 0xdc, 0x87, 0x76, + 0x21, 0x45, 0x33, 0x6e, 0x36, 0xb2, 0x6e, 0xb6, 0xda, 0xb0, 0x9e, 0xcb, 0x4c, 0xeb, 0xcb, 0x3a, + 0xb4, 0x6c, 0xc6, 0x43, 0x19, 0x3e, 0xe4, 0x11, 0x98, 0x6c, 0x31, 0x66, 0x0a, 0x14, 0x8d, 0x02, + 0xe4, 0x28, 0x99, 0x27, 0x31, 0x5f, 0x26, 0x67, 0x22, 0x4c, 0xee, 0xe7, 0x00, 0x7d, 0xb3, 0xa8, + 0x94, 0x45, 0xf4, 0xbd, 0x3c, 0xa2, 0xdf, 0x2c, 0xc8, 0x16, 0x20, 0xfd, 0x7e, 0x0e, 0xd2, 0x8b, + 0x1b, 0xe7, 0x30, 0xfd, 0x71, 0x09, 0xa6, 0x17, 0xaf, 0xbf, 0x04, 0xd4, 0x1f, 0x97, 0x80, 0x7a, + 0xf7, 0xca, 0x59, 0xa5, 0xa8, 0xbe, 0x97, 0x47, 0xf5, 0xa2, 0x39, 0x05, 0x58, 0xff, 0x5e, 0x19, + 0xac, 0xdf, 0x2e, 0xe8, 0x2c, 0xc5, 0xf5, 0xf7, 0xae, 0xe0, 0xfa, 0x56, 0x41, 0xb5, 0x04, 0xd8, + 0x1f, 0xe7, 0x10, 0x17, 0x4a, 0x6d, 0x2b, 0x87, 0x5c, 0xf2, 0xf0, 0x6a, 0x4d, 0xd8, 0x2e, 0xfe, + 0xb4, 0x65, 0x45, 0xe1, 0xa0, 0x50, 0x14, 0x6e, 0x15, 0x6f, 0x59, 0xa8, 0x0a, 0x29, 0xb6, 0xdf, + 0x97, 0xf9, 0x5e, 0x88, 0x34, 0x89, 0x0d, 0x2c, 0x8a, 0x82, 0x48, 0x83, 0xaf, 0x22, 0xac, 0x5d, + 0x89, 0x40, 0x69, 0x7c, 0xbd, 0xa6, 0x0e, 0x60, 0xd0, 0x67, 0xa2, 0xcb, 0xfa, 0xb5, 0x91, 0xea, + 0x62, 0x29, 0xc8, 0xa2, 0x97, 0xa9, 0xd1, 0x2b, 0x53, 0x1e, 0x2a, 0xb9, 0xf2, 0x40, 0xbe, 0x0d, + 0x37, 0xa6, 0x94, 0x0b, 0xe5, 0x97, 0x61, 0x0e, 0xce, 0xda, 0x92, 0xa1, 0x1c, 0xa2, 0x70, 0xed, + 0x5d, 0xd8, 0xcc, 0xc8, 0x4a, 0x68, 0x45, 0xe8, 0xaa, 0x61, 0xf2, 0x76, 0x12, 0xe9, 0xa3, 0x30, + 0x1c, 0x50, 0x3e, 0xb1, 0x7e, 0x9c, 0xda, 0x9f, 0x96, 0x1e, 0x02, 0xb5, 0x71, 0xe0, 0x28, 0xb3, + 0xd6, 0x6d, 0x5c, 0xcb, 0x72, 0x34, 0x0d, 0x5c, 0x3c, 0xd5, 0xb4, 0xe5, 0x52, 0x4a, 0x25, 0x99, + 0x62, 0xaa, 0x94, 0xb0, 0x7e, 0x65, 0xa4, 0xfb, 0xa5, 0xd5, 0xa8, 0xac, 0xbc, 0x18, 0xff, 0x4b, + 0x79, 0xa9, 0x5c, 0xb7, 0xbc, 0x58, 0x7f, 0x30, 0xd2, 0xdf, 0x22, 0x29, 0x1c, 0x6f, 0x66, 0x9c, + 0x0c, 0x0b, 0xcf, 0x77, 0xd8, 0x02, 0x53, 0xbd, 0x6a, 0x2b, 0x22, 0xae, 0xd3, 0x0d, 0x74, 0x70, + 0xbe, 0x4e, 0x37, 0xf1, 0x9b, 0x22, 0x74, 0xc1, 0x09, 0xce, 0x30, 0x07, 0xd7, 0x6c, 0x45, 0x64, + 0x70, 0xd3, 0xcc, 0xe1, 0xe6, 0x29, 0x90, 0xab, 0xd9, 0x49, 0x3e, 0x80, 0x9a, 0xa0, 0xae, 0x74, + 0x9e, 0xb4, 0x7f, 0x63, 0x5f, 0x75, 0xbd, 0xfb, 0x9f, 0x3e, 0x3f, 0xa5, 0x5e, 0xd4, 0xdf, 0x92, + 0xd6, 0xff, 0xf3, 0xd5, 0x9d, 0x0d, 0x29, 0xb3, 0x17, 0xcc, 0x3c, 0xc1, 0x66, 0xa1, 0xb8, 0xb0, + 0x51, 0xc7, 0xfa, 0xb7, 0x21, 0x51, 0x3b, 0x97, 0xb5, 0xa5, 0xbe, 0x88, 0x43, 0xb3, 0x92, 0x29, + 0xac, 0xd7, 0xf3, 0xcf, 0x37, 0x01, 0x5c, 0xca, 0x87, 0x5f, 0x50, 0x5f, 0x30, 0x47, 0x3b, 0xc9, + 0x74, 0x29, 0xff, 0x39, 0x7e, 0x90, 0xfd, 0x87, 0x64, 0xcf, 0x39, 0x73, 0xd0, 0x5b, 0x55, 0xbb, + 0xe9, 0x52, 0xfe, 0x19, 0x67, 0x4e, 0x62, 0x57, 0xf3, 0xbf, 0xb7, 0x8b, 0xec, 0x42, 0xf5, 0x8c, + 0x31, 0x8d, 0x6c, 0x9d, 0x44, 0xf5, 0xe4, 0xe1, 0xfb, 0xa8, 0xac, 0x42, 0x42, 0x8a, 0x58, 0xbf, + 0xac, 0xa4, 0xc1, 0x99, 0x16, 0xb7, 0xff, 0x2f, 0x1f, 0x7c, 0x8d, 0xdd, 0x62, 0x1e, 0x4a, 0xc9, + 0x31, 0xdc, 0x48, 0x52, 0x66, 0x38, 0x0f, 0x1d, 0x2a, 0xbb, 0x30, 0xe3, 0xb5, 0x39, 0xd6, 0x49, + 0x14, 0x3e, 0x53, 0xf2, 0xe4, 0x27, 0xb0, 0x5d, 0x48, 0xf2, 0x64, 0xab, 0xca, 0x6b, 0x73, 0xfd, + 0x56, 0x3e, 0xd7, 0xe3, 0xfd, 0x62, 0x7f, 0x54, 0xdf, 0x20, 0xd6, 0xbf, 0x25, 0xdb, 0x9c, 0x2c, + 0xf4, 0x97, 0xfd, 0xa2, 0xd6, 0x6f, 0x0c, 0x68, 0x17, 0x2e, 0x43, 0x0e, 0x00, 0x14, 0x72, 0x72, + 0xef, 0x25, 0xd3, 0x20, 0x15, 0xfb, 0x00, 0x9d, 0xf5, 0xd4, 0x7b, 0xc9, 0x6c, 0x73, 0x14, 0x2f, + 0xc9, 0x3d, 0x68, 0x8a, 0x85, 0x92, 0xce, 0x37, 0x82, 0xcf, 0x16, 0x28, 0xda, 0x10, 0xf8, 0x9f, + 0x3c, 0x80, 0x35, 0xb5, 0xb1, 0x1b, 0x70, 0xee, 0x85, 0xba, 0x19, 0x21, 0xd9, 0xad, 0x3f, 0x41, + 0x8e, 0xbd, 0x3a, 0x4a, 0x09, 0xeb, 0x17, 0x60, 0x26, 0xc7, 0x92, 0xb7, 0xc0, 0x9c, 0xd1, 0x85, + 0xee, 0x92, 0xe5, 0xdd, 0xea, 0x76, 0x6b, 0x46, 0x17, 0xd8, 0x20, 0x93, 0x6d, 0x68, 0x4a, 0xa6, + 0x58, 0x28, 0x7f, 0xd7, 0xed, 0xc6, 0x8c, 0x2e, 0x9e, 0x2d, 0x12, 0x86, 0x4b, 0x79, 0xdc, 0x02, + 0xcf, 0xe8, 0xe2, 0x13, 0xca, 0xad, 0x8f, 0xa0, 0xa1, 0x2e, 0x79, 0xad, 0x8d, 0xa5, 0x7e, 0x25, + 0xa7, 0xff, 0x03, 0x58, 0xcd, 0xdc, 0x9b, 0x7c, 0x17, 0x6e, 0x29, 0x0b, 0x43, 0x1a, 0x09, 0xf4, + 0x48, 0x6e, 0x43, 0x82, 0xcc, 0x53, 0x1a, 0x09, 0x79, 0xa4, 0x6a, 0xea, 0x7f, 0x5f, 0x81, 0x86, + 0x6a, 0x98, 0xc9, 0xbd, 0xcc, 0x74, 0x82, 0x55, 0xb1, 0xbf, 0x7a, 0xf9, 0xea, 0x4e, 0x13, 0x0b, + 0xc8, 0xc9, 0xc7, 0xe9, 0xa8, 0x92, 0x02, 0x66, 0x25, 0xd7, 0xcf, 0xc7, 0x13, 0x4f, 0x35, 0x33, + 0xf1, 0x6c, 0x43, 0xd3, 0x9f, 0xcf, 0xd0, 0x25, 0x35, 0xe5, 0x12, 0x7f, 0x3e, 0x93, 0x2e, 0x79, + 0x0b, 0x4c, 0x11, 0x08, 0x3a, 0x45, 0x96, 0x4a, 0xd2, 0x16, 0x7e, 0x90, 0xcc, 0x7b, 0xd0, 0xce, + 0x56, 0x5b, 0x59, 0x3d, 0x15, 0xb8, 0xaf, 0xa7, 0xb5, 0x56, 0x4e, 0x00, 0x6f, 0x43, 0x3b, 0x2d, + 0x34, 0x4a, 0x4e, 0x01, 0xfe, 0x46, 0xfa, 0x19, 0x05, 0x6f, 0x43, 0x2b, 0xa9, 0xc3, 0x0a, 0xfc, + 0x9b, 0x54, 0x95, 0x5f, 0x39, 0x38, 0x87, 0x51, 0x10, 0x06, 0x9c, 0x45, 0xba, 0xc1, 0x5a, 0x96, + 0x70, 0x89, 0x9c, 0xe5, 0x81, 0x99, 0x30, 0x65, 0xd3, 0x40, 0x1d, 0x27, 0x62, 0x9c, 0xeb, 0xfe, + 0x3c, 0x26, 0xc9, 0x1e, 0x34, 0xc3, 0xf9, 0x68, 0x28, 0x6b, 0x53, 0x3e, 0x30, 0x4f, 0xe7, 0xa3, + 0x4f, 0xd9, 0x45, 0x3c, 0xa1, 0x84, 0x48, 0x61, 0x75, 0x0a, 0xbe, 0x60, 0x91, 0xf6, 0x9f, 0x22, + 0x2c, 0x01, 0x9d, 0xe2, 0x78, 0x42, 0xde, 0x07, 0x33, 0xb1, 0xaf, 0x90, 0x20, 0xc5, 0x3b, 0xa7, + 0x82, 0xb2, 0x85, 0xe1, 0x9e, 0xeb, 0x33, 0x67, 0x98, 0xfa, 0x16, 0xef, 0xd5, 0xb2, 0xdb, 0x8a, + 0xf1, 0xa3, 0xd8, 0xb9, 0xd6, 0x77, 0xa0, 0xa1, 0xee, 0x88, 0x3f, 0xea, 0x45, 0x18, 0xf7, 0x57, + 0xb8, 0x2e, 0xcd, 0xe4, 0xdf, 0x19, 0xd0, 0x8a, 0xc7, 0x9f, 0x52, 0xa5, 0xdc, 0xa5, 0x2b, 0xd7, + 0xbd, 0xf4, 0xb2, 0xd9, 0x31, 0x8e, 0xb5, 0x5a, 0x26, 0xd6, 0xf6, 0x80, 0xa8, 0x90, 0x3a, 0x0f, + 0x84, 0xe7, 0xbb, 0x43, 0xe5, 0x4d, 0x15, 0x5b, 0x1d, 0xe4, 0x3c, 0x47, 0xc6, 0xa9, 0xfc, 0x7e, + 0xf8, 0x65, 0x1d, 0xda, 0x47, 0xfd, 0xe3, 0x93, 0xa3, 0x30, 0x9c, 0x7a, 0x63, 0x8a, 0x5d, 0xd7, + 0x01, 0xd4, 0xb0, 0xaf, 0x2c, 0x79, 0x9d, 0xea, 0x95, 0x0d, 0x38, 0xe4, 0x10, 0xea, 0xd8, 0x5e, + 0x92, 0xb2, 0x47, 0xaa, 0x5e, 0xe9, 0x9c, 0x23, 0x0f, 0x51, 0x0d, 0xe8, 0xd5, 0xb7, 0xaa, 0x5e, + 0xd9, 0xb0, 0x43, 0x3e, 0x02, 0x33, 0x6d, 0x0c, 0x97, 0xbd, 0x58, 0xf5, 0x96, 0x8e, 0x3d, 0x52, + 0x3f, 0xad, 0xb5, 0xcb, 0x1e, 0x5e, 0x7a, 0x4b, 0xe7, 0x03, 0xf2, 0x08, 0x9a, 0x71, 0xb7, 0x52, + 0xfe, 0xa6, 0xd4, 0x5b, 0x32, 0x92, 0x48, 0xf7, 0xa8, 0x8e, 0xaf, 0xec, 0xe1, 0xab, 0x57, 0x3a, + 0x37, 0x91, 0x07, 0xd0, 0xd0, 0x05, 0xa3, 0xf4, 0x5d, 0xa9, 0x57, 0x3e, 0x58, 0x48, 0x23, 0xd3, + 0x6e, 0x77, 0xd9, 0xe3, 0x5c, 0x6f, 0xe9, 0x80, 0x47, 0x8e, 0x00, 0x32, 0x5d, 0xde, 0xd2, 0x57, + 0xb7, 0xde, 0xf2, 0xc1, 0x8d, 0x7c, 0x08, 0xad, 0x74, 0x18, 0x2f, 0x7f, 0x47, 0xeb, 0x2d, 0x9b, + 0xa5, 0xfa, 0xdf, 0xf8, 0xd7, 0xdf, 0x77, 0x8c, 0xdf, 0x5e, 0xee, 0x18, 0x7f, 0xbc, 0xdc, 0x31, + 0xbe, 0xba, 0xdc, 0x31, 0xfe, 0x72, 0xb9, 0x63, 0xfc, 0xed, 0x72, 0xc7, 0xf8, 0xd3, 0xd7, 0x3b, + 0xc6, 0xa8, 0x81, 0xef, 0xa9, 0xef, 0xfd, 0x27, 0x00, 0x00, 0xff, 0xff, 0xf4, 0x59, 0x8b, 0xa6, + 0xd9, 0x15, 0x00, 0x00, } diff --git a/abci/types/types.proto b/abci/types/types.proto index b4f4b2aa6..0e1c18430 100644 --- a/abci/types/types.proto +++ b/abci/types/types.proto @@ -4,12 +4,21 @@ package types; // For more information on gogo.proto, see: // https://github.com/gogo/protobuf/blob/master/extensions.md import "github.com/gogo/protobuf/gogoproto/gogo.proto"; -import "github.com/tendermint/tmlibs/common/types.proto"; +import "github.com/tendermint/tendermint/libs/common/types.proto"; // This file is copied from http://github.com/tendermint/abci // NOTE: When using custom types, mind the warnings. // https://github.com/gogo/protobuf/blob/master/custom_types.md#warnings-and-issues +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.goproto_registration) = true; +// Generate tests +option (gogoproto.populate_all) = true; +option (gogoproto.equal_all) = true; +option (gogoproto.testgen_all) = true; + //---------------------------------------- // Request types diff --git a/abci/types/typespb_test.go b/abci/types/typespb_test.go new file mode 100644 index 000000000..d1316239e --- /dev/null +++ b/abci/types/typespb_test.go @@ -0,0 +1,4281 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: abci/types/types.proto + +/* +Package types is a generated protocol buffer package. + +It is generated from these files: + abci/types/types.proto + +It has these top-level messages: + Request + RequestEcho + RequestFlush + RequestInfo + RequestSetOption + RequestInitChain + RequestQuery + RequestBeginBlock + RequestCheckTx + RequestDeliverTx + RequestEndBlock + RequestCommit + Response + ResponseException + ResponseEcho + ResponseFlush + ResponseInfo + ResponseSetOption + ResponseInitChain + ResponseQuery + ResponseBeginBlock + ResponseCheckTx + ResponseDeliverTx + ResponseEndBlock + ResponseCommit + ConsensusParams + BlockSize + TxSize + BlockGossip + Header + Validator + SigningValidator + PubKey + Evidence +*/ +package types + +import testing "testing" +import rand "math/rand" +import time "time" +import proto "github.com/gogo/protobuf/proto" +import jsonpb "github.com/gogo/protobuf/jsonpb" +import golang_proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" +import _ "github.com/tendermint/tendermint/libs/common" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = golang_proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +func TestRequestProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequest(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Request{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequest(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Request{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestEchoProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEcho(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestEcho{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestEchoMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEcho(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestEcho{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestFlushProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestFlush(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestFlush{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestFlushMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestFlush(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestFlush{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestInfoProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInfo(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestInfo{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestInfoMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInfo(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestInfo{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestSetOptionProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestSetOption(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestSetOption{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestSetOptionMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestSetOption(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestSetOption{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestInitChainProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInitChain(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestInitChain{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestInitChainMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInitChain(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestInitChain{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestQueryProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestQuery(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestQuery{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestQueryMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestQuery(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestQuery{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestBeginBlockProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBeginBlock(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestBeginBlock{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestBeginBlockMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBeginBlock(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestBeginBlock{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestCheckTxProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCheckTx(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestCheckTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestCheckTxMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCheckTx(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestCheckTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestDeliverTxProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestDeliverTx(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestDeliverTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestDeliverTxMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestDeliverTx(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestDeliverTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestEndBlockProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEndBlock(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestEndBlock{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestEndBlockMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEndBlock(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestEndBlock{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestCommitProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCommit(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestCommit{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestCommitMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCommit(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestCommit{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponse(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Response{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponse(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Response{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseExceptionProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseException(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseException{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseExceptionMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseException(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseException{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseEchoProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEcho(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseEcho{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseEchoMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEcho(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseEcho{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseFlushProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseFlush(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseFlush{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseFlushMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseFlush(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseFlush{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseInfoProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInfo(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseInfo{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseInfoMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInfo(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseInfo{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseSetOptionProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseSetOption(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseSetOption{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseSetOptionMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseSetOption(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseSetOption{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseInitChainProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInitChain(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseInitChain{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseInitChainMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInitChain(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseInitChain{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseQueryProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseQuery(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseQuery{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseQueryMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseQuery(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseQuery{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseBeginBlockProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBeginBlock(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseBeginBlock{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseBeginBlockMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBeginBlock(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseBeginBlock{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseCheckTxProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCheckTx(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseCheckTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseCheckTxMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCheckTx(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseCheckTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseDeliverTxProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseDeliverTx(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseDeliverTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseDeliverTxMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseDeliverTx(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseDeliverTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseEndBlockProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEndBlock(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseEndBlock{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseEndBlockMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEndBlock(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseEndBlock{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseCommitProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCommit(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseCommit{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseCommitMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCommit(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseCommit{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestConsensusParamsProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedConsensusParams(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ConsensusParams{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestConsensusParamsMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedConsensusParams(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ConsensusParams{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestBlockSizeProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockSize(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &BlockSize{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestBlockSizeMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockSize(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &BlockSize{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestTxSizeProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedTxSize(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &TxSize{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestTxSizeMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedTxSize(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &TxSize{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestBlockGossipProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockGossip(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &BlockGossip{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestBlockGossipMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockGossip(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &BlockGossip{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestHeaderProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedHeader(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Header{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestHeaderMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedHeader(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Header{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestValidatorProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedValidator(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Validator{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestValidatorMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedValidator(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Validator{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestSigningValidatorProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedSigningValidator(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &SigningValidator{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestSigningValidatorMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedSigningValidator(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &SigningValidator{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestPubKeyProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedPubKey(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &PubKey{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestPubKeyMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedPubKey(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &PubKey{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestEvidenceProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedEvidence(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Evidence{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestEvidenceMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedEvidence(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Evidence{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequest(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Request{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestEchoJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEcho(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestEcho{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestFlushJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestFlush(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestFlush{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestInfoJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInfo(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestInfo{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestSetOptionJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestSetOption(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestSetOption{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestInitChainJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInitChain(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestInitChain{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestQueryJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestQuery(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestQuery{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestBeginBlockJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBeginBlock(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestBeginBlock{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestCheckTxJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCheckTx(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestCheckTx{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestDeliverTxJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestDeliverTx(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestDeliverTx{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestEndBlockJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEndBlock(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestEndBlock{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestCommitJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCommit(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestCommit{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponse(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Response{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseExceptionJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseException(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseException{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseEchoJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEcho(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseEcho{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseFlushJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseFlush(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseFlush{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseInfoJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInfo(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseInfo{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseSetOptionJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseSetOption(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseSetOption{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseInitChainJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInitChain(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseInitChain{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseQueryJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseQuery(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseQuery{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseBeginBlockJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBeginBlock(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseBeginBlock{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseCheckTxJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCheckTx(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseCheckTx{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseDeliverTxJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseDeliverTx(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseDeliverTx{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseEndBlockJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEndBlock(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseEndBlock{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseCommitJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCommit(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseCommit{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestConsensusParamsJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedConsensusParams(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ConsensusParams{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestBlockSizeJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockSize(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &BlockSize{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestTxSizeJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedTxSize(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &TxSize{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestBlockGossipJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockGossip(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &BlockGossip{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestHeaderJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedHeader(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Header{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestValidatorJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedValidator(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Validator{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestSigningValidatorJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedSigningValidator(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &SigningValidator{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestPubKeyJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedPubKey(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &PubKey{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestEvidenceJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedEvidence(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &Evidence{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequest(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &Request{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequest(popr, true) + dAtA := proto.CompactTextString(p) + msg := &Request{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestEchoProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEcho(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestEcho{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestEchoProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEcho(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestEcho{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestFlushProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestFlush(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestFlush{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestFlushProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestFlush(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestFlush{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestInfoProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInfo(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestInfo{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestInfoProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInfo(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestInfo{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestSetOptionProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestSetOption(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestSetOption{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestSetOptionProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestSetOption(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestSetOption{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestInitChainProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInitChain(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestInitChain{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestInitChainProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInitChain(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestInitChain{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestQueryProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestQuery(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestQuery{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestQueryProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestQuery(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestQuery{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestBeginBlockProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBeginBlock(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestBeginBlock{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestBeginBlockProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBeginBlock(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestBeginBlock{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestCheckTxProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCheckTx(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestCheckTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestCheckTxProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCheckTx(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestCheckTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestDeliverTxProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestDeliverTx(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestDeliverTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestDeliverTxProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestDeliverTx(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestDeliverTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestEndBlockProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEndBlock(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestEndBlock{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestEndBlockProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEndBlock(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestEndBlock{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestCommitProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCommit(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestCommit{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestCommitProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCommit(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestCommit{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponse(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &Response{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponse(popr, true) + dAtA := proto.CompactTextString(p) + msg := &Response{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseExceptionProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseException(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseException{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseExceptionProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseException(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseException{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseEchoProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEcho(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseEcho{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseEchoProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEcho(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseEcho{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseFlushProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseFlush(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseFlush{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseFlushProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseFlush(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseFlush{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseInfoProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInfo(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseInfo{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseInfoProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInfo(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseInfo{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseSetOptionProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseSetOption(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseSetOption{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseSetOptionProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseSetOption(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseSetOption{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseInitChainProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInitChain(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseInitChain{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseInitChainProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInitChain(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseInitChain{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseQueryProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseQuery(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseQuery{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseQueryProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseQuery(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseQuery{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseBeginBlockProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBeginBlock(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseBeginBlock{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseBeginBlockProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBeginBlock(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseBeginBlock{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseCheckTxProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCheckTx(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseCheckTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseCheckTxProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCheckTx(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseCheckTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseDeliverTxProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseDeliverTx(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseDeliverTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseDeliverTxProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseDeliverTx(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseDeliverTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseEndBlockProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEndBlock(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseEndBlock{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseEndBlockProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEndBlock(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseEndBlock{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseCommitProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCommit(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseCommit{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseCommitProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCommit(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseCommit{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestConsensusParamsProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedConsensusParams(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ConsensusParams{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestConsensusParamsProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedConsensusParams(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ConsensusParams{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestBlockSizeProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockSize(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &BlockSize{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestBlockSizeProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockSize(popr, true) + dAtA := proto.CompactTextString(p) + msg := &BlockSize{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestTxSizeProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedTxSize(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &TxSize{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestTxSizeProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedTxSize(popr, true) + dAtA := proto.CompactTextString(p) + msg := &TxSize{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestBlockGossipProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockGossip(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &BlockGossip{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestBlockGossipProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockGossip(popr, true) + dAtA := proto.CompactTextString(p) + msg := &BlockGossip{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestHeaderProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedHeader(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &Header{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestHeaderProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedHeader(popr, true) + dAtA := proto.CompactTextString(p) + msg := &Header{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestValidatorProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedValidator(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &Validator{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestValidatorProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedValidator(popr, true) + dAtA := proto.CompactTextString(p) + msg := &Validator{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestSigningValidatorProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedSigningValidator(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &SigningValidator{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestSigningValidatorProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedSigningValidator(popr, true) + dAtA := proto.CompactTextString(p) + msg := &SigningValidator{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestPubKeyProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedPubKey(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &PubKey{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestPubKeyProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedPubKey(popr, true) + dAtA := proto.CompactTextString(p) + msg := &PubKey{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestEvidenceProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedEvidence(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &Evidence{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestEvidenceProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedEvidence(popr, true) + dAtA := proto.CompactTextString(p) + msg := &Evidence{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequest(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestEchoSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEcho(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestFlushSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestFlush(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestInfoSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInfo(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestSetOptionSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestSetOption(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestInitChainSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestInitChain(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestQuerySize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestQuery(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestBeginBlockSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBeginBlock(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestCheckTxSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCheckTx(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestDeliverTxSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestDeliverTx(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestEndBlockSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestEndBlock(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestCommitSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestCommit(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponse(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseExceptionSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseException(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseEchoSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEcho(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseFlushSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseFlush(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseInfoSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInfo(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseSetOptionSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseSetOption(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseInitChainSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseInitChain(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseQuerySize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseQuery(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseBeginBlockSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBeginBlock(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseCheckTxSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCheckTx(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseDeliverTxSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseDeliverTx(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseEndBlockSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseEndBlock(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseCommitSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseCommit(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestConsensusParamsSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedConsensusParams(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestBlockSizeSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockSize(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestTxSizeSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedTxSize(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestBlockGossipSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedBlockGossip(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestHeaderSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedHeader(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestValidatorSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedValidator(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestSigningValidatorSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedSigningValidator(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestPubKeySize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedPubKey(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestEvidenceSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedEvidence(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +//These tests are generated by github.com/gogo/protobuf/plugin/testgen diff --git a/benchmarks/codec_test.go b/benchmarks/codec_test.go index 53cbf632c..09487563a 100644 --- a/benchmarks/codec_test.go +++ b/benchmarks/codec_test.go @@ -7,7 +7,7 @@ import ( "github.com/tendermint/go-amino" proto "github.com/tendermint/tendermint/benchmarks/proto" - "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/p2p" ctypes "github.com/tendermint/tendermint/rpc/core/types" ) @@ -16,7 +16,7 @@ func BenchmarkEncodeStatusWire(b *testing.B) { b.StopTimer() cdc := amino.NewCodec() ctypes.RegisterAmino(cdc) - nodeKey := p2p.NodeKey{PrivKey: crypto.GenPrivKeyEd25519()} + nodeKey := p2p.NodeKey{PrivKey: ed25519.GenPrivKey()} status := &ctypes.ResultStatus{ NodeInfo: p2p.NodeInfo{ ID: nodeKey.ID(), @@ -52,7 +52,7 @@ func BenchmarkEncodeNodeInfoWire(b *testing.B) { b.StopTimer() cdc := amino.NewCodec() ctypes.RegisterAmino(cdc) - nodeKey := p2p.NodeKey{PrivKey: crypto.GenPrivKeyEd25519()} + nodeKey := p2p.NodeKey{PrivKey: ed25519.GenPrivKey()} nodeInfo := p2p.NodeInfo{ ID: nodeKey.ID(), Moniker: "SOMENAME", @@ -77,7 +77,7 @@ func BenchmarkEncodeNodeInfoBinary(b *testing.B) { b.StopTimer() cdc := amino.NewCodec() ctypes.RegisterAmino(cdc) - nodeKey := p2p.NodeKey{PrivKey: crypto.GenPrivKeyEd25519()} + nodeKey := p2p.NodeKey{PrivKey: ed25519.GenPrivKey()} nodeInfo := p2p.NodeInfo{ ID: nodeKey.ID(), Moniker: "SOMENAME", @@ -98,7 +98,7 @@ func BenchmarkEncodeNodeInfoBinary(b *testing.B) { func BenchmarkEncodeNodeInfoProto(b *testing.B) { b.StopTimer() - nodeKey := p2p.NodeKey{PrivKey: crypto.GenPrivKeyEd25519()} + nodeKey := p2p.NodeKey{PrivKey: ed25519.GenPrivKey()} nodeID := string(nodeKey.ID()) someName := "SOMENAME" someAddr := "SOMEADDR" diff --git a/blockchain/pool.go b/blockchain/pool.go index e379d846a..a881c7cb7 100644 --- a/blockchain/pool.go +++ b/blockchain/pool.go @@ -29,10 +29,10 @@ eg, L = latency = 0.1s */ const ( - requestIntervalMS = 100 - maxTotalRequesters = 1000 + requestIntervalMS = 2 + maxTotalRequesters = 600 maxPendingRequests = maxTotalRequesters - maxPendingRequestsPerPeer = 50 + maxPendingRequestsPerPeer = 20 // Minimum recv rate to ensure we're receiving blocks from a peer fast // enough. If a peer is not sending us data at at least that rate, we @@ -219,14 +219,12 @@ func (pool *BlockPool) RedoRequest(height int64) p2p.ID { defer pool.mtx.Unlock() request := pool.requesters[height] - - if request.block == nil { - panic("Expected block to be non-nil") + peerID := request.getPeerID() + if peerID != p2p.ID("") { + // RemovePeer will redo all requesters associated with this peer. + pool.removePeer(peerID) } - - // RemovePeer will redo all requesters associated with this peer. - pool.removePeer(request.peerID) - return request.peerID + return peerID } // TODO: ensure that blocks come in order for each peer. diff --git a/blockchain/pool_test.go b/blockchain/pool_test.go index c2f615f94..01187bcfe 100644 --- a/blockchain/pool_test.go +++ b/blockchain/pool_test.go @@ -1,7 +1,6 @@ package blockchain import ( - "math/rand" "testing" "time" @@ -25,7 +24,7 @@ func makePeers(numPeers int, minHeight, maxHeight int64) map[p2p.ID]testPeer { peers := make(map[p2p.ID]testPeer, numPeers) for i := 0; i < numPeers; i++ { peerID := p2p.ID(cmn.RandStr(12)) - height := minHeight + rand.Int63n(maxHeight-minHeight) + height := minHeight + cmn.RandInt63n(maxHeight-minHeight) peers[peerID] = testPeer{peerID, height} } return peers @@ -80,7 +79,7 @@ func TestBasic(t *testing.T) { } // Request desired, pretend like we got the block immediately. go func() { - block := &types.Block{Header: &types.Header{Height: request.Height}} + block := &types.Block{Header: types.Header{Height: request.Height}} pool.AddBlock(request.PeerID, block, 123) t.Logf("Added block from peer %v (height: %v)", request.PeerID, request.Height) }() diff --git a/blockchain/reactor.go b/blockchain/reactor.go index 70a599bab..eadeedc91 100644 --- a/blockchain/reactor.go +++ b/blockchain/reactor.go @@ -5,19 +5,21 @@ import ( "reflect" "time" - "github.com/tendermint/go-amino" + amino "github.com/tendermint/go-amino" + + cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/p2p" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" - cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/libs/log" ) const ( // BlockchainChannel is a channel for blocks and status updates (`BlockStore` height) BlockchainChannel = byte(0x40) - trySyncIntervalMS = 50 + trySyncIntervalMS = 10 + // stop syncing when last block's time is // within this much of the system time. // stopSyncingDurationMinutes = 10 @@ -75,8 +77,9 @@ func NewBlockchainReactor(state sm.State, blockExec *sm.BlockExecutor, store *Bl store.Height())) } - const capacity = 1000 // must be bigger than peers count - requestsCh := make(chan BlockRequest, capacity) + requestsCh := make(chan BlockRequest, maxTotalRequesters) + + const capacity = 1000 // must be bigger than peers count errorsCh := make(chan peerError, capacity) // so we don't block in #Receive#pool.AddBlock pool := NewBlockPool( @@ -174,7 +177,7 @@ func (bcR *BlockchainReactor) respondToPeer(msg *bcBlockRequestMessage, // Receive implements Reactor by handling 4 types of messages (look below). func (bcR *BlockchainReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) { - msg, err := DecodeMessage(msgBytes) + msg, err := decodeMsg(msgBytes) if err != nil { bcR.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes) bcR.Switch.StopPeerForError(src, err) @@ -208,7 +211,6 @@ func (bcR *BlockchainReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) // Handle messages from the poolReactor telling the reactor what to do. // NOTE: Don't sleep in the FOR_LOOP or otherwise slow it down! -// (Except for the SYNC_LOOP, which is the primary purpose and must be synchronous.) func (bcR *BlockchainReactor) poolRoutine() { trySyncTicker := time.NewTicker(trySyncIntervalMS * time.Millisecond) @@ -223,6 +225,8 @@ func (bcR *BlockchainReactor) poolRoutine() { lastHundred := time.Now() lastRate := 0.0 + didProcessCh := make(chan struct{}, 1) + FOR_LOOP: for { select { @@ -238,14 +242,17 @@ FOR_LOOP: // The pool handles timeouts, just let it go. continue FOR_LOOP } + case err := <-bcR.errorsCh: peer := bcR.Switch.Peers().Get(err.peerID) if peer != nil { bcR.Switch.StopPeerForError(peer, err) } + case <-statusUpdateTicker.C: // ask for status updates go bcR.BroadcastStatusRequest() // nolint: errcheck + case <-switchToConsensusTicker.C: height, numPending, lenRequesters := bcR.pool.GetStatus() outbound, inbound, _ := bcR.Switch.NumPeers() @@ -260,60 +267,78 @@ FOR_LOOP: break FOR_LOOP } + case <-trySyncTicker.C: // chan time - // This loop can be slow as long as it's doing syncing work. - SYNC_LOOP: - for i := 0; i < 10; i++ { - // See if there are any blocks to sync. - first, second := bcR.pool.PeekTwoBlocks() - //bcR.Logger.Info("TrySync peeked", "first", first, "second", second) - if first == nil || second == nil { - // We need both to sync the first block. - break SYNC_LOOP + select { + case didProcessCh <- struct{}{}: + default: + } + + case <-didProcessCh: + // NOTE: It is a subtle mistake to process more than a single block + // at a time (e.g. 10) here, because we only TrySend 1 request per + // loop. The ratio mismatch can result in starving of blocks, a + // sudden burst of requests and responses, and repeat. + // Consequently, it is better to split these routines rather than + // coupling them as it's written here. TODO uncouple from request + // routine. + + // See if there are any blocks to sync. + first, second := bcR.pool.PeekTwoBlocks() + //bcR.Logger.Info("TrySync peeked", "first", first, "second", second) + if first == nil || second == nil { + // We need both to sync the first block. + continue FOR_LOOP + } else { + // Try again quickly next loop. + didProcessCh <- struct{}{} + } + + firstParts := first.MakePartSet(state.ConsensusParams.BlockPartSizeBytes) + firstPartsHeader := firstParts.Header() + firstID := types.BlockID{first.Hash(), firstPartsHeader} + // Finally, verify the first block using the second's commit + // NOTE: we can probably make this more efficient, but note that calling + // first.Hash() doesn't verify the tx contents, so MakePartSet() is + // currently necessary. + err := state.Validators.VerifyCommit( + chainID, firstID, first.Height, second.LastCommit) + if err != nil { + bcR.Logger.Error("Error in validation", "err", err) + peerID := bcR.pool.RedoRequest(first.Height) + peer := bcR.Switch.Peers().Get(peerID) + if peer != nil { + // NOTE: we've already removed the peer's request, but we + // still need to clean up the rest. + bcR.Switch.StopPeerForError(peer, fmt.Errorf("BlockchainReactor validation error: %v", err)) } - firstParts := first.MakePartSet(state.ConsensusParams.BlockPartSizeBytes) - firstPartsHeader := firstParts.Header() - firstID := types.BlockID{first.Hash(), firstPartsHeader} - // Finally, verify the first block using the second's commit - // NOTE: we can probably make this more efficient, but note that calling - // first.Hash() doesn't verify the tx contents, so MakePartSet() is - // currently necessary. - err := state.Validators.VerifyCommit( - chainID, firstID, first.Height, second.LastCommit) + continue FOR_LOOP + } else { + bcR.pool.PopRequest() + + // TODO: batch saves so we dont persist to disk every block + bcR.store.SaveBlock(first, firstParts, second.LastCommit) + + // TODO: same thing for app - but we would need a way to + // get the hash without persisting the state + var err error + state, err = bcR.blockExec.ApplyBlock(state, firstID, first) if err != nil { - bcR.Logger.Error("Error in validation", "err", err) - peerID := bcR.pool.RedoRequest(first.Height) - peer := bcR.Switch.Peers().Get(peerID) - if peer != nil { - bcR.Switch.StopPeerForError(peer, fmt.Errorf("BlockchainReactor validation error: %v", err)) - } - break SYNC_LOOP - } else { - bcR.pool.PopRequest() - - // TODO: batch saves so we dont persist to disk every block - bcR.store.SaveBlock(first, firstParts, second.LastCommit) - - // TODO: same thing for app - but we would need a way to - // get the hash without persisting the state - var err error - state, err = bcR.blockExec.ApplyBlock(state, firstID, first) - if err != nil { - // TODO This is bad, are we zombie? - cmn.PanicQ(cmn.Fmt("Failed to process committed block (%d:%X): %v", - first.Height, first.Hash(), err)) - } - blocksSynced++ - - if blocksSynced%100 == 0 { - lastRate = 0.9*lastRate + 0.1*(100/time.Since(lastHundred).Seconds()) - bcR.Logger.Info("Fast Sync Rate", "height", bcR.pool.height, - "max_peer_height", bcR.pool.MaxPeerHeight(), "blocks/s", lastRate) - lastHundred = time.Now() - } + // TODO This is bad, are we zombie? + cmn.PanicQ(cmn.Fmt("Failed to process committed block (%d:%X): %v", + first.Height, first.Hash(), err)) + } + blocksSynced++ + + if blocksSynced%100 == 0 { + lastRate = 0.9*lastRate + 0.1*(100/time.Since(lastHundred).Seconds()) + bcR.Logger.Info("Fast Sync Rate", "height", bcR.pool.height, + "max_peer_height", bcR.pool.MaxPeerHeight(), "blocks/s", lastRate) + lastHundred = time.Now() } } continue FOR_LOOP + case <-bcR.Quit(): break FOR_LOOP } @@ -342,17 +367,11 @@ func RegisterBlockchainMessages(cdc *amino.Codec) { cdc.RegisterConcrete(&bcStatusRequestMessage{}, "tendermint/mempool/StatusRequest", nil) } -// DecodeMessage decodes BlockchainMessage. -// TODO: ensure that bz is completely read. -func DecodeMessage(bz []byte) (msg BlockchainMessage, err error) { +func decodeMsg(bz []byte) (msg BlockchainMessage, err error) { if len(bz) > maxMsgSize { - return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", - len(bz), maxMsgSize) + return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", len(bz), maxMsgSize) } err = cdc.UnmarshalBinaryBare(bz, &msg) - if err != nil { - err = cmn.ErrorWrap(err, "DecodeMessage() had bytes left over") - } return } diff --git a/blockchain/reactor_test.go b/blockchain/reactor_test.go index 2bb6e9762..21eaae4ba 100644 --- a/blockchain/reactor_test.go +++ b/blockchain/reactor_test.go @@ -206,3 +206,4 @@ func (tp *bcrTestPeer) IsPersistent() bool { return true } func (tp *bcrTestPeer) Get(s string) interface{} { return s } func (tp *bcrTestPeer) Set(string, interface{}) {} func (tp *bcrTestPeer) RemoteIP() net.IP { return []byte{127, 0, 0, 1} } +func (tp *bcrTestPeer) OriginalAddr() *p2p.NetAddress { return nil } diff --git a/blockchain/store_test.go b/blockchain/store_test.go index 637557980..21ee529fd 100644 --- a/blockchain/store_test.go +++ b/blockchain/store_test.go @@ -126,7 +126,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { eraseSeenCommitInDB bool }{ { - block: newBlock(&header1, commitAtH10), + block: newBlock(header1, commitAtH10), parts: validPartSet, seenCommit: seenCommit1, }, @@ -137,19 +137,19 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { }, { - block: newBlock(&header2, commitAtH10), + block: newBlock(header2, commitAtH10), parts: uncontiguousPartSet, wantPanic: "only save contiguous blocks", // and incomplete and uncontiguous parts }, { - block: newBlock(&header1, commitAtH10), + block: newBlock(header1, commitAtH10), parts: incompletePartSet, wantPanic: "only save complete block", // incomplete parts }, { - block: newBlock(&header1, commitAtH10), + block: newBlock(header1, commitAtH10), parts: validPartSet, seenCommit: seenCommit1, corruptCommitInDB: true, // Corrupt the DB's commit entry @@ -157,7 +157,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { }, { - block: newBlock(&header1, commitAtH10), + block: newBlock(header1, commitAtH10), parts: validPartSet, seenCommit: seenCommit1, wantPanic: "unmarshal to types.BlockMeta failed", @@ -165,7 +165,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { }, { - block: newBlock(&header1, commitAtH10), + block: newBlock(header1, commitAtH10), parts: validPartSet, seenCommit: seenCommit1, @@ -174,7 +174,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { }, { - block: newBlock(&header1, commitAtH10), + block: newBlock(header1, commitAtH10), parts: validPartSet, seenCommit: seenCommit1, @@ -183,7 +183,7 @@ func TestBlockStoreSaveLoadBlock(t *testing.T) { }, { - block: newBlock(&header1, commitAtH10), + block: newBlock(header1, commitAtH10), parts: validPartSet, seenCommit: seenCommit1, @@ -375,7 +375,7 @@ func doFn(fn func() (interface{}, error)) (res interface{}, err error, panicErr return res, err, panicErr } -func newBlock(hdr *types.Header, lastCommit *types.Commit) *types.Block { +func newBlock(hdr types.Header, lastCommit *types.Commit) *types.Block { return &types.Block{ Header: hdr, LastCommit: lastCommit, diff --git a/blockchain/wire.go b/blockchain/wire.go index 70b50565d..ff02d58c1 100644 --- a/blockchain/wire.go +++ b/blockchain/wire.go @@ -2,12 +2,12 @@ package blockchain import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) var cdc = amino.NewCodec() func init() { RegisterBlockchainMessages(cdc) - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) } diff --git a/cmd/priv_val_server/main.go b/cmd/priv_val_server/main.go index 20c23f4c4..03aa57f4e 100644 --- a/cmd/priv_val_server/main.go +++ b/cmd/priv_val_server/main.go @@ -4,7 +4,7 @@ import ( "flag" "os" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" @@ -37,7 +37,7 @@ func main() { *chainID, *addr, pv, - crypto.GenPrivKeyEd25519(), + ed25519.GenPrivKey(), ) err := rs.Start() if err != nil { diff --git a/cmd/tendermint/commands/wire.go b/cmd/tendermint/commands/wire.go index a09019133..0f0b536df 100644 --- a/cmd/tendermint/commands/wire.go +++ b/cmd/tendermint/commands/wire.go @@ -2,11 +2,11 @@ package commands import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) var cdc = amino.NewCodec() func init() { - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) } diff --git a/codecov.yml b/codecov.yml index b190853de..4b3d527fa 100644 --- a/codecov.yml +++ b/codecov.yml @@ -21,3 +21,4 @@ ignore: - "docs" - "DOCKER" - "scripts" + - "**/*.pb.go" diff --git a/config/config.go b/config/config.go index 22cecf989..fb8e79086 100644 --- a/config/config.go +++ b/config/config.go @@ -284,7 +284,6 @@ type P2PConfig struct { Seeds string `mapstructure:"seeds"` // Comma separated list of nodes to keep persistent connections to - // Do not add private peers to this list if you don't want them advertised PersistentPeers string `mapstructure:"persistent_peers"` // UPNP port forwarding @@ -349,9 +348,9 @@ func DefaultP2PConfig() *P2PConfig { AddrBookStrict: true, MaxNumPeers: 50, FlushThrottleTimeout: 100, - MaxPacketMsgPayloadSize: 1024, // 1 kB - SendRate: 512000, // 500 kB/s - RecvRate: 512000, // 500 kB/s + MaxPacketMsgPayloadSize: 1024, // 1 kB + SendRate: 5120000, // 5 mB/s + RecvRate: 5120000, // 5 mB/s PexReactor: true, SeedMode: false, AllowDuplicateIP: true, // so non-breaking yet @@ -606,6 +605,12 @@ type InstrumentationConfig struct { // Address to listen for Prometheus collector(s) connections. PrometheusListenAddr string `mapstructure:"prometheus_listen_addr"` + + // Maximum number of simultaneous connections. + // If you want to accept more significant number than the default, make sure + // you increase your OS limits. + // 0 - unlimited. + MaxOpenConnections int `mapstructure:"max_open_connections"` } // DefaultInstrumentationConfig returns a default configuration for metrics @@ -614,6 +619,7 @@ func DefaultInstrumentationConfig() *InstrumentationConfig { return &InstrumentationConfig{ Prometheus: false, PrometheusListenAddr: ":26660", + MaxOpenConnections: 3, } } diff --git a/config/toml.go b/config/toml.go index 084325baa..60ce15de8 100644 --- a/config/toml.go +++ b/config/toml.go @@ -152,7 +152,6 @@ external_address = "{{ .P2P.ExternalAddress }}" seeds = "{{ .P2P.Seeds }}" # Comma separated list of nodes to keep persistent connections to -# Do not add private peers to this list if you don't want them advertised persistent_peers = "{{ .P2P.PersistentPeers }}" # UPNP port forwarding @@ -262,6 +261,12 @@ prometheus = {{ .Instrumentation.Prometheus }} # Address to listen for Prometheus collector(s) connections prometheus_listen_addr = "{{ .Instrumentation.PrometheusListenAddr }}" + +# Maximum number of simultaneous connections. +# If you want to accept more significant number than the default, make sure +# you increase your OS limits. +# 0 - unlimited. +max_open_connections = {{ .Instrumentation.MaxOpenConnections }} ` /****** these are for test settings ***********/ diff --git a/consensus/reactor.go b/consensus/reactor.go index 54407ae1e..3eb1d73aa 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -9,11 +9,11 @@ import ( "github.com/pkg/errors" amino "github.com/tendermint/go-amino" - cmn "github.com/tendermint/tendermint/libs/common" - "github.com/tendermint/tendermint/libs/log" cstypes "github.com/tendermint/tendermint/consensus/types" + cmn "github.com/tendermint/tendermint/libs/common" tmevents "github.com/tendermint/tendermint/libs/events" + "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/p2p" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" @@ -80,6 +80,9 @@ func (conR *ConsensusReactor) OnStop() { conR.BaseReactor.OnStop() conR.unsubscribeFromBroadcastEvents() conR.conS.Stop() + if !conR.FastSync() { + conR.conS.Wait() + } } // SwitchToConsensus switches from fast_sync mode to consensus mode. @@ -183,7 +186,7 @@ func (conR *ConsensusReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) return } - msg, err := DecodeMessage(msgBytes) + msg, err := decodeMsg(msgBytes) if err != nil { conR.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes) conR.Switch.StopPeerForError(src, err) @@ -1306,11 +1309,9 @@ func RegisterConsensusMessages(cdc *amino.Codec) { cdc.RegisterConcrete(&ProposalHeartbeatMessage{}, "tendermint/ProposalHeartbeat", nil) } -// DecodeMessage decodes the given bytes into a ConsensusMessage. -func DecodeMessage(bz []byte) (msg ConsensusMessage, err error) { +func decodeMsg(bz []byte) (msg ConsensusMessage, err error) { if len(bz) > maxMsgSize { - return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", - len(bz), maxMsgSize) + return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", len(bz), maxMsgSize) } err = cdc.UnmarshalBinaryBare(bz, &msg) return diff --git a/consensus/replay.go b/consensus/replay.go index 972a7b178..33e14424e 100644 --- a/consensus/replay.go +++ b/consensus/replay.go @@ -273,7 +273,7 @@ func (h *Handshaker) ReplayBlocks(state sm.State, appHash []byte, appBlockHeight ChainId: h.genDoc.ChainID, ConsensusParams: csParams, Validators: nextVals, - AppStateBytes: h.genDoc.AppStateJSON, + AppStateBytes: h.genDoc.AppState, } res, err := proxyApp.Consensus().InitChainSync(req) if err != nil { diff --git a/consensus/state.go b/consensus/state.go index 842e0ca25..2c45d9973 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -80,7 +80,7 @@ type ConsensusState struct { evpool sm.EvidencePool // internal state - mtx sync.Mutex + mtx sync.RWMutex cstypes.RoundState state sm.State // State until height-1. @@ -191,8 +191,8 @@ func (cs *ConsensusState) String() string { // GetState returns a copy of the chain state. func (cs *ConsensusState) GetState() sm.State { - cs.mtx.Lock() - defer cs.mtx.Unlock() + cs.mtx.RLock() + defer cs.mtx.RUnlock() return cs.state.Copy() } @@ -207,8 +207,8 @@ func (cs *ConsensusState) GetLastHeight() int64 { // GetRoundState returns a shallow copy of the internal consensus state. func (cs *ConsensusState) GetRoundState() *cstypes.RoundState { - cs.mtx.Lock() - defer cs.mtx.Unlock() + cs.mtx.RLock() + defer cs.mtx.RUnlock() rs := cs.RoundState // copy return &rs @@ -216,24 +216,24 @@ func (cs *ConsensusState) GetRoundState() *cstypes.RoundState { // GetRoundStateJSON returns a json of RoundState, marshalled using go-amino. func (cs *ConsensusState) GetRoundStateJSON() ([]byte, error) { - cs.mtx.Lock() - defer cs.mtx.Unlock() + cs.mtx.RLock() + defer cs.mtx.RUnlock() return cdc.MarshalJSON(cs.RoundState) } // GetRoundStateSimpleJSON returns a json of RoundStateSimple, marshalled using go-amino. func (cs *ConsensusState) GetRoundStateSimpleJSON() ([]byte, error) { - cs.mtx.Lock() - defer cs.mtx.Unlock() + cs.mtx.RLock() + defer cs.mtx.RUnlock() return cdc.MarshalJSON(cs.RoundState.RoundStateSimple()) } // GetValidators returns a copy of the current validators. func (cs *ConsensusState) GetValidators() (int64, []*types.Validator) { - cs.mtx.Lock() - defer cs.mtx.Unlock() + cs.mtx.RLock() + defer cs.mtx.RUnlock() return cs.state.LastBlockHeight, cs.state.Validators.Copy().Validators } @@ -253,8 +253,8 @@ func (cs *ConsensusState) SetTimeoutTicker(timeoutTicker TimeoutTicker) { // LoadCommit loads the commit for a given height. func (cs *ConsensusState) LoadCommit(height int64) *types.Commit { - cs.mtx.Lock() - defer cs.mtx.Unlock() + cs.mtx.RLock() + defer cs.mtx.RUnlock() if height == cs.blockStore.Height() { return cs.blockStore.LoadSeenCommit(height) } @@ -322,13 +322,8 @@ func (cs *ConsensusState) startRoutines(maxSteps int) { // OnStop implements cmn.Service. It stops all routines and waits for the WAL to finish. func (cs *ConsensusState) OnStop() { - cs.BaseService.OnStop() - cs.evsw.Stop() - cs.timeoutTicker.Stop() - - cs.wal.Stop() } // Wait waits for the the main routine to return. @@ -584,8 +579,8 @@ func (cs *ConsensusState) receiveRoutine(maxSteps int) { var mi msgInfo select { - case height := <-cs.mempool.TxsAvailable(): - cs.handleTxsAvailable(height) + case <-cs.mempool.TxsAvailable(): + cs.handleTxsAvailable() case mi = <-cs.peerMsgQueue: cs.wal.Write(mi) // handles proposals, block parts, votes @@ -608,6 +603,7 @@ func (cs *ConsensusState) receiveRoutine(maxSteps int) { // close wal now that we're done writing to it cs.wal.Stop() + cs.wal.Wait() close(cs.done) return @@ -695,11 +691,11 @@ func (cs *ConsensusState) handleTimeout(ti timeoutInfo, rs cstypes.RoundState) { } -func (cs *ConsensusState) handleTxsAvailable(height int64) { +func (cs *ConsensusState) handleTxsAvailable() { cs.mtx.Lock() defer cs.mtx.Unlock() // we only need to do this for round 0 - cs.enterPropose(height, 0) + cs.enterPropose(cs.Height, 0) } //----------------------------------------------------------------------------- diff --git a/consensus/types/round_state_test.go b/consensus/types/round_state_test.go index 080178f24..bcaa63085 100644 --- a/consensus/types/round_state_test.go +++ b/consensus/types/round_state_test.go @@ -4,10 +4,10 @@ import ( "testing" "time" - "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/types" + amino "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/types" ) func BenchmarkRoundStateDeepCopy(b *testing.B) { @@ -23,7 +23,7 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) { Hash: cmn.RandBytes(20), }, } - sig := crypto.SignatureEd25519{} + sig := ed25519.SignatureEd25519{} for i := 0; i < nval; i++ { precommits[i] = &types.Vote{ ValidatorAddress: types.Address(cmn.RandBytes(20)), @@ -38,7 +38,7 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) { } // Random block block := &types.Block{ - Header: &types.Header{ + Header: types.Header{ ChainID: cmn.RandStr(12), Time: time.Now(), LastBlockID: blockID, @@ -50,7 +50,7 @@ func BenchmarkRoundStateDeepCopy(b *testing.B) { LastResultsHash: cmn.RandBytes(20), EvidenceHash: cmn.RandBytes(20), }, - Data: &types.Data{ + Data: types.Data{ Txs: txs, }, Evidence: types.EvidenceData{}, diff --git a/consensus/types/wire.go b/consensus/types/wire.go index 6342d7eba..9221de968 100644 --- a/consensus/types/wire.go +++ b/consensus/types/wire.go @@ -2,11 +2,11 @@ package types import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) var cdc = amino.NewCodec() func init() { - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) } diff --git a/consensus/wire.go b/consensus/wire.go index 5f231c0c7..cc172bead 100644 --- a/consensus/wire.go +++ b/consensus/wire.go @@ -2,7 +2,7 @@ package consensus import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) var cdc = amino.NewCodec() @@ -10,5 +10,5 @@ var cdc = amino.NewCodec() func init() { RegisterConsensusMessages(cdc) RegisterWALMessages(cdc) - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) } diff --git a/crypto/Gopkg.lock b/crypto/Gopkg.lock deleted file mode 100644 index 7dbe6ae72..000000000 --- a/crypto/Gopkg.lock +++ /dev/null @@ -1,137 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - name = "github.com/btcsuite/btcd" - packages = ["btcec"] - revision = "86fed781132ac890ee03e906e4ecd5d6fa180c64" - -[[projects]] - branch = "master" - name = "github.com/btcsuite/btcutil" - packages = ["base58"] - revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" - -[[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", - "proto", - "protoc-gen-gogo/descriptor" - ] - revision = "1adfc126b41513cc696b209667c8656ea7aac67c" - version = "v1.0.0" - -[[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/stretchr/testify" - packages = [ - "assert", - "require" - ] - revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" - version = "v1.2.2" - -[[projects]] - branch = "master" - name = "github.com/tendermint/ed25519" - packages = [ - ".", - "edwards25519", - "extra25519" - ] - revision = "d8387025d2b9d158cf4efb07e7ebf814bcce2057" - -[[projects]] - name = "github.com/tendermint/go-amino" - packages = ["."] - revision = "2106ca61d91029c931fd54968c2bb02dc96b1412" - version = "0.10.1" - -[[projects]] - name = "github.com/tendermint/tmlibs" - packages = [ - "common", - "log", - "test" - ] - revision = "692f1d86a6e2c0efa698fd1e4541b68c74ffaf38" - version = "v0.8.4" - -[[projects]] - branch = "master" - name = "golang.org/x/crypto" - packages = [ - "bcrypt", - "blowfish", - "chacha20poly1305", - "hkdf", - "internal/chacha20", - "internal/subtle", - "nacl/secretbox", - "openpgp/armor", - "openpgp/errors", - "poly1305", - "ripemd160", - "salsa20/salsa" - ] - revision = "7f39a6fea4fe9364fb61e1def6a268a51b4f3a06" - -[[projects]] - branch = "master" - name = "golang.org/x/sys" - packages = ["cpu"] - revision = "ad87a3a340fa7f3bed189293fbfa7a9b7e021ae1" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "027b22b86396a971d5d5c1d298947f531f39743975d65a22e98601140aa1b1a1" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/crypto/Gopkg.toml b/crypto/Gopkg.toml deleted file mode 100644 index a614df866..000000000 --- a/crypto/Gopkg.toml +++ /dev/null @@ -1,49 +0,0 @@ -# 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 - -[[constraint]] - name = "github.com/btcsuite/btcutil" - branch = "master" - -[[constraint]] - name = "github.com/stretchr/testify" - version = "1.2.1" - -[[constraint]] - name = "github.com/tendermint/ed25519" - branch = "master" - -[[constraint]] - name = "github.com/tendermint/go-amino" - version = "0.10.0-rc2" - -[[constraint]] - name = "github.com/tendermint/tmlibs" - version = "0.8.1" - -[prune] - go-tests = true - unused-packages = true diff --git a/crypto/README.md b/crypto/README.md index 32afde699..5fac67338 100644 --- a/crypto/README.md +++ b/crypto/README.md @@ -3,8 +3,15 @@ crypto is the cryptographic package adapted for Tendermint's uses ## Importing it +To get the interfaces, `import "github.com/tendermint/tendermint/crypto"` +For any specific algorithm, use its specific module e.g. +`import "github.com/tendermint/tendermint/crypto/ed25519"` + +If you want to decode bytes into one of the types, but don't care about the specific algorithm, use +`import "github.com/tendermint/tendermint/crypto/amino"` + ## Binary encoding For Binary encoding, please refer to the [Tendermint encoding spec](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/encoding.md). @@ -16,9 +23,9 @@ crypto `.Bytes()` uses Amino:binary encoding, but Amino:JSON is also supported. ```go Example Amino:JSON encodings: -crypto.PrivKeyEd25519 - {"type":"954568A3288910","value":"EVkqJO/jIXp3rkASXfh9YnyToYXRXhBr6g9cQVxPFnQBP/5povV4HTjvsy530kybxKHwEi85iU8YL0qQhSYVoQ=="} +ed25519.PrivKeyEd25519 - {"type":"954568A3288910","value":"EVkqJO/jIXp3rkASXfh9YnyToYXRXhBr6g9cQVxPFnQBP/5povV4HTjvsy530kybxKHwEi85iU8YL0qQhSYVoQ=="} crypto.SignatureEd25519 - {"type":"6BF5903DA1DB28","value":"77sQNZOrf7ltExpf7AV1WaYPCHbyRLgjBsoWVzcduuLk+jIGmYk+s5R6Emm29p12HeiNAuhUJgdFGmwkpeGJCA=="} -crypto.PubKeyEd25519 - {"type":"AC26791624DE60","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="} +ed25519.PubKeyEd25519 - {"type":"AC26791624DE60","value":"AT/+aaL1eB0477Mud9JMm8Sh8BIvOYlPGC9KkIUmFaE="} crypto.PrivKeySecp256k1 - {"type":"019E82E1B0F798","value":"zx4Pnh67N+g2V+5vZbQzEyRerX9c4ccNZOVzM9RvJ0Y="} crypto.SignatureSecp256k1 - {"type":"6D1EA416E1FEE8","value":"MEUCIQCIg5TqS1l7I+MKTrSPIuUN2+4m5tA29dcauqn3NhEJ2wIgICaZ+lgRc5aOTVahU/XoLopXKn8BZcl0bnuYWLvohR8="} crypto.PubKeySecp256k1 - {"type":"F8CCEAEB5AE980","value":"A8lPKJXcNl5VHt1FK8a244K9EJuS4WX1hFBnwisi0IJx"} diff --git a/crypto/amino.go b/crypto/amino.go deleted file mode 100644 index 6a8703fc9..000000000 --- a/crypto/amino.go +++ /dev/null @@ -1,37 +0,0 @@ -package crypto - -import ( - amino "github.com/tendermint/go-amino" -) - -var cdc = amino.NewCodec() - -func init() { - // NOTE: It's important that there be no conflicts here, - // as that would change the canonical representations, - // and therefore change the address. - // TODO: Add feature to go-amino to ensure that there - // are no conflicts. - RegisterAmino(cdc) -} - -// RegisterAmino registers all crypto related types in the given (amino) codec. -func RegisterAmino(cdc *amino.Codec) { - cdc.RegisterInterface((*PubKey)(nil), nil) - cdc.RegisterConcrete(PubKeyEd25519{}, - "tendermint/PubKeyEd25519", nil) - cdc.RegisterConcrete(PubKeySecp256k1{}, - "tendermint/PubKeySecp256k1", nil) - - cdc.RegisterInterface((*PrivKey)(nil), nil) - cdc.RegisterConcrete(PrivKeyEd25519{}, - "tendermint/PrivKeyEd25519", nil) - cdc.RegisterConcrete(PrivKeySecp256k1{}, - "tendermint/PrivKeySecp256k1", nil) - - cdc.RegisterInterface((*Signature)(nil), nil) - cdc.RegisterConcrete(SignatureEd25519{}, - "tendermint/SignatureEd25519", nil) - cdc.RegisterConcrete(SignatureSecp256k1{}, - "tendermint/SignatureSecp256k1", nil) -} diff --git a/crypto/armor.go b/crypto/armor/armor.go similarity index 98% rename from crypto/armor.go rename to crypto/armor/armor.go index 4146048ad..c15d070e6 100644 --- a/crypto/armor.go +++ b/crypto/armor/armor.go @@ -1,4 +1,4 @@ -package crypto +package armor import ( "bytes" diff --git a/crypto/armor_test.go b/crypto/armor/armor_test.go similarity index 96% rename from crypto/armor_test.go rename to crypto/armor/armor_test.go index 5eae87c00..4aa23b211 100644 --- a/crypto/armor_test.go +++ b/crypto/armor/armor_test.go @@ -1,4 +1,4 @@ -package crypto +package armor import ( "testing" diff --git a/crypto/crypto.go b/crypto/crypto.go new file mode 100644 index 000000000..4c097b351 --- /dev/null +++ b/crypto/crypto.go @@ -0,0 +1,36 @@ +package crypto + +import ( + cmn "github.com/tendermint/tendermint/libs/common" +) + +type PrivKey interface { + Bytes() []byte + Sign(msg []byte) (Signature, error) + PubKey() PubKey + Equals(PrivKey) bool +} + +// An address is a []byte, but hex-encoded even in JSON. +// []byte leaves us the option to change the address length. +// Use an alias so Unmarshal methods (with ptr receivers) are available too. +type Address = cmn.HexBytes + +type PubKey interface { + Address() Address + Bytes() []byte + VerifyBytes(msg []byte, sig Signature) bool + Equals(PubKey) bool +} + +type Signature interface { + Bytes() []byte + IsZero() bool + Equals(Signature) bool +} + +type Symmetric interface { + Keygen() []byte + Encrypt(plaintext []byte, secret []byte) (ciphertext []byte) + Decrypt(ciphertext []byte, secret []byte) (plaintext []byte, err error) +} diff --git a/crypto/doc.go b/crypto/doc.go index 544e0df36..41b3f3021 100644 --- a/crypto/doc.go +++ b/crypto/doc.go @@ -22,7 +22,7 @@ // pubKey := key.PubKey() // For example: -// privKey, err := crypto.GenPrivKeyEd25519() +// privKey, err := ed25519.GenPrivKey() // if err != nil { // ... // } diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go new file mode 100644 index 000000000..8b7bd42bd --- /dev/null +++ b/crypto/ed25519/ed25519.go @@ -0,0 +1,227 @@ +package ed25519 + +import ( + "bytes" + "crypto/subtle" + "fmt" + + "github.com/tendermint/ed25519" + "github.com/tendermint/ed25519/extra25519" + amino "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/tmhash" + cmn "github.com/tendermint/tendermint/libs/common" +) + +//------------------------------------- + +var _ crypto.PrivKey = PrivKeyEd25519{} + +const ( + Ed25519PrivKeyAminoRoute = "tendermint/PrivKeyEd25519" + Ed25519PubKeyAminoRoute = "tendermint/PubKeyEd25519" + Ed25519SignatureAminoRoute = "tendermint/SignatureEd25519" +) + +var cdc = amino.NewCodec() + +func init() { + cdc.RegisterInterface((*crypto.PubKey)(nil), nil) + cdc.RegisterConcrete(PubKeyEd25519{}, + Ed25519PubKeyAminoRoute, nil) + + cdc.RegisterInterface((*crypto.PrivKey)(nil), nil) + cdc.RegisterConcrete(PrivKeyEd25519{}, + Ed25519PrivKeyAminoRoute, nil) + + cdc.RegisterInterface((*crypto.Signature)(nil), nil) + cdc.RegisterConcrete(SignatureEd25519{}, + Ed25519SignatureAminoRoute, nil) +} + +// PrivKeyEd25519 implements crypto.PrivKey. +type PrivKeyEd25519 [64]byte + +// Bytes marshals the privkey using amino encoding. +func (privKey PrivKeyEd25519) Bytes() []byte { + return cdc.MustMarshalBinaryBare(privKey) +} + +// Sign produces a signature on the provided message. +func (privKey PrivKeyEd25519) Sign(msg []byte) (crypto.Signature, error) { + privKeyBytes := [64]byte(privKey) + signatureBytes := ed25519.Sign(&privKeyBytes, msg) + return SignatureEd25519(*signatureBytes), nil +} + +// PubKey gets the corresponding public key from the private key. +func (privKey PrivKeyEd25519) PubKey() crypto.PubKey { + privKeyBytes := [64]byte(privKey) + initialized := false + // If the latter 32 bytes of the privkey are all zero, compute the pubkey + // otherwise privkey is initialized and we can use the cached value inside + // of the private key. + for _, v := range privKeyBytes[32:] { + if v != 0 { + initialized = true + break + } + } + if initialized { + var pubkeyBytes [PubKeyEd25519Size]byte + copy(pubkeyBytes[:], privKeyBytes[32:]) + return PubKeyEd25519(pubkeyBytes) + } + + pubBytes := *ed25519.MakePublicKey(&privKeyBytes) + return PubKeyEd25519(pubBytes) +} + +// Equals - you probably don't need to use this. +// Runs in constant time based on length of the keys. +func (privKey PrivKeyEd25519) Equals(other crypto.PrivKey) bool { + if otherEd, ok := other.(PrivKeyEd25519); ok { + return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 + } else { + return false + } +} + +// ToCurve25519 takes a private key and returns its representation on +// Curve25519. Curve25519 is birationally equivalent to Edwards25519, +// which Ed25519 uses internally. This method is intended for use in +// an X25519 Diffie Hellman key exchange. +func (privKey PrivKeyEd25519) ToCurve25519() *[PubKeyEd25519Size]byte { + keyCurve25519 := new([32]byte) + privKeyBytes := [64]byte(privKey) + extra25519.PrivateKeyToCurve25519(keyCurve25519, &privKeyBytes) + return keyCurve25519 +} + +// GenPrivKey generates a new ed25519 private key. +// It uses OS randomness in conjunction with the current global random seed +// in tendermint/libs/common to generate the private key. +func GenPrivKey() PrivKeyEd25519 { + privKey := new([64]byte) + copy(privKey[:32], crypto.CRandBytes(32)) + // ed25519.MakePublicKey(privKey) alters the last 32 bytes of privKey. + // It places the pubkey in the last 32 bytes of privKey, and returns the + // public key. + ed25519.MakePublicKey(privKey) + return PrivKeyEd25519(*privKey) +} + +// GenPrivKeyFromSecret hashes the secret with SHA2, and uses +// that 32 byte output to create the private key. +// NOTE: secret should be the output of a KDF like bcrypt, +// if it's derived from user input. +func GenPrivKeyFromSecret(secret []byte) PrivKeyEd25519 { + privKey32 := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes. + privKey := new([64]byte) + copy(privKey[:32], privKey32) + // ed25519.MakePublicKey(privKey) alters the last 32 bytes of privKey. + // It places the pubkey in the last 32 bytes of privKey, and returns the + // public key. + ed25519.MakePublicKey(privKey) + return PrivKeyEd25519(*privKey) +} + +//------------------------------------- + +var _ crypto.PubKey = PubKeyEd25519{} + +// PubKeyEd25519Size is the number of bytes in an Ed25519 signature. +const PubKeyEd25519Size = 32 + +// PubKeyEd25519 implements crypto.PubKey for the Ed25519 signature scheme. +type PubKeyEd25519 [PubKeyEd25519Size]byte + +// Address is the SHA256-20 of the raw pubkey bytes. +func (pubKey PubKeyEd25519) Address() crypto.Address { + return crypto.Address(tmhash.Sum(pubKey[:])) +} + +// Bytes marshals the PubKey using amino encoding. +func (pubKey PubKeyEd25519) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(pubKey) + if err != nil { + panic(err) + } + return bz +} + +func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ crypto.Signature) bool { + // make sure we use the same algorithm to sign + sig, ok := sig_.(SignatureEd25519) + if !ok { + return false + } + pubKeyBytes := [PubKeyEd25519Size]byte(pubKey) + sigBytes := [SignatureEd25519Size]byte(sig) + return ed25519.Verify(&pubKeyBytes, msg, &sigBytes) +} + +// ToCurve25519 takes a public key and returns its representation on +// Curve25519. Curve25519 is birationally equivalent to Edwards25519, +// which Ed25519 uses internally. This method is intended for use in +// an X25519 Diffie Hellman key exchange. +// +// If there is an error, then this function returns nil. +func (pubKey PubKeyEd25519) ToCurve25519() *[PubKeyEd25519Size]byte { + keyCurve25519, pubKeyBytes := new([PubKeyEd25519Size]byte), [PubKeyEd25519Size]byte(pubKey) + ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes) + if !ok { + return nil + } + return keyCurve25519 +} + +func (pubKey PubKeyEd25519) String() string { + return fmt.Sprintf("PubKeyEd25519{%X}", pubKey[:]) +} + +// nolint: golint +func (pubKey PubKeyEd25519) Equals(other crypto.PubKey) bool { + if otherEd, ok := other.(PubKeyEd25519); ok { + return bytes.Equal(pubKey[:], otherEd[:]) + } else { + return false + } +} + +//------------------------------------- + +var _ crypto.Signature = SignatureEd25519{} + +// Size of an Edwards25519 signature. Namely the size of a compressed +// Edwards25519 point, and a field element. Both of which are 32 bytes. +const SignatureEd25519Size = 64 + +// SignatureEd25519 implements crypto.Signature +type SignatureEd25519 [SignatureEd25519Size]byte + +func (sig SignatureEd25519) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(sig) + if err != nil { + panic(err) + } + return bz +} + +func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } + +func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", cmn.Fingerprint(sig[:])) } + +func (sig SignatureEd25519) Equals(other crypto.Signature) bool { + if otherEd, ok := other.(SignatureEd25519); ok { + return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 1 + } else { + return false + } +} + +func SignatureEd25519FromBytes(data []byte) crypto.Signature { + var sig SignatureEd25519 + copy(sig[:], data) + return sig +} diff --git a/crypto/ed25519/ed25519_test.go b/crypto/ed25519/ed25519_test.go new file mode 100644 index 000000000..5c407ccd1 --- /dev/null +++ b/crypto/ed25519/ed25519_test.go @@ -0,0 +1,31 @@ +package ed25519_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" +) + +func TestSignAndValidateEd25519(t *testing.T) { + + privKey := ed25519.GenPrivKey() + pubKey := privKey.PubKey() + + msg := crypto.CRandBytes(128) + sig, err := privKey.Sign(msg) + require.Nil(t, err) + + // Test the signature + assert.True(t, pubKey.VerifyBytes(msg, sig)) + + // Mutate the signature, just one bit. + // TODO: Replace this with a much better fuzzer, tendermint/ed25519/issues/10 + sigEd := sig.(ed25519.SignatureEd25519) + sigEd[7] ^= byte(0x01) + sig = sigEd + + assert.False(t, pubKey.VerifyBytes(msg, sig)) +} diff --git a/crypto/encoding/amino/amino.go b/crypto/encoding/amino/amino.go new file mode 100644 index 000000000..2b5e15b4f --- /dev/null +++ b/crypto/encoding/amino/amino.go @@ -0,0 +1,57 @@ +package cryptoAmino + +import ( + amino "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" +) + +var cdc = amino.NewCodec() + +func init() { + // NOTE: It's important that there be no conflicts here, + // as that would change the canonical representations, + // and therefore change the address. + // TODO: Remove above note when + // https://github.com/tendermint/go-amino/issues/9 + // is resolved + RegisterAmino(cdc) +} + +// RegisterAmino registers all crypto related types in the given (amino) codec. +func RegisterAmino(cdc *amino.Codec) { + // These are all written here instead of + cdc.RegisterInterface((*crypto.PubKey)(nil), nil) + cdc.RegisterConcrete(ed25519.PubKeyEd25519{}, + "tendermint/PubKeyEd25519", nil) + cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{}, + "tendermint/PubKeySecp256k1", nil) + + cdc.RegisterInterface((*crypto.PrivKey)(nil), nil) + cdc.RegisterConcrete(ed25519.PrivKeyEd25519{}, + "tendermint/PrivKeyEd25519", nil) + cdc.RegisterConcrete(secp256k1.PrivKeySecp256k1{}, + "tendermint/PrivKeySecp256k1", nil) + + cdc.RegisterInterface((*crypto.Signature)(nil), nil) + cdc.RegisterConcrete(ed25519.SignatureEd25519{}, + "tendermint/SignatureEd25519", nil) + cdc.RegisterConcrete(secp256k1.SignatureSecp256k1{}, + "tendermint/SignatureSecp256k1", nil) +} + +func PrivKeyFromBytes(privKeyBytes []byte) (privKey crypto.PrivKey, err error) { + err = cdc.UnmarshalBinaryBare(privKeyBytes, &privKey) + return +} + +func PubKeyFromBytes(pubKeyBytes []byte) (pubKey crypto.PubKey, err error) { + err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) + return +} + +func SignatureFromBytes(pubKeyBytes []byte) (pubKey crypto.Signature, err error) { + err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) + return +} diff --git a/crypto/encode_test.go b/crypto/encoding/amino/encode_test.go similarity index 71% rename from crypto/encode_test.go rename to crypto/encoding/amino/encode_test.go index 16555bf71..e01206089 100644 --- a/crypto/encode_test.go +++ b/crypto/encoding/amino/encode_test.go @@ -1,4 +1,4 @@ -package crypto +package cryptoAmino import ( "os" @@ -6,6 +6,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" ) type byter interface { @@ -56,64 +59,70 @@ func ExamplePrintRegisteredTypes() { func TestKeyEncodings(t *testing.T) { cases := []struct { - privKey PrivKey + privKey crypto.PrivKey privSize, pubSize int // binary sizes }{ { - privKey: GenPrivKeyEd25519(), + privKey: ed25519.GenPrivKey(), privSize: 69, pubSize: 37, }, { - privKey: GenPrivKeySecp256k1(), + privKey: secp256k1.GenPrivKey(), privSize: 37, pubSize: 38, }, } - for _, tc := range cases { + for tcIndex, tc := range cases { // Check (de/en)codings of PrivKeys. - var priv2, priv3 PrivKey + var priv2, priv3 crypto.PrivKey checkAminoBinary(t, tc.privKey, &priv2, tc.privSize) - assert.EqualValues(t, tc.privKey, priv2) + assert.EqualValues(t, tc.privKey, priv2, "tc #%d", tcIndex) checkAminoJSON(t, tc.privKey, &priv3, false) // TODO also check Prefix bytes. - assert.EqualValues(t, tc.privKey, priv3) + assert.EqualValues(t, tc.privKey, priv3, "tc #%d", tcIndex) // Check (de/en)codings of Signatures. - var sig1, sig2, sig3 Signature + var sig1, sig2, sig3 crypto.Signature sig1, err := tc.privKey.Sign([]byte("something")) - assert.NoError(t, err) + assert.NoError(t, err, "tc #%d", tcIndex) checkAminoBinary(t, sig1, &sig2, -1) // Signature size changes for Secp anyways. - assert.EqualValues(t, sig1, sig2) + assert.EqualValues(t, sig1, sig2, "tc #%d", tcIndex) checkAminoJSON(t, sig1, &sig3, false) // TODO also check Prefix bytes. - assert.EqualValues(t, sig1, sig3) + assert.EqualValues(t, sig1, sig3, "tc #%d", tcIndex) // Check (de/en)codings of PubKeys. pubKey := tc.privKey.PubKey() - var pub2, pub3 PubKey + var pub2, pub3 crypto.PubKey checkAminoBinary(t, pubKey, &pub2, tc.pubSize) - assert.EqualValues(t, pubKey, pub2) + assert.EqualValues(t, pubKey, pub2, "tc #%d", tcIndex) checkAminoJSON(t, pubKey, &pub3, false) // TODO also check Prefix bytes. - assert.EqualValues(t, pubKey, pub3) + assert.EqualValues(t, pubKey, pub3, "tc #%d", tcIndex) } } func TestNilEncodings(t *testing.T) { // Check nil Signature. - var a, b Signature + var a, b crypto.Signature checkAminoJSON(t, &a, &b, true) assert.EqualValues(t, a, b) // Check nil PubKey. - var c, d PubKey + var c, d crypto.PubKey checkAminoJSON(t, &c, &d, true) assert.EqualValues(t, c, d) // Check nil PrivKey. - var e, f PrivKey + var e, f crypto.PrivKey checkAminoJSON(t, &e, &f, true) assert.EqualValues(t, e, f) } + +func TestPubKeyInvalidDataProperReturnsEmpty(t *testing.T) { + pk, err := PubKeyFromBytes([]byte("foo")) + require.NotNil(t, err, "expecting a non-nil error") + require.Nil(t, pk, "expecting an empty public key on error") +} diff --git a/crypto/hash.go b/crypto/hash.go index 165b1e153..c1fb41f7a 100644 --- a/crypto/hash.go +++ b/crypto/hash.go @@ -2,6 +2,7 @@ package crypto import ( "crypto/sha256" + "golang.org/x/crypto/ripemd160" ) diff --git a/crypto/hkdfchacha20poly1305/hkdfchachapoly.go b/crypto/hkdfchacha20poly1305/hkdfchachapoly.go index ab3b9df3a..4bf24cb18 100644 --- a/crypto/hkdfchacha20poly1305/hkdfchachapoly.go +++ b/crypto/hkdfchacha20poly1305/hkdfchachapoly.go @@ -14,6 +14,7 @@ import ( "golang.org/x/crypto/hkdf" ) +// Implements crypto.AEAD type hkdfchacha20poly1305 struct { key [KeySize]byte } diff --git a/crypto/priv_key.go b/crypto/priv_key.go deleted file mode 100644 index dbfe64c33..000000000 --- a/crypto/priv_key.go +++ /dev/null @@ -1,164 +0,0 @@ -package crypto - -import ( - "crypto/subtle" - - secp256k1 "github.com/btcsuite/btcd/btcec" - "github.com/tendermint/ed25519" - "github.com/tendermint/ed25519/extra25519" -) - -func PrivKeyFromBytes(privKeyBytes []byte) (privKey PrivKey, err error) { - err = cdc.UnmarshalBinaryBare(privKeyBytes, &privKey) - return -} - -//---------------------------------------- - -type PrivKey interface { - Bytes() []byte - Sign(msg []byte) (Signature, error) - PubKey() PubKey - Equals(PrivKey) bool -} - -//------------------------------------- - -var _ PrivKey = PrivKeyEd25519{} - -// Implements PrivKey -type PrivKeyEd25519 [64]byte - -func (privKey PrivKeyEd25519) Bytes() []byte { - return cdc.MustMarshalBinaryBare(privKey) -} - -func (privKey PrivKeyEd25519) Sign(msg []byte) (Signature, error) { - privKeyBytes := [64]byte(privKey) - signatureBytes := ed25519.Sign(&privKeyBytes, msg) - return SignatureEd25519(*signatureBytes), nil -} - -func (privKey PrivKeyEd25519) PubKey() PubKey { - privKeyBytes := [64]byte(privKey) - pubBytes := *ed25519.MakePublicKey(&privKeyBytes) - return PubKeyEd25519(pubBytes) -} - -// Equals - you probably don't need to use this. -// Runs in constant time based on length of the keys. -func (privKey PrivKeyEd25519) Equals(other PrivKey) bool { - if otherEd, ok := other.(PrivKeyEd25519); ok { - return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 - } else { - return false - } -} - -func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte { - keyCurve25519 := new([32]byte) - privKeyBytes := [64]byte(privKey) - extra25519.PrivateKeyToCurve25519(keyCurve25519, &privKeyBytes) - return keyCurve25519 -} - -// Deterministically generates new priv-key bytes from key. -func (privKey PrivKeyEd25519) Generate(index int) PrivKeyEd25519 { - bz, err := cdc.MarshalBinaryBare(struct { - PrivKey [64]byte - Index int - }{privKey, index}) - if err != nil { - panic(err) - } - newBytes := Sha256(bz) - newKey := new([64]byte) - copy(newKey[:32], newBytes) - ed25519.MakePublicKey(newKey) - return PrivKeyEd25519(*newKey) -} - -func GenPrivKeyEd25519() PrivKeyEd25519 { - privKeyBytes := new([64]byte) - copy(privKeyBytes[:32], CRandBytes(32)) - ed25519.MakePublicKey(privKeyBytes) - return PrivKeyEd25519(*privKeyBytes) -} - -// NOTE: secret should be the output of a KDF like bcrypt, -// if it's derived from user input. -func GenPrivKeyEd25519FromSecret(secret []byte) PrivKeyEd25519 { - privKey32 := Sha256(secret) // Not Ripemd160 because we want 32 bytes. - privKeyBytes := new([64]byte) - copy(privKeyBytes[:32], privKey32) - ed25519.MakePublicKey(privKeyBytes) - return PrivKeyEd25519(*privKeyBytes) -} - -//------------------------------------- - -var _ PrivKey = PrivKeySecp256k1{} - -// Implements PrivKey -type PrivKeySecp256k1 [32]byte - -func (privKey PrivKeySecp256k1) Bytes() []byte { - return cdc.MustMarshalBinaryBare(privKey) -} - -func (privKey PrivKeySecp256k1) Sign(msg []byte) (Signature, error) { - priv__, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) - sig__, err := priv__.Sign(Sha256(msg)) - if err != nil { - return nil, err - } - return SignatureSecp256k1(sig__.Serialize()), nil -} - -func (privKey PrivKeySecp256k1) PubKey() PubKey { - _, pub__ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) - var pub PubKeySecp256k1 - copy(pub[:], pub__.SerializeCompressed()) - return pub -} - -// Equals - you probably don't need to use this. -// Runs in constant time based on length of the keys. -func (privKey PrivKeySecp256k1) Equals(other PrivKey) bool { - if otherSecp, ok := other.(PrivKeySecp256k1); ok { - return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 1 - } else { - return false - } -} - -/* -// Deterministically generates new priv-key bytes from key. -func (key PrivKeySecp256k1) Generate(index int) PrivKeySecp256k1 { - newBytes := cdc.BinarySha256(struct { - PrivKey [64]byte - Index int - }{key, index}) - var newKey [64]byte - copy(newKey[:], newBytes) - return PrivKeySecp256k1(newKey) -} -*/ - -func GenPrivKeySecp256k1() PrivKeySecp256k1 { - privKeyBytes := [32]byte{} - copy(privKeyBytes[:], CRandBytes(32)) - priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKeyBytes[:]) - copy(privKeyBytes[:], priv.Serialize()) - return PrivKeySecp256k1(privKeyBytes) -} - -// NOTE: secret should be the output of a KDF like bcrypt, -// if it's derived from user input. -func GenPrivKeySecp256k1FromSecret(secret []byte) PrivKeySecp256k1 { - privKey32 := Sha256(secret) // Not Ripemd160 because we want 32 bytes. - priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey32) - privKeyBytes := [32]byte{} - copy(privKeyBytes[:], priv.Serialize()) - return PrivKeySecp256k1(privKeyBytes) -} diff --git a/crypto/priv_key_test.go b/crypto/priv_key_test.go deleted file mode 100644 index c1ae33ed1..000000000 --- a/crypto/priv_key_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package crypto_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/tendermint/tendermint/crypto" -) - -func TestGeneratePrivKey(t *testing.T) { - testPriv := crypto.GenPrivKeyEd25519() - testGenerate := testPriv.Generate(1) - signBytes := []byte("something to sign") - pub := testGenerate.PubKey() - sig, err := testGenerate.Sign(signBytes) - assert.NoError(t, err) - assert.True(t, pub.VerifyBytes(signBytes, sig)) -} - -/* - -type BadKey struct { - PrivKeyEd25519 -} - -func TestReadPrivKey(t *testing.T) { - assert, require := assert.New(t), require.New(t) - - // garbage in, garbage out - garbage := []byte("hjgewugfbiewgofwgewr") - XXX This test wants to register BadKey globally to crypto, - but we don't want to support that. - _, err := PrivKeyFromBytes(garbage) - require.Error(err) - - edKey := GenPrivKeyEd25519() - badKey := BadKey{edKey} - - cases := []struct { - key PrivKey - valid bool - }{ - {edKey, true}, - {badKey, false}, - } - - for i, tc := range cases { - data := tc.key.Bytes() - fmt.Println(">>>", data) - key, err := PrivKeyFromBytes(data) - fmt.Printf("!!! %#v\n", key, err) - if tc.valid { - assert.NoError(err, "%d", i) - assert.Equal(tc.key, key, "%d", i) - } else { - assert.Error(err, "%d: %#v", i, key) - } - } -} -*/ diff --git a/crypto/pub_key.go b/crypto/pub_key.go deleted file mode 100644 index 588c54113..000000000 --- a/crypto/pub_key.go +++ /dev/null @@ -1,153 +0,0 @@ -package crypto - -import ( - "bytes" - "crypto/sha256" - "fmt" - - "golang.org/x/crypto/ripemd160" - - secp256k1 "github.com/btcsuite/btcd/btcec" - - "github.com/tendermint/ed25519" - "github.com/tendermint/ed25519/extra25519" - - cmn "github.com/tendermint/tendermint/libs/common" - - "github.com/tendermint/tendermint/crypto/tmhash" -) - -// An address is a []byte, but hex-encoded even in JSON. -// []byte leaves us the option to change the address length. -// Use an alias so Unmarshal methods (with ptr receivers) are available too. -type Address = cmn.HexBytes - -func PubKeyFromBytes(pubKeyBytes []byte) (pubKey PubKey, err error) { - err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) - return -} - -//---------------------------------------- - -type PubKey interface { - Address() Address - Bytes() []byte - VerifyBytes(msg []byte, sig Signature) bool - Equals(PubKey) bool -} - -//------------------------------------- - -var _ PubKey = PubKeyEd25519{} - -const PubKeyEd25519Size = 32 - -// Implements PubKeyInner -type PubKeyEd25519 [PubKeyEd25519Size]byte - -// Address is the SHA256-20 of the raw pubkey bytes. -func (pubKey PubKeyEd25519) Address() Address { - return Address(tmhash.Sum(pubKey[:])) -} - -func (pubKey PubKeyEd25519) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(pubKey) - if err != nil { - panic(err) - } - return bz -} - -func (pubKey PubKeyEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { - // make sure we use the same algorithm to sign - sig, ok := sig_.(SignatureEd25519) - if !ok { - return false - } - pubKeyBytes := [PubKeyEd25519Size]byte(pubKey) - sigBytes := [SignatureEd25519Size]byte(sig) - return ed25519.Verify(&pubKeyBytes, msg, &sigBytes) -} - -// For use with golang/crypto/nacl/box -// If error, returns nil. -func (pubKey PubKeyEd25519) ToCurve25519() *[PubKeyEd25519Size]byte { - keyCurve25519, pubKeyBytes := new([PubKeyEd25519Size]byte), [PubKeyEd25519Size]byte(pubKey) - ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes) - if !ok { - return nil - } - return keyCurve25519 -} - -func (pubKey PubKeyEd25519) String() string { - return fmt.Sprintf("PubKeyEd25519{%X}", pubKey[:]) -} - -func (pubKey PubKeyEd25519) Equals(other PubKey) bool { - if otherEd, ok := other.(PubKeyEd25519); ok { - return bytes.Equal(pubKey[:], otherEd[:]) - } else { - return false - } -} - -//------------------------------------- - -var _ PubKey = PubKeySecp256k1{} - -const PubKeySecp256k1Size = 33 - -// Implements PubKey. -// Compressed pubkey (just the x-cord), -// prefixed with 0x02 or 0x03, depending on the y-cord. -type PubKeySecp256k1 [PubKeySecp256k1Size]byte - -// Implements Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) -func (pubKey PubKeySecp256k1) Address() Address { - hasherSHA256 := sha256.New() - hasherSHA256.Write(pubKey[:]) // does not error - sha := hasherSHA256.Sum(nil) - - hasherRIPEMD160 := ripemd160.New() - hasherRIPEMD160.Write(sha) // does not error - return Address(hasherRIPEMD160.Sum(nil)) -} - -func (pubKey PubKeySecp256k1) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(pubKey) - if err != nil { - panic(err) - } - return bz -} - -func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { - // and assert same algorithm to sign and verify - sig, ok := sig_.(SignatureSecp256k1) - if !ok { - return false - } - - pub__, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256()) - if err != nil { - return false - } - sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256()) - if err != nil { - return false - } - return sig__.Verify(Sha256(msg), pub__) -} - -func (pubKey PubKeySecp256k1) String() string { - return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey[:]) -} - -func (pubKey PubKeySecp256k1) Equals(other PubKey) bool { - if otherSecp, ok := other.(PubKeySecp256k1); ok { - return bytes.Equal(pubKey[:], otherSecp[:]) - } else { - return false - } -} diff --git a/crypto/pub_key_test.go b/crypto/pub_key_test.go deleted file mode 100644 index 7b856cf18..000000000 --- a/crypto/pub_key_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package crypto - -import ( - "encoding/hex" - "testing" - - "github.com/btcsuite/btcutil/base58" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -type keyData struct { - priv string - pub string - addr string -} - -var secpDataTable = []keyData{ - { - priv: "a96e62ed3955e65be32703f12d87b6b5cf26039ecfa948dc5107a495418e5330", - pub: "02950e1cdfcb133d6024109fd489f734eeb4502418e538c28481f22bce276f248c", - addr: "1CKZ9Nx4zgds8tU7nJHotKSDr4a9bYJCa3", - }, -} - -func TestPubKeySecp256k1Address(t *testing.T) { - for _, d := range secpDataTable { - privB, _ := hex.DecodeString(d.priv) - pubB, _ := hex.DecodeString(d.pub) - addrBbz, _, _ := base58.CheckDecode(d.addr) - addrB := Address(addrBbz) - - var priv PrivKeySecp256k1 - copy(priv[:], privB) - - pubKey := priv.PubKey() - pubT, _ := pubKey.(PubKeySecp256k1) - pub := pubT[:] - addr := pubKey.Address() - - assert.Equal(t, pub, pubB, "Expected pub keys to match") - assert.Equal(t, addr, addrB, "Expected addresses to match") - } -} - -func TestPubKeyInvalidDataProperReturnsEmpty(t *testing.T) { - pk, err := PubKeyFromBytes([]byte("foo")) - require.NotNil(t, err, "expecting a non-nil error") - require.Nil(t, pk, "expecting an empty public key on error") -} diff --git a/crypto/secp256k1/secp256k1.go b/crypto/secp256k1/secp256k1.go new file mode 100644 index 000000000..4b210dc7f --- /dev/null +++ b/crypto/secp256k1/secp256k1.go @@ -0,0 +1,198 @@ +package secp256k1 + +import ( + "bytes" + "crypto/sha256" + "crypto/subtle" + "fmt" + + secp256k1 "github.com/btcsuite/btcd/btcec" + amino "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/common" + "golang.org/x/crypto/ripemd160" +) + +//------------------------------------- +const ( + Secp256k1PrivKeyAminoRoute = "tendermint/PrivKeySecp256k1" + Secp256k1PubKeyAminoRoute = "tendermint/PubKeySecp256k1" + Secp256k1SignatureAminoRoute = "tendermint/SignatureSecp256k1" +) + +var cdc = amino.NewCodec() + +func init() { + cdc.RegisterInterface((*crypto.PubKey)(nil), nil) + cdc.RegisterConcrete(PubKeySecp256k1{}, + Secp256k1PubKeyAminoRoute, nil) + + cdc.RegisterInterface((*crypto.PrivKey)(nil), nil) + cdc.RegisterConcrete(PrivKeySecp256k1{}, + Secp256k1PrivKeyAminoRoute, nil) + + cdc.RegisterInterface((*crypto.Signature)(nil), nil) + cdc.RegisterConcrete(SignatureSecp256k1{}, + Secp256k1SignatureAminoRoute, nil) +} + +//------------------------------------- + +var _ crypto.PrivKey = PrivKeySecp256k1{} + +// PrivKeySecp256k1 implements PrivKey. +type PrivKeySecp256k1 [32]byte + +// Bytes marshalls the private key using amino encoding. +func (privKey PrivKeySecp256k1) Bytes() []byte { + return cdc.MustMarshalBinaryBare(privKey) +} + +// Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg. +func (privKey PrivKeySecp256k1) Sign(msg []byte) (crypto.Signature, error) { + priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) + sig, err := priv.Sign(crypto.Sha256(msg)) + if err != nil { + return nil, err + } + return SignatureSecp256k1(sig.Serialize()), nil +} + +// PubKey performs the point-scalar multiplication from the privKey on the +// generator point to get the pubkey. +func (privKey PrivKeySecp256k1) PubKey() crypto.PubKey { + _, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) + var pubkeyBytes PubKeySecp256k1 + copy(pubkeyBytes[:], pubkeyObject.SerializeCompressed()) + return pubkeyBytes +} + +// Equals - you probably don't need to use this. +// Runs in constant time based on length of the keys. +func (privKey PrivKeySecp256k1) Equals(other crypto.PrivKey) bool { + if otherSecp, ok := other.(PrivKeySecp256k1); ok { + return subtle.ConstantTimeCompare(privKey[:], otherSecp[:]) == 1 + } + return false +} + +// GenPrivKey generates a new ECDSA private key on curve secp256k1 private key. +// It uses OS randomness in conjunction with the current global random seed +// in tendermint/libs/common to generate the private key. +func GenPrivKey() PrivKeySecp256k1 { + privKeyBytes := [32]byte{} + copy(privKeyBytes[:], crypto.CRandBytes(32)) + // crypto.CRandBytes is guaranteed to be 32 bytes long, so it can be + // casted to PrivKeySecp256k1. + return PrivKeySecp256k1(privKeyBytes) +} + +// GenPrivKeySecp256k1 hashes the secret with SHA2, and uses +// that 32 byte output to create the private key. +// NOTE: secret should be the output of a KDF like bcrypt, +// if it's derived from user input. +func GenPrivKeySecp256k1(secret []byte) PrivKeySecp256k1 { + privKey32 := sha256.Sum256(secret) + // sha256.Sum256() is guaranteed to be 32 bytes long, so it can be + // casted to PrivKeySecp256k1. + return PrivKeySecp256k1(privKey32) +} + +//------------------------------------- + +var _ crypto.PubKey = PubKeySecp256k1{} + +// PubKeySecp256k1Size is comprised of 32 bytes for one field element +// (the x-coordinate), plus one byte for the parity of the y-coordinate. +const PubKeySecp256k1Size = 33 + +// PubKeySecp256k1 implements crypto.PubKey. +// It is the compressed form of the pubkey. The first byte depends is a 0x02 byte +// if the y-coordinate is the lexicographically largest of the two associated with +// the x-coordinate. Otherwise the first byte is a 0x03. +// This prefix is followed with the x-coordinate. +type PubKeySecp256k1 [PubKeySecp256k1Size]byte + +// Address returns a Bitcoin style addresses: RIPEMD160(SHA256(pubkey)) +func (pubKey PubKeySecp256k1) Address() crypto.Address { + hasherSHA256 := sha256.New() + hasherSHA256.Write(pubKey[:]) // does not error + sha := hasherSHA256.Sum(nil) + + hasherRIPEMD160 := ripemd160.New() + hasherRIPEMD160.Write(sha) // does not error + return crypto.Address(hasherRIPEMD160.Sum(nil)) +} + +// Bytes returns the pubkey marshalled with amino encoding. +func (pubKey PubKeySecp256k1) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(pubKey) + if err != nil { + panic(err) + } + return bz +} + +func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, interfaceSig crypto.Signature) bool { + // and assert same algorithm to sign and verify + sig, ok := interfaceSig.(SignatureSecp256k1) + if !ok { + return false + } + + pub, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256()) + if err != nil { + return false + } + parsedSig, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256()) + if err != nil { + return false + } + return parsedSig.Verify(crypto.Sha256(msg), pub) +} + +func (pubKey PubKeySecp256k1) String() string { + return fmt.Sprintf("PubKeySecp256k1{%X}", pubKey[:]) +} + +func (pubKey PubKeySecp256k1) Equals(other crypto.PubKey) bool { + if otherSecp, ok := other.(PubKeySecp256k1); ok { + return bytes.Equal(pubKey[:], otherSecp[:]) + } + return false +} + +//------------------------------------- + +var _ crypto.Signature = SignatureSecp256k1{} + +// SignatureSecp256k1 implements crypto.Signature +type SignatureSecp256k1 []byte + +func (sig SignatureSecp256k1) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(sig) + if err != nil { + panic(err) + } + return bz +} + +func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } + +func (sig SignatureSecp256k1) String() string { + return fmt.Sprintf("/%X.../", common.Fingerprint(sig[:])) +} + +func (sig SignatureSecp256k1) Equals(other crypto.Signature) bool { + if otherSecp, ok := other.(SignatureSecp256k1); ok { + return subtle.ConstantTimeCompare(sig[:], otherSecp[:]) == 1 + } else { + return false + } +} + +func SignatureSecp256k1FromBytes(data []byte) crypto.Signature { + sig := make(SignatureSecp256k1, len(data)) + copy(sig[:], data) + return sig +} diff --git a/crypto/secp256k1/secpk256k1_test.go b/crypto/secp256k1/secpk256k1_test.go new file mode 100644 index 000000000..46a27b3e6 --- /dev/null +++ b/crypto/secp256k1/secpk256k1_test.go @@ -0,0 +1,88 @@ +package secp256k1_test + +import ( + "encoding/hex" + "testing" + + "github.com/btcsuite/btcutil/base58" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/secp256k1" + + underlyingSecp256k1 "github.com/btcsuite/btcd/btcec" +) + +type keyData struct { + priv string + pub string + addr string +} + +var secpDataTable = []keyData{ + { + priv: "a96e62ed3955e65be32703f12d87b6b5cf26039ecfa948dc5107a495418e5330", + pub: "02950e1cdfcb133d6024109fd489f734eeb4502418e538c28481f22bce276f248c", + addr: "1CKZ9Nx4zgds8tU7nJHotKSDr4a9bYJCa3", + }, +} + +func TestPubKeySecp256k1Address(t *testing.T) { + for _, d := range secpDataTable { + privB, _ := hex.DecodeString(d.priv) + pubB, _ := hex.DecodeString(d.pub) + addrBbz, _, _ := base58.CheckDecode(d.addr) + addrB := crypto.Address(addrBbz) + + var priv secp256k1.PrivKeySecp256k1 + copy(priv[:], privB) + + pubKey := priv.PubKey() + pubT, _ := pubKey.(secp256k1.PubKeySecp256k1) + pub := pubT[:] + addr := pubKey.Address() + + assert.Equal(t, pub, pubB, "Expected pub keys to match") + assert.Equal(t, addr, addrB, "Expected addresses to match") + } +} + +func TestSignAndValidateSecp256k1(t *testing.T) { + privKey := secp256k1.GenPrivKey() + pubKey := privKey.PubKey() + + msg := crypto.CRandBytes(128) + sig, err := privKey.Sign(msg) + require.Nil(t, err) + + assert.True(t, pubKey.VerifyBytes(msg, sig)) + + // Mutate the signature, just one bit. + sigEd := sig.(secp256k1.SignatureSecp256k1) + sigEd[3] ^= byte(0x01) + sig = sigEd + + assert.False(t, pubKey.VerifyBytes(msg, sig)) +} + +// This test is intended to justify the removal of calls to the underlying library +// in creating the privkey. +func TestSecp256k1LoadPrivkeyAndSerializeIsIdentity(t *testing.T) { + numberOfTests := 256 + for i := 0; i < numberOfTests; i++ { + // Seed the test case with some random bytes + privKeyBytes := [32]byte{} + copy(privKeyBytes[:], crypto.CRandBytes(32)) + + // This function creates a private and public key in the underlying libraries format. + // The private key is basically calling new(big.Int).SetBytes(pk), which removes leading zero bytes + priv, _ := underlyingSecp256k1.PrivKeyFromBytes(underlyingSecp256k1.S256(), privKeyBytes[:]) + // this takes the bytes returned by `(big int).Bytes()`, and if the length is less than 32 bytes, + // pads the bytes from the left with zero bytes. Therefore these two functions composed + // result in the identity function on privKeyBytes, hence the following equality check + // always returning true. + serializedBytes := priv.Serialize() + require.Equal(t, privKeyBytes[:], serializedBytes) + } +} diff --git a/crypto/signature.go b/crypto/signature.go deleted file mode 100644 index ae447da64..000000000 --- a/crypto/signature.go +++ /dev/null @@ -1,90 +0,0 @@ -package crypto - -import ( - "fmt" - - "crypto/subtle" - - . "github.com/tendermint/tendermint/libs/common" -) - -func SignatureFromBytes(pubKeyBytes []byte) (pubKey Signature, err error) { - err = cdc.UnmarshalBinaryBare(pubKeyBytes, &pubKey) - return -} - -//---------------------------------------- - -type Signature interface { - Bytes() []byte - IsZero() bool - Equals(Signature) bool -} - -//------------------------------------- - -var _ Signature = SignatureEd25519{} - -const SignatureEd25519Size = 64 - -// Implements Signature -type SignatureEd25519 [SignatureEd25519Size]byte - -func (sig SignatureEd25519) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(sig) - if err != nil { - panic(err) - } - return bz -} - -func (sig SignatureEd25519) IsZero() bool { return len(sig) == 0 } - -func (sig SignatureEd25519) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } - -func (sig SignatureEd25519) Equals(other Signature) bool { - if otherEd, ok := other.(SignatureEd25519); ok { - return subtle.ConstantTimeCompare(sig[:], otherEd[:]) == 1 - } else { - return false - } -} - -func SignatureEd25519FromBytes(data []byte) Signature { - var sig SignatureEd25519 - copy(sig[:], data) - return sig -} - -//------------------------------------- - -var _ Signature = SignatureSecp256k1{} - -// Implements Signature -type SignatureSecp256k1 []byte - -func (sig SignatureSecp256k1) Bytes() []byte { - bz, err := cdc.MarshalBinaryBare(sig) - if err != nil { - panic(err) - } - return bz -} - -func (sig SignatureSecp256k1) IsZero() bool { return len(sig) == 0 } - -func (sig SignatureSecp256k1) String() string { return fmt.Sprintf("/%X.../", Fingerprint(sig[:])) } - -func (sig SignatureSecp256k1) Equals(other Signature) bool { - if otherSecp, ok := other.(SignatureSecp256k1); ok { - return subtle.ConstantTimeCompare(sig[:], otherSecp[:]) == 1 - } else { - return false - } -} - -func SignatureSecp256k1FromBytes(data []byte) Signature { - sig := make(SignatureSecp256k1, len(data)) - copy(sig[:], data) - return sig -} diff --git a/crypto/signature_test.go b/crypto/signature_test.go deleted file mode 100644 index d6ae2b7a9..000000000 --- a/crypto/signature_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package crypto - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestSignAndValidateEd25519(t *testing.T) { - - privKey := GenPrivKeyEd25519() - pubKey := privKey.PubKey() - - msg := CRandBytes(128) - sig, err := privKey.Sign(msg) - require.Nil(t, err) - - // Test the signature - assert.True(t, pubKey.VerifyBytes(msg, sig)) - - // Mutate the signature, just one bit. - sigEd := sig.(SignatureEd25519) - sigEd[7] ^= byte(0x01) - sig = sigEd - - assert.False(t, pubKey.VerifyBytes(msg, sig)) -} - -func TestSignAndValidateSecp256k1(t *testing.T) { - privKey := GenPrivKeySecp256k1() - pubKey := privKey.PubKey() - - msg := CRandBytes(128) - sig, err := privKey.Sign(msg) - require.Nil(t, err) - - assert.True(t, pubKey.VerifyBytes(msg, sig)) - - // Mutate the signature, just one bit. - sigEd := sig.(SignatureSecp256k1) - sigEd[3] ^= byte(0x01) - sig = sigEd - - assert.False(t, pubKey.VerifyBytes(msg, sig)) -} diff --git a/crypto/symmetric.go b/crypto/xsalsa20symmetric/symmetric.go similarity index 79% rename from crypto/symmetric.go rename to crypto/xsalsa20symmetric/symmetric.go index 62379c15f..d2369675d 100644 --- a/crypto/symmetric.go +++ b/crypto/xsalsa20symmetric/symmetric.go @@ -1,12 +1,15 @@ -package crypto +package xsalsa20symmetric import ( "errors" - . "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/crypto" + cmn "github.com/tendermint/tendermint/libs/common" "golang.org/x/crypto/nacl/secretbox" ) +// TODO, make this into a struct that implements crypto.Symmetric. + const nonceLen = 24 const secretLen = 32 @@ -15,9 +18,9 @@ const secretLen = 32 // NOTE: call crypto.MixEntropy() first. func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte) { if len(secret) != secretLen { - PanicSanity(Fmt("Secret must be 32 bytes long, got len %v", len(secret))) + cmn.PanicSanity(cmn.Fmt("Secret must be 32 bytes long, got len %v", len(secret))) } - nonce := CRandBytes(nonceLen) + nonce := crypto.CRandBytes(nonceLen) nonceArr := [nonceLen]byte{} copy(nonceArr[:], nonce) secretArr := [secretLen]byte{} @@ -32,7 +35,7 @@ func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte) { // The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error) { if len(secret) != secretLen { - PanicSanity(Fmt("Secret must be 32 bytes long, got len %v", len(secret))) + cmn.PanicSanity(cmn.Fmt("Secret must be 32 bytes long, got len %v", len(secret))) } if len(ciphertext) <= secretbox.Overhead+nonceLen { return nil, errors.New("Ciphertext is too short") diff --git a/crypto/symmetric_test.go b/crypto/xsalsa20symmetric/symmetric_test.go similarity index 81% rename from crypto/symmetric_test.go rename to crypto/xsalsa20symmetric/symmetric_test.go index d92bff1aa..d955307ea 100644 --- a/crypto/symmetric_test.go +++ b/crypto/xsalsa20symmetric/symmetric_test.go @@ -1,4 +1,4 @@ -package crypto +package xsalsa20symmetric import ( "testing" @@ -6,12 +6,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" "golang.org/x/crypto/bcrypt" ) func TestSimple(t *testing.T) { - MixEntropy([]byte("someentropy")) + crypto.MixEntropy([]byte("someentropy")) plaintext := []byte("sometext") secret := []byte("somesecretoflengththirtytwo===32") @@ -24,7 +25,7 @@ func TestSimple(t *testing.T) { func TestSimpleWithKDF(t *testing.T) { - MixEntropy([]byte("someentropy")) + crypto.MixEntropy([]byte("someentropy")) plaintext := []byte("sometext") secretPass := []byte("somesecret") @@ -32,7 +33,7 @@ func TestSimpleWithKDF(t *testing.T) { if err != nil { t.Error(err) } - secret = Sha256(secret) + secret = crypto.Sha256(secret) ciphertext := EncryptSymmetric(plaintext, secret) plaintext2, err := DecryptSymmetric(ciphertext, secret) diff --git a/docs/DOCS_README.md b/docs/DOCS_README.md new file mode 100644 index 000000000..016bac5e4 --- /dev/null +++ b/docs/DOCS_README.md @@ -0,0 +1,21 @@ +# Documentation Maintenance Overview + +The documentation found in this directory is hosted at: + +- https://tendermint.com/docs/ + +and built using [VuePress](https://vuepress.vuejs.org/) from the tendermint website repo: + +- https://github.com/tendermint/tendermint.com + +which has a [configuration file](https://github.com/tendermint/tendermint.com/blob/develop/docs/.vuepress/config.js) for displaying +the Table of Contents that lists all the documentation. + +Under the hood, Jenkins listens for changes in ./docs then pushes a `docs-staging` branch to the tendermint.com repo with the latest documentation. That branch must be manually PR'd to `develop` then `master` for staging then production. This process should happen in synchrony with a release. + +The `README.md` in this directory is the landing page for +website documentation and the following folders are intentionally +ommitted: + +- `architecture/` ==> contains Architecture Design Records +- `spec/` ==> contains the detailed specification diff --git a/docs/README.md b/docs/README.md index 0ed3aaec9..16ea708ad 100644 --- a/docs/README.md +++ b/docs/README.md @@ -11,18 +11,17 @@ replicates it on many machines. In other words, a blockchain. Tendermint requires an application running over the Application Blockchain Interface (ABCI) - and comes packaged with an example application to do so. -Follow the [installation instructions](./install) to get up and running -quickly. For more details on [using tendermint](./using-tendermint) see that +Follow the [installation instructions](./introduction/install) to get up and running +quickly. For more details on [using tendermint](./tendermint-core/using-tendermint) see that and the following sections. ## Networks Testnets can be setup manually on one or more machines, or automatically on one or more machine, using a variety of methods described in the [deploy testnets -section](./deploy-testnets). For more information (and to join) about the -Cosmos Network testnets, see [here](/getting-started/full-node.md). +section](./networks/deploy-testnets). ## Application Development The first step to building application on Tendermint is to [install -ABCI-CLI](./getting-started) and play with the example applications. +ABCI-CLI](./app-dev/getting-started) and play with the example applications. diff --git a/docs/abci-spec.md b/docs/abci-spec.md deleted file mode 100644 index f9677f448..000000000 --- a/docs/abci-spec.md +++ /dev/null @@ -1,324 +0,0 @@ -# ABCI Specification - -## Message Types - -ABCI requests/responses are defined as simple Protobuf messages in [this -schema file](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto). -TendermintCore sends the requests, and the ABCI application sends the -responses. Here, we provide an overview of the messages types and how -they 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. - -## Request/Response Messages - -### Echo - -- **Request**: - - `Message (string)`: A string to echo back -- **Response**: - - `Message (string)`: The input string -- **Usage**: - - Echo a string to test an abci client/server implementation - -### Flush - -- **Usage**: - - Signals that messages queued on the client should be flushed to - the server. It is called periodically by the client - implementation to ensure asynchronous requests are actually - sent, and is called immediately to make a synchronous request, - which returns when the Flush response comes back. - -### Info - -- **Request**: - - `Version (string)`: The Tendermint version -- **Response**: - - `Data (string)`: Some arbitrary information - - `Version (Version)`: Version information - - `LastBlockHeight (int64)`: Latest block for which the app has - called Commit - - `LastBlockAppHash ([]byte)`: Latest result of Commit -- **Usage**: - - Return information about the application state. - - Used to sync 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 - -- **Request**: - - `Key (string)`: Key to set - - `Value (string)`: Value to set for key -- **Response**: - - `Code (uint32)`: Response code - - `Log (string)`: The output of the application's logger. May - be non-deterministic. - - `Info (string)`: Additional information. May - be non-deterministic. -- **Usage**: - - Set non-consensus critical application specific options. - - e.g. Key="min-fee", Value="100fermion" could set the minimum fee - required for CheckTx (but not DeliverTx - that would be - consensus critical). - -### InitChain - -- **Request**: - - `Validators ([]Validator)`: Initial genesis validators - - `AppStateBytes ([]byte)`: Serialized initial application state -- **Response**: - - `ConsensusParams (ConsensusParams)`: Initial - consensus-critical parameters. - - `Validators ([]Validator)`: Initial validator set. -- **Usage**: - - Called once upon genesis. - -### Query - -- **Request**: - - `Data ([]byte)`: Raw query bytes. Can be used with or in lieu - of Path. - - `Path (string)`: Path of request, like an HTTP GET path. Can be - used with or in liue of Data. - - Apps MUST interpret '/store' as a query by key on the - underlying store. The key SHOULD be specified in the Data field. - - Apps SHOULD allow queries over specific types like - '/accounts/...' or '/votes/...' - - `Height (int64)`: The block height for which you want the query - (default=0 returns data for the latest committed block). Note - that this is the height of the block containing the - application's Merkle root hash, which represents the state as it - was after committing the block at Height-1 - - `Prove (bool)`: Return Merkle proof with response if possible -- **Response**: - - `Code (uint32)`: Response code. - - `Log (string)`: The output of the application's logger. May - be non-deterministic. - - `Info (string)`: Additional information. May - be non-deterministic. - - `Index (int64)`: The index of the key in the tree. - - `Key ([]byte)`: The key of the matching data. - - `Value ([]byte)`: The value of the matching data. - - `Proof ([]byte)`: Proof for the data, if requested. - - `Height (int64)`: The block height from which data was derived. - Note that this is the height of the block containing the - application's Merkle root hash, which represents the state as it - was after committing the block at Height-1 -- **Usage**: - - Query for data from the application at current or past height. - - Optionally return Merkle proof. - -### BeginBlock - -- **Request**: - - `Hash ([]byte)`: The block's hash. This can be derived from the - block header. - - `Header (struct{})`: The block header - - `Validators ([]SigningValidator)`: List of validators in the current validator - set and whether or not they signed a vote in the LastCommit - - `ByzantineValidators ([]Evidence)`: List of evidence of - validators that acted maliciously -- **Response**: - - `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing -- **Usage**: - - Signals the beginning of a new block. Called prior to - any DeliverTxs. - - The header is expected to at least contain the Height. - - The `Validators` and `ByzantineValidators` can be used to - determine rewards and punishments for the validators. - -### CheckTx - -- **Request**: - - `Tx ([]byte)`: The request transaction bytes -- **Response**: - - `Code (uint32)`: Response code - - `Data ([]byte)`: Result bytes, if any. - - `Log (string)`: The output of the application's logger. May - be non-deterministic. - - `Info (string)`: Additional information. May - be non-deterministic. - - `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). - - `Fee (cmn.KI64Pair)`: Fee paid for the transaction. -- **Usage**: Validate a mempool transaction, prior to broadcasting - or proposing. CheckTx should perform stateful but light-weight - checks of the validity of the transaction (like checking signatures - and account balances), but need not execute in full (like running a - smart contract). - - Tendermint runs CheckTx and DeliverTx concurrently with eachother, - though on distinct ABCI connections - the mempool connection and the - consensus connection, respectively. - - The application should maintain a separate state to support CheckTx. - 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. - - Keys and values in Tags must be UTF-8 encoded strings (e.g. - "account.owner": "Bob", "balance": "100.0", "date": "2018-01-02") - -### DeliverTx - -- **Request**: - - `Tx ([]byte)`: The request transaction bytes. -- **Response**: - - `Code (uint32)`: Response code. - - `Data ([]byte)`: Result bytes, if any. - - `Log (string)`: The output of the application's logger. May - be non-deterministic. - - `Info (string)`: Additional information. May - be non-deterministic. - - `GasWanted (int64)`: Amount of gas requested for transaction. - - `GasUsed (int64)`: Amount of gas consumed by transaction. - - `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing - transactions (eg. by account). - - `Fee (cmn.KI64Pair)`: Fee paid for the transaction. -- **Usage**: - - Deliver a transaction to be executed in full by the application. - If the transaction is valid, returns CodeType.OK. - - Keys and values in Tags must be UTF-8 encoded strings (e.g. - "account.owner": "Bob", "balance": "100.0", - "time": "2018-01-02T12:30:00Z") - -### EndBlock - -- **Request**: - - `Height (int64)`: Height of the block just executed. -- **Response**: - - `ValidatorUpdates ([]Validator)`: Changes to validator set (set - voting power to 0 to remove). - - `ConsensusParamUpdates (ConsensusParams)`: Changes to - consensus-critical time, size, and other parameters. - - `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing -- **Usage**: - - Signals the end of a block. - - Called prior to each Commit, after all transactions. - - Validator set and consensus params are updated with the result. - - Validator pubkeys are expected to be go-wire encoded. - -### Commit - -- **Response**: - - `Data ([]byte)`: The Merkle root hash -- **Usage**: - - Persist the application state. - - Return a Merkle root hash of the application state. - - It's critical that all application instances return the - same hash. If not, they will not be able to agree on the next - block, because the hash is included in the next block! - -## Data Messages - -### Header - -- **Fields**: - - `ChainID (string)`: ID of the blockchain - - `Height (int64)`: Height of the block in the chain - - `Time (int64)`: Unix time of the block - - `NumTxs (int32)`: Number of transactions in the block - - `TotalTxs (int64)`: Total number of transactions in the blockchain until - now - - `LastBlockHash ([]byte)`: Hash of the previous (parent) block - - `ValidatorsHash ([]byte)`: Hash of the validator set for this block - - `AppHash ([]byte)`: Data returned by the last call to `Commit` - typically the - Merkle root of the application state after executing the previous block's - transactions - - `Proposer (Validator)`: Original proposer for the block -- **Usage**: - - Provided in RequestBeginBlock - - Provides important context about the current state of the blockchain - - especially height and time. - - Provides the proposer of the current block, for use in proposer-based - reward mechanisms. - -### Validator - -- **Fields**: - - `Address ([]byte)`: Address of the validator (hash of the public key) - - `PubKey (PubKey)`: Public key of the validator - - `Power (int64)`: Voting power of the validator -- **Usage**: - - Provides all identifying information about the validator - -### SigningValidator - -- **Fields**: - - `Validator (Validator)`: A validator - - `SignedLastBlock (bool)`: Indicated whether or not the validator signed - the last block -- **Usage**: - - Indicates whether a validator signed the last block, allowing for rewards - based on validator availability - -### PubKey - -- **Fields**: - - `Type (string)`: Type of the public key. A simple string like `"ed25519"`. - In the future, may indicate a serialization algorithm to parse the `Data`, - for instance `"amino"`. - - `Data ([]byte)`: Public key data. For a simple public key, it's just the - raw bytes. If the `Type` indicates an encoding algorithm, this is the - encoded public key. -- **Usage**: - - A generic and extensible typed public key - -### Evidence - -- **Fields**: - - `Type (string)`: Type of the evidence. A hierarchical path like - "duplicate/vote". - - `Validator (Validator`: The offending validator - - `Height (int64)`: Height when the offense was committed - - `Time (int64)`: Unix time of the block at height `Height` - - `TotalVotingPower (int64)`: Total voting power of the validator set at - height `Height` diff --git a/docs/abci-cli.md b/docs/app-dev/abci-cli.md similarity index 55% rename from docs/abci-cli.md rename to docs/app-dev/abci-cli.md index 246e8b1a2..4f9019fda 100644 --- a/docs/abci-cli.md +++ b/docs/app-dev/abci-cli.md @@ -10,41 +10,47 @@ Make sure you [have Go installed](https://golang.org/doc/install). Next, install the `abci-cli` tool and example applications: - go get github.com/tendermint/tendermint +``` +go get github.com/tendermint/tendermint +``` to get vendored dependencies: - cd $GOPATH/src/github.com/tendermint/tendermint - make get_tools - make get_vendor_deps - make install_abci +``` +cd $GOPATH/src/github.com/tendermint/tendermint +make get_tools +make get_vendor_deps +make install_abci +``` Now run `abci-cli` to see the list of commands: - Usage: - abci-cli [command] - - Available Commands: - batch Run a batch of abci commands against an application - check_tx Validate a tx - commit Commit the application state and return the Merkle root hash - console Start an interactive abci console for multiple commands - counter ABCI demo example - deliver_tx Deliver a new tx to the application - kvstore ABCI demo example - echo Have the application echo a message - help Help about any command - info Get some info about the application - query Query the application state - set_option Set an options on the application - - Flags: - --abci string socket or grpc (default "socket") - --address string address of application socket (default "tcp://127.0.0.1:26658") - -h, --help help for abci-cli - -v, --verbose print the command and results as if it were a console session - - Use "abci-cli [command] --help" for more information about a command. +``` +Usage: + abci-cli [command] + +Available Commands: + batch Run a batch of abci commands against an application + check_tx Validate a tx + commit Commit the application state and return the Merkle root hash + console Start an interactive abci console for multiple commands + counter ABCI demo example + deliver_tx Deliver a new tx to the application + kvstore ABCI demo example + echo Have the application echo a message + help Help about any command + info Get some info about the application + query Query the application state + set_option Set an options on the application + +Flags: + --abci string socket or grpc (default "socket") + --address string address of application socket (default "tcp://127.0.0.1:26658") + -h, --help help for abci-cli + -v, --verbose print the command and results as if it were a console session + +Use "abci-cli [command] --help" for more information about a command. +``` ## KVStore - First Example @@ -63,59 +69,69 @@ Its code can be found [here](https://github.com/tendermint/tendermint/blob/develop/abci/cmd/abci-cli/abci-cli.go) and looks like: - func cmdKVStore(cmd *cobra.Command, args []string) error { - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - - // Create the application - in memory or persisted to disk - var app types.Application - if flagPersist == "" { - app = kvstore.NewKVStoreApplication() - } else { - app = kvstore.NewPersistentKVStoreApplication(flagPersist) - app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore")) - } - - // Start the listener - srv, err := server.NewServer(flagAddrD, flagAbci, app) - if err != nil { - return err - } - srv.SetLogger(logger.With("module", "abci-server")) - if err := srv.Start(); err != nil { - return err - } - - // Wait forever - cmn.TrapSignal(func() { - // Cleanup - srv.Stop() - }) - return nil +``` +func cmdKVStore(cmd *cobra.Command, args []string) error { + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + + // Create the application - in memory or persisted to disk + var app types.Application + if flagPersist == "" { + app = kvstore.NewKVStoreApplication() + } else { + app = kvstore.NewPersistentKVStoreApplication(flagPersist) + app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore")) } + // Start the listener + srv, err := server.NewServer(flagAddrD, flagAbci, app) + if err != nil { + return err + } + srv.SetLogger(logger.With("module", "abci-server")) + if err := srv.Start(); err != nil { + return err + } + + // Wait forever + cmn.TrapSignal(func() { + // Cleanup + srv.Stop() + }) + return nil +} +``` + Start by running: - abci-cli kvstore +``` +abci-cli kvstore +``` And in another terminal, run - abci-cli echo hello - abci-cli info +``` +abci-cli echo hello +abci-cli info +``` You'll see something like: - -> data: hello - -> data.hex: 68656C6C6F +``` +-> data: hello +-> data.hex: 68656C6C6F +``` and: - -> data: {"size":0} - -> data.hex: 7B2273697A65223A307D +``` +-> data: {"size":0} +-> data.hex: 7B2273697A65223A307D +``` An ABCI application must provide two things: -- a socket server -- a handler for ABCI messages +- a socket server +- a handler for ABCI messages When we run the `abci-cli` tool we open a new connection to the application's socket server, send the given ABCI message, and wait for a @@ -144,52 +160,54 @@ speaking ABCI messages to your application. Try running these commands: - > echo hello - -> code: OK - -> data: hello - -> data.hex: 0x68656C6C6F - - > info - -> code: OK - -> data: {"size":0} - -> data.hex: 0x7B2273697A65223A307D - - > commit - -> code: OK - -> data.hex: 0x0000000000000000 - - > deliver_tx "abc" - -> code: OK - - > info - -> code: OK - -> data: {"size":1} - -> data.hex: 0x7B2273697A65223A317D - - > commit - -> code: OK - -> data.hex: 0x0200000000000000 - - > query "abc" - -> code: OK - -> log: exists - -> height: 0 - -> value: abc - -> value.hex: 616263 - - > deliver_tx "def=xyz" - -> code: OK - - > commit - -> code: OK - -> data.hex: 0x0400000000000000 - - > query "def" - -> code: OK - -> log: exists - -> height: 0 - -> value: xyz - -> value.hex: 78797A +``` +> echo hello +-> code: OK +-> data: hello +-> data.hex: 0x68656C6C6F + +> info +-> code: OK +-> data: {"size":0} +-> data.hex: 0x7B2273697A65223A307D + +> commit +-> code: OK +-> data.hex: 0x0000000000000000 + +> deliver_tx "abc" +-> code: OK + +> info +-> code: OK +-> data: {"size":1} +-> data.hex: 0x7B2273697A65223A317D + +> commit +-> code: OK +-> data.hex: 0x0200000000000000 + +> query "abc" +-> code: OK +-> log: exists +-> height: 0 +-> value: abc +-> value.hex: 616263 + +> deliver_tx "def=xyz" +-> code: OK + +> commit +-> code: OK +-> data.hex: 0x0400000000000000 + +> query "def" +-> code: OK +-> log: exists +-> height: 0 +-> value: xyz +-> value.hex: 78797A +``` Note that if we do `deliver_tx "abc"` it will store `(abc, abc)`, but if we do `deliver_tx "abc=efg"` it will store `(abc, efg)`. @@ -206,29 +224,31 @@ Like the kvstore app, its code can be found [here](https://github.com/tendermint/tendermint/blob/master/abci/cmd/abci-cli/abci-cli.go) and looks like: - func cmdCounter(cmd *cobra.Command, args []string) error { - - app := counter.NewCounterApplication(flagSerial) - - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - - // Start the listener - srv, err := server.NewServer(flagAddrC, flagAbci, app) - if err != nil { - return err - } - srv.SetLogger(logger.With("module", "abci-server")) - if err := srv.Start(); err != nil { - return err - } - - // Wait forever - cmn.TrapSignal(func() { - // Cleanup - srv.Stop() - }) - return nil +``` +func cmdCounter(cmd *cobra.Command, args []string) error { + + app := counter.NewCounterApplication(flagSerial) + + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + + // Start the listener + srv, err := server.NewServer(flagAddrC, flagAbci, app) + if err != nil { + return err } + srv.SetLogger(logger.With("module", "abci-server")) + if err := srv.Start(); err != nil { + return err + } + + // Wait forever + cmn.TrapSignal(func() { + // Cleanup + srv.Stop() + }) + return nil +} +``` The counter app doesn't use a Merkle tree, it just counts how many times we've sent a transaction, asked for a hash, or committed the state. The @@ -256,38 +276,42 @@ whose integer is greater than the last committed one. Let's kill the console and the kvstore application, and start the counter app: - abci-cli counter +``` +abci-cli counter +``` In another window, start the `abci-cli console`: - > set_option serial on - -> code: OK - -> log: OK (SetOption doesn't return anything.) +``` +> set_option serial on +-> code: OK +-> log: OK (SetOption doesn't return anything.) - > check_tx 0x00 - -> code: OK +> check_tx 0x00 +-> code: OK - > check_tx 0xff - -> code: OK +> check_tx 0xff +-> code: OK - > deliver_tx 0x00 - -> code: OK +> deliver_tx 0x00 +-> code: OK - > check_tx 0x00 - -> code: BadNonce - -> log: Invalid nonce. Expected >= 1, got 0 +> check_tx 0x00 +-> code: BadNonce +-> log: Invalid nonce. Expected >= 1, got 0 - > deliver_tx 0x01 - -> code: OK +> deliver_tx 0x01 +-> code: OK - > deliver_tx 0x04 - -> code: BadNonce - -> log: Invalid nonce. Expected 2, got 4 +> deliver_tx 0x04 +-> code: BadNonce +-> log: Invalid nonce. Expected 2, got 4 - > info - -> code: OK - -> data: {"hashes":0,"txs":2} - -> data.hex: 0x7B22686173686573223A302C22747873223A327D +> info +-> code: OK +-> data: {"hashes":0,"txs":2} +-> data.hex: 0x7B22686173686573223A302C22747873223A327D +``` This is a very simple application, but between `counter` and `kvstore`, its easy to see how you can build out arbitrary application states on @@ -304,7 +328,9 @@ example directory](https://github.com/tendermint/tendermint/tree/develop/abci/ex To run the Node JS version, `cd` to `example/js` and run - node app.js +``` +node app.js +``` (you'll have to kill the other counter application process). In another window, run the console and those previous ABCI commands. You should get diff --git a/docs/app-dev/abci-spec.md b/docs/app-dev/abci-spec.md new file mode 100644 index 000000000..ef274a4e8 --- /dev/null +++ b/docs/app-dev/abci-spec.md @@ -0,0 +1,325 @@ +# ABCI Specification + +## Message Types + +ABCI requests/responses are defined as simple Protobuf messages in [this +schema file](https://github.com/tendermint/tendermint/blob/master/abci/types/types.proto). +TendermintCore sends the requests, and the ABCI application sends the +responses. Here, we provide an overview of the messages types and how +they 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. + +## Request/Response Messages + +### Echo + +- **Request**: + - `Message (string)`: A string to echo back +- **Response**: + - `Message (string)`: The input string +- **Usage**: + - Echo a string to test an abci client/server implementation + +### Flush + +- **Usage**: + - Signals that messages queued on the client should be flushed to + the server. It is called periodically by the client + implementation to ensure asynchronous requests are actually + sent, and is called immediately to make a synchronous request, + which returns when the Flush response comes back. + +### Info + +- **Request**: + - `Version (string)`: The Tendermint version +- **Response**: + - `Data (string)`: Some arbitrary information + - `Version (Version)`: Version information + - `LastBlockHeight (int64)`: Latest block for which the app has + called Commit + - `LastBlockAppHash ([]byte)`: Latest result of Commit +- **Usage**: + - Return information about the application state. + - Used to sync 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 + +- **Request**: + - `Key (string)`: Key to set + - `Value (string)`: Value to set for key +- **Response**: + - `Code (uint32)`: Response code + - `Log (string)`: The output of the application's logger. May + be non-deterministic. + - `Info (string)`: Additional information. May + be non-deterministic. +- **Usage**: + - Set non-consensus critical application specific options. + - e.g. Key="min-fee", Value="100fermion" could set the minimum fee + required for CheckTx (but not DeliverTx - that would be + consensus critical). + +### InitChain + +- **Request**: + - `Validators ([]Validator)`: Initial genesis validators + - `AppStateBytes ([]byte)`: Serialized initial application state +- **Response**: + - `ConsensusParams (ConsensusParams)`: Initial + consensus-critical parameters. + - `Validators ([]Validator)`: Initial validator set. +- **Usage**: + - Called once upon genesis. + +### Query + +- **Request**: + - `Data ([]byte)`: Raw query bytes. Can be used with or in lieu + of Path. + - `Path (string)`: Path of request, like an HTTP GET path. Can be + used with or in liue of Data. + - Apps MUST interpret '/store' as a query by key on the + underlying store. The key SHOULD be specified in the Data field. + - Apps SHOULD allow queries over specific types like + '/accounts/...' or '/votes/...' + - `Height (int64)`: The block height for which you want the query + (default=0 returns data for the latest committed block). Note + that this is the height of the block containing the + application's Merkle root hash, which represents the state as it + was after committing the block at Height-1 + - `Prove (bool)`: Return Merkle proof with response if possible +- **Response**: + - `Code (uint32)`: Response code. + - `Log (string)`: The output of the application's logger. May + be non-deterministic. + - `Info (string)`: Additional information. May + be non-deterministic. + - `Index (int64)`: The index of the key in the tree. + - `Key ([]byte)`: The key of the matching data. + - `Value ([]byte)`: The value of the matching data. + - `Proof ([]byte)`: Proof for the data, if requested. + - `Height (int64)`: The block height from which data was derived. + Note that this is the height of the block containing the + application's Merkle root hash, which represents the state as it + was after committing the block at Height-1 +- **Usage**: + - Query for data from the application at current or past height. + - Optionally return Merkle proof. + +### BeginBlock + +- **Request**: + - `Hash ([]byte)`: The block's hash. This can be derived from the + block header. + - `Header (struct{})`: The block header + - `Validators ([]SigningValidator)`: List of validators in the current validator + set and whether or not they signed a vote in the LastCommit + - `ByzantineValidators ([]Evidence)`: List of evidence of + validators that acted maliciously +- **Response**: + - `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing +- **Usage**: + - Signals the beginning of a new block. Called prior to + any DeliverTxs. + - The header is expected to at least contain the Height. + - The `Validators` and `ByzantineValidators` can be used to + determine rewards and punishments for the validators. + +### CheckTx + +- **Request**: + - `Tx ([]byte)`: The request transaction bytes +- **Response**: + - `Code (uint32)`: Response code + - `Data ([]byte)`: Result bytes, if any. + - `Log (string)`: The output of the application's logger. May + be non-deterministic. + - `Info (string)`: Additional information. May + be non-deterministic. + - `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). + - `Fee (cmn.KI64Pair)`: Fee paid for the transaction. +- **Usage**: Validate a mempool transaction, prior to broadcasting + or proposing. CheckTx should perform stateful but light-weight + checks of the validity of the transaction (like checking signatures + and account balances), but need not execute in full (like running a + smart contract). + + Tendermint runs CheckTx and DeliverTx concurrently with eachother, + though on distinct ABCI connections - the mempool connection and the + consensus connection, respectively. + + The application should maintain a separate state to support CheckTx. + This state can be reset to the latest committed state during + `Commit`. Before calling Commit, Tendermint will lock and flush the mempool, + ensuring that all existing CheckTx are responded to and no new ones can + begin. After `Commit`, the mempool will rerun + CheckTx for all remaining transactions, throwing out any that are no longer valid. + Then the mempool will unlock and start sending CheckTx again. + + Keys and values in Tags must be UTF-8 encoded strings (e.g. + "account.owner": "Bob", "balance": "100.0", "date": "2018-01-02") + +### DeliverTx + +- **Request**: + - `Tx ([]byte)`: The request transaction bytes. +- **Response**: + - `Code (uint32)`: Response code. + - `Data ([]byte)`: Result bytes, if any. + - `Log (string)`: The output of the application's logger. May + be non-deterministic. + - `Info (string)`: Additional information. May + be non-deterministic. + - `GasWanted (int64)`: Amount of gas requested for transaction. + - `GasUsed (int64)`: Amount of gas consumed by transaction. + - `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing + transactions (eg. by account). + - `Fee (cmn.KI64Pair)`: Fee paid for the transaction. +- **Usage**: + - Deliver a transaction to be executed in full by the application. + If the transaction is valid, returns CodeType.OK. + - Keys and values in Tags must be UTF-8 encoded strings (e.g. + "account.owner": "Bob", "balance": "100.0", + "time": "2018-01-02T12:30:00Z") + +### EndBlock + +- **Request**: + - `Height (int64)`: Height of the block just executed. +- **Response**: + - `ValidatorUpdates ([]Validator)`: Changes to validator set (set + voting power to 0 to remove). + - `ConsensusParamUpdates (ConsensusParams)`: Changes to + consensus-critical time, size, and other parameters. + - `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing +- **Usage**: + - Signals the end of a block. + - Called prior to each Commit, after all transactions. + - Validator set and consensus params are updated with the result. + - Validator pubkeys are expected to be go-wire encoded. + +### Commit + +- **Response**: + - `Data ([]byte)`: The Merkle root hash +- **Usage**: + - Persist the application state. + - Return a Merkle root hash of the application state. + - It's critical that all application instances return the + same hash. If not, they will not be able to agree on the next + block, because the hash is included in the next block! + +## Data Messages + +### Header + +- **Fields**: + - `ChainID (string)`: ID of the blockchain + - `Height (int64)`: Height of the block in the chain + - `Time (int64)`: Unix time of the block + - `NumTxs (int32)`: Number of transactions in the block + - `TotalTxs (int64)`: Total number of transactions in the blockchain until + now + - `LastBlockHash ([]byte)`: Hash of the previous (parent) block + - `ValidatorsHash ([]byte)`: Hash of the validator set for this block + - `AppHash ([]byte)`: Data returned by the last call to `Commit` - typically the + Merkle root of the application state after executing the previous block's + transactions + - `Proposer (Validator)`: Original proposer for the block +- **Usage**: + - Provided in RequestBeginBlock + - Provides important context about the current state of the blockchain - + especially height and time. + - Provides the proposer of the current block, for use in proposer-based + reward mechanisms. + +### Validator + +- **Fields**: + - `Address ([]byte)`: Address of the validator (hash of the public key) + - `PubKey (PubKey)`: Public key of the validator + - `Power (int64)`: Voting power of the validator +- **Usage**: + - Provides all identifying information about the validator + +### SigningValidator + +- **Fields**: + - `Validator (Validator)`: A validator + - `SignedLastBlock (bool)`: Indicated whether or not the validator signed + the last block +- **Usage**: + - Indicates whether a validator signed the last block, allowing for rewards + based on validator availability + +### PubKey + +- **Fields**: + - `Type (string)`: Type of the public key. A simple string like `"ed25519"`. + In the future, may indicate a serialization algorithm to parse the `Data`, + for instance `"amino"`. + - `Data ([]byte)`: Public key data. For a simple public key, it's just the + raw bytes. If the `Type` indicates an encoding algorithm, this is the + encoded public key. +- **Usage**: + - A generic and extensible typed public key + +### Evidence + +- **Fields**: + - `Type (string)`: Type of the evidence. A hierarchical path like + "duplicate/vote". + - `Validator (Validator`: The offending validator + - `Height (int64)`: Height when the offense was committed + - `Time (int64)`: Unix time of the block at height `Height` + - `TotalVotingPower (int64)`: Total voting power of the validator set at + height `Height` diff --git a/docs/app-architecture.md b/docs/app-dev/app-architecture.md similarity index 97% rename from docs/app-architecture.md rename to docs/app-dev/app-architecture.md index 401e28cca..9ce0fae9f 100644 --- a/docs/app-architecture.md +++ b/docs/app-dev/app-architecture.md @@ -17,7 +17,7 @@ transaction is actually processed. The ABCI application must be a deterministic result of the Tendermint consensus - any external influence on the application state that didn't -come through Tendermint could cause a consensus failure. Thus *nothing* +come through Tendermint could cause a consensus failure. Thus _nothing_ should communicate with the application except Tendermint via ABCI. If the application is written in Go, it can be compiled into the @@ -43,6 +43,7 @@ all transactions, and possibly all queries, should still pass through Tendermint. See the following for more extensive documentation: + - [Interchain Standard for the Light-Client REST API](https://github.com/cosmos/cosmos-sdk/pull/1028) - [Tendermint RPC Docs](https://tendermint.github.io/slate/) - [Tendermint in Production](https://github.com/tendermint/tendermint/pull/1618) diff --git a/docs/app-development.md b/docs/app-dev/app-development.md similarity index 62% rename from docs/app-development.md rename to docs/app-dev/app-development.md index f8c70f21b..a795673f1 100644 --- a/docs/app-development.md +++ b/docs/app-dev/app-development.md @@ -16,28 +16,27 @@ committed in hash-linked blocks. The ABCI design has a few distinct components: -- message protocol - - pairs of request and response messages - - consensus makes requests, application responds - - defined using protobuf -- server/client - - consensus engine runs the client - - application runs the server - - two implementations: - - async raw bytes - - grpc -- blockchain protocol - - abci is connection oriented - - Tendermint Core maintains three connections: - - [mempool connection](#mempool-connection): for checking if - transactions should be relayed before they are committed; - only uses `CheckTx` - - [consensus connection](#consensus-connection): for executing - transactions that have been committed. Message sequence is - -for every block - -`BeginBlock, [DeliverTx, ...], EndBlock, Commit` - - [query connection](#query-connection): for querying the - application state; only uses Query and Info +- message protocol + - pairs of request and response messages + - consensus makes requests, application responds + - defined using protobuf +- server/client + - consensus engine runs the client + - application runs the server + - two implementations: + - async raw bytes + - grpc +- blockchain protocol + - abci is connection oriented + - Tendermint Core maintains three connections: + - [mempool connection](#mempool-connection): for checking if + transactions should be relayed before they are committed; + only uses `CheckTx` + - [consensus connection](#consensus-connection): for executing + transactions that have been committed. Message sequence is + -for every block -`BeginBlock, [DeliverTx, ...], EndBlock, Commit` + - [query connection](#query-connection): for querying the + application state; only uses Query and Info The mempool and consensus logic act as clients, and each maintains an open ABCI connection with the application, which hosts an ABCI server. @@ -64,9 +63,9 @@ To use ABCI in your programming language of choice, there must be a ABCI server in that language. Tendermint supports two kinds of implementation of the server: -- Asynchronous, raw socket server (Tendermint Socket Protocol, also - known as TSP or Teaspoon) -- GRPC +- Asynchronous, raw socket server (Tendermint Socket Protocol, also + known as TSP or Teaspoon) +- GRPC Both can be tested using the `abci-cli` by setting the `--abci` flag appropriately (ie. to `socket` or `grpc`). @@ -161,7 +160,7 @@ connection, to query the local state of the app. ### Mempool Connection -The mempool connection is used *only* for CheckTx requests. Transactions +The mempool connection is used _only_ for CheckTx requests. Transactions are run using CheckTx in the same order they were received by the validator. If the CheckTx returns `OK`, the transaction is kept in memory and relayed to other peers in the same order it was received. @@ -180,23 +179,27 @@ mempool state (this behaviour can be turned off with In go: - func (app *KVStoreApplication) CheckTx(tx []byte) types.Result { - return types.OK - } +``` +func (app *KVStoreApplication) CheckTx(tx []byte) types.Result { + return types.OK +} +``` In Java: - ResponseCheckTx requestCheckTx(RequestCheckTx req) { - byte[] transaction = req.getTx().toByteArray(); +``` +ResponseCheckTx requestCheckTx(RequestCheckTx req) { + byte[] transaction = req.getTx().toByteArray(); - // validate transaction + // validate transaction - if (notValid) { - return ResponseCheckTx.newBuilder().setCode(CodeType.BadNonce).setLog("invalid tx").build(); - } else { - return ResponseCheckTx.newBuilder().setCode(CodeType.OK).build(); - } + if (notValid) { + return ResponseCheckTx.newBuilder().setCode(CodeType.BadNonce).setLog("invalid tx").build(); + } else { + return ResponseCheckTx.newBuilder().setCode(CodeType.OK).build(); } +} +``` ### Replay Protection @@ -242,43 +245,47 @@ merkle root of the data returned by the DeliverTx requests, or both. In go: - // tx is either "key=value" or just arbitrary bytes - func (app *KVStoreApplication) DeliverTx(tx []byte) types.Result { - parts := strings.Split(string(tx), "=") - if len(parts) == 2 { - app.state.Set([]byte(parts[0]), []byte(parts[1])) - } else { - app.state.Set(tx, tx) - } - return types.OK - } +``` +// tx is either "key=value" or just arbitrary bytes +func (app *KVStoreApplication) DeliverTx(tx []byte) types.Result { + parts := strings.Split(string(tx), "=") + if len(parts) == 2 { + app.state.Set([]byte(parts[0]), []byte(parts[1])) + } else { + app.state.Set(tx, tx) + } + return types.OK +} +``` In Java: - /** - * Using Protobuf types from the protoc compiler, we always start with a byte[] - */ - ResponseDeliverTx deliverTx(RequestDeliverTx request) { - byte[] transaction = request.getTx().toByteArray(); +``` +/** + * Using Protobuf types from the protoc compiler, we always start with a byte[] + */ +ResponseDeliverTx deliverTx(RequestDeliverTx request) { + byte[] transaction = request.getTx().toByteArray(); - // validate your transaction - - if (notValid) { - return ResponseDeliverTx.newBuilder().setCode(CodeType.BadNonce).setLog("transaction was invalid").build(); - } else { - ResponseDeliverTx.newBuilder().setCode(CodeType.OK).build(); - } + // validate your transaction + if (notValid) { + return ResponseDeliverTx.newBuilder().setCode(CodeType.BadNonce).setLog("transaction was invalid").build(); + } else { + ResponseDeliverTx.newBuilder().setCode(CodeType.OK).build(); } +} +``` + ### Commit Once all processing of the block is complete, Tendermint sends the Commit request and blocks waiting for a response. While the mempool may run concurrently with block processing (the BeginBlock, DeliverTxs, and EndBlock), it is locked for the Commit request so that its state can be -safely reset during Commit. This means the app *MUST NOT* do any -blocking communication with the mempool (ie. broadcast\_tx) during +safely reset during Commit. This means the app _MUST NOT_ do any +blocking communication with the mempool (ie. broadcast_tx) during Commit, or there will be deadlock. Note also that all remaining transactions in the mempool are replayed on the mempool connection (CheckTx) following a commit. @@ -294,21 +301,25 @@ job of the [Handshake](#handshake). In go: - func (app *KVStoreApplication) Commit() types.Result { - hash := app.state.Hash() - return types.NewResultOK(hash, "") - } +``` +func (app *KVStoreApplication) Commit() types.Result { + hash := app.state.Hash() + return types.NewResultOK(hash, "") +} +``` In Java: - ResponseCommit requestCommit(RequestCommit requestCommit) { +``` +ResponseCommit requestCommit(RequestCommit requestCommit) { - // update the internal app-state - byte[] newAppState = calculateAppState(); + // update the internal app-state + byte[] newAppState = calculateAppState(); - // and return it to the node - return ResponseCommit.newBuilder().setCode(CodeType.OK).setData(ByteString.copyFrom(newAppState)).build(); - } + // and return it to the node + return ResponseCommit.newBuilder().setCode(CodeType.OK).setData(ByteString.copyFrom(newAppState)).build(); +} +``` ### BeginBlock @@ -322,31 +333,35 @@ pick up from when it restarts. See information on the Handshake, below. In go: - // Track the block hash and header information - func (app *PersistentKVStoreApplication) BeginBlock(params types.RequestBeginBlock) { - // update latest block info - app.blockHeader = params.Header +``` +// Track the block hash and header information +func (app *PersistentKVStoreApplication) BeginBlock(params types.RequestBeginBlock) { + // update latest block info + app.blockHeader = params.Header - // reset valset changes - app.changes = make([]*types.Validator, 0) - } + // reset valset changes + app.changes = make([]*types.Validator, 0) +} +``` In Java: - /* - * all types come from protobuf definition - */ - ResponseBeginBlock requestBeginBlock(RequestBeginBlock req) { +``` +/* + * all types come from protobuf definition + */ +ResponseBeginBlock requestBeginBlock(RequestBeginBlock req) { - Header header = req.getHeader(); - byte[] prevAppHash = header.getAppHash().toByteArray(); - long prevHeight = header.getHeight(); - long numTxs = header.getNumTxs(); + Header header = req.getHeader(); + byte[] prevAppHash = header.getAppHash().toByteArray(); + long prevHeight = header.getHeight(); + long numTxs = header.getNumTxs(); - // run your pre-block logic. Maybe prepare a state snapshot, message components, etc + // run your pre-block logic. Maybe prepare a state snapshot, message components, etc - return ResponseBeginBlock.newBuilder().build(); - } + return ResponseBeginBlock.newBuilder().build(); +} +``` ### EndBlock @@ -364,25 +379,29 @@ for details on how it tracks validators. In go: - // Update the validator set - func (app *PersistentKVStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { - return types.ResponseEndBlock{ValidatorUpdates: app.ValUpdates} - } +``` +// Update the validator set +func (app *PersistentKVStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { + return types.ResponseEndBlock{ValidatorUpdates: app.ValUpdates} +} +``` In Java: - /* - * Assume that one validator changes. The new validator has a power of 10 - */ - ResponseEndBlock requestEndBlock(RequestEndBlock req) { - final long currentHeight = req.getHeight(); - final byte[] validatorPubKey = getValPubKey(); +``` +/* + * Assume that one validator changes. The new validator has a power of 10 + */ +ResponseEndBlock requestEndBlock(RequestEndBlock req) { + final long currentHeight = req.getHeight(); + final byte[] validatorPubKey = getValPubKey(); - ResponseEndBlock.Builder builder = ResponseEndBlock.newBuilder(); - builder.addDiffs(1, Types.Validator.newBuilder().setPower(10L).setPubKey(ByteString.copyFrom(validatorPubKey)).build()); + ResponseEndBlock.Builder builder = ResponseEndBlock.newBuilder(); + builder.addDiffs(1, Types.Validator.newBuilder().setPower(10L).setPubKey(ByteString.copyFrom(validatorPubKey)).build()); - return builder.build(); - } + return builder.build(); +} +``` ### Query Connection @@ -398,67 +417,71 @@ connecting, according to IP address or node ID. For instance, returning non-OK ABCI response to either of the following queries will cause Tendermint to not connect to the corresponding peer: -- `p2p/filter/addr/`, where `` is an IP address. -- `p2p/filter/id/`, where `` is the hex-encoded node ID (the hash of - the node's p2p pubkey). +- `p2p/filter/addr/`, where `` is an IP address. +- `p2p/filter/id/`, where `` is the hex-encoded node ID (the hash of + the node's p2p pubkey). Note: these query formats are subject to change! In go: - func (app *KVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { - if reqQuery.Prove { - value, proof, exists := app.state.Proof(reqQuery.Data) - resQuery.Index = -1 // TODO make Proof return index - resQuery.Key = reqQuery.Data - resQuery.Value = value - resQuery.Proof = proof - if exists { - resQuery.Log = "exists" - } else { - resQuery.Log = "does not exist" - } - return - } else { - index, value, exists := app.state.Get(reqQuery.Data) - resQuery.Index = int64(index) - resQuery.Value = value - if exists { - resQuery.Log = "exists" - } else { - resQuery.Log = "does not exist" - } - return - } +``` +func (app *KVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { + if reqQuery.Prove { + value, proof, exists := app.state.Proof(reqQuery.Data) + resQuery.Index = -1 // TODO make Proof return index + resQuery.Key = reqQuery.Data + resQuery.Value = value + resQuery.Proof = proof + if exists { + resQuery.Log = "exists" + } else { + resQuery.Log = "does not exist" } + return + } else { + index, value, exists := app.state.Get(reqQuery.Data) + resQuery.Index = int64(index) + resQuery.Value = value + if exists { + resQuery.Log = "exists" + } else { + resQuery.Log = "does not exist" + } + return + } +} +``` In Java: - ResponseQuery requestQuery(RequestQuery req) { - final boolean isProveQuery = req.getProve(); - final ResponseQuery.Builder responseBuilder = ResponseQuery.newBuilder(); - - if (isProveQuery) { - com.app.example.ProofResult proofResult = generateProof(req.getData().toByteArray()); - final byte[] proofAsByteArray = proofResult.getAsByteArray(); +``` +ResponseQuery requestQuery(RequestQuery req) { + final boolean isProveQuery = req.getProve(); + final ResponseQuery.Builder responseBuilder = ResponseQuery.newBuilder(); - responseBuilder.setProof(ByteString.copyFrom(proofAsByteArray)); - responseBuilder.setKey(req.getData()); - responseBuilder.setValue(ByteString.copyFrom(proofResult.getData())); - responseBuilder.setLog(result.getLogValue()); - } else { - byte[] queryData = req.getData().toByteArray(); + if (isProveQuery) { + com.app.example.ProofResult proofResult = generateProof(req.getData().toByteArray()); + final byte[] proofAsByteArray = proofResult.getAsByteArray(); - final com.app.example.QueryResult result = generateQueryResult(queryData); + responseBuilder.setProof(ByteString.copyFrom(proofAsByteArray)); + responseBuilder.setKey(req.getData()); + responseBuilder.setValue(ByteString.copyFrom(proofResult.getData())); + responseBuilder.setLog(result.getLogValue()); + } else { + byte[] queryData = req.getData().toByteArray(); - responseBuilder.setIndex(result.getIndex()); - responseBuilder.setValue(ByteString.copyFrom(result.getValue())); - responseBuilder.setLog(result.getLogValue()); - } + final com.app.example.QueryResult result = generateQueryResult(queryData); - return responseBuilder.build(); + responseBuilder.setIndex(result.getIndex()); + responseBuilder.setValue(ByteString.copyFrom(result.getValue())); + responseBuilder.setLog(result.getLogValue()); } + return responseBuilder.build(); +} +``` + ### Handshake When the app or tendermint restarts, they need to sync to a common @@ -477,17 +500,21 @@ all blocks. In go: - func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: cmn.Fmt("{\"size\":%v}", app.state.Size())} - } +``` +func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { + return types.ResponseInfo{Data: cmn.Fmt("{\"size\":%v}", app.state.Size())} +} +``` In Java: - ResponseInfo requestInfo(RequestInfo req) { - final byte[] lastAppHash = getLastAppHash(); - final long lastHeight = getLastHeight(); - return ResponseInfo.newBuilder().setLastBlockAppHash(ByteString.copyFrom(lastAppHash)).setLastBlockHeight(lastHeight).build(); - } +``` +ResponseInfo requestInfo(RequestInfo req) { + final byte[] lastAppHash = getLastAppHash(); + final long lastHeight = getLastHeight(); + return ResponseInfo.newBuilder().setLastBlockAppHash(ByteString.copyFrom(lastAppHash)).setLastBlockHeight(lastHeight).build(); +} +``` ### Genesis @@ -497,31 +524,35 @@ consensus params. In go: - // Save the validators in the merkle tree - func (app *PersistentKVStoreApplication) InitChain(params types.RequestInitChain) { - for _, v := range params.Validators { - r := app.updateValidator(v) - if r.IsErr() { - app.logger.Error("Error updating validators", "r", r) - } - } +``` +// Save the validators in the merkle tree +func (app *PersistentKVStoreApplication) InitChain(params types.RequestInitChain) { + for _, v := range params.Validators { + r := app.updateValidator(v) + if r.IsErr() { + app.logger.Error("Error updating validators", "r", r) } + } +} +``` In Java: - /* - * all types come from protobuf definition - */ - ResponseInitChain requestInitChain(RequestInitChain req) { - final int validatorsCount = req.getValidatorsCount(); - final List validatorsList = req.getValidatorsList(); +``` +/* + * all types come from protobuf definition + */ +ResponseInitChain requestInitChain(RequestInitChain req) { + final int validatorsCount = req.getValidatorsCount(); + final List validatorsList = req.getValidatorsList(); - validatorsList.forEach((validator) -> { - long power = validator.getPower(); - byte[] validatorPubKey = validator.getPubKey().toByteArray(); + validatorsList.forEach((validator) -> { + long power = validator.getPower(); + byte[] validatorPubKey = validator.getPubKey().toByteArray(); - // do somehing for validator setup in app - }); + // do somehing for validator setup in app + }); - return ResponseInitChain.newBuilder().build(); - } + return ResponseInitChain.newBuilder().build(); +} +``` diff --git a/docs/app-dev/ecosystem.json b/docs/app-dev/ecosystem.json new file mode 100644 index 000000000..363f18902 --- /dev/null +++ b/docs/app-dev/ecosystem.json @@ -0,0 +1,213 @@ +{ + "abciApps": [ + { + "name": "Cosmos SDK", + "url": "https://github.com/cosmos/cosmos-sdk", + "language": "Go", + "author": "Cosmos", + "description": + "A prototypical account based crypto currency state machine supporting plugins" + }, + { + "name": "cb-ledger", + "url": "https://github.com/block-finance/cpp-abci", + "language": "C++", + "author": "Block Finance", + "description": + "Custodian Bank Ledger, integrating central banking with the blockchains of tomorrow" + }, + { + "name": "Clearchain", + "url": "https://github.com/tendermint/clearchain", + "language": "Go", + "author": "FXCLR", + "description": + "Application to manage a distributed ledger for money transfers that support multi-currency accounts" + }, + { + "name": "Ethermint", + "url": "https://github.com/tendermint/ethermint", + "language": "Go", + "author": "Tendermint", + "description": "The go-ethereum state machine run as an ABCI app" + }, + { + "name": "Merkle AVL Tree", + "url": "https://github.com/tendermint/merkleeyes", + "language": "Go", + "author": "Tendermint", + "description": "Tendermint IAVL tree implemented as an ABCI app" + }, + { + "name": "Burrow", + "url": "https://github.com/hyperledger/burrow", + "language": "Go", + "author": "Monax Industries", + "description": + "Ethereum Virtual Machine augmented with native permissioning scheme and global key-value store" + }, + { + "name": "Merkle AVL Tree", + "url": "https://github.com/jTMSP/MerkleTree", + "language": "Java", + "author": "jTMSP", + "description": "Tendermint IAVL tree implemented as an ABCI app" + }, + { + "name": "TMChat", + "url": "https://github.com/wolfposd/TMChat", + "language": "Java", + "author": "jTMSP", + "description": "P2P chat using Tendermint" + }, + { + "name": "Comit", + "url": "https://github.com/zballs/comit", + "language": "Go", + "author": "Zach Balder", + "description": "Public service reporting and tracking" + }, + { + "name": "Passchain", + "url": "https://github.com/trusch/passchain", + "language": "Go", + "author": "trusch", + "description": + "Tool to securely store and share passwords, tokens and other short secrets" + }, + { + "name": "Passwerk", + "url": "https://github.com/rigelrozanski/passwerk", + "language": "Go", + "author": "Rigel Rozanski", + "description": "Encrypted storage web-utility backed by Tendermint" + }, + { + "name": "py-tendermint", + "url": "https://github.com/davebryson/py-tendermint", + "language": "Python", + "author": "Dave Bryson", + "description": + "A Python microframework for building blockchain applications with Tendermint" + }, + { + "name": "Stratumn SDK", + "url": "https://github.com/stratumn/sdk", + "language": "Go", + "author": "Stratumn", + "description": "SDK for Proof-of-Process networks" + }, + { + "name": "Lotion", + "url": "https://github.com/keppel/lotion", + "language": "Javascript", + "author": "Judd Keppel", + "description": + "A Javascript microframework for building blockchain applications with Tendermint" + }, + { + "name": "Tendermint Blockchain Chat App", + "url": "https://github.com/SaifRehman/tendermint-chat-app/", + "language": "Javascript", + "author": "Saif Rehman", + "description": + "This is a minimal chat application based on Tendermint using Lotion.js in 30 lines of code!. It also includes web/mobile application built using Ionic 3." + }, + { + "name": "BigchainDB", + "url": "https://github.com/bigchaindb/bigchaindb", + "language": "Python", + "author": "BigchainDB GmbH and the BigchainDB community", + "description": "Blockchain database" + }, + { + "name": "Mint", + "url": "https://github.com/Hashnode/mint", + "language": "Go", + "author": "Hashnode", + "description": "Build blockchain-powered social apps" + } + ], + "abciServers": [ + { + "name": "abci", + "url": "https://github.com/tendermint/abci", + "language": "Go", + "author": "Tendermint" + }, + { + "name": "js-abci", + "url": "https://github.com/tendermint/js-abci", + "language": "Javascript", + "author": "Tendermint" + }, + { + "name": "cpp-tmsp", + "url": "https://github.com/mdyring/cpp-tmsp", + "language": "C++", + "author": "Martin Dyring" + }, + { + "name": "jabci", + "url": "https://github.com/jTendermint/jabci", + "language": "Java", + "author": "jTendermint" + }, + { + "name": "ocaml-tmsp", + "url": "https://github.com/zballs/ocaml-tmsp", + "language": "Ocaml", + "author": "Zach Balder" + }, + { + "name": "abci_server", + "url": "https://github.com/KrzysiekJ/abci_server", + "language": "Erlang", + "author": "Krzysztof Jurewicz" + }, + { + "name": "py-abci", + "url": "https://github.com/davebryson/py-abci", + "language": "Python", + "author": "Dave Bryson" + }, + { + "name": "Spearmint", + "url": "https://github.com/dennismckinnon/spearmint", + "language": "Javascript", + "author": "Dennis McKinnon" + } + ], + "deploymentTools": [ + { + "name": "mintnet-kubernetes", + "url": "https://github.com/tendermint/tools", + "technology": "Docker and Kubernetes", + "author": "Tendermint", + "description": + "Deploy a Tendermint test network using Google's kubernetes" + }, + { + "name": "terraforce", + "url": "https://github.com/tendermint/tools", + "technology": "Terraform", + "author": "Tendermint", + "description": + "Terraform + our custom terraforce tool; deploy a production Tendermint network with load balancing over multiple AWS availability zones" + }, + { + "name": "ansible-tendermint", + "url": "https://github.com/tendermint/tools", + "technology": "Ansible", + "author": "Tendermint", + "description": "Ansible playbooks + Tendermint" + }, + { + "name": "brooklyn-tendermint", + "url": "https://github.com/cloudsoft/brooklyn-tendermint", + "technology": "Clocker for Apache Brooklyn ", + "author": "Cloudsoft", + "description": "Deploy a tendermint test network in docker containers " + } + ] +} diff --git a/docs/ecosystem.md b/docs/app-dev/ecosystem.md similarity index 83% rename from docs/ecosystem.md rename to docs/app-dev/ecosystem.md index 6b7f833a8..7960e6c0d 100644 --- a/docs/ecosystem.md +++ b/docs/app-dev/ecosystem.md @@ -3,11 +3,11 @@ The growing list of applications built using various pieces of the Tendermint stack can be found at: -- https://tendermint.com/ecosystem +- https://tendermint.com/ecosystem We thank the community for their contributions thus far and welcome the addition of new projects. A pull request can be submitted to [this -file](https://github.com/tendermint/aib-data/blob/master/json/ecosystem.json) +file](https://github.com/tendermint/tendermint/blob/master/docs/app-dev/ecosystem.json) to include your project. ## Other Tools diff --git a/docs/getting-started.md b/docs/app-dev/getting-started.md similarity index 69% rename from docs/getting-started.md rename to docs/app-dev/getting-started.md index 1fa1405f2..cfc614ddc 100644 --- a/docs/getting-started.md +++ b/docs/app-dev/getting-started.md @@ -25,11 +25,13 @@ more info. Then run - go get github.com/tendermint/tendermint - cd $GOPATH/src/github.com/tendermint/tendermint - make get_tools - make get_vendor_deps - make install_abci +``` +go get github.com/tendermint/tendermint +cd $GOPATH/src/github.com/tendermint/tendermint +make get_tools +make get_vendor_deps +make install_abci +``` Now you should have the `abci-cli` installed; you'll see a couple of commands (`counter` and `kvstore`) that are example applications written @@ -47,13 +49,17 @@ full transaction bytes are stored as the key and the value. Let's start a kvstore application. - abci-cli kvstore +``` +abci-cli kvstore +``` In another terminal, we can start Tendermint. If you have never run Tendermint before, use: - tendermint init - tendermint node +``` +tendermint init +tendermint node +``` If you have used Tendermint, you may want to reset the data for a new blockchain by running `tendermint unsafe_reset_all`. Then you can run @@ -63,14 +69,18 @@ details, see [the guide on using Tendermint](./using-tendermint.md). You should see Tendermint making blocks! We can get the status of our Tendermint node as follows: - curl -s localhost:26657/status +``` +curl -s localhost:26657/status +``` The `-s` just silences `curl`. For nicer output, pipe the result into a tool like [jq](https://stedolan.github.io/jq/) or `json_pp`. Now let's send some transactions to the kvstore. - curl -s 'localhost:26657/broadcast_tx_commit?tx="abcd"' +``` +curl -s 'localhost:26657/broadcast_tx_commit?tx="abcd"' +``` Note the single quote (`'`) around the url, which ensures that the double quotes (`"`) are not escaped by bash. This command sent a @@ -78,50 +88,56 @@ transaction with bytes `abcd`, so `abcd` will be stored as both the key and the value in the Merkle tree. The response should look something like: - { - "jsonrpc": "2.0", - "id": "", - "result": { - "check_tx": { - "fee": {} +``` +{ + "jsonrpc": "2.0", + "id": "", + "result": { + "check_tx": { + "fee": {} + }, + "deliver_tx": { + "tags": [ + { + "key": "YXBwLmNyZWF0b3I=", + "value": "amFl" }, - "deliver_tx": { - "tags": [ - { - "key": "YXBwLmNyZWF0b3I=", - "value": "amFl" - }, - { - "key": "YXBwLmtleQ==", - "value": "YWJjZA==" - } - ], - "fee": {} - }, - "hash": "9DF66553F98DE3C26E3C3317A3E4CED54F714E39", - "height": 14 - } - } + { + "key": "YXBwLmtleQ==", + "value": "YWJjZA==" + } + ], + "fee": {} + }, + "hash": "9DF66553F98DE3C26E3C3317A3E4CED54F714E39", + "height": 14 + } +} +``` We can confirm that our transaction worked and the value got stored by querying the app: - curl -s 'localhost:26657/abci_query?data="abcd"' +``` +curl -s 'localhost:26657/abci_query?data="abcd"' +``` The result should look like: - { - "jsonrpc": "2.0", - "id": "", - "result": { - "response": { - "log": "exists", - "index": "-1", - "key": "YWJjZA==", - "value": "YWJjZA==" - } - } +``` +{ + "jsonrpc": "2.0", + "id": "", + "result": { + "response": { + "log": "exists", + "index": "-1", + "key": "YWJjZA==", + "value": "YWJjZA==" } + } +} +``` Note the `value` in the result (`YWJjZA==`); this is the base64-encoding of the ASCII of `abcd`. You can verify this in a python 2 shell by @@ -132,12 +148,16 @@ human-readable](https://github.com/tendermint/tendermint/issues/1794). Now let's try setting a different key and value: - curl -s 'localhost:26657/broadcast_tx_commit?tx="name=satoshi"' +``` +curl -s 'localhost:26657/broadcast_tx_commit?tx="name=satoshi"' +``` Now if we query for `name`, we should get `satoshi`, or `c2F0b3NoaQ==` in base64: - curl -s 'localhost:26657/abci_query?data="name"' +``` +curl -s 'localhost:26657/abci_query?data="name"' +``` Try some other transactions and queries to make sure everything is working! @@ -171,57 +191,67 @@ Let's kill the previous instance of `tendermint` and the `kvstore` application, and start the counter app. We can enable `serial=on` with a flag: - abci-cli counter --serial +``` +abci-cli counter --serial +``` In another window, reset then start Tendermint: - tendermint unsafe_reset_all - tendermint node +``` +tendermint unsafe_reset_all +tendermint node +``` Once again, you can see the blocks streaming by. Let's send some transactions. Since we have set `serial=on`, the first transaction must be the number `0`: - curl localhost:26657/broadcast_tx_commit?tx=0x00 +``` +curl localhost:26657/broadcast_tx_commit?tx=0x00 +``` Note the empty (hence successful) response. The next transaction must be the number `1`. If instead, we try to send a `5`, we get an error: - > curl localhost:26657/broadcast_tx_commit?tx=0x05 - { - "jsonrpc": "2.0", - "id": "", - "result": { - "check_tx": { - "fee": {} - }, - "deliver_tx": { - "code": 2, - "log": "Invalid nonce. Expected 1, got 5", - "fee": {} - }, - "hash": "33B93DFF98749B0D6996A70F64071347060DC19C", - "height": 34 - } - } +``` +> curl localhost:26657/broadcast_tx_commit?tx=0x05 +{ + "jsonrpc": "2.0", + "id": "", + "result": { + "check_tx": { + "fee": {} + }, + "deliver_tx": { + "code": 2, + "log": "Invalid nonce. Expected 1, got 5", + "fee": {} + }, + "hash": "33B93DFF98749B0D6996A70F64071347060DC19C", + "height": 34 + } +} +``` But if we send a `1`, it works again: - > curl localhost:26657/broadcast_tx_commit?tx=0x01 - { - "jsonrpc": "2.0", - "id": "", - "result": { - "check_tx": { - "fee": {} - }, - "deliver_tx": { - "fee": {} - }, - "hash": "F17854A977F6FA7EEA1BD758E296710B86F72F3D", - "height": 60 - } - } +``` +> curl localhost:26657/broadcast_tx_commit?tx=0x01 +{ + "jsonrpc": "2.0", + "id": "", + "result": { + "check_tx": { + "fee": {} + }, + "deliver_tx": { + "fee": {} + }, + "hash": "F17854A977F6FA7EEA1BD758E296710B86F72F3D", + "height": 60 + } +} +``` For more details on the `broadcast_tx` API, see [the guide on using Tendermint](./using-tendermint.md). @@ -236,26 +266,34 @@ You'll also need to fetch the relevant repository, from [here](https://github.com/tendermint/js-abci) then install it. As go devs, we keep all our code under the `$GOPATH`, so run: - go get github.com/tendermint/js-abci &> /dev/null - cd $GOPATH/src/github.com/tendermint/js-abci/example - npm install - cd .. +``` +go get github.com/tendermint/js-abci &> /dev/null +cd $GOPATH/src/github.com/tendermint/js-abci/example +npm install +cd .. +``` Kill the previous `counter` and `tendermint` processes. Now run the app: - node example/counter.js +``` +node example/counter.js +``` In another window, reset and start `tendermint`: - tendermint unsafe_reset_all - tendermint node +``` +tendermint unsafe_reset_all +tendermint node +``` Once again, you should see blocks streaming by - but now, our application is written in javascript! Try sending some transactions, and like before - the results should be the same: - curl localhost:26657/broadcast_tx_commit?tx=0x00 # ok - curl localhost:26657/broadcast_tx_commit?tx=0x05 # invalid nonce - curl localhost:26657/broadcast_tx_commit?tx=0x01 # ok +``` +curl localhost:26657/broadcast_tx_commit?tx=0x00 # ok +curl localhost:26657/broadcast_tx_commit?tx=0x05 # invalid nonce +curl localhost:26657/broadcast_tx_commit?tx=0x01 # ok +``` Neat, eh? diff --git a/docs/app-dev/indexing-transactions.md b/docs/app-dev/indexing-transactions.md new file mode 100644 index 000000000..3bca10959 --- /dev/null +++ b/docs/app-dev/indexing-transactions.md @@ -0,0 +1,97 @@ +# Indexing Transactions + +Tendermint allows you to index transactions and later query or subscribe +to their results. + +Let's take a look at the `[tx_index]` config section: + +``` +##### transactions indexer configuration options ##### +[tx_index] + +# What indexer to use for transactions +# +# Options: +# 1) "null" (default) +# 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). +indexer = "kv" + +# Comma-separated list of tags to index (by default the only tag is tx hash) +# +# It's recommended to index only a subset of tags due to possible memory +# bloat. This is, of course, depends on the indexer's DB and the volume of +# transactions. +index_tags = "" + +# When set to true, tells indexer to index all tags. Note this may be not +# desirable (see the comment above). IndexTags has a precedence over +# IndexAllTags (i.e. when given both, IndexTags will be indexed). +index_all_tags = false +``` + +By default, Tendermint will index all transactions by their respective +hashes using an embedded simple indexer. Note, we are planning to add +more options in the future (e.g., Postgresql indexer). + +## Adding tags + +In your application's `DeliverTx` method, add the `Tags` field with the +pairs of UTF-8 encoded strings (e.g. "account.owner": "Bob", "balance": +"100.0", "date": "2018-01-02"). + +Example: + +``` +func (app *KVStoreApplication) DeliverTx(tx []byte) types.Result { + ... + tags := []cmn.KVPair{ + {[]byte("account.name"), []byte("igor")}, + {[]byte("account.address"), []byte("0xdeadbeef")}, + {[]byte("tx.amount"), []byte("7")}, + } + return types.ResponseDeliverTx{Code: code.CodeTypeOK, Tags: tags} +} +``` + +If you want Tendermint to only index transactions by "account.name" tag, +in the config set `tx_index.index_tags="account.name"`. If you to index +all tags, set `index_all_tags=true` + +Note, there are a few predefined tags: + +- `tm.event` (event type) +- `tx.hash` (transaction's hash) +- `tx.height` (height of the block transaction was committed in) + +Tendermint will throw a warning if you try to use any of the above keys. + +## Querying transactions + +You can query the transaction results by calling `/tx_search` RPC +endpoint: + +``` +curl "localhost:26657/tx_search?query=\"account.name='igor'\"&prove=true" +``` + +Check out [API docs](https://tendermint.github.io/slate/?shell#txsearch) +for more information on query syntax and other options. + +## Subscribing to transactions + +Clients can subscribe to transactions with the given tags via Websocket +by providing a query to `/subscribe` RPC endpoint. + +``` +{ + "jsonrpc": "2.0", + "method": "subscribe", + "id": "0", + "params": { + "query": "account.name='igor'" + } +} +``` + +Check out [API docs](https://tendermint.github.io/slate/#subscribe) for +more information on query syntax and other options. diff --git a/docs/subscribing-to-events-via-websocket.md b/docs/app-dev/subscribing-to-events-via-websocket.md similarity index 82% rename from docs/subscribing-to-events-via-websocket.md rename to docs/app-dev/subscribing-to-events-via-websocket.md index 43d3f7767..9e7c642a0 100644 --- a/docs/subscribing-to-events-via-websocket.md +++ b/docs/app-dev/subscribing-to-events-via-websocket.md @@ -9,14 +9,16 @@ for third-party applications (for analysys) or inspecting state. You can subscribe to any of the events above by calling `subscribe` RPC method via Websocket. - { - "jsonrpc": "2.0", - "method": "subscribe", - "id": "0", - "params": { - "query": "tm.event='NewBlock'" - } +``` +{ + "jsonrpc": "2.0", + "method": "subscribe", + "id": "0", + "params": { + "query": "tm.event='NewBlock'" } +} +``` Check out [API docs](https://tendermint.github.io/slate/#subscribe) for more information on query syntax and other options. diff --git a/docs/deploy-testnets.md b/docs/deploy-testnets.md deleted file mode 100644 index e5b300836..000000000 --- a/docs/deploy-testnets.md +++ /dev/null @@ -1,68 +0,0 @@ -# Deploy a Testnet - -Now that we've seen how ABCI works, and even played with a few -applications on a single validator node, it's time to deploy a test -network to four validator nodes. - -## Manual Deployments - -It's relatively easy to setup a Tendermint cluster manually. The only -requirements for a particular Tendermint node are a private key for the -validator, stored as `priv_validator.json`, a node key, stored as -`node_key.json` and a list of the public keys of all validators, stored -as `genesis.json`. These files should be stored in -`~/.tendermint/config`, or wherever the `$TMHOME` variable might be set -to. - -Here are the steps to setting up a testnet manually: - -1) Provision nodes on your cloud provider of choice -2) Install Tendermint and the application of interest on all nodes -3) Generate a private key and a node key for each validator using - `tendermint init` -4) Compile a list of public keys for each validator into a - `genesis.json` file and replace the existing file with it. -5) Run - `tendermint node --proxy_app=kvstore --p2p.persistent_peers=< peer addresses >` - on each node, where `< peer addresses >` is a comma separated list - of the IP:PORT combination for each node. The default port for - Tendermint is `26656`. Thus, if the IP addresses of your nodes were - `192.168.0.1, 192.168.0.2, 192.168.0.3, 192.168.0.4`, the command - would look like: - - - tendermint node --proxy_app=kvstore --p2p.persistent_peers=96663a3dd0d7b9d17d4c8211b191af259621c693@192.168.0.1:26656, 429fcf25974313b95673f58d77eacdd434402665@192.168.0.2:26656, 0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@192.168.0.3:26656, f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@192.168.0.4:26656 - -After a few seconds, all the nodes should connect to each other and -start making blocks! For more information, see the Tendermint Networks -section of [the guide to using Tendermint](./using-tendermint.md). - -But wait! Steps 3 and 4 are quite manual. Instead, use [this -script](https://github.com/tendermint/tendermint/blob/develop/docs/examples/init_testnet.sh), -which does the heavy lifting for you. And it gets better. - -Instead of the previously linked script to initialize the files required -for a testnet, we have the `tendermint testnet` command. By default, -running `tendermint testnet` will create all the required files, just -like the script. Of course, you'll still need to manually edit some -fields in the `config.toml`. Alternatively, see the available flags to -auto-populate the `config.toml` with the fields that would otherwise be -passed in via flags when running `tendermint node`. As you might -imagine, this command is useful for manual or automated deployments. - -## Automated Deployments - -The easiest and fastest way to get a testnet up in less than 5 minutes. - -### Local - -With `docker` and `docker-compose` installed, run the command: - - make localnet-start - -from the root of the tendermint repository. This will spin up a 4-node -local testnet. Review the target in the Makefile to debug any problems. - -### Cloud - -See the [next section](./terraform-and-ansible.html) for details. diff --git a/docs/examples/init_testnet.sh b/docs/examples/init_testnet.sh deleted file mode 100644 index 84e54674c..000000000 --- a/docs/examples/init_testnet.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bash - -# make all the files -tendermint init --home ./tester/node0 -tendermint init --home ./tester/node1 -tendermint init --home ./tester/node2 -tendermint init --home ./tester/node3 - -file0=./tester/node0/config/genesis.json -file1=./tester/node1/config/genesis.json -file2=./tester/node2/config/genesis.json -file3=./tester/node3/config/genesis.json - -genesis_time=`cat $file0 | jq '.genesis_time'` -chain_id=`cat $file0 | jq '.chain_id'` - -value0=`cat $file0 | jq '.validators[0].pub_key.value'` -value1=`cat $file1 | jq '.validators[0].pub_key.value'` -value2=`cat $file2 | jq '.validators[0].pub_key.value'` -value3=`cat $file3 | jq '.validators[0].pub_key.value'` - -rm $file0 -rm $file1 -rm $file2 -rm $file3 - -echo "{ - \"genesis_time\": $genesis_time, - \"chain_id\": $chain_id, - \"validators\": [ - { - \"pub_key\": { - \"type\": \"tendermint/PubKeyEd25519\", - \"value\": $value0 - }, - \"power:\": 10, - \"name\":, \"\" - }, - { - \"pub_key\": { - \"type\": \"tendermint/PubKeyEd25519\", - \"value\": $value1 - }, - \"power:\": 10, - \"name\":, \"\" - }, - { - \"pub_key\": { - \"type\": \"tendermint/PubKeyEd25519\", - \"value\": $value2 - }, - \"power:\": 10, - \"name\":, \"\" - }, - { - \"pub_key\": { - \"type\": \"tendermint/PubKeyEd25519\", - \"value\": $value3 - }, - \"power:\": 10, - \"name\":, \"\" - } - ], - \"app_hash\": \"\" -}" >> $file0 - -cp $file0 $file1 -cp $file0 $file2 -cp $file2 $file3 diff --git a/docs/examples/install_tendermint.sh b/docs/examples/install_tendermint.sh deleted file mode 100644 index 5a9c49d78..000000000 --- a/docs/examples/install_tendermint.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash - -# XXX: this script is meant to be used only on a fresh Ubuntu 16.04 instance -# and has only been tested on Digital Ocean - -# get and unpack golang -curl -O https://storage.googleapis.com/golang/go1.10.linux-amd64.tar.gz -tar -xvf go1.10.linux-amd64.tar.gz - -apt install make - -## move go and add binary to path -mv go /usr/local -echo "export PATH=\$PATH:/usr/local/go/bin" >> ~/.profile - -## create the GOPATH directory, set GOPATH and put on PATH -mkdir goApps -echo "export GOPATH=/root/goApps" >> ~/.profile -echo "export PATH=\$PATH:\$GOPATH/bin" >> ~/.profile - -source ~/.profile - -## get the code and move into it -REPO=github.com/tendermint/tendermint -go get $REPO -cd $GOPATH/src/$REPO - -## build -git checkout master -make get_tools -make get_vendor_deps -make install diff --git a/docs/examples/node0/config/config.toml b/docs/examples/node0/config/config.toml deleted file mode 100644 index d1ecf238a..000000000 --- a/docs/examples/node0/config/config.toml +++ /dev/null @@ -1,166 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -##### main base config options ##### - -# TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy_app = "tcp://127.0.0.1:26658" - -# A custom human readable name for this node -moniker = "alpha" - -# If this node is many blocks behind the tip of the chain, FastSync -# allows them to catchup quickly by downloading blocks in parallel -# and verifying their commits -fast_sync = true - -# Database backend: leveldb | memdb -db_backend = "leveldb" - -# Database directory -db_path = "data" - -# Output level for logging, including package level options -log_level = "main:info,state:info,*:error" - -##### additional base config options ##### - -# Path to the JSON file containing the initial validator set and other meta data -genesis_file = "config/genesis.json" - -# Path to the JSON file containing the private key to use as a validator in the consensus protocol -priv_validator_file = "config/priv_validator.json" - -# Path to the JSON file containing the private key to use for node authentication in the p2p protocol -node_key_file = "config/node_key.json" - -# Mechanism to connect to the ABCI application: socket | grpc -abci = "socket" - -# TCP or UNIX socket address for the profiling server to listen on -prof_laddr = "" - -# If true, query the ABCI app on connecting to a new peer -# so the app can decide if we should keep the connection or not -filter_peers = false - -##### advanced configuration options ##### - -##### rpc server configuration options ##### -[rpc] - -# TCP or UNIX socket address for the RPC server to listen on -laddr = "tcp://0.0.0.0:26657" - -# TCP or UNIX socket address for the gRPC server to listen on -# NOTE: This server only supports /broadcast_tx_commit -grpc_laddr = "" - -# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool -unsafe = false - -##### peer to peer configuration options ##### -[p2p] - -# Address to listen for incoming connections -laddr = "tcp://0.0.0.0:26656" - -# Comma separated list of seed nodes to connect to -seeds = "" - -# Comma separated list of nodes to keep persistent connections to -# Do not add private peers to this list if you don't want them advertised -persistent_peers = "" - -# Path to address book -addr_book_file = "config/addrbook.json" - -# Set true for strict address routability rules -addr_book_strict = true - -# Time to wait before flushing messages out on the connection, in ms -flush_throttle_timeout = 100 - -# Maximum number of peers to connect to -max_num_peers = 50 - -# Maximum size of a message packet payload, in bytes -max_packet_msg_payload_size = 1024 - -# Rate at which packets can be sent, in bytes/second -send_rate = 512000 - -# Rate at which packets can be received, in bytes/second -recv_rate = 512000 - -# Set true to enable the peer-exchange reactor -pex = true - -# Seed mode, in which node constantly crawls the network and looks for -# peers. If another node asks it for addresses, it responds and disconnects. -# -# Does not work if the peer-exchange reactor is disabled. -seed_mode = false - -# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) -private_peer_ids = "" - -##### mempool configuration options ##### -[mempool] - -recheck = true -recheck_empty = true -broadcast = true -wal_dir = "data/mempool.wal" - -##### consensus configuration options ##### -[consensus] - -wal_file = "data/cs.wal/wal" - -# All timeouts are in milliseconds -timeout_propose = 3000 -timeout_propose_delta = 500 -timeout_prevote = 1000 -timeout_prevote_delta = 500 -timeout_precommit = 1000 -timeout_precommit_delta = 500 -timeout_commit = 1000 - -# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) -skip_timeout_commit = false - -# BlockSize -max_block_size_txs = 10000 -max_block_size_bytes = 1 - -# EmptyBlocks mode and possible interval between empty blocks in seconds -create_empty_blocks = true -create_empty_blocks_interval = 0 - -# Reactor sleep duration parameters are in milliseconds -peer_gossip_sleep_duration = 100 -peer_query_maj23_sleep_duration = 2000 - -##### transactions indexer configuration options ##### -[tx_index] - -# What indexer to use for transactions -# -# Options: -# 1) "null" (default) -# 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). -indexer = "kv" - -# Comma-separated list of tags to index (by default the only tag is tx hash) -# -# It's recommended to index only a subset of tags due to possible memory -# bloat. This is, of course, depends on the indexer's DB and the volume of -# transactions. -index_tags = "" - -# When set to true, tells indexer to index all tags. Note this may be not -# desirable (see the comment above). IndexTags has a precedence over -# IndexAllTags (i.e. when given both, IndexTags will be indexed). -index_all_tags = false diff --git a/docs/examples/node0/config/genesis.json b/docs/examples/node0/config/genesis.json deleted file mode 100644 index ac306bd2f..000000000 --- a/docs/examples/node0/config/genesis.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "genesis_time": "0001-01-01T00:00:00Z", - "chain_id": "test-chain-A2i3OZ", - "validators": [ - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" - }, - "power": "10", - "name": "" - } - ], - "app_hash": "" -} diff --git a/docs/examples/node0/config/node_key.json b/docs/examples/node0/config/node_key.json deleted file mode 100644 index dec1fd42d..000000000 --- a/docs/examples/node0/config/node_key.json +++ /dev/null @@ -1 +0,0 @@ -{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"7lY+k6EDllG8Q9gVbF5313t/ag2YGkBVKdVa0YHJ9xO5k0w3Q/hke0Z7UFT1KgVDGRUEKzwAwwjwFQUvgF0ZWg=="}} diff --git a/docs/examples/node0/config/priv_validator.json b/docs/examples/node0/config/priv_validator.json deleted file mode 100644 index ef2daccbb..000000000 --- a/docs/examples/node0/config/priv_validator.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "address": "122A9414774A2FCAD026201DA477EF3F41970EF0", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" - }, - "last_height": "0", - "last_round": "0", - "last_step": 0, - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "YLxp3ho+kySgAnzjBptbxDzSGw2ntGZLsIHQsaVxY/cP6TgB2Odg9ZsH3CZp3XfsF2mj+QC6U6hNFCsvL9BziQ==" - } -} diff --git a/docs/examples/node1/config/config.toml b/docs/examples/node1/config/config.toml deleted file mode 100644 index bc5a5bde1..000000000 --- a/docs/examples/node1/config/config.toml +++ /dev/null @@ -1,166 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -##### main base config options ##### - -# TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy_app = "tcp://127.0.0.1:26658" - -# A custom human readable name for this node -moniker = "bravo" - -# If this node is many blocks behind the tip of the chain, FastSync -# allows them to catchup quickly by downloading blocks in parallel -# and verifying their commits -fast_sync = true - -# Database backend: leveldb | memdb -db_backend = "leveldb" - -# Database directory -db_path = "data" - -# Output level for logging, including package level options -log_level = "main:info,state:info,*:error" - -##### additional base config options ##### - -# Path to the JSON file containing the initial validator set and other meta data -genesis_file = "config/genesis.json" - -# Path to the JSON file containing the private key to use as a validator in the consensus protocol -priv_validator_file = "config/priv_validator.json" - -# Path to the JSON file containing the private key to use for node authentication in the p2p protocol -node_key_file = "config/node_key.json" - -# Mechanism to connect to the ABCI application: socket | grpc -abci = "socket" - -# TCP or UNIX socket address for the profiling server to listen on -prof_laddr = "" - -# If true, query the ABCI app on connecting to a new peer -# so the app can decide if we should keep the connection or not -filter_peers = false - -##### advanced configuration options ##### - -##### rpc server configuration options ##### -[rpc] - -# TCP or UNIX socket address for the RPC server to listen on -laddr = "tcp://0.0.0.0:26657" - -# TCP or UNIX socket address for the gRPC server to listen on -# NOTE: This server only supports /broadcast_tx_commit -grpc_laddr = "" - -# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool -unsafe = false - -##### peer to peer configuration options ##### -[p2p] - -# Address to listen for incoming connections -laddr = "tcp://0.0.0.0:26656" - -# Comma separated list of seed nodes to connect to -seeds = "" - -# Comma separated list of nodes to keep persistent connections to -# Do not add private peers to this list if you don't want them advertised -persistent_peers = "" - -# Path to address book -addr_book_file = "config/addrbook.json" - -# Set true for strict address routability rules -addr_book_strict = true - -# Time to wait before flushing messages out on the connection, in ms -flush_throttle_timeout = 100 - -# Maximum number of peers to connect to -max_num_peers = 50 - -# Maximum size of a message packet payload, in bytes -max_packet_msg_payload_size = 1024 - -# Rate at which packets can be sent, in bytes/second -send_rate = 512000 - -# Rate at which packets can be received, in bytes/second -recv_rate = 512000 - -# Set true to enable the peer-exchange reactor -pex = true - -# Seed mode, in which node constantly crawls the network and looks for -# peers. If another node asks it for addresses, it responds and disconnects. -# -# Does not work if the peer-exchange reactor is disabled. -seed_mode = false - -# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) -private_peer_ids = "" - -##### mempool configuration options ##### -[mempool] - -recheck = true -recheck_empty = true -broadcast = true -wal_dir = "data/mempool.wal" - -##### consensus configuration options ##### -[consensus] - -wal_file = "data/cs.wal/wal" - -# All timeouts are in milliseconds -timeout_propose = 3000 -timeout_propose_delta = 500 -timeout_prevote = 1000 -timeout_prevote_delta = 500 -timeout_precommit = 1000 -timeout_precommit_delta = 500 -timeout_commit = 1000 - -# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) -skip_timeout_commit = false - -# BlockSize -max_block_size_txs = 10000 -max_block_size_bytes = 1 - -# EmptyBlocks mode and possible interval between empty blocks in seconds -create_empty_blocks = true -create_empty_blocks_interval = 0 - -# Reactor sleep duration parameters are in milliseconds -peer_gossip_sleep_duration = 100 -peer_query_maj23_sleep_duration = 2000 - -##### transactions indexer configuration options ##### -[tx_index] - -# What indexer to use for transactions -# -# Options: -# 1) "null" (default) -# 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). -indexer = "kv" - -# Comma-separated list of tags to index (by default the only tag is tx hash) -# -# It's recommended to index only a subset of tags due to possible memory -# bloat. This is, of course, depends on the indexer's DB and the volume of -# transactions. -index_tags = "" - -# When set to true, tells indexer to index all tags. Note this may be not -# desirable (see the comment above). IndexTags has a precedence over -# IndexAllTags (i.e. when given both, IndexTags will be indexed). -index_all_tags = false diff --git a/docs/examples/node1/config/genesis.json b/docs/examples/node1/config/genesis.json deleted file mode 100644 index ac306bd2f..000000000 --- a/docs/examples/node1/config/genesis.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "genesis_time": "0001-01-01T00:00:00Z", - "chain_id": "test-chain-A2i3OZ", - "validators": [ - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" - }, - "power": "10", - "name": "" - } - ], - "app_hash": "" -} diff --git a/docs/examples/node1/config/node_key.json b/docs/examples/node1/config/node_key.json deleted file mode 100644 index 05f4ea846..000000000 --- a/docs/examples/node1/config/node_key.json +++ /dev/null @@ -1 +0,0 @@ -{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"H71dc/TIG7nTselfa9nG0WRArXLKYnm7P5eFCk2lk8ASKQ3sIHpbdxCSHQD/RcdHe7TiabJeuOssNPvPWiyQEQ=="}} diff --git a/docs/examples/node1/config/priv_validator.json b/docs/examples/node1/config/priv_validator.json deleted file mode 100644 index 3a38793e4..000000000 --- a/docs/examples/node1/config/priv_validator.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "address": "BEA1B57F5806CF9AC4D54C8CF806DED5C0F102E1", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" - }, - "last_height": "0", - "last_round": "0", - "last_step": 0, - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "o0IqrHSPtd5YqGefodWxpJuRzvuVBjgbH785vbMgk7Vvno3kYJHVp1xVG4Q2N8rD+aubZ2SFPvA1ldX9IOwqxQ==" - } -} diff --git a/docs/examples/node2/config/config.toml b/docs/examples/node2/config/config.toml deleted file mode 100644 index 1bf06286a..000000000 --- a/docs/examples/node2/config/config.toml +++ /dev/null @@ -1,166 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -##### main base config options ##### - -# TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy_app = "tcp://127.0.0.1:26658" - -# A custom human readable name for this node -moniker = "charlie" - -# If this node is many blocks behind the tip of the chain, FastSync -# allows them to catchup quickly by downloading blocks in parallel -# and verifying their commits -fast_sync = true - -# Database backend: leveldb | memdb -db_backend = "leveldb" - -# Database directory -db_path = "data" - -# Output level for logging, including package level options -log_level = "main:info,state:info,*:error" - -##### additional base config options ##### - -# Path to the JSON file containing the initial validator set and other meta data -genesis_file = "config/genesis.json" - -# Path to the JSON file containing the private key to use as a validator in the consensus protocol -priv_validator_file = "config/priv_validator.json" - -# Path to the JSON file containing the private key to use for node authentication in the p2p protocol -node_key_file = "config/node_key.json" - -# Mechanism to connect to the ABCI application: socket | grpc -abci = "socket" - -# TCP or UNIX socket address for the profiling server to listen on -prof_laddr = "" - -# If true, query the ABCI app on connecting to a new peer -# so the app can decide if we should keep the connection or not -filter_peers = false - -##### advanced configuration options ##### - -##### rpc server configuration options ##### -[rpc] - -# TCP or UNIX socket address for the RPC server to listen on -laddr = "tcp://0.0.0.0:26657" - -# TCP or UNIX socket address for the gRPC server to listen on -# NOTE: This server only supports /broadcast_tx_commit -grpc_laddr = "" - -# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool -unsafe = false - -##### peer to peer configuration options ##### -[p2p] - -# Address to listen for incoming connections -laddr = "tcp://0.0.0.0:26656" - -# Comma separated list of seed nodes to connect to -seeds = "" - -# Comma separated list of nodes to keep persistent connections to -# Do not add private peers to this list if you don't want them advertised -persistent_peers = "" - -# Path to address book -addr_book_file = "config/addrbook.json" - -# Set true for strict address routability rules -addr_book_strict = true - -# Time to wait before flushing messages out on the connection, in ms -flush_throttle_timeout = 100 - -# Maximum number of peers to connect to -max_num_peers = 50 - -# Maximum size of a message packet payload, in bytes -max_packet_msg_payload_size = 1024 - -# Rate at which packets can be sent, in bytes/second -send_rate = 512000 - -# Rate at which packets can be received, in bytes/second -recv_rate = 512000 - -# Set true to enable the peer-exchange reactor -pex = true - -# Seed mode, in which node constantly crawls the network and looks for -# peers. If another node asks it for addresses, it responds and disconnects. -# -# Does not work if the peer-exchange reactor is disabled. -seed_mode = false - -# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) -private_peer_ids = "" - -##### mempool configuration options ##### -[mempool] - -recheck = true -recheck_empty = true -broadcast = true -wal_dir = "data/mempool.wal" - -##### consensus configuration options ##### -[consensus] - -wal_file = "data/cs.wal/wal" - -# All timeouts are in milliseconds -timeout_propose = 3000 -timeout_propose_delta = 500 -timeout_prevote = 1000 -timeout_prevote_delta = 500 -timeout_precommit = 1000 -timeout_precommit_delta = 500 -timeout_commit = 1000 - -# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) -skip_timeout_commit = false - -# BlockSize -max_block_size_txs = 10000 -max_block_size_bytes = 1 - -# EmptyBlocks mode and possible interval between empty blocks in seconds -create_empty_blocks = true -create_empty_blocks_interval = 0 - -# Reactor sleep duration parameters are in milliseconds -peer_gossip_sleep_duration = 100 -peer_query_maj23_sleep_duration = 2000 - -##### transactions indexer configuration options ##### -[tx_index] - -# What indexer to use for transactions -# -# Options: -# 1) "null" (default) -# 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). -indexer = "kv" - -# Comma-separated list of tags to index (by default the only tag is tx hash) -# -# It's recommended to index only a subset of tags due to possible memory -# bloat. This is, of course, depends on the indexer's DB and the volume of -# transactions. -index_tags = "" - -# When set to true, tells indexer to index all tags. Note this may be not -# desirable (see the comment above). IndexTags has a precedence over -# IndexAllTags (i.e. when given both, IndexTags will be indexed). -index_all_tags = false diff --git a/docs/examples/node2/config/genesis.json b/docs/examples/node2/config/genesis.json deleted file mode 100644 index ac306bd2f..000000000 --- a/docs/examples/node2/config/genesis.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "genesis_time": "0001-01-01T00:00:00Z", - "chain_id": "test-chain-A2i3OZ", - "validators": [ - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" - }, - "power": "10", - "name": "" - } - ], - "app_hash": "" -} diff --git a/docs/examples/node2/config/node_key.json b/docs/examples/node2/config/node_key.json deleted file mode 100644 index 6f15a541b..000000000 --- a/docs/examples/node2/config/node_key.json +++ /dev/null @@ -1 +0,0 @@ -{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"COHZ/Y2cWGWxJNkRwtpQBt5sYvOnb6Gpz0lO46XERRJFBIdSWD5x1UMGRSTmnvW1ec5G4bMdg6zUZKOZD+vVPg=="}} diff --git a/docs/examples/node2/config/priv_validator.json b/docs/examples/node2/config/priv_validator.json deleted file mode 100644 index 2bcd31a76..000000000 --- a/docs/examples/node2/config/priv_validator.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "address": "F0AA266949FB29ADA0B679C27889ED930BD1BDA1", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" - }, - "last_height": "0", - "last_round": "0", - "last_step": 0, - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "khADeZ5K/8u/L99DFaZNRq8V5g+EHWbwfqFjhCrppaAiBkOkm8YDRMBqaJwDyKtzL5Ff8GRSWPoNfAzv3XLAhQ==" - } -} diff --git a/docs/examples/node3/config/config.toml b/docs/examples/node3/config/config.toml deleted file mode 100644 index 8c23f7d38..000000000 --- a/docs/examples/node3/config/config.toml +++ /dev/null @@ -1,166 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -##### main base config options ##### - -# TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy_app = "tcp://127.0.0.1:26658" - -# A custom human readable name for this node -moniker = "delta" - -# If this node is many blocks behind the tip of the chain, FastSync -# allows them to catchup quickly by downloading blocks in parallel -# and verifying their commits -fast_sync = true - -# Database backend: leveldb | memdb -db_backend = "leveldb" - -# Database directory -db_path = "data" - -# Output level for logging, including package level options -log_level = "main:info,state:info,*:error" - -##### additional base config options ##### - -# Path to the JSON file containing the initial validator set and other meta data -genesis_file = "config/genesis.json" - -# Path to the JSON file containing the private key to use as a validator in the consensus protocol -priv_validator_file = "config/priv_validator.json" - -# Path to the JSON file containing the private key to use for node authentication in the p2p protocol -node_key_file = "config/node_key.json" - -# Mechanism to connect to the ABCI application: socket | grpc -abci = "socket" - -# TCP or UNIX socket address for the profiling server to listen on -prof_laddr = "" - -# If true, query the ABCI app on connecting to a new peer -# so the app can decide if we should keep the connection or not -filter_peers = false - -##### advanced configuration options ##### - -##### rpc server configuration options ##### -[rpc] - -# TCP or UNIX socket address for the RPC server to listen on -laddr = "tcp://0.0.0.0:26657" - -# TCP or UNIX socket address for the gRPC server to listen on -# NOTE: This server only supports /broadcast_tx_commit -grpc_laddr = "" - -# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool -unsafe = false - -##### peer to peer configuration options ##### -[p2p] - -# Address to listen for incoming connections -laddr = "tcp://0.0.0.0:26656" - -# Comma separated list of seed nodes to connect to -seeds = "" - -# Comma separated list of nodes to keep persistent connections to -# Do not add private peers to this list if you don't want them advertised -persistent_peers = "" - -# Path to address book -addr_book_file = "config/addrbook.json" - -# Set true for strict address routability rules -addr_book_strict = true - -# Time to wait before flushing messages out on the connection, in ms -flush_throttle_timeout = 100 - -# Maximum number of peers to connect to -max_num_peers = 50 - -# Maximum size of a message packet payload, in bytes -max_packet_msg_payload_size = 1024 - -# Rate at which packets can be sent, in bytes/second -send_rate = 512000 - -# Rate at which packets can be received, in bytes/second -recv_rate = 512000 - -# Set true to enable the peer-exchange reactor -pex = true - -# Seed mode, in which node constantly crawls the network and looks for -# peers. If another node asks it for addresses, it responds and disconnects. -# -# Does not work if the peer-exchange reactor is disabled. -seed_mode = false - -# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) -private_peer_ids = "" - -##### mempool configuration options ##### -[mempool] - -recheck = true -recheck_empty = true -broadcast = true -wal_dir = "data/mempool.wal" - -##### consensus configuration options ##### -[consensus] - -wal_file = "data/cs.wal/wal" - -# All timeouts are in milliseconds -timeout_propose = 3000 -timeout_propose_delta = 500 -timeout_prevote = 1000 -timeout_prevote_delta = 500 -timeout_precommit = 1000 -timeout_precommit_delta = 500 -timeout_commit = 1000 - -# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) -skip_timeout_commit = false - -# BlockSize -max_block_size_txs = 10000 -max_block_size_bytes = 1 - -# EmptyBlocks mode and possible interval between empty blocks in seconds -create_empty_blocks = true -create_empty_blocks_interval = 0 - -# Reactor sleep duration parameters are in milliseconds -peer_gossip_sleep_duration = 100 -peer_query_maj23_sleep_duration = 2000 - -##### transactions indexer configuration options ##### -[tx_index] - -# What indexer to use for transactions -# -# Options: -# 1) "null" (default) -# 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). -indexer = "kv" - -# Comma-separated list of tags to index (by default the only tag is tx hash) -# -# It's recommended to index only a subset of tags due to possible memory -# bloat. This is, of course, depends on the indexer's DB and the volume of -# transactions. -index_tags = "" - -# When set to true, tells indexer to index all tags. Note this may be not -# desirable (see the comment above). IndexTags has a precedence over -# IndexAllTags (i.e. when given both, IndexTags will be indexed). -index_all_tags = false diff --git a/docs/examples/node3/config/genesis.json b/docs/examples/node3/config/genesis.json deleted file mode 100644 index ac306bd2f..000000000 --- a/docs/examples/node3/config/genesis.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "genesis_time": "0001-01-01T00:00:00Z", - "chain_id": "test-chain-A2i3OZ", - "validators": [ - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" - }, - "power": "10", - "name": "" - }, - { - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" - }, - "power": "10", - "name": "" - } - ], - "app_hash": "" -} diff --git a/docs/examples/node3/config/node_key.json b/docs/examples/node3/config/node_key.json deleted file mode 100644 index 01a14a3bf..000000000 --- a/docs/examples/node3/config/node_key.json +++ /dev/null @@ -1 +0,0 @@ -{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"9Y9xp/tUJJ6pHTF5SUV0bGKYSdVbFtMHu+Lr8S0JBSZAwneaejnfOEU1LMKOnQ07skrDUaJcj5di3jAyjxJzqg=="}} diff --git a/docs/examples/node3/config/priv_validator.json b/docs/examples/node3/config/priv_validator.json deleted file mode 100644 index bc8a66513..000000000 --- a/docs/examples/node3/config/priv_validator.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "address": "9A1A6914EB5F4FF0269C7EEEE627C27310CC64F9", - "pub_key": { - "type": "tendermint/PubKeyEd25519", - "value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" - }, - "last_height": "0", - "last_round": "0", - "last_step": 0, - "priv_key": { - "type": "tendermint/PrivKeyEd25519", - "value": "jb52LZ5gp+eQ8nJlFK1z06nBMp1gD8ICmyzdM1icGOgoYBl/Fm8hntptt4hDzlTUQIbr4jrYpJ1ofy6VzT46JQ==" - } -} diff --git a/docs/how-to-read-logs.md b/docs/how-to-read-logs.md deleted file mode 100644 index 2b019e549..000000000 --- a/docs/how-to-read-logs.md +++ /dev/null @@ -1,130 +0,0 @@ -# How to read logs - -## Walkabout example - -We first create three connections (mempool, consensus and query) to the -application (running `kvstore` locally in this case). - - I[10-04|13:54:27.364] Starting multiAppConn module=proxy impl=multiAppConn - I[10-04|13:54:27.366] Starting localClient module=abci-client connection=query impl=localClient - I[10-04|13:54:27.366] Starting localClient module=abci-client connection=mempool impl=localClient - I[10-04|13:54:27.367] Starting localClient module=abci-client connection=consensus impl=localClient - -Then Tendermint Core and the application perform a handshake. - - I[10-04|13:54:27.367] ABCI Handshake module=consensus appHeight=90 appHash=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD - I[10-04|13:54:27.368] ABCI Replay Blocks module=consensus appHeight=90 storeHeight=90 stateHeight=90 - I[10-04|13:54:27.368] Completed ABCI Handshake - Tendermint and App are synced module=consensus appHeight=90 appHash=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD - -After that, we start a few more things like the event switch, reactors, -and perform UPNP discover in order to detect the IP address. - - I[10-04|13:54:27.374] Starting EventSwitch module=types impl=EventSwitch - I[10-04|13:54:27.375] This node is a validator module=consensus - I[10-04|13:54:27.379] Starting Node module=main impl=Node - I[10-04|13:54:27.381] Local listener module=p2p ip=:: port=26656 - I[10-04|13:54:27.382] Getting UPNP external address module=p2p - I[10-04|13:54:30.386] Could not perform UPNP discover module=p2p err="write udp4 0.0.0.0:38238->239.255.255.250:1900: i/o timeout" - I[10-04|13:54:30.386] Starting DefaultListener module=p2p impl=Listener(@10.0.2.15:26656) - I[10-04|13:54:30.387] Starting P2P Switch module=p2p impl="P2P Switch" - I[10-04|13:54:30.387] Starting MempoolReactor module=mempool impl=MempoolReactor - I[10-04|13:54:30.387] Starting BlockchainReactor module=blockchain impl=BlockchainReactor - I[10-04|13:54:30.387] Starting ConsensusReactor module=consensus impl=ConsensusReactor - I[10-04|13:54:30.387] ConsensusReactor module=consensus fastSync=false - I[10-04|13:54:30.387] Starting ConsensusState module=consensus impl=ConsensusState - I[10-04|13:54:30.387] Starting WAL module=consensus wal=/home/vagrant/.tendermint/data/cs.wal/wal impl=WAL - I[10-04|13:54:30.388] Starting TimeoutTicker module=consensus impl=TimeoutTicker - -Notice the second row where Tendermint Core reports that "This node is a -validator". It also could be just an observer (regular node). - -Next we replay all the messages from the WAL. - - I[10-04|13:54:30.390] Catchup by replaying consensus messages module=consensus height=91 - I[10-04|13:54:30.390] Replay: New Step module=consensus height=91 round=0 step=RoundStepNewHeight - I[10-04|13:54:30.390] Replay: Done module=consensus - -"Started node" message signals that everything is ready for work. - - I[10-04|13:54:30.391] Starting RPC HTTP server on tcp socket 0.0.0.0:26657 module=rpc-server - I[10-04|13:54:30.392] Started node module=main nodeInfo="NodeInfo{id: DF22D7C92C91082324A1312F092AA1DA197FA598DBBFB6526E, moniker: anonymous, network: test-chain-3MNw2N [remote , listen 10.0.2.15:26656], version: 0.11.0-10f361fc ([wire_version=0.6.2 p2p_version=0.5.0 consensus_version=v1/0.2.2 rpc_version=0.7.0/3 tx_index=on rpc_addr=tcp://0.0.0.0:26657])}" - -Next follows a standard block creation cycle, where we enter a new -round, propose a block, receive more than 2/3 of prevotes, then -precommits and finally have a chance to commit a block. For details, -please refer to [Consensus -Overview](./introduction.md#consensus-overview) or [Byzantine Consensus -Algorithm](./spec/consensus). - - I[10-04|13:54:30.393] enterNewRound(91/0). Current: 91/0/RoundStepNewHeight module=consensus - I[10-04|13:54:30.393] enterPropose(91/0). Current: 91/0/RoundStepNewRound module=consensus - I[10-04|13:54:30.393] enterPropose: Our turn to propose module=consensus proposer=125B0E3C5512F5C2B0E1109E31885C4511570C42 privValidator="PrivValidator{125B0E3C5512F5C2B0E1109E31885C4511570C42 LH:90, LR:0, LS:3}" - I[10-04|13:54:30.394] Signed proposal module=consensus height=91 round=0 proposal="Proposal{91/0 1:21B79872514F (-1,:0:000000000000) {/10EDEDD7C84E.../}}" - I[10-04|13:54:30.397] Received complete proposal block module=consensus height=91 hash=F671D562C7B9242900A286E1882EE64E5556FE9E - I[10-04|13:54:30.397] enterPrevote(91/0). Current: 91/0/RoundStepPropose module=consensus - I[10-04|13:54:30.397] enterPrevote: ProposalBlock is valid module=consensus height=91 round=0 - I[10-04|13:54:30.398] Signed and pushed vote module=consensus height=91 round=0 vote="Vote{0:125B0E3C5512 91/00/1(Prevote) F671D562C7B9 {/89047FFC21D8.../}}" err=null - I[10-04|13:54:30.401] Added to prevote module=consensus vote="Vote{0:125B0E3C5512 91/00/1(Prevote) F671D562C7B9 {/89047FFC21D8.../}}" prevotes="VoteSet{H:91 R:0 T:1 +2/3:F671D562C7B9242900A286E1882EE64E5556FE9E:1:21B79872514F BA{1:X} map[]}" - I[10-04|13:54:30.401] enterPrecommit(91/0). Current: 91/0/RoundStepPrevote module=consensus - I[10-04|13:54:30.401] enterPrecommit: +2/3 prevoted proposal block. Locking module=consensus hash=F671D562C7B9242900A286E1882EE64E5556FE9E - I[10-04|13:54:30.402] Signed and pushed vote module=consensus height=91 round=0 vote="Vote{0:125B0E3C5512 91/00/2(Precommit) F671D562C7B9 {/80533478E41A.../}}" err=null - I[10-04|13:54:30.404] Added to precommit module=consensus vote="Vote{0:125B0E3C5512 91/00/2(Precommit) F671D562C7B9 {/80533478E41A.../}}" precommits="VoteSet{H:91 R:0 T:2 +2/3:F671D562C7B9242900A286E1882EE64E5556FE9E:1:21B79872514F BA{1:X} map[]}" - I[10-04|13:54:30.404] enterCommit(91/0). Current: 91/0/RoundStepPrecommit module=consensus - I[10-04|13:54:30.405] Finalizing commit of block with 0 txs module=consensus height=91 hash=F671D562C7B9242900A286E1882EE64E5556FE9E root=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD - I[10-04|13:54:30.405] Block{ - Header{ - ChainID: test-chain-3MNw2N - Height: 91 - Time: 2017-10-04 13:54:30.393 +0000 UTC - NumTxs: 0 - LastBlockID: F15AB8BEF9A6AAB07E457A6E16BC410546AA4DC6:1:D505DA273544 - LastCommit: 56FEF2EFDB8B37E9C6E6D635749DF3169D5F005D - Data: - Validators: CE25FBFF2E10C0D51AA1A07C064A96931BC8B297 - App: E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD - }#F671D562C7B9242900A286E1882EE64E5556FE9E - Data{ - - }# - Commit{ - BlockID: F15AB8BEF9A6AAB07E457A6E16BC410546AA4DC6:1:D505DA273544 - Precommits: Vote{0:125B0E3C5512 90/00/2(Precommit) F15AB8BEF9A6 {/FE98E2B956F0.../}} - }#56FEF2EFDB8B37E9C6E6D635749DF3169D5F005D - }#F671D562C7B9242900A286E1882EE64E5556FE9E module=consensus - I[10-04|13:54:30.408] Executed block module=state height=91 validTxs=0 invalidTxs=0 - I[10-04|13:54:30.410] Committed state module=state height=91 txs=0 hash=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD - I[10-04|13:54:30.410] Recheck txs module=mempool numtxs=0 height=91 - -## List of modules - -Here is the list of modules you may encounter in Tendermint's log and a -little overview what they do. - -- `abci-client` As mentioned in [Application Development Guide](./app-development.md), Tendermint acts as an ABCI - client with respect to the application and maintains 3 connections: - mempool, consensus and query. The code used by Tendermint Core can - be found [here](https://github.com/tendermint/tendermint/tree/develop/abci/client). -- `blockchain` Provides storage, pool (a group of peers), and reactor - for both storing and exchanging blocks between peers. -- `consensus` The heart of Tendermint core, which is the - implementation of the consensus algorithm. Includes two - "submodules": `wal` (write-ahead logging) for ensuring data - integrity and `replay` to replay blocks and messages on recovery - from a crash. -- `events` Simple event notification system. The list of events can be - found - [here](https://github.com/tendermint/tendermint/blob/master/types/events.go). - You can subscribe to them by calling `subscribe` RPC method. Refer - to [RPC docs](./specification/rpc.md) for additional information. -- `mempool` Mempool module handles all incoming transactions, whenever - they are coming from peers or the application. -- `p2p` Provides an abstraction around peer-to-peer communication. For - more details, please check out the - [README](https://github.com/tendermint/tendermint/blob/master/p2p/README.md). -- `rpc` [Tendermint's RPC](./specification/rpc.md). -- `rpc-server` RPC server. For implementation details, please read the - [README](https://github.com/tendermint/tendermint/blob/master/rpc/lib/README.md). -- `state` Represents the latest state and execution submodule, which - executes blocks against the application. -- `types` A collection of the publicly exposed types and methods to - work with them. diff --git a/docs/images/tmint-logo-blue.png b/docs/images/tmint-logo-blue.png deleted file mode 100644 index cc4c8fb82..000000000 Binary files a/docs/images/tmint-logo-blue.png and /dev/null differ diff --git a/docs/index.rst b/docs/index.rst index b3158c219..bafbec354 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,7 +8,7 @@ Welcome to Tendermint! This location for our documentation has been deprecated, please see: -- https://tendermint.com/docs +- https://tendermint.com/docs/ The last version built by Read The Docs will still be available at: diff --git a/docs/indexing-transactions.md b/docs/indexing-transactions.md deleted file mode 100644 index 93a61fe6b..000000000 --- a/docs/indexing-transactions.md +++ /dev/null @@ -1,89 +0,0 @@ -# Indexing Transactions - -Tendermint allows you to index transactions and later query or subscribe -to their results. - -Let's take a look at the `[tx_index]` config section: - - ##### transactions indexer configuration options ##### - [tx_index] - - # What indexer to use for transactions - # - # Options: - # 1) "null" (default) - # 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). - indexer = "kv" - - # Comma-separated list of tags to index (by default the only tag is tx hash) - # - # It's recommended to index only a subset of tags due to possible memory - # bloat. This is, of course, depends on the indexer's DB and the volume of - # transactions. - index_tags = "" - - # When set to true, tells indexer to index all tags. Note this may be not - # desirable (see the comment above). IndexTags has a precedence over - # IndexAllTags (i.e. when given both, IndexTags will be indexed). - index_all_tags = false - -By default, Tendermint will index all transactions by their respective -hashes using an embedded simple indexer. Note, we are planning to add -more options in the future (e.g., Postgresql indexer). - -## Adding tags - -In your application's `DeliverTx` method, add the `Tags` field with the -pairs of UTF-8 encoded strings (e.g. "account.owner": "Bob", "balance": -"100.0", "date": "2018-01-02"). - -Example: - - func (app *KVStoreApplication) DeliverTx(tx []byte) types.Result { - ... - tags := []cmn.KVPair{ - {[]byte("account.name"), []byte("igor")}, - {[]byte("account.address"), []byte("0xdeadbeef")}, - {[]byte("tx.amount"), []byte("7")}, - } - return types.ResponseDeliverTx{Code: code.CodeTypeOK, Tags: tags} - } - -If you want Tendermint to only index transactions by "account.name" tag, -in the config set `tx_index.index_tags="account.name"`. If you to index -all tags, set `index_all_tags=true` - -Note, there are a few predefined tags: - -- `tm.event` (event type) -- `tx.hash` (transaction's hash) -- `tx.height` (height of the block transaction was committed in) - -Tendermint will throw a warning if you try to use any of the above keys. - -## Querying transactions - -You can query the transaction results by calling `/tx_search` RPC -endpoint: - - curl "localhost:26657/tx_search?query=\"account.name='igor'\"&prove=true" - -Check out [API docs](https://tendermint.github.io/slate/?shell#txsearch) -for more information on query syntax and other options. - -## Subscribing to transactions - -Clients can subscribe to transactions with the given tags via Websocket -by providing a query to `/subscribe` RPC endpoint. - - { - "jsonrpc": "2.0", - "method": "subscribe", - "id": "0", - "params": { - "query": "account.name='igor'" - } - } - -Check out [API docs](https://tendermint.github.io/slate/#subscribe) for -more information on query syntax and other options. diff --git a/docs/interviews/tendermint-bft.md b/docs/interviews/tendermint-bft.md new file mode 100644 index 000000000..8b3ad5743 --- /dev/null +++ b/docs/interviews/tendermint-bft.md @@ -0,0 +1,250 @@ +# Interview Transcript with Tendermint core researcher, Zarko Milosevic, by Chjango + +**ZM**: Regarding leader election, it's round robin, but a weighted one. You +take into account the amount of bonded tokens. Depending on how much weight +they have of voting power, they would be elected more frequently. So we do +rotate, but just the guys who are having more voting power would be elected +more frequently. We are having 4 validators, and 1 of them have 2 times more +voting power, they have 2 times more elected as a leader. + +**CC**: 2x more absolute voting power or probabilistic voting power? + +**ZM**: It's actually very deterministic. It's not probabilistic at all. See +[Tendermint proposal election specification][1]. In Tendermint, there is no +pseudorandom leader election. It's a deterministic protocol. So leader election +is a built-in function in the code, so you know exactly—depending on the voting +power in the validator set, you'd know who exactly would be the leader in round +x, x + 1, and so on. There is nothing random there; we are not trying to hide +who would be the leader. It's really well known. It's just that there is a +function, it's a mathematical function, and it's just basically—it's kind of an +implementation detail—it starts from the voting power, and when you are +elected, you get decreased some number, and in each round you keep increasing +depending on your voting power, so that you are elected after k rounds again. +But knowing the validator set and the voting power, it's very simple function, +you can calculate yourself to know exactly who would be next. For each round, +this function will return you the leader for that round. In every round, we do +this computation. It's all part of the same flow. It enforces the properties +which are: proportional to your voting power, you will be elected, and we keep +changing the leaders. So it can't happen to have one guy being more elected +than other guys, if they have the same voting power. So one time it will be guy +B, and next time it will be guy B1. So it's not random. + +**CC**: Assuming the validator set remains unchanged for a month, then if you +run this function, are you able to know exactly who is going to go for that +entire month? + +**ZM**: Yes. + +**CC**: What're the attack scenarios for this? + +**ZM**: This is something which is easily attacked by people who argue that +Tendermint is not decentralized enough. They say that by knowing the leader, +you can DDoS the leader. And by DDoSing the leader, you are able to stop the +progress. Because it's true. If you would be able to DDoS the leader, the +leader would not be able to propose and then effectively will not be making +progress. How we are addressing this thing is Sentry Architecture. So the +validator—or at least a proper validator—will never be available. You don't +know the ip address of the validator. You are never able to open the connection +to the validator. So validator is spawning sentry nodes and this is the single +administration domain and there is only connection from validator in the sense +of sentry nodes. And ip address of validator is not shared in the p2p network. +It’s completely private. This is our answer to DDoS attack. By playing clever +at this sentry node architecture and spawning additional sentry nodes in case, +for ex your sentry nodes are being DDoS’d, bc your sentry nodes are public, +then you will be able to connect to sentry nodes. this is where we will expect +the validator to be clever enough that so that in case they are DDoS’d at the +sentry level, they will spawn a different sentry node and then you communicate +through them. We are in a sense pushing the responsibility on the validator. + +**CC**: So if I understand this correctly, the public identity of the validator +doesn’t even matter because that entity can obfuscate where their real full +nodes reside via a proxy through this sentry architecture. + +**ZM**: Exactly. So you do know what is the address or identity of the validator +but you don’t know the network address of it; you’re not able to attack it +because you don’t know where they are. They are completely obfuscated by the +sentry nodes. There is now, if you really want to figure out….There is the +Tendermint protocol, the structure of the protocol is not fully decentralized +in the sense that the flow of information is going from the round proposer, or +the round coordinator, to other nodes, and then after they receive this it’s +basically like [inaudible: “O to 1”]. So by tracking where this information is +coming from, you might be able to identify who are the sentry nodes behind it. +So if you are doing some network analysis, you might be able to deduce +something. If the thing would be completely stuck, where the validator would +never change their sentry nodes or ip addresses of sentry nodes, it could be +possible to deduce something. This is where economic game comes into play. We +are doing an economics game there. We say that it’s a validator business. If +they are not able to hide themselves well enough, they’ll be DDoS’d and they +will be kicked out of the active validator set. So it’s in their interest. + +[Proposer Selection Procedure in Tendermint][1]. This is how it should work no +matter what implementation. + +**CC**: Going back to the proposer, lets say the validator does get DDoS’d, then +the proposer goes down. What happens? + +**ZM**: How the proposal mechanism works—there’s nothing special there—it goes +through a sequence of rounds. Normal execution of Tendermint is that for each +height, we are going through a sequence of rounds, starting from round 0, and +then we are incrementing through the rounds. The nodes are moving through the +rounds as part of normal procedure until they decide to commit. In case you +have one proposer—the proposer of a single round—being DDoS’d, we will probably +not decide in that round, because he will not be able to send his proposal. So +we will go to the next round, and hopefully the next proposer will be able to +communicate with the validators and then we’ll decide in the next round. + +**CC**: Are there timeouts between one round to another, if a round gets +skipped? + +**ZM**: There are timeouts. It’s a bit more complex. I think we have 5 timeouts. +We may be able to simplify this a bit. What is important to understand is: The +only condition which needs to be satisfied so we can go to the next round is +that your validator is able to communicate with more than 2/3rds of voting +power. To be able to move to the next round, you need to receive more than +2/3rd of voting power equivalent of pre-commit messages. + +We have two kinds of messages: 1) Proposal: Where the current round proposer is +suggesting how the next block should look like. This is first one. Every round +starts with proposer sending a proposal. And then there are two more rounds of +voting, where the validator is trying to agree whether they will commit the +proposal or not. And the first of such vote messages is called `pre-vote` and +the second one is `pre-commit`. Now, to be able to move between steps, between +a `pre-vote` and `pre-commit` step, you need to receive enough number of +messages where if message is sent by validator A, then also this message has a +weight, or voting power which is equal to the voting power of the validator who +sent this message. Before you receive more than 2/3 of voting power messages, you are not +able to move to the higher round. Only when you receive more than 2/3 of +messages, you actually start the timeout. The timeout is happening only after +you receive enough messages. And it happens because of the asynchrony of the +message communication so you give more time to guys with this timeout to +receive some messages which are maybe delayed. + +**CC**: In this way that you just described via the whole network gossiping +before we commit a block, that is what makes Tendermint BFT deterministic in a +partially synchronous setting vs Bitcoin which has synchrony assumptions +whereby blocks are first mined and then gossiped to the network. + +**ZM**: It's true that in Bitcoin, this is where the synchrony assumption comes +to play because if they're not able to communicate timely, they are not able to +converge to a single longest chain. Why are they not able to decrease timeout +in Bitcoin? Because if they would decrease, there would be so many forks that +they won't be able to converge to a single chain. By increasing this +complexity and the block time, they're able to have not so many forks. This is +effectively the timing assumption—the block duration in a sense because it's +enough time so that the decided block is propagated through the network before +someone else start deciding on the same block and creating forks. It's very +different from the consensus algorithms in a distributed computing setup where +Tendermint fits. In Tendermint, where we talk about the timing dependency, they +are really part of this 3-communication step protocol I just explained. We have +the following assumption: If the good guys are not able to communicate timely +and reliably without having message loss within a round, the Tendermint will +not make progress—it will not be making blocks. So if you are in a completely +asynchronous network where messages get lost or delayed unpredictably, +Tendermint will not make progress, it will not create forks, but it will not +decide, it will not tell you what is the next block. For termination, it's a +liveness property of consensus. It's a guarantee to decide. We do need timing +assumptions. Within a round, correct validators are able to communicate to each +other the consensus messages, not the transactions, but consensus messages. +They need to communicate in a timely and reliable fashion. But this doesn't +need to hold forever. It's just that what we are assuming when we say it's a +partially synchronous system, we assume that the system will be going through a +period of asynchrony, where we don't have this guarantee; the messages will be +delayed or some will be lost and then will not make progress for some period of +time, or we're not guaranteed to make progress. And the period of synchrony +where these guarantees hold. And if we think about internet, internet is best +described using such a model. Sometimes when we send a message to SF to +Belgrade, it takes 100 ms, sometimes it takes 300 ms, sometimes it takes 1 s. +But in most cases, it takes 100 ms or less than this. + +There is one thing which would be really nice if you understand it. In a global +wide area network, we can't make assumption on the communication unless we are +very conservative about this. If you want to be very fast, then we can't make +assumption and say we'll be for sure communicating with 1 ms communication +delay. Because of the complexity and various congestion issues on the network, +it might happen that during a short period of time, this doesn't hold. If this +doesn't hold and you depend on this for correctness of your protocol, you will +have a fork. So the partially synchronous protocol, most of them like +Tendermint, they don't depend on the timing assumption from the internet for +correctness. This is where we state: safety always. So we never make a fork no +matter how bad our estimates about the internet communication delays are. We'll +never make a fork, but we do make some assumptions, and these assumptions are +built-in our timeouts in our protocol which are actually adaptive. So we are +adapting to the current condition and this is where we're saying...We do assume +some properties, or some communication delays, to eventually hold on the +network. During this period, we guarantee that we will be deciding and +committing blocks. And we will be doing this very fast. We will be basically on +the speed of the current network. + +**CC**: We make liveness assumptions based on the integrity of the validator +businesses, assuming they're up and running fine. + +**ZM**: This is where we are saying, the protocol will be live if we have at +most 1/3, or a bit less than 1/3, of faulty validators. Which means that all +other guys should be online and available. This is also for liveness. This is +related to the condition that we are not able to make progress in rounds if we +don't receive enough messages. If half of our voting power, or half of our +validators are down, we don't have enough messages, so the protocol is +completely blocked. It doesn't make progress in a round, which means it's not +able to be signed. So it's completely critical for Tendermint that we make +progress in rounds. It's like breathing. Tendermint is breathing. If there is +no progress, it's dead; it's blocked, we're not able to breathe, that's why +we're not able to make progress. + +**CC**: How does Tendermint compare to other consensus algos? + +**ZM**: Tendermint is a very interesting protocol. From an academic point of +view, I'm convinced that there is value there. Hopefully, we prove it by +publishing it on some good conference. What is novel is, if we compare first +Tendermint to this existing BFT problem, it's a continuation of academic +research on BFT consensus. What is novel in Tendermint is that it somehow +merges consensus protocol with gossip. This is completely novel idea. +Originally, in BFT, people were assuming the single administration domain, +small number of nodes, local area network, 4-7 nodes max. If you look at the +research paper, 99% of them have this kind of setup. Wide area was studied but +there is significantly less work in wide area networks. No one studied how to +scale those protocols to hundreds or thousands of nodes before blockchain. It +was always a single administration domain. So in Tendermint now, you are able +to reach consensus among different administration domains which are potentially +hundreds of them in wide area network. The system model is potentially harder +because we have more nodes and wide area network. The second thing is that: +normally, in bft protocols, the protocol itself are normally designed in a way +that has two phases, or two parts. The one which is called normal case, which +is normally quite simple, in this normal case. In spite of some failures, which +are part of the normal execution of the protocol, like for example leader +crashes or leader being DDoS'd, they need to go through a quite complex +protocol, which is like being called view change or leader election or +whatever. These two parts of the same protocol are having quite different +complexity. And most of the people only understand this normal case. In +Tendermint, there is no this difference. We have only one protocol, there are +not two protocols. It's always the same steps and they are much closer to the +normal case than this complex view change protocol. + +_This is a bit too technical but this is on a high level things to remember, +that: The system it addresses it's harder than the others and the algorithm +complexity in Tendermint is simpler._ The initial goal of Jae and Bucky which +is inspired by Raft, is that it's simpler so normal engineers could understand. + +**CC**: Can you expand on the termination requirement? + +_Important point about Liveness in Tendermint_ + +**ZM**: In Tendermint, we are saying, for termination, we are making assumption +that the system is partially synchronous. And in a partially synchronous system +model, we are able to mathematically prove that the protocol will make +decisions; it will decide. + +**CC**: What is a persistent peer? + +**ZM**: It's a list of peer identities, which you will try to establish +connection to them, in case connection is broken, Tendermint will automatically +try to reestablish connection. These are important peers, you will really try +persistently to establish connection to them. For other peers, you just drop it +and try from your address book to connect to someone else. The address book is a +list of peers which you discover that they exist, because we are talking about a +very dynamic network—so the nodes are coming and going away—and the gossiping +protocol is discovering new nodes and gossiping them around. So every node will +keep the list of new nodes it discovers, and when you need to establish +connection to a peer, you'll look to address book and get some addresses from +there. There's categorization/ranking of nodes there. + +[1]: https://github.com/tendermint/tendermint/blob/master/docs/spec/reactors/consensus/proposer-selection.md diff --git a/docs/install.md b/docs/introduction/install.md similarity index 99% rename from docs/install.md rename to docs/introduction/install.md index ff101715b..d02691102 100644 --- a/docs/install.md +++ b/docs/introduction/install.md @@ -57,7 +57,7 @@ cd $GOPATH/src/github.com/tendermint/tendermint make install ``` -To upgrade, run +To upgrade, run ``` cd $GOPATH/src/github.com/tendermint/tendermint diff --git a/docs/introduction.md b/docs/introduction/introduction.md similarity index 92% rename from docs/introduction.md rename to docs/introduction/introduction.md index 4503e195e..d43fa9b2d 100644 --- a/docs/introduction.md +++ b/docs/introduction/introduction.md @@ -61,13 +61,14 @@ providing basic services to distributed systems, such as dynamic configuration, service discovery, locking, leader-election, and so on. Tendermint is in essence similar software, but with two key differences: + - It is Byzantine Fault Tolerant, meaning it can only tolerate up to a -1/3 of failures, but those failures can include arbitrary behaviour - -including hacking and malicious attacks. - It does not specify a -particular application, like a fancy key-value store. Instead, it -focuses on arbitrary state machine replication, so developers can build -the application logic that's right for them, from key-value store to -cryptocurrency to e-voting platform and beyond. + 1/3 of failures, but those failures can include arbitrary behaviour - + including hacking and malicious attacks. - It does not specify a + particular application, like a fancy key-value store. Instead, it + focuses on arbitrary state machine replication, so developers can build + the application logic that's right for them, from key-value store to + cryptocurrency to e-voting platform and beyond. The layout of this Tendermint website content is also ripped directly and without shame from [consul.io](https://www.consul.io/) and the other @@ -167,16 +168,16 @@ maintains a fully audited Unspent Transaction Output (UTXO) database. If one wanted to create a Bitcoin-like system on top of ABCI, Tendermint Core would be responsible for -- Sharing blocks and transactions between nodes -- Establishing a canonical/immutable order of transactions - (the blockchain) +- Sharing blocks and transactions between nodes +- Establishing a canonical/immutable order of transactions + (the blockchain) The application will be responsible for -- Maintaining the UTXO database -- Validating cryptographic signatures of transactions -- Preventing transactions from spending non-existent transactions -- Allowing clients to query the UTXO database. +- Maintaining the UTXO database +- Validating cryptographic signatures of transactions +- Preventing transactions from spending non-existent transactions +- Allowing clients to query the UTXO database. Tendermint is able to decompose the blockchain design by offering a very simple API (ie. the ABCI) between the application process and consensus @@ -242,14 +243,14 @@ Java, C++, Python, or Go. Game programmers and blockchain developers are already familiar with creating deterministic programs by avoiding sources of non-determinism such as: -- random number generators (without deterministic seeding) -- race conditions on threads (or avoiding threads altogether) -- the system clock -- uninitialized memory (in unsafe programming languages like C - or C++) -- [floating point - arithmetic](http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/) -- language features that are random (e.g. map iteration in Go) +- random number generators (without deterministic seeding) +- race conditions on threads (or avoiding threads altogether) +- the system clock +- uninitialized memory (in unsafe programming languages like C + or C++) +- [floating point + arithmetic](http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/) +- language features that are random (e.g. map iteration in Go) While programmers can avoid non-determinism by being careful, it is also possible to create a special linter or static analyzer for each language @@ -298,8 +299,8 @@ introduces a few **locking** rules which modulate which paths can be followed in the flow diagram. Once a validator precommits a block, it is locked on that block. Then, -1) it must prevote for the block it is locked on -2) it can only unlock, and precommit for a new block, if there is a +1. it must prevote for the block it is locked on +2. it can only unlock, and precommit for a new block, if there is a polka for that block in a later round ## Stake diff --git a/docs/examples/getting-started.md b/docs/introduction/quick-start.md similarity index 66% rename from docs/examples/getting-started.md rename to docs/introduction/quick-start.md index ed61f9998..8e4908784 100644 --- a/docs/examples/getting-started.md +++ b/docs/introduction/quick-start.md @@ -3,17 +3,16 @@ ## Overview This is a quick start guide. If you have a vague idea about how Tendermint -works and want to get started right away, continue. Otherwise, [review the -documentation](http://tendermint.readthedocs.io/en/master/). +works and want to get started right away, continue. ## Install ### Quick Install -On a fresh Ubuntu 16.04 machine can be done with [this script](https://git.io/vpgEI), like so: +On a fresh Ubuntu 16.04 machine can be done with [this script](https://git.io/fFfOR), like so: ``` -curl -L https://git.io/vpgEI | bash +curl -L https://git.io/fFfOR | bash source ~/.profile ``` @@ -24,6 +23,7 @@ The script is also used to facilitate cluster deployment below. ### Manual Install Requires: + - `go` minimum version 1.10 - `$GOPATH` environment variable must be set - `$GOPATH/bin` must be on your `$PATH` (see https://github.com/tendermint/tendermint/wiki/Setting-GOPATH) @@ -43,7 +43,7 @@ Confirm installation: ``` $ tendermint version -0.18.0-XXXXXXX +0.23.0-dev ``` ## Initialization @@ -122,22 +122,22 @@ First create four Ubuntu cloud machines. The following was tested on Digital Ocean Ubuntu 16.04 x64 (3GB/1CPU, 20GB SSD). We'll refer to their respective IP addresses below as IP1, IP2, IP3, IP4. -Then, `ssh` into each machine, and execute [this script](https://git.io/vNLfY): +Then, `ssh` into each machine, and execute [this script](https://git.io/fFfOR): ``` -curl -L https://git.io/vpgEI | bash +curl -L https://git.io/fFfOR | bash source ~/.profile ``` This will install `go` and other dependencies, get the Tendermint source code, then compile the `tendermint` binary. -Next, `cd` into `docs/examples`. Each command below should be run from each node, in sequence: +Next, use the `tendermint testnet` command to create four directories of config files (found in `./mytestnet`) and copy each directory to the relevant machine in the cloud, so that each machine has `$HOME/mytestnet/node[0-3]` directory. Then from each machine, run: ``` -tendermint node --home ./node0 --proxy_app=kvstore --p2p.persistent_peers="167b80242c300bf0ccfb3ced3dec60dc2a81776e@IP1:26656,3c7a5920811550c04bf7a0b2f1e02ab52317b5e6@IP2:26656,303a1a4312c30525c99ba66522dd81cca56a361a@IP3:26656,b686c2a7f4b1b46dca96af3a0f31a6a7beae0be4@IP4:26656" -tendermint node --home ./node1 --proxy_app=kvstore --p2p.persistent_peers="167b80242c300bf0ccfb3ced3dec60dc2a81776e@IP1:26656,3c7a5920811550c04bf7a0b2f1e02ab52317b5e6@IP2:26656,303a1a4312c30525c99ba66522dd81cca56a361a@IP3:26656,b686c2a7f4b1b46dca96af3a0f31a6a7beae0be4@IP4:26656" -tendermint node --home ./node2 --proxy_app=kvstore --p2p.persistent_peers="167b80242c300bf0ccfb3ced3dec60dc2a81776e@IP1:26656,3c7a5920811550c04bf7a0b2f1e02ab52317b5e6@IP2:26656,303a1a4312c30525c99ba66522dd81cca56a361a@IP3:26656,b686c2a7f4b1b46dca96af3a0f31a6a7beae0be4@IP4:26656" -tendermint node --home ./node3 --proxy_app=kvstore --p2p.persistent_peers="167b80242c300bf0ccfb3ced3dec60dc2a81776e@IP1:26656,3c7a5920811550c04bf7a0b2f1e02ab52317b5e6@IP2:26656,303a1a4312c30525c99ba66522dd81cca56a361a@IP3:26656,b686c2a7f4b1b46dca96af3a0f31a6a7beae0be4@IP4:26656" +tendermint node --home ./mytestnet/node0 --proxy_app=kvstore --p2p.persistent_peers="ID1@IP1:26656,ID2@IP2:26656,ID3@IP3:26656,ID4@IP4:26656" +tendermint node --home ./mytestnet/node1 --proxy_app=kvstore --p2p.persistent_peers="ID1@IP1:26656,ID2@IP2:26656,ID3@IP3:26656,ID4@IP4:26656" +tendermint node --home ./mytestnet/node2 --proxy_app=kvstore --p2p.persistent_peers="ID1@IP1:26656,ID2@IP2:26656,ID3@IP3:26656,ID4@IP4:26656" +tendermint node --home ./mytestnet/node3 --proxy_app=kvstore --p2p.persistent_peers="ID1@IP1:26656,ID2@IP2:26656,ID3@IP3:26656,ID4@IP4:26656" ``` Note that after the third node is started, blocks will start to stream in diff --git a/docs/networks/deploy-testnets.md b/docs/networks/deploy-testnets.md new file mode 100644 index 000000000..88e5c6f72 --- /dev/null +++ b/docs/networks/deploy-testnets.md @@ -0,0 +1,74 @@ +# Deploy a Testnet + +Now that we've seen how ABCI works, and even played with a few +applications on a single validator node, it's time to deploy a test +network to four validator nodes. + +## Manual Deployments + +It's relatively easy to setup a Tendermint cluster manually. The only +requirements for a particular Tendermint node are a private key for the +validator, stored as `priv_validator.json`, a node key, stored as +`node_key.json` and a list of the public keys of all validators, stored +as `genesis.json`. These files should be stored in +`~/.tendermint/config`, or wherever the `$TMHOME` variable might be set +to. + +Here are the steps to setting up a testnet manually: + +1. Provision nodes on your cloud provider of choice +2. Install Tendermint and the application of interest on all nodes +3. Generate a private key and a node key for each validator using + `tendermint init` +4. Compile a list of public keys for each validator into a + `genesis.json` file and replace the existing file with it. +5. Run + `tendermint node --proxy_app=kvstore --p2p.persistent_peers=< peer addresses >` on each node, where `< peer addresses >` is a comma separated + list of the ID@IP:PORT combination for each node. The default port for + Tendermint is `26656`. The ID of a node can be obtained by running + `tendermint show_node_id` command. Thus, if the IP addresses of your nodes + were `192.168.0.1, 192.168.0.2, 192.168.0.3, 192.168.0.4`, the command + would look like: + +``` +tendermint node --proxy_app=kvstore --p2p.persistent_peers=96663a3dd0d7b9d17d4c8211b191af259621c693@192.168.0.1:26656, 429fcf25974313b95673f58d77eacdd434402665@192.168.0.2:26656, 0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@192.168.0.3:26656, f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@192.168.0.4:26656 +``` + +After a few seconds, all the nodes should connect to each other and +start making blocks! For more information, see the Tendermint Networks +section of [the guide to using Tendermint](./using-tendermint.md). + +But wait! Steps 3, 4 and 5 are quite manual. Instead, use the `tendermint testnet` command. By default, running `tendermint testnet` will create all the +required files, but it won't populate the list of persistent peers. It will do +it however if you provide the `--populate-persistent-peers` flag and optional +`--starting-ip-address` flag. Run `tendermint testnet --help` for more details +on the available flags. + +``` +tendermint testnet --populate-persistent-peers --starting-ip-address 192.168.0.1 +``` + +This command will generate four folders, prefixed with "node" and put them into +the "./mytestnet" directory by default. + +As you might imagine, this command is useful for manual or automated +deployments. + +## Automated Deployments + +The easiest and fastest way to get a testnet up in less than 5 minutes. + +### Local + +With `docker` and `docker-compose` installed, run the command: + +``` +make localnet-start +``` + +from the root of the tendermint repository. This will spin up a 4-node +local testnet. Review the target in the Makefile to debug any problems. + +### Cloud + +See the [next section](./terraform-and-ansible.html) for details. diff --git a/docs/specification/fast-sync.rst b/docs/networks/fast-sync.md similarity index 62% rename from docs/specification/fast-sync.rst rename to docs/networks/fast-sync.md index c98ec43a3..e92d82394 100644 --- a/docs/specification/fast-sync.rst +++ b/docs/networks/fast-sync.md @@ -1,8 +1,4 @@ -Fast Sync -========= - -Background ----------- +# Fast Sync In a proof of work blockchain, syncing with the chain is the same process as staying up-to-date with the consensus: download blocks, and @@ -14,21 +10,19 @@ scratch can take a very long time. It's much faster to just download blocks and check the merkle tree of validators than to run the real-time consensus gossip protocol. -Fast Sync ---------- +## Using Fast Sync -To support faster syncing, tendermint offers a ``fast-sync`` mode, which -is enabled by default, and can be toggled in the ``config.toml`` or via -``--fast_sync=false``. +To support faster syncing, tendermint offers a `fast-sync` mode, which +is enabled by default, and can be toggled in the `config.toml` or via +`--fast_sync=false`. In this mode, the tendermint daemon will sync hundreds of times faster than if it used the real-time consensus process. Once caught up, the daemon will switch out of fast sync and into the normal consensus mode. -After running for some time, the node is considered ``caught up`` if it +After running for some time, the node is considered `caught up` if it has at least one peer and it's height is at least as high as the max -reported peer height. See `the IsCaughtUp -method `__. +reported peer height. See [the IsCaughtUp +method](https://github.com/tendermint/tendermint/blob/b467515719e686e4678e6da4e102f32a491b85a0/blockchain/pool.go#L128). If we're lagging sufficiently, we should go back to fast syncing, but -this is an open issue: -https://github.com/tendermint/tendermint/issues/129 +this is an [open issue](https://github.com/tendermint/tendermint/issues/129). diff --git a/docs/terraform-and-ansible.md b/docs/networks/terraform-and-ansible.md similarity index 92% rename from docs/terraform-and-ansible.md rename to docs/networks/terraform-and-ansible.md index 55c38cef7..5a4b9c53b 100644 --- a/docs/terraform-and-ansible.md +++ b/docs/networks/terraform-and-ansible.md @@ -12,17 +12,17 @@ script](https://github.com/tendermint/tendermint/blob/develop/networks/remote/in that can be run on a fresh DO droplet and will automatically spin up a 4 node testnet. The script more or less does everything described below. -- Install [Terraform](https://www.terraform.io/downloads.html) and - [Ansible](http://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) - on a Linux machine. -- Create a [DigitalOcean API - token](https://cloud.digitalocean.com/settings/api/tokens) with read - and write capability. -- Install the python dopy package (`pip install dopy`) -- Create SSH keys (`ssh-keygen`) -- Set environment variables: - -``` +- Install [Terraform](https://www.terraform.io/downloads.html) and + [Ansible](http://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) + on a Linux machine. +- Create a [DigitalOcean API + token](https://cloud.digitalocean.com/settings/api/tokens) with read + and write capability. +- Install the python dopy package (`pip install dopy`) +- Create SSH keys (`ssh-keygen`) +- Set environment variables: + +``` export DO_API_TOKEN="abcdef01234567890abcdef01234567890" export SSH_KEY_FILE="$HOME/.ssh/id_rsa.pub" ``` @@ -44,6 +44,7 @@ then: terraform init terraform apply -var DO_API_TOKEN="$DO_API_TOKEN" -var SSH_KEY_FILE="$SSH_KEY_FILE" ``` + and you will get a list of IP addresses that belong to your droplets. With the droplets created and running, let's setup Ansible. @@ -154,7 +155,7 @@ page](https://app.logz.io/#/dashboard/data-sources/Filebeat), then: ``` yum install systemd-devel || echo "This will only work on RHEL-based systems." apt-get install libsystemd-dev || echo "This will only work on Debian-based systems." - + go get github.com/mheese/journalbeat ansible-playbook -i inventory/digital_ocean.py -l sentrynet logzio.yml -e LOGZIO_TOKEN=ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 ``` diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 000000000..c76bb37c4 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,37 @@ +{ + "dependencies": { + "prettier": "^1.13.7", + "remark-cli": "^5.0.0", + "remark-lint-no-dead-urls": "^0.3.0", + "textlint": "^10.2.1" + }, + "name": "tendermint", + "description": "Tendermint Core Documentation", + "version": "0.0.1", + "main": "README.md", + "devDependencies": {}, + "scripts": { + "lint:json": "prettier \"**/*.json\" --write", + "lint:md": "prettier \"**/*.md\" --write && remark . && textlint \"md/**\"", + "lint": "yarn lint:json && yarn lint:md" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/tendermint/tendermint.git" + }, + "keywords": [ + "tendermint", + "blockchain" + ], + "author": "Tendermint", + "license": "ISC", + "bugs": { + "url": "https://github.com/tendermint/tendermint/issues" + }, + "homepage": "https://tendermint.com/docs/", + "remarkConfig": { + "plugins": [ + "remark-lint-no-dead-urls" + ] + } +} diff --git a/docs/determinism.md b/docs/research/determinism.md similarity index 100% rename from docs/determinism.md rename to docs/research/determinism.md diff --git a/docs/transactional-semantics.md b/docs/research/transactional-semantics.md similarity index 100% rename from docs/transactional-semantics.md rename to docs/research/transactional-semantics.md diff --git a/docs/spec/blockchain/encoding.md b/docs/spec/blockchain/encoding.md index 16902d099..49c88475b 100644 --- a/docs/spec/blockchain/encoding.md +++ b/docs/spec/blockchain/encoding.md @@ -149,7 +149,33 @@ func MakeParts(obj interface{}, partSize int) []Part ## Merkle Trees -Simple Merkle trees are used in numerous places in Tendermint to compute a cryptographic digest of a data structure. +For an overview of Merkle trees, see +[wikipedia](https://en.wikipedia.org/wiki/Merkle_tree) + + +A Simple Tree is a simple compact binary tree for a static list of items. Simple Merkle trees are used in numerous places in Tendermint to compute a cryptographic digest of a data structure. In a Simple Tree, the transactions and validation signatures of a block are hashed using this simple merkle tree logic. + +If the number of items is not a power of two, the tree will not be full +and some leaf nodes will be at different levels. Simple Tree tries to +keep both sides of the tree the same size, but the left side may be one +greater, for example: + +``` + Simple Tree with 6 items Simple Tree with 7 items + + * * + / \ / \ + / \ / \ + / \ / \ + / \ / \ + * * * * + / \ / \ / \ / \ + / \ / \ / \ / \ + / \ / \ / \ / \ + * h2 * h5 * * * h6 + / \ / \ / \ / \ / \ +h0 h1 h3 h4 h0 h1 h2 h3 h4 h5 +``` Tendermint always uses the `TMHASH` hash function, which is the first 20-bytes of the SHA256: @@ -235,6 +261,18 @@ func computeHashFromAunts(index, total int, leafHash []byte, innerHashes [][]byt } ``` +### Simple Tree with Dictionaries + +The Simple Tree is used to merkelize a list of items, so to merkelize a +(short) dictionary of key-value pairs, encode the dictionary as an +ordered list of ``KVPair`` structs. The block hash is such a hash +derived from all the fields of the block ``Header``. The state hash is +similarly derived. + +### IAVL+ Tree + +Because Tendermint only uses a Simple Merkle Tree, application developers are expect to use their own Merkle tree in their applications. For example, the IAVL+ Tree - an immutable self-balancing binary tree for persisting application state is used by the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk/blob/develop/docs/core/multistore.md) + ## JSON ### Amino diff --git a/docs/spec/consensus/consensus.md b/docs/spec/consensus/consensus.md index 1bf075773..d6804779c 100644 --- a/docs/spec/consensus/consensus.md +++ b/docs/spec/consensus/consensus.md @@ -1,9 +1,329 @@ -We are working to finalize an updated Tendermint specification with formal -proofs of safety and liveness. +# Byzantine Consensus Algorithm -In the meantime, see the [description in the -docs](http://tendermint.readthedocs.io/en/master/specification/byzantine-consensus-algorithm.html). +## Terms -There are also relevant but somewhat outdated descriptions in Jae Kwon's [original -whitepaper](https://tendermint.com/static/docs/tendermint.pdf) and Ethan Buchman's [master's -thesis](https://atrium.lib.uoguelph.ca/xmlui/handle/10214/9769). +- The network is composed of optionally connected *nodes*. Nodes + directly connected to a particular node are called *peers*. +- The consensus process in deciding the next block (at some *height* + `H`) is composed of one or many *rounds*. +- `NewHeight`, `Propose`, `Prevote`, `Precommit`, and `Commit` + represent state machine states of a round. (aka `RoundStep` or + just "step"). +- A node is said to be *at* a given height, round, and step, or at + `(H,R,S)`, or at `(H,R)` in short to omit the step. +- To *prevote* or *precommit* something means to broadcast a [prevote + vote](https://godoc.org/github.com/tendermint/tendermint/types#Vote) + or [first precommit + vote](https://godoc.org/github.com/tendermint/tendermint/types#FirstPrecommit) + for something. +- A vote *at* `(H,R)` is a vote signed with the bytes for `H` and `R` + included in its [sign-bytes](block-structure.html#vote-sign-bytes). +- *+2/3* is short for "more than 2/3" +- *1/3+* is short for "1/3 or more" +- A set of +2/3 of prevotes for a particular block or `` at + `(H,R)` is called a *proof-of-lock-change* or *PoLC* for short. + +## State Machine Overview + +At each height of the blockchain a round-based protocol is run to +determine the next block. Each round is composed of three *steps* +(`Propose`, `Prevote`, and `Precommit`), along with two special steps +`Commit` and `NewHeight`. + +In the optimal scenario, the order of steps is: + +``` +NewHeight -> (Propose -> Prevote -> Precommit)+ -> Commit -> NewHeight ->... +``` + +The sequence `(Propose -> Prevote -> Precommit)` is called a *round*. +There may be more than one round required to commit a block at a given +height. Examples for why more rounds may be required include: + +- The designated proposer was not online. +- The block proposed by the designated proposer was not valid. +- The block proposed by the designated proposer did not propagate + in time. +- The block proposed was valid, but +2/3 of prevotes for the proposed + block were not received in time for enough validator nodes by the + time they reached the `Precommit` step. Even though +2/3 of prevotes + are necessary to progress to the next step, at least one validator + may have voted `` or maliciously voted for something else. +- The block proposed was valid, and +2/3 of prevotes were received for + enough nodes, but +2/3 of precommits for the proposed block were not + received for enough validator nodes. + +Some of these problems are resolved by moving onto the next round & +proposer. Others are resolved by increasing certain round timeout +parameters over each successive round. + +## State Machine Diagram + +``` + +-------------------------------------+ + v |(Wait til `CommmitTime+timeoutCommit`) + +-----------+ +-----+-----+ + +----------> | Propose +--------------+ | NewHeight | + | +-----------+ | +-----------+ + | | ^ + |(Else, after timeoutPrecommit) v | ++-----+-----+ +-----------+ | +| Precommit | <------------------------+ Prevote | | ++-----+-----+ +-----------+ | + |(When +2/3 Precommits for block found) | + v | ++--------------------------------------------------------------------+ + | Commit | + | | + | * Set CommitTime = now; | + | * Wait for block, then stage/save/commit block; | + +--------------------------------------------------------------------+ +``` + +Background Gossip +================= + +A node may not have a corresponding validator private key, but it +nevertheless plays an active role in the consensus process by relaying +relevant meta-data, proposals, blocks, and votes to its peers. A node +that has the private keys of an active validator and is engaged in +signing votes is called a *validator-node*. All nodes (not just +validator-nodes) have an associated state (the current height, round, +and step) and work to make progress. + +Between two nodes there exists a `Connection`, and multiplexed on top of +this connection are fairly throttled `Channel`s of information. An +epidemic gossip protocol is implemented among some of these channels to +bring peers up to speed on the most recent state of consensus. For +example, + +- Nodes gossip `PartSet` parts of the current round's proposer's + proposed block. A LibSwift inspired algorithm is used to quickly + broadcast blocks across the gossip network. +- Nodes gossip prevote/precommit votes. A node `NODE_A` that is ahead + of `NODE_B` can send `NODE_B` prevotes or precommits for `NODE_B`'s + current (or future) round to enable it to progress forward. +- Nodes gossip prevotes for the proposed PoLC (proof-of-lock-change) + round if one is proposed. +- Nodes gossip to nodes lagging in blockchain height with block + [commits](https://godoc.org/github.com/tendermint/tendermint/types#Commit) + for older blocks. +- Nodes opportunistically gossip `HasVote` messages to hint peers what + votes it already has. +- Nodes broadcast their current state to all neighboring peers. (but + is not gossiped further) + +There's more, but let's not get ahead of ourselves here. + +## Proposals + +A proposal is signed and published by the designated proposer at each +round. The proposer is chosen by a deterministic and non-choking round +robin selection algorithm that selects proposers in proportion to their +voting power (see +[implementation](https://github.com/tendermint/tendermint/blob/develop/types/validator_set.go)). + +A proposal at `(H,R)` is composed of a block and an optional latest +`PoLC-Round < R` which is included iff the proposer knows of one. This +hints the network to allow nodes to unlock (when safe) to ensure the +liveness property. + +## State Machine Spec + +### Propose Step (height:H,round:R) + +Upon entering `Propose`: - The designated proposer proposes a block at +`(H,R)`. + +The `Propose` step ends: - After `timeoutProposeR` after entering +`Propose`. --> goto `Prevote(H,R)` - After receiving proposal block +and all prevotes at `PoLC-Round`. --> goto `Prevote(H,R)` - After +[common exit conditions](#common-exit-conditions) + +### Prevote Step (height:H,round:R) + +Upon entering `Prevote`, each validator broadcasts its prevote vote. + +- First, if the validator is locked on a block since `LastLockRound` + but now has a PoLC for something else at round `PoLC-Round` where + `LastLockRound < PoLC-Round < R`, then it unlocks. +- If the validator is still locked on a block, it prevotes that. +- Else, if the proposed block from `Propose(H,R)` is good, it + prevotes that. +- Else, if the proposal is invalid or wasn't received on time, it + prevotes ``. + +The `Prevote` step ends: - After +2/3 prevotes for a particular block or +``. -->; goto `Precommit(H,R)` - After `timeoutPrevote` after +receiving any +2/3 prevotes. --> goto `Precommit(H,R)` - After +[common exit conditions](#common-exit-conditions) + +### Precommit Step (height:H,round:R) + +Upon entering `Precommit`, each validator broadcasts its precommit vote. +- If the validator has a PoLC at `(H,R)` for a particular block `B`, it +(re)locks (or changes lock to) and precommits `B` and sets +`LastLockRound = R`. - Else, if the validator has a PoLC at `(H,R)` for +``, it unlocks and precommits ``. - Else, it keeps the lock +unchanged and precommits ``. + +A precommit for `` means "I didn’t see a PoLC for this round, but I +did get +2/3 prevotes and waited a bit". + +The Precommit step ends: - After +2/3 precommits for ``. --> +goto `Propose(H,R+1)` - After `timeoutPrecommit` after receiving any ++2/3 precommits. --> goto `Propose(H,R+1)` - After [common exit +conditions](#common-exit-conditions) + +### Common exit conditions + +- After +2/3 precommits for a particular block. --> goto + `Commit(H)` +- After any +2/3 prevotes received at `(H,R+x)`. --> goto + `Prevote(H,R+x)` +- After any +2/3 precommits received at `(H,R+x)`. --> goto + `Precommit(H,R+x)` + +### Commit Step (height:H) + +- Set `CommitTime = now()` +- Wait until block is received. --> goto `NewHeight(H+1)` + +### NewHeight Step (height:H) + +- Move `Precommits` to `LastCommit` and increment height. +- Set `StartTime = CommitTime+timeoutCommit` +- Wait until `StartTime` to receive straggler commits. --> goto + `Propose(H,0)` + +## Proofs + +### Proof of Safety + +Assume that at most -1/3 of the voting power of validators is byzantine. +If a validator commits block `B` at round `R`, it's because it saw +2/3 +of precommits at round `R`. This implies that 1/3+ of honest nodes are +still locked at round `R' > R`. These locked validators will remain +locked until they see a PoLC at `R' > R`, but this won't happen because +1/3+ are locked and honest, so at most -2/3 are available to vote for +anything other than `B`. + +### Proof of Liveness + +If 1/3+ honest validators are locked on two different blocks from +different rounds, a proposers' `PoLC-Round` will eventually cause nodes +locked from the earlier round to unlock. Eventually, the designated +proposer will be one that is aware of a PoLC at the later round. Also, +`timeoutProposalR` increments with round `R`, while the size of a +proposal are capped, so eventually the network is able to "fully gossip" +the whole proposal (e.g. the block & PoLC). + +### Proof of Fork Accountability + +Define the JSet (justification-vote-set) at height `H` of a validator +`V1` to be all the votes signed by the validator at `H` along with +justification PoLC prevotes for each lock change. For example, if `V1` +signed the following precommits: `Precommit(B1 @ round 0)`, +`Precommit( @ round 1)`, `Precommit(B2 @ round 4)` (note that no +precommits were signed for rounds 2 and 3, and that's ok), +`Precommit(B1 @ round 0)` must be justified by a PoLC at round 0, and +`Precommit(B2 @ round 4)` must be justified by a PoLC at round 4; but +the precommit for `` at round 1 is not a lock-change by definition +so the JSet for `V1` need not include any prevotes at round 1, 2, or 3 +(unless `V1` happened to have prevoted for those rounds). + +Further, define the JSet at height `H` of a set of validators `VSet` to +be the union of the JSets for each validator in `VSet`. For a given +commit by honest validators at round `R` for block `B` we can construct +a JSet to justify the commit for `B` at `R`. We say that a JSet +*justifies* a commit at `(H,R)` if all the committers (validators in the +commit-set) are each justified in the JSet with no duplicitous vote +signatures (by the committers). + +- **Lemma**: When a fork is detected by the existence of two + conflicting [commits](./validators.html#commiting-a-block), the + union of the JSets for both commits (if they can be compiled) must + include double-signing by at least 1/3+ of the validator set. + **Proof**: The commit cannot be at the same round, because that + would immediately imply double-signing by 1/3+. Take the union of + the JSets of both commits. If there is no double-signing by at least + 1/3+ of the validator set in the union, then no honest validator + could have precommitted any different block after the first commit. + Yet, +2/3 did. Reductio ad absurdum. + +As a corollary, when there is a fork, an external process can determine +the blame by requiring each validator to justify all of its round votes. +Either we will find 1/3+ who cannot justify at least one of their votes, +and/or, we will find 1/3+ who had double-signed. + +### Alternative algorithm + +Alternatively, we can take the JSet of a commit to be the "full commit". +That is, if light clients and validators do not consider a block to be +committed unless the JSet of the commit is also known, then we get the +desirable property that if there ever is a fork (e.g. there are two +conflicting "full commits"), then 1/3+ of the validators are immediately +punishable for double-signing. + +There are many ways to ensure that the gossip network efficiently share +the JSet of a commit. One solution is to add a new message type that +tells peers that this node has (or does not have) a +2/3 majority for B +(or) at (H,R), and a bitarray of which votes contributed towards that +majority. Peers can react by responding with appropriate votes. + +We will implement such an algorithm for the next iteration of the +Tendermint consensus protocol. + +Other potential improvements include adding more data in votes such as +the last known PoLC round that caused a lock change, and the last voted +round/step (or, we may require that validators not skip any votes). This +may make JSet verification/gossip logic easier to implement. + +### Censorship Attacks + +Due to the definition of a block +[commit](../../tendermint-core/validator.md#commiting-a-block), any 1/3+ coalition of +validators can halt the blockchain by not broadcasting their votes. Such +a coalition can also censor particular transactions by rejecting blocks +that include these transactions, though this would result in a +significant proportion of block proposals to be rejected, which would +slow down the rate of block commits of the blockchain, reducing its +utility and value. The malicious coalition might also broadcast votes in +a trickle so as to grind blockchain block commits to a near halt, or +engage in any combination of these attacks. + +If a global active adversary were also involved, it can partition the +network in such a way that it may appear that the wrong subset of +validators were responsible for the slowdown. This is not just a +limitation of Tendermint, but rather a limitation of all consensus +protocols whose network is potentially controlled by an active +adversary. + +### Overcoming Forks and Censorship Attacks + +For these types of attacks, a subset of the validators through external +means should coordinate to sign a reorg-proposal that chooses a fork +(and any evidence thereof) and the initial subset of validators with +their signatures. Validators who sign such a reorg-proposal forego its +collateral on all other forks. Clients should verify the signatures on +the reorg-proposal, verify any evidence, and make a judgement or prompt +the end-user for a decision. For example, a phone wallet app may prompt +the user with a security warning, while a refrigerator may accept any +reorg-proposal signed by +1/2 of the original validators. + +No non-synchronous Byzantine fault-tolerant algorithm can come to +consensus when 1/3+ of validators are dishonest, yet a fork assumes that +1/3+ of validators have already been dishonest by double-signing or +lock-changing without justification. So, signing the reorg-proposal is a +coordination problem that cannot be solved by any non-synchronous +protocol (i.e. automatically, and without making assumptions about the +reliability of the underlying network). It must be provided by means +external to the weakly-synchronous Tendermint consensus algorithm. For +now, we leave the problem of reorg-proposal coordination to human +coordination via internet media. Validators must take care to ensure +that there are no significant network partitions, to avoid situations +where two conflicting reorg-proposals are signed. + +Assuming that the external coordination medium and protocol is robust, +it follows that forks are less of a concern than [censorship +attacks](#censorship-attacks). diff --git a/docs/spec/scripts/crypto.go b/docs/spec/scripts/crypto.go index 9ae800f8f..e040f0e6a 100644 --- a/docs/spec/scripts/crypto.go +++ b/docs/spec/scripts/crypto.go @@ -5,12 +5,12 @@ import ( "os" amino "github.com/tendermint/go-amino" - crypto "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) func main() { cdc := amino.NewCodec() - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) cdc.PrintTypes(os.Stdout) fmt.Println("") } diff --git a/docs/specification/block-structure.rst b/docs/specification/block-structure.rst deleted file mode 100644 index 7d8f3464c..000000000 --- a/docs/specification/block-structure.rst +++ /dev/null @@ -1,218 +0,0 @@ -Block Structure -=============== - -The tendermint consensus engine records all agreements by a -supermajority of nodes into a blockchain, which is replicated among all -nodes. This blockchain is accessible via various rpc endpoints, mainly -``/block?height=`` to get the full block, as well as -``/blockchain?minHeight=_&maxHeight=_`` to get a list of headers. But -what exactly is stored in these blocks? - -Block -~~~~~ - -A -`Block `__ -contains: - -- a `Header <#header>`__ contains merkle hashes for various chain - states -- the - `Data `__ - is all transactions which are to be processed -- the `LastCommit <#commit>`__ > 2/3 signatures for the last block - -The signatures returned along with block ``H`` are those validating -block ``H-1``. This can be a little confusing, but we must also consider -that the ``Header`` also contains the ``LastCommitHash``. It would be -impossible for a Header to include the commits that sign it, as it would -cause an infinite loop here. But when we get block ``H``, we find -``Header.LastCommitHash``, which must match the hash of ``LastCommit``. - -Header -~~~~~~ - -The -`Header `__ -contains lots of information (follow link for up-to-date info). Notably, -it maintains the ``Height``, the ``LastBlockID`` (to make it a chain), -and hashes of the data, the app state, and the validator set. This is -important as the only item that is signed by the validators is the -``Header``, and all other data must be validated against one of the -merkle hashes in the ``Header``. - -The ``DataHash`` can provide a nice check on the -`Data `__ -returned in this same block. If you are subscribed to new blocks, via -tendermint RPC, in order to display or process the new transactions you -should at least validate that the ``DataHash`` is valid. If it is -important to verify autheniticity, you must wait for the ``LastCommit`` -from the next block to make sure the block header (including -``DataHash``) was properly signed. - -The ``ValidatorHash`` contains a hash of the current -`Validators `__. -Tracking all changes in the validator set is complex, but a client can -quickly compare this hash with the `hash of the currently known -validators `__ -to see if there have been changes. - -The ``AppHash`` serves as the basis for validating any merkle proofs -that come from the ABCI application. It represents the -state of the actual application, rather that the state of the blockchain -itself. This means it's necessary in order to perform any business -logic, such as verifying an account balance. - -**Note** After the transactions are committed to a block, they still -need to be processed in a separate step, which happens between the -blocks. If you find a given transaction in the block at height ``H``, -the effects of running that transaction will be first visible in the -``AppHash`` from the block header at height ``H+1``. - -Like the ``LastCommit`` issue, this is a requirement of the immutability -of the block chain, as the application only applies transactions *after* -they are commited to the chain. - -Commit -~~~~~~ - -The -`Commit `__ -contains a set of -`Votes `__ -that were made by the validator set to reach consensus on this block. -This is the key to the security in any PoS system, and actually no data -that cannot be traced back to a block header with a valid set of Votes -can be trusted. Thus, getting the Commit data and verifying the votes is -extremely important. - -As mentioned above, in order to find the ``precommit votes`` for block -header ``H``, we need to query block ``H+1``. Then we need to check the -votes, make sure they really are for that block, and properly formatted. -Much of this code is implemented in Go in the -`light-client `__ package. -If you look at the code, you will notice that we need to provide the -``chainID`` of the blockchain in order to properly calculate the votes. -This is to protect anyone from swapping votes between chains to fake (or -frame) a validator. Also note that this ``chainID`` is in the -``genesis.json`` from *Tendermint*, not the ``genesis.json`` from the -basecoin app (`that is a different -chainID... `__). - -Once we have those votes, and we calculated the proper `sign -bytes `__ -using the chainID and a `nice helper -function `__, -we can verify them. The light client is responsible for maintaining a -set of validators that we trust. Each vote only stores the validators -``Address``, as well as the ``Signature``. Assuming we have a local copy -of the trusted validator set, we can look up the ``Public Key`` of the -validator given its ``Address``, then verify that the ``Signature`` -matches the ``SignBytes`` and ``Public Key``. Then we sum up the total -voting power of all validators, whose votes fulfilled all these -stringent requirements. If the total number of voting power for a single -block is greater than 2/3 of all voting power, then we can finally trust -the block header, the AppHash, and the proof we got from the ABCI -application. - -Vote Sign Bytes -^^^^^^^^^^^^^^^ - -The ``sign-bytes`` of a vote is produced by taking a -`stable-json `__-like -deterministic JSON `wire <./wire-protocol.html>`__ encoding of -the vote (excluding the ``Signature`` field), and wrapping it with -``{"chain_id":"my_chain","vote":...}``. - -For example, a precommit vote might have the following ``sign-bytes``: - -.. code:: json - - {"chain_id":"my_chain","vote":{"block_hash":"611801F57B4CE378DF1A3FFF1216656E89209A99","block_parts_header":{"hash":"B46697379DBE0774CC2C3B656083F07CA7E0F9CE","total":123},"height":1234,"round":1,"type":2}} - -Block Hash -~~~~~~~~~~ - -The `block -hash `__ -is the `Simple Tree hash <./merkle.html#simple-tree-with-dictionaries>`__ -of the fields of the block ``Header`` encoded as a list of -``KVPair``\ s. - -Transaction -~~~~~~~~~~~ - -A transaction is any sequence of bytes. It is up to your -ABCI application to accept or reject transactions. - -BlockID -~~~~~~~ - -Many of these data structures refer to the -`BlockID `__, -which is the ``BlockHash`` (hash of the block header, also referred to -by the next block) along with the ``PartSetHeader``. The -``PartSetHeader`` is explained below and is used internally to -orchestrate the p2p propogation. For clients, it is basically opaque -bytes, but they must match for all votes. - -PartSetHeader -~~~~~~~~~~~~~ - -The -`PartSetHeader `__ -contains the total number of pieces in a -`PartSet `__, -and the Merkle root hash of those pieces. - -PartSet -~~~~~~~ - -PartSet is used to split a byteslice of data into parts (pieces) for -transmission. By splitting data into smaller parts and computing a -Merkle root hash on the list, you can verify that a part is legitimately -part of the complete data, and the part can be forwarded to other peers -before all the parts are known. In short, it's a fast way to securely -propagate a large chunk of data (like a block) over a gossip network. - -PartSet was inspired by the LibSwift project. - -Usage: - -.. code:: go - - data := RandBytes(2 << 20) // Something large - - partSet := NewPartSetFromData(data) - partSet.Total() // Total number of 4KB parts - partSet.Count() // Equal to the Total, since we already have all the parts - partSet.Hash() // The Merkle root hash - partSet.BitArray() // A BitArray of partSet.Total() 1's - - header := partSet.Header() // Send this to the peer - header.Total // Total number of parts - header.Hash // The merkle root hash - - // Now we'll reconstruct the data from the parts - partSet2 := NewPartSetFromHeader(header) - partSet2.Total() // Same total as partSet.Total() - partSet2.Count() // Zero, since this PartSet doesn't have any parts yet. - partSet2.Hash() // Same hash as in partSet.Hash() - partSet2.BitArray() // A BitArray of partSet.Total() 0's - - // In a gossip network the parts would arrive in arbitrary order, perhaps - // in response to explicit requests for parts, or optimistically in response - // to the receiving peer's partSet.BitArray(). - for !partSet2.IsComplete() { - part := receivePartFromGossipNetwork() - added, err := partSet2.AddPart(part) - if err != nil { - // A wrong part, - // the merkle trail does not hash to partSet2.Hash() - } else if !added { - // A duplicate part already received - } - } - - data2, _ := ioutil.ReadAll(partSet2.GetReader()) - bytes.Equal(data, data2) // true diff --git a/docs/specification/byzantine-consensus-algorithm.rst b/docs/specification/byzantine-consensus-algorithm.rst deleted file mode 100644 index 15eab32d7..000000000 --- a/docs/specification/byzantine-consensus-algorithm.rst +++ /dev/null @@ -1,349 +0,0 @@ -Byzantine Consensus Algorithm -============================= - -Terms ------ - -- The network is composed of optionally connected *nodes*. Nodes - directly connected to a particular node are called *peers*. -- The consensus process in deciding the next block (at some *height* - ``H``) is composed of one or many *rounds*. -- ``NewHeight``, ``Propose``, ``Prevote``, ``Precommit``, and - ``Commit`` represent state machine states of a round. (aka - ``RoundStep`` or just "step"). -- A node is said to be *at* a given height, round, and step, or at - ``(H,R,S)``, or at ``(H,R)`` in short to omit the step. -- To *prevote* or *precommit* something means to broadcast a `prevote - vote `__ - or `first precommit - vote `__ - for something. -- A vote *at* ``(H,R)`` is a vote signed with the bytes for ``H`` and - ``R`` included in its - `sign-bytes `__. -- *+2/3* is short for "more than 2/3" -- *1/3+* is short for "1/3 or more" -- A set of +2/3 of prevotes for a particular block or ```` at - ``(H,R)`` is called a *proof-of-lock-change* or *PoLC* for short. - -State Machine Overview ----------------------- - -At each height of the blockchain a round-based protocol is run to -determine the next block. Each round is composed of three *steps* -(``Propose``, ``Prevote``, and ``Precommit``), along with two special -steps ``Commit`` and ``NewHeight``. - -In the optimal scenario, the order of steps is: - -:: - - NewHeight -> (Propose -> Prevote -> Precommit)+ -> Commit -> NewHeight ->... - -The sequence ``(Propose -> Prevote -> Precommit)`` is called a *round*. -There may be more than one round required to commit a block at a given -height. Examples for why more rounds may be required include: - -- The designated proposer was not online. -- The block proposed by the designated proposer was not valid. -- The block proposed by the designated proposer did not propagate in - time. -- The block proposed was valid, but +2/3 of prevotes for the proposed - block were not received in time for enough validator nodes by the - time they reached the ``Precommit`` step. Even though +2/3 of - prevotes are necessary to progress to the next step, at least one - validator may have voted ```` or maliciously voted for something - else. -- The block proposed was valid, and +2/3 of prevotes were received for - enough nodes, but +2/3 of precommits for the proposed block were not - received for enough validator nodes. - -Some of these problems are resolved by moving onto the next round & -proposer. Others are resolved by increasing certain round timeout -parameters over each successive round. - -State Machine Diagram ---------------------- - -:: - - +-------------------------------------+ - v |(Wait til `CommmitTime+timeoutCommit`) - +-----------+ +-----+-----+ - +----------> | Propose +--------------+ | NewHeight | - | +-----------+ | +-----------+ - | | ^ - |(Else, after timeoutPrecommit) v | - +-----+-----+ +-----------+ | - | Precommit | <------------------------+ Prevote | | - +-----+-----+ +-----------+ | - |(When +2/3 Precommits for block found) | - v | - +--------------------------------------------------------------------+ - | Commit | - | | - | * Set CommitTime = now; | - | * Wait for block, then stage/save/commit block; | - +--------------------------------------------------------------------+ - -Background Gossip ------------------ - -A node may not have a corresponding validator private key, but it -nevertheless plays an active role in the consensus process by relaying -relevant meta-data, proposals, blocks, and votes to its peers. A node -that has the private keys of an active validator and is engaged in -signing votes is called a *validator-node*. All nodes (not just -validator-nodes) have an associated state (the current height, round, -and step) and work to make progress. - -Between two nodes there exists a ``Connection``, and multiplexed on top -of this connection are fairly throttled ``Channel``\ s of information. -An epidemic gossip protocol is implemented among some of these channels -to bring peers up to speed on the most recent state of consensus. For -example, - -- Nodes gossip ``PartSet`` parts of the current round's proposer's - proposed block. A LibSwift inspired algorithm is used to quickly - broadcast blocks across the gossip network. -- Nodes gossip prevote/precommit votes. A node NODE\_A that is ahead of - NODE\_B can send NODE\_B prevotes or precommits for NODE\_B's current - (or future) round to enable it to progress forward. -- Nodes gossip prevotes for the proposed PoLC (proof-of-lock-change) - round if one is proposed. -- Nodes gossip to nodes lagging in blockchain height with block - `commits `__ - for older blocks. -- Nodes opportunistically gossip ``HasVote`` messages to hint peers - what votes it already has. -- Nodes broadcast their current state to all neighboring peers. (but is - not gossiped further) - -There's more, but let's not get ahead of ourselves here. - -Proposals ---------- - -A proposal is signed and published by the designated proposer at each -round. The proposer is chosen by a deterministic and non-choking round -robin selection algorithm that selects proposers in proportion to their -voting power. (see -`implementation `__) - -A proposal at ``(H,R)`` is composed of a block and an optional latest -``PoLC-Round < R`` which is included iff the proposer knows of one. This -hints the network to allow nodes to unlock (when safe) to ensure the -liveness property. - -State Machine Spec ------------------- - -Propose Step (height:H,round:R) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Upon entering ``Propose``: - The designated proposer proposes a block at -``(H,R)``. - -The ``Propose`` step ends: - After ``timeoutProposeR`` after entering -``Propose``. --> goto ``Prevote(H,R)`` - After receiving proposal block -and all prevotes at ``PoLC-Round``. --> goto ``Prevote(H,R)`` - After -`common exit conditions <#common-exit-conditions>`__ - -Prevote Step (height:H,round:R) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Upon entering ``Prevote``, each validator broadcasts its prevote vote. - -- First, if the validator is locked on a block since ``LastLockRound`` - but now has a PoLC for something else at round ``PoLC-Round`` where - ``LastLockRound < PoLC-Round < R``, then it unlocks. -- If the validator is still locked on a block, it prevotes that. -- Else, if the proposed block from ``Propose(H,R)`` is good, it - prevotes that. -- Else, if the proposal is invalid or wasn't received on time, it - prevotes ````. - -The ``Prevote`` step ends: - After +2/3 prevotes for a particular block -or ````. --> goto ``Precommit(H,R)`` - After ``timeoutPrevote`` -after receiving any +2/3 prevotes. --> goto ``Precommit(H,R)`` - After -`common exit conditions <#common-exit-conditions>`__ - -Precommit Step (height:H,round:R) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Upon entering ``Precommit``, each validator broadcasts its precommit -vote. - If the validator has a PoLC at ``(H,R)`` for a particular block -``B``, it (re)locks (or changes lock to) and precommits ``B`` and sets -``LastLockRound = R``. - Else, if the validator has a PoLC at ``(H,R)`` -for ````, it unlocks and precommits ````. - Else, it keeps the -lock unchanged and precommits ````. - -A precommit for ```` means "I didn’t see a PoLC for this round, but -I did get +2/3 prevotes and waited a bit". - -The Precommit step ends: - After +2/3 precommits for ````. --> goto -``Propose(H,R+1)`` - After ``timeoutPrecommit`` after receiving any +2/3 -precommits. --> goto ``Propose(H,R+1)`` - After `common exit -conditions <#common-exit-conditions>`__ - -common exit conditions -^^^^^^^^^^^^^^^^^^^^^^ - -- After +2/3 precommits for a particular block. --> goto ``Commit(H)`` -- After any +2/3 prevotes received at ``(H,R+x)``. --> goto - ``Prevote(H,R+x)`` -- After any +2/3 precommits received at ``(H,R+x)``. --> goto - ``Precommit(H,R+x)`` - -Commit Step (height:H) -~~~~~~~~~~~~~~~~~~~~~~ - -- Set ``CommitTime = now()`` -- Wait until block is received. --> goto ``NewHeight(H+1)`` - -NewHeight Step (height:H) -~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Move ``Precommits`` to ``LastCommit`` and increment height. -- Set ``StartTime = CommitTime+timeoutCommit`` -- Wait until ``StartTime`` to receive straggler commits. --> goto - ``Propose(H,0)`` - -Proofs ------- - -Proof of Safety -~~~~~~~~~~~~~~~ - -Assume that at most -1/3 of the voting power of validators is byzantine. -If a validator commits block ``B`` at round ``R``, it's because it saw -+2/3 of precommits at round ``R``. This implies that 1/3+ of honest -nodes are still locked at round ``R' > R``. These locked validators will -remain locked until they see a PoLC at ``R' > R``, but this won't happen -because 1/3+ are locked and honest, so at most -2/3 are available to -vote for anything other than ``B``. - -Proof of Liveness -~~~~~~~~~~~~~~~~~ - -If 1/3+ honest validators are locked on two different blocks from -different rounds, a proposers' ``PoLC-Round`` will eventually cause -nodes locked from the earlier round to unlock. Eventually, the -designated proposer will be one that is aware of a PoLC at the later -round. Also, ``timeoutProposalR`` increments with round ``R``, while the -size of a proposal are capped, so eventually the network is able to -"fully gossip" the whole proposal (e.g. the block & PoLC). - -Proof of Fork Accountability -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Define the JSet (justification-vote-set) at height ``H`` of a validator -``V1`` to be all the votes signed by the validator at ``H`` along with -justification PoLC prevotes for each lock change. For example, if ``V1`` -signed the following precommits: ``Precommit(B1 @ round 0)``, -``Precommit( @ round 1)``, ``Precommit(B2 @ round 4)`` (note that -no precommits were signed for rounds 2 and 3, and that's ok), -``Precommit(B1 @ round 0)`` must be justified by a PoLC at round 0, and -``Precommit(B2 @ round 4)`` must be justified by a PoLC at round 4; but -the precommit for ```` at round 1 is not a lock-change by -definition so the JSet for ``V1`` need not include any prevotes at round -1, 2, or 3 (unless ``V1`` happened to have prevoted for those rounds). - -Further, define the JSet at height ``H`` of a set of validators ``VSet`` -to be the union of the JSets for each validator in ``VSet``. For a given -commit by honest validators at round ``R`` for block ``B`` we can -construct a JSet to justify the commit for ``B`` at ``R``. We say that a -JSet *justifies* a commit at ``(H,R)`` if all the committers (validators -in the commit-set) are each justified in the JSet with no duplicitous -vote signatures (by the committers). - -- **Lemma**: When a fork is detected by the existence of two - conflicting `commits <./validators.html#commiting-a-block>`__, - the union of the JSets for both commits (if they can be compiled) - must include double-signing by at least 1/3+ of the validator set. - **Proof**: The commit cannot be at the same round, because that would - immediately imply double-signing by 1/3+. Take the union of the JSets - of both commits. If there is no double-signing by at least 1/3+ of - the validator set in the union, then no honest validator could have - precommitted any different block after the first commit. Yet, +2/3 - did. Reductio ad absurdum. - -As a corollary, when there is a fork, an external process can determine -the blame by requiring each validator to justify all of its round votes. -Either we will find 1/3+ who cannot justify at least one of their votes, -and/or, we will find 1/3+ who had double-signed. - -Alternative algorithm -~~~~~~~~~~~~~~~~~~~~~ - -Alternatively, we can take the JSet of a commit to be the "full commit". -That is, if light clients and validators do not consider a block to be -committed unless the JSet of the commit is also known, then we get the -desirable property that if there ever is a fork (e.g. there are two -conflicting "full commits"), then 1/3+ of the validators are immediately -punishable for double-signing. - -There are many ways to ensure that the gossip network efficiently share -the JSet of a commit. One solution is to add a new message type that -tells peers that this node has (or does not have) a +2/3 majority for B -(or ) at (H,R), and a bitarray of which votes contributed towards that -majority. Peers can react by responding with appropriate votes. - -We will implement such an algorithm for the next iteration of the -Tendermint consensus protocol. - -Other potential improvements include adding more data in votes such as -the last known PoLC round that caused a lock change, and the last voted -round/step (or, we may require that validators not skip any votes). This -may make JSet verification/gossip logic easier to implement. - -Censorship Attacks -~~~~~~~~~~~~~~~~~~ - -Due to the definition of a block -`commit `__, any 1/3+ -coalition of validators can halt the blockchain by not broadcasting -their votes. Such a coalition can also censor particular transactions by -rejecting blocks that include these transactions, though this would -result in a significant proportion of block proposals to be rejected, -which would slow down the rate of block commits of the blockchain, -reducing its utility and value. The malicious coalition might also -broadcast votes in a trickle so as to grind blockchain block commits to -a near halt, or engage in any combination of these attacks. - -If a global active adversary were also involved, it can partition the -network in such a way that it may appear that the wrong subset of -validators were responsible for the slowdown. This is not just a -limitation of Tendermint, but rather a limitation of all consensus -protocols whose network is potentially controlled by an active -adversary. - -Overcoming Forks and Censorship Attacks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For these types of attacks, a subset of the validators through external -means should coordinate to sign a reorg-proposal that chooses a fork -(and any evidence thereof) and the initial subset of validators with -their signatures. Validators who sign such a reorg-proposal forego its -collateral on all other forks. Clients should verify the signatures on -the reorg-proposal, verify any evidence, and make a judgement or prompt -the end-user for a decision. For example, a phone wallet app may prompt -the user with a security warning, while a refrigerator may accept any -reorg-proposal signed by +1/2 of the original validators. - -No non-synchronous Byzantine fault-tolerant algorithm can come to -consensus when 1/3+ of validators are dishonest, yet a fork assumes that -1/3+ of validators have already been dishonest by double-signing or -lock-changing without justification. So, signing the reorg-proposal is a -coordination problem that cannot be solved by any non-synchronous -protocol (i.e. automatically, and without making assumptions about the -reliability of the underlying network). It must be provided by means -external to the weakly-synchronous Tendermint consensus algorithm. For -now, we leave the problem of reorg-proposal coordination to human -coordination via internet media. Validators must take care to ensure -that there are no significant network partitions, to avoid situations -where two conflicting reorg-proposals are signed. - -Assuming that the external coordination medium and protocol is robust, -it follows that forks are less of a concern than `censorship -attacks <#censorship-attacks>`__. diff --git a/docs/specification/corruption.rst b/docs/specification/corruption.rst deleted file mode 100644 index 6ae19fb18..000000000 --- a/docs/specification/corruption.rst +++ /dev/null @@ -1,70 +0,0 @@ -Corruption -========== - -Important step --------------- - -Make sure you have a backup of the Tendermint data directory. - -Possible causes ---------------- - -Remember that most corruption is caused by hardware issues: - -- RAID controllers with faulty / worn out battery backup, and an unexpected power loss -- Hard disk drives with write-back cache enabled, and an unexpected power loss -- Cheap SSDs with insufficient power-loss protection, and an unexpected power-loss -- Defective RAM -- Defective or overheating CPU(s) - -Other causes can be: - -- Database systems configured with fsync=off and an OS crash or power loss -- Filesystems configured to use write barriers plus a storage layer that ignores write barriers. LVM is a particular culprit. -- Tendermint bugs -- Operating system bugs -- Admin error - - directly modifying Tendermint data-directory contents - -(Source: https://wiki.postgresql.org/wiki/Corruption) - -WAL Corruption --------------- - -If consensus WAL is corrupted at the lastest height and you are trying to start -Tendermint, replay will fail with panic. - -Recovering from data corruption can be hard and time-consuming. Here are two approaches you can take: - -1) Delete the WAL file and restart Tendermint. It will attempt to sync with other peers. -2) Try to repair the WAL file manually: - - 1. Create a backup of the corrupted WAL file: - - .. code:: bash - - cp "$TMHOME/data/cs.wal/wal" > /tmp/corrupted_wal_backup - - 2. Use ./scripts/wal2json to create a human-readable version - - .. code:: bash - - ./scripts/wal2json/wal2json "$TMHOME/data/cs.wal/wal" > /tmp/corrupted_wal - - 3. Search for a "CORRUPTED MESSAGE" line. - 4. By looking at the previous message and the message after the corrupted one - and looking at the logs, try to rebuild the message. If the consequent - messages are marked as corrupted too (this may happen if length header - got corrupted or some writes did not make it to the WAL ~ truncation), - then remove all the lines starting from the corrupted one and restart - Tendermint. - - .. code:: bash - - $EDITOR /tmp/corrupted_wal - - 5. After editing, convert this file back into binary form by running: - - .. code:: bash - - ./scripts/json2wal/json2wal /tmp/corrupted_wal > "$TMHOME/data/cs.wal/wal" diff --git a/docs/specification/genesis.rst b/docs/specification/genesis.rst deleted file mode 100644 index 427c88bb2..000000000 --- a/docs/specification/genesis.rst +++ /dev/null @@ -1,71 +0,0 @@ -Genesis -======= - -The genesis.json file in ``$TMHOME/config`` defines the initial TendermintCore -state upon genesis of the blockchain (`see -definition `__). - -Fields -~~~~~~ - -- ``genesis_time``: Official time of blockchain start. -- ``chain_id``: ID of the blockchain. This must be unique for every - blockchain. If your testnet blockchains do not have unique chain IDs, - you will have a bad time. -- ``validators``: -- ``pub_key``: The first element specifies the pub\_key type. 1 == - Ed25519. The second element are the pubkey bytes. -- ``power``: The validator's voting power. -- ``name``: Name of the validator (optional). -- ``app_hash``: The expected application hash (as returned by the - ``ResponseInfo`` ABCI message) upon genesis. If the app's hash does not - match, Tendermint will panic. -- ``app_state``: The application state (e.g. initial distribution of tokens). - -Sample genesis.json -~~~~~~~~~~~~~~~~~~~ - -.. code:: json - - { - "genesis_time": "2016-02-05T06:02:31.526Z", - "chain_id": "chain-tTH4mi", - "validators": [ - { - "pub_key": [ - 1, - "9BC5112CB9614D91CE423FA8744885126CD9D08D9FC9D1F42E552D662BAA411E" - ], - "power": 1, - "name": "mach1" - }, - { - "pub_key": [ - 1, - "F46A5543D51F31660D9F59653B4F96061A740FF7433E0DC1ECBC30BE8494DE06" - ], - "power": 1, - "name": "mach2" - }, - { - "pub_key": [ - 1, - "0E7B423C1635FD07C0FC3603B736D5D27953C1C6CA865BB9392CD79DE1A682BB" - ], - "power": 1, - "name": "mach3" - }, - { - "pub_key": [ - 1, - "4F49237B9A32EB50682EDD83C48CE9CDB1D02A7CFDADCFF6EC8C1FAADB358879" - ], - "power": 1, - "name": "mach4" - } - ], - "app_hash": "15005165891224E721CB664D15CB972240F5703F", - "app_state": { - {"account": "Bob", "coins": 5000} - } - } diff --git a/docs/specification/light-client-protocol.rst b/docs/specification/light-client-protocol.rst deleted file mode 100644 index 6c6083b45..000000000 --- a/docs/specification/light-client-protocol.rst +++ /dev/null @@ -1,33 +0,0 @@ -Light Client Protocol -===================== - -Light clients are an important part of the complete blockchain system -for most applications. Tendermint provides unique speed and security -properties for light client applications. - -See our `lite package -`__. - -Overview --------- - -The objective of the light client protocol is to get a -`commit <./validators.html#committing-a-block>`__ for a recent -`block hash <./block-structure.html#block-hash>`__ where the commit -includes a majority of signatures from the last known validator set. -From there, all the application state is verifiable with `merkle -proofs <./merkle.html#iavl-tree>`__. - -Properties ----------- - -- You get the full collateralized security benefits of Tendermint; No - need to wait for confirmations. -- You get the full speed benefits of Tendermint; transactions commit - instantly. -- You can get the most recent version of the application state - non-interactively (without committing anything to the blockchain). - For example, this means that you can get the most recent value of a - name from the name-registry without worrying about fork censorship - attacks, without posting a commit and waiting for confirmations. It's - fast, secure, and free! diff --git a/docs/specification/merkle.rst b/docs/specification/merkle.rst deleted file mode 100644 index 588f24a98..000000000 --- a/docs/specification/merkle.rst +++ /dev/null @@ -1,88 +0,0 @@ -Merkle -====== - -For an overview of Merkle trees, see -`wikipedia `__. - -There are two types of Merkle trees used in Tendermint. - -- **IAVL+ Tree**: An immutable self-balancing binary - tree for persistent application state -- **Simple Tree**: A simple compact binary tree for - a static list of items - -IAVL+ Tree ----------- - -The purpose of this data structure is to provide persistent storage for -key-value pairs (e.g. account state, name-registrar data, and -per-contract data) such that a deterministic merkle root hash can be -computed. The tree is balanced using a variant of the `AVL -algorithm `__ so all operations -are O(log(n)). - -Nodes of this tree are immutable and indexed by its hash. Thus any node -serves as an immutable snapshot which lets us stage uncommitted -transactions from the mempool cheaply, and we can instantly roll back to -the last committed state to process transactions of a newly committed -block (which may not be the same set of transactions as those from the -mempool). - -In an AVL tree, the heights of the two child subtrees of any node differ -by at most one. Whenever this condition is violated upon an update, the -tree is rebalanced by creating O(log(n)) new nodes that point to -unmodified nodes of the old tree. In the original AVL algorithm, inner -nodes can also hold key-value pairs. The AVL+ algorithm (note the plus) -modifies the AVL algorithm to keep all values on leaf nodes, while only -using branch-nodes to store keys. This simplifies the algorithm while -minimizing the size of merkle proofs - -In Ethereum, the analog is the `Patricia -trie `__. There are tradeoffs. -Keys do not need to be hashed prior to insertion in IAVL+ trees, so this -provides faster iteration in the key space which may benefit some -applications. The logic is simpler to implement, requiring only two -types of nodes -- inner nodes and leaf nodes. The IAVL+ tree is a binary -tree, so merkle proofs are much shorter than the base 16 Patricia trie. -On the other hand, while IAVL+ trees provide a deterministic merkle root -hash, it depends on the order of updates. In practice this shouldn't be -a problem, since you can efficiently encode the tree structure when -serializing the tree contents. - -Simple Tree ------------ - -For merkelizing smaller static lists, use the Simple Tree. The -transactions and validation signatures of a block are hashed using this -simple merkle tree logic. - -If the number of items is not a power of two, the tree will not be full -and some leaf nodes will be at different levels. Simple Tree tries to -keep both sides of the tree the same size, but the left side may be one -greater. - -:: - - Simple Tree with 6 items Simple Tree with 7 items - - * * - / \ / \ - / \ / \ - / \ / \ - / \ / \ - * * * * - / \ / \ / \ / \ - / \ / \ / \ / \ - / \ / \ / \ / \ - * h2 * h5 * * * h6 - / \ / \ / \ / \ / \ - h0 h1 h3 h4 h0 h1 h2 h3 h4 h5 - -Simple Tree with Dictionaries -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Simple Tree is used to merkelize a list of items, so to merkelize a -(short) dictionary of key-value pairs, encode the dictionary as an -ordered list of ``KVPair`` structs. The block hash is such a hash -derived from all the fields of the block ``Header``. The state hash is -similarly derived. diff --git a/docs/specification/new-spec/README.md b/docs/specification/new-spec/README.md deleted file mode 100644 index 907ddd945..000000000 --- a/docs/specification/new-spec/README.md +++ /dev/null @@ -1 +0,0 @@ -Spec moved to [docs/spec](https://github.com/tendermint/tendermint/tree/master/docs/spec). diff --git a/docs/specification/wire-protocol.rst b/docs/specification/wire-protocol.rst deleted file mode 100644 index c0bf3b0ef..000000000 --- a/docs/specification/wire-protocol.rst +++ /dev/null @@ -1,172 +0,0 @@ -Wire Protocol -============= - -The `Tendermint wire protocol `__ -encodes data in `c-style binary <#binary>`__ and `JSON <#json>`__ form. - -Supported types ---------------- - -- Primitive types -- ``uint8`` (aka ``byte``), ``uint16``, ``uint32``, ``uint64`` -- ``int8``, ``int16``, ``int32``, ``int64`` -- ``uint``, ``int``: variable length (un)signed integers -- ``string``, ``[]byte`` -- ``time`` -- Derived types -- structs -- var-length arrays of a particular type -- fixed-length arrays of a particular type -- interfaces: registered union types preceded by a ``type byte`` -- pointers - -Binary ------- - -**Fixed-length primitive types** are encoded with 1,2,3, or 4 big-endian -bytes. - ``uint8`` (aka ``byte``), ``uint16``, ``uint32``, ``uint64``: -takes 1,2,3, and 4 bytes respectively - ``int8``, ``int16``, ``int32``, -``int64``: takes 1,2,3, and 4 bytes respectively - ``time``: ``int64`` -representation of nanoseconds since epoch - -**Variable-length integers** are encoded with a single leading byte -representing the length of the following big-endian bytes. For signed -negative integers, the most significant bit of the leading byte is a 1. - -- ``uint``: 1-byte length prefixed variable-size (0 ~ 255 bytes) - unsigned integers -- ``int``: 1-byte length prefixed variable-size (0 ~ 127 bytes) signed - integers - -NOTE: While the number 0 (zero) is encoded with a single byte ``x00``, -the number 1 (one) takes two bytes to represent: ``x0101``. This isn't -the most efficient representation, but the rules are easier to remember. - -+---------------+----------------+----------------+ -| number | binary | binary ``int`` | -| | ``uint`` | | -+===============+================+================+ -| 0 | ``x00`` | ``x00`` | -+---------------+----------------+----------------+ -| 1 | ``x0101`` | ``x0101`` | -+---------------+----------------+----------------+ -| 2 | ``x0102`` | ``x0102`` | -+---------------+----------------+----------------+ -| 256 | ``x020100`` | ``x020100`` | -+---------------+----------------+----------------+ -| 2^(127\ *8)-1 | ``x800100...`` | overflow | -| \| | | | -| ``x7FFFFF...` | | | -| ` | | | -| \| | | | -| ``x7FFFFF...` | | | -| ` | | | -| \| \| | | | -| 2^(127*\ 8) | | | -+---------------+----------------+----------------+ -| 2^(255\*8)-1 | -| \| | -| ``xFFFFFF...` | -| ` | -| \| overflow | -| \| \| -1 \| | -| n/a \| | -| ``x8101`` \| | -| \| -2 \| n/a | -| \| ``x8102`` | -| \| \| -256 \| | -| n/a \| | -| ``x820100`` | -| \| | -+---------------+----------------+----------------+ - -**Structures** are encoded by encoding the field values in order of -declaration. - -.. code:: go - - type Foo struct { - MyString string - MyUint32 uint32 - } - var foo = Foo{"626172", math.MaxUint32} - - /* The binary representation of foo: - 0103626172FFFFFFFF - 0103: `int` encoded length of string, here 3 - 626172: 3 bytes of string "bar" - FFFFFFFF: 4 bytes of uint32 MaxUint32 - */ - -**Variable-length arrays** are encoded with a leading ``int`` denoting -the length of the array followed by the binary representation of the -items. **Fixed-length arrays** are similar but aren't preceded by the -leading ``int``. - -.. code:: go - - foos := []Foo{foo, foo} - - /* The binary representation of foos: - 01020103626172FFFFFFFF0103626172FFFFFFFF - 0102: `int` encoded length of array, here 2 - 0103626172FFFFFFFF: the first `foo` - 0103626172FFFFFFFF: the second `foo` - */ - - foos := [2]Foo{foo, foo} // fixed-length array - - /* The binary representation of foos: - 0103626172FFFFFFFF0103626172FFFFFFFF - 0103626172FFFFFFFF: the first `foo` - 0103626172FFFFFFFF: the second `foo` - */ - -**Interfaces** can represent one of any number of concrete types. The -concrete types of an interface must first be declared with their -corresponding ``type byte``. An interface is then encoded with the -leading ``type byte``, then the binary encoding of the underlying -concrete type. - -NOTE: The byte ``x00`` is reserved for the ``nil`` interface value and -``nil`` pointer values. - -.. code:: go - - type Animal interface{} - type Dog uint32 - type Cat string - - RegisterInterface( - struct{ Animal }{}, // Convenience for referencing the 'Animal' interface - ConcreteType{Dog(0), 0x01}, // Register the byte 0x01 to denote a Dog - ConcreteType{Cat(""), 0x02}, // Register the byte 0x02 to denote a Cat - ) - - var animal Animal = Dog(02) - - /* The binary representation of animal: - 010102 - 01: the type byte for a `Dog` - 0102: the bytes of Dog(02) - */ - -**Pointers** are encoded with a single leading byte ``x00`` for ``nil`` -pointers, otherwise encoded with a leading byte ``x01`` followed by the -binary encoding of the value pointed to. - -NOTE: It's easy to convert pointer types into interface types, since the -``type byte`` ``x00`` is always ``nil``. - -JSON ----- - -The JSON codec is compatible with the ```binary`` <#binary>`__ codec, -and is fairly intuitive if you're already familiar with golang's JSON -encoding. Some quirks are noted below: - -- variable-length and fixed-length bytes are encoded as uppercase - hexadecimal strings -- interface values are encoded as an array of two items: - ``[type_byte, concrete_value]`` -- times are encoded as rfc2822 strings diff --git a/docs/tendermint-core/block-structure.md b/docs/tendermint-core/block-structure.md new file mode 100644 index 000000000..803805529 --- /dev/null +++ b/docs/tendermint-core/block-structure.md @@ -0,0 +1,206 @@ +# Block Structure + +The tendermint consensus engine records all agreements by a +supermajority of nodes into a blockchain, which is replicated among all +nodes. This blockchain is accessible via various rpc endpoints, mainly +`/block?height=` to get the full block, as well as +`/blockchain?minHeight=_&maxHeight=_` to get a list of headers. But what +exactly is stored in these blocks? + +## Block + +A +[Block](https://godoc.org/github.com/tendermint/tendermint/types#Block) +contains: + +- a [Header](#header) contains merkle hashes for various chain states +- the + [Data](https://godoc.org/github.com/tendermint/tendermint/types#Data) + is all transactions which are to be processed +- the [LastCommit](#commit) > 2/3 signatures for the last block + +The signatures returned along with block `H` are those validating block +`H-1`. This can be a little confusing, but we must also consider that +the `Header` also contains the `LastCommitHash`. It would be impossible +for a Header to include the commits that sign it, as it would cause an +infinite loop here. But when we get block `H`, we find +`Header.LastCommitHash`, which must match the hash of `LastCommit`. + +## Header + +The +[Header](https://godoc.org/github.com/tendermint/tendermint/types#Header) +contains lots of information (follow link for up-to-date info). Notably, +it maintains the `Height`, the `LastBlockID` (to make it a chain), and +hashes of the data, the app state, and the validator set. This is +important as the only item that is signed by the validators is the +`Header`, and all other data must be validated against one of the merkle +hashes in the `Header`. + +The `DataHash` can provide a nice check on the +[Data](https://godoc.org/github.com/tendermint/tendermint/types#Data) +returned in this same block. If you are subscribed to new blocks, via +tendermint RPC, in order to display or process the new transactions you +should at least validate that the `DataHash` is valid. If it is +important to verify autheniticity, you must wait for the `LastCommit` +from the next block to make sure the block header (including `DataHash`) +was properly signed. + +The `ValidatorHash` contains a hash of the current +[Validators](https://godoc.org/github.com/tendermint/tendermint/types#Validator). +Tracking all changes in the validator set is complex, but a client can +quickly compare this hash with the [hash of the currently known +validators](https://godoc.org/github.com/tendermint/tendermint/types#ValidatorSet.Hash) +to see if there have been changes. + +The `AppHash` serves as the basis for validating any merkle proofs that +come from the ABCI application. It represents the state of the actual +application, rather that the state of the blockchain itself. This means +it's necessary in order to perform any business logic, such as verifying +an account balance. + +**Note** After the transactions are committed to a block, they still +need to be processed in a separate step, which happens between the +blocks. If you find a given transaction in the block at height `H`, the +effects of running that transaction will be first visible in the +`AppHash` from the block header at height `H+1`. + +Like the `LastCommit` issue, this is a requirement of the immutability +of the block chain, as the application only applies transactions *after* +they are commited to the chain. + +## Commit + +The +[Commit](https://godoc.org/github.com/tendermint/tendermint/types#Commit) +contains a set of +[Votes](https://godoc.org/github.com/tendermint/tendermint/types#Vote) +that were made by the validator set to reach consensus on this block. +This is the key to the security in any PoS system, and actually no data +that cannot be traced back to a block header with a valid set of Votes +can be trusted. Thus, getting the Commit data and verifying the votes is +extremely important. + +As mentioned above, in order to find the `precommit votes` for block +header `H`, we need to query block `H+1`. Then we need to check the +votes, make sure they really are for that block, and properly formatted. +Much of this code is implemented in Go in the +[light-client](https://github.com/tendermint/light-client) package. If +you look at the code, you will notice that we need to provide the +`chainID` of the blockchain in order to properly calculate the votes. +This is to protect anyone from swapping votes between chains to fake (or +frame) a validator. Also note that this `chainID` is in the +`genesis.json` from *Tendermint*, not the `genesis.json` from the +basecoin app ([that is a different +chainID...](https://github.com/cosmos/cosmos-sdk/issues/32)). + +Once we have those votes, and we calculated the proper [sign +bytes](https://godoc.org/github.com/tendermint/tendermint/types#Vote.WriteSignBytes) +using the chainID and a [nice helper +function](https://godoc.org/github.com/tendermint/tendermint/types#SignBytes), +we can verify them. The light client is responsible for maintaining a +set of validators that we trust. Each vote only stores the validators +`Address`, as well as the `Signature`. Assuming we have a local copy of +the trusted validator set, we can look up the `Public Key` of the +validator given its `Address`, then verify that the `Signature` matches +the `SignBytes` and `Public Key`. Then we sum up the total voting power +of all validators, whose votes fulfilled all these stringent +requirements. If the total number of voting power for a single block is +greater than 2/3 of all voting power, then we can finally trust the +block header, the AppHash, and the proof we got from the ABCI +application. + +### Vote Sign Bytes + +The `sign-bytes` of a vote is produced by taking a +[stable-json](https://github.com/substack/json-stable-stringify)-like +deterministic JSON [wire](./wire-protocol.html) encoding of the vote +(excluding the `Signature` field), and wrapping it with +`{"chain_id":"my_chain","vote":...}`. + +For example, a precommit vote might have the following `sign-bytes`: + +``` +{"chain_id":"my_chain","vote":{"block_hash":"611801F57B4CE378DF1A3FFF1216656E89209A99","block_parts_header":{"hash":"B46697379DBE0774CC2C3B656083F07CA7E0F9CE","total":123},"height":1234,"round":1,"type":2}} +``` + +## Block Hash + +The [block +hash](https://godoc.org/github.com/tendermint/tendermint/types#Block.Hash) +is the [Simple Tree hash](./merkle.html#simple-tree-with-dictionaries) +of the fields of the block `Header` encoded as a list of `KVPair`s. + +## Transaction + +A transaction is any sequence of bytes. It is up to your ABCI +application to accept or reject transactions. + +## BlockID + +Many of these data structures refer to the +[BlockID](https://godoc.org/github.com/tendermint/tendermint/types#BlockID), +which is the `BlockHash` (hash of the block header, also referred to by +the next block) along with the `PartSetHeader`. The `PartSetHeader` is +explained below and is used internally to orchestrate the p2p +propogation. For clients, it is basically opaque bytes, but they must +match for all votes. + +## PartSetHeader + +The +[PartSetHeader](https://godoc.org/github.com/tendermint/tendermint/types#PartSetHeader) +contains the total number of pieces in a +[PartSet](https://godoc.org/github.com/tendermint/tendermint/types#PartSet), +and the Merkle root hash of those pieces. + +## PartSet + +PartSet is used to split a byteslice of data into parts (pieces) for +transmission. By splitting data into smaller parts and computing a +Merkle root hash on the list, you can verify that a part is legitimately +part of the complete data, and the part can be forwarded to other peers +before all the parts are known. In short, it's a fast way to securely +propagate a large chunk of data (like a block) over a gossip network. + +PartSet was inspired by the LibSwift project. + +Usage: + +``` +data := RandBytes(2 << 20) // Something large + +partSet := NewPartSetFromData(data) +partSet.Total() // Total number of 4KB parts +partSet.Count() // Equal to the Total, since we already have all the parts +partSet.Hash() // The Merkle root hash +partSet.BitArray() // A BitArray of partSet.Total() 1's + +header := partSet.Header() // Send this to the peer +header.Total // Total number of parts +header.Hash // The merkle root hash + +// Now we'll reconstruct the data from the parts +partSet2 := NewPartSetFromHeader(header) +partSet2.Total() // Same total as partSet.Total() +partSet2.Count() // Zero, since this PartSet doesn't have any parts yet. +partSet2.Hash() // Same hash as in partSet.Hash() +partSet2.BitArray() // A BitArray of partSet.Total() 0's + +// In a gossip network the parts would arrive in arbitrary order, perhaps +// in response to explicit requests for parts, or optimistically in response +// to the receiving peer's partSet.BitArray(). +for !partSet2.IsComplete() { + part := receivePartFromGossipNetwork() + added, err := partSet2.AddPart(part) + if err != nil { + // A wrong part, + // the merkle trail does not hash to partSet2.Hash() + } else if !added { + // A duplicate part already received + } +} + +data2, _ := ioutil.ReadAll(partSet2.GetReader()) +bytes.Equal(data, data2) // true +``` diff --git a/docs/specification/configuration.md b/docs/tendermint-core/configuration.md similarity index 95% rename from docs/specification/configuration.md rename to docs/tendermint-core/configuration.md index 214757b9f..ab2d7cc17 100644 --- a/docs/specification/configuration.md +++ b/docs/tendermint-core/configuration.md @@ -2,8 +2,7 @@ Tendermint Core can be configured via a TOML file in `$TMHOME/config/config.toml`. Some of these parameters can be overridden by -command-line flags. For most users, the options in the `##### main -base configuration options #####` are intended to be modified while +command-line flags. For most users, the options in the `##### main base configuration options #####` are intended to be modified while config options further below are intended for advance power users. ## Options @@ -100,7 +99,6 @@ laddr = "tcp://0.0.0.0:26656" seeds = "" # Comma separated list of nodes to keep persistent connections to -# Do not add private peers to this list if you don't want them advertised persistent_peers = "" # UPNP port forwarding @@ -122,10 +120,10 @@ max_num_peers = 50 max_packet_msg_payload_size = 1024 # Rate at which packets can be sent, in bytes/second -send_rate = 512000 +send_rate = 5120000 # Rate at which packets can be received, in bytes/second -recv_rate = 512000 +recv_rate = 5120000 # Set true to enable the peer-exchange reactor pex = true @@ -210,4 +208,10 @@ prometheus = false # Address to listen for Prometheus collector(s) connections prometheus_listen_addr = ":26660" + +# Maximum number of simultaneous connections. +# If you want to accept a more significant number than the default, make sure +# you increase your OS limits. +# 0 - unlimited. +max_open_connections = 3 ``` diff --git a/docs/tendermint-core/how-to-read-logs.md b/docs/tendermint-core/how-to-read-logs.md new file mode 100644 index 000000000..83dab3870 --- /dev/null +++ b/docs/tendermint-core/how-to-read-logs.md @@ -0,0 +1,142 @@ +# How to read logs + +## Walkabout example + +We first create three connections (mempool, consensus and query) to the +application (running `kvstore` locally in this case). + +``` +I[10-04|13:54:27.364] Starting multiAppConn module=proxy impl=multiAppConn +I[10-04|13:54:27.366] Starting localClient module=abci-client connection=query impl=localClient +I[10-04|13:54:27.366] Starting localClient module=abci-client connection=mempool impl=localClient +I[10-04|13:54:27.367] Starting localClient module=abci-client connection=consensus impl=localClient +``` + +Then Tendermint Core and the application perform a handshake. + +``` +I[10-04|13:54:27.367] ABCI Handshake module=consensus appHeight=90 appHash=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD +I[10-04|13:54:27.368] ABCI Replay Blocks module=consensus appHeight=90 storeHeight=90 stateHeight=90 +I[10-04|13:54:27.368] Completed ABCI Handshake - Tendermint and App are synced module=consensus appHeight=90 appHash=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD +``` + +After that, we start a few more things like the event switch, reactors, +and perform UPNP discover in order to detect the IP address. + +``` +I[10-04|13:54:27.374] Starting EventSwitch module=types impl=EventSwitch +I[10-04|13:54:27.375] This node is a validator module=consensus +I[10-04|13:54:27.379] Starting Node module=main impl=Node +I[10-04|13:54:27.381] Local listener module=p2p ip=:: port=26656 +I[10-04|13:54:27.382] Getting UPNP external address module=p2p +I[10-04|13:54:30.386] Could not perform UPNP discover module=p2p err="write udp4 0.0.0.0:38238->239.255.255.250:1900: i/o timeout" +I[10-04|13:54:30.386] Starting DefaultListener module=p2p impl=Listener(@10.0.2.15:26656) +I[10-04|13:54:30.387] Starting P2P Switch module=p2p impl="P2P Switch" +I[10-04|13:54:30.387] Starting MempoolReactor module=mempool impl=MempoolReactor +I[10-04|13:54:30.387] Starting BlockchainReactor module=blockchain impl=BlockchainReactor +I[10-04|13:54:30.387] Starting ConsensusReactor module=consensus impl=ConsensusReactor +I[10-04|13:54:30.387] ConsensusReactor module=consensus fastSync=false +I[10-04|13:54:30.387] Starting ConsensusState module=consensus impl=ConsensusState +I[10-04|13:54:30.387] Starting WAL module=consensus wal=/home/vagrant/.tendermint/data/cs.wal/wal impl=WAL +I[10-04|13:54:30.388] Starting TimeoutTicker module=consensus impl=TimeoutTicker +``` + +Notice the second row where Tendermint Core reports that "This node is a +validator". It also could be just an observer (regular node). + +Next we replay all the messages from the WAL. + +``` +I[10-04|13:54:30.390] Catchup by replaying consensus messages module=consensus height=91 +I[10-04|13:54:30.390] Replay: New Step module=consensus height=91 round=0 step=RoundStepNewHeight +I[10-04|13:54:30.390] Replay: Done module=consensus +``` + +"Started node" message signals that everything is ready for work. + +``` +I[10-04|13:54:30.391] Starting RPC HTTP server on tcp socket 0.0.0.0:26657 module=rpc-server +I[10-04|13:54:30.392] Started node module=main nodeInfo="NodeInfo{id: DF22D7C92C91082324A1312F092AA1DA197FA598DBBFB6526E, moniker: anonymous, network: test-chain-3MNw2N [remote , listen 10.0.2.15:26656], version: 0.11.0-10f361fc ([wire_version=0.6.2 p2p_version=0.5.0 consensus_version=v1/0.2.2 rpc_version=0.7.0/3 tx_index=on rpc_addr=tcp://0.0.0.0:26657])}" +``` + +Next follows a standard block creation cycle, where we enter a new +round, propose a block, receive more than 2/3 of prevotes, then +precommits and finally have a chance to commit a block. For details, +please refer to [Consensus +Overview](./introduction.md#consensus-overview) or [Byzantine Consensus +Algorithm](./spec/consensus). + +``` +I[10-04|13:54:30.393] enterNewRound(91/0). Current: 91/0/RoundStepNewHeight module=consensus +I[10-04|13:54:30.393] enterPropose(91/0). Current: 91/0/RoundStepNewRound module=consensus +I[10-04|13:54:30.393] enterPropose: Our turn to propose module=consensus proposer=125B0E3C5512F5C2B0E1109E31885C4511570C42 privValidator="PrivValidator{125B0E3C5512F5C2B0E1109E31885C4511570C42 LH:90, LR:0, LS:3}" +I[10-04|13:54:30.394] Signed proposal module=consensus height=91 round=0 proposal="Proposal{91/0 1:21B79872514F (-1,:0:000000000000) {/10EDEDD7C84E.../}}" +I[10-04|13:54:30.397] Received complete proposal block module=consensus height=91 hash=F671D562C7B9242900A286E1882EE64E5556FE9E +I[10-04|13:54:30.397] enterPrevote(91/0). Current: 91/0/RoundStepPropose module=consensus +I[10-04|13:54:30.397] enterPrevote: ProposalBlock is valid module=consensus height=91 round=0 +I[10-04|13:54:30.398] Signed and pushed vote module=consensus height=91 round=0 vote="Vote{0:125B0E3C5512 91/00/1(Prevote) F671D562C7B9 {/89047FFC21D8.../}}" err=null +I[10-04|13:54:30.401] Added to prevote module=consensus vote="Vote{0:125B0E3C5512 91/00/1(Prevote) F671D562C7B9 {/89047FFC21D8.../}}" prevotes="VoteSet{H:91 R:0 T:1 +2/3:F671D562C7B9242900A286E1882EE64E5556FE9E:1:21B79872514F BA{1:X} map[]}" +I[10-04|13:54:30.401] enterPrecommit(91/0). Current: 91/0/RoundStepPrevote module=consensus +I[10-04|13:54:30.401] enterPrecommit: +2/3 prevoted proposal block. Locking module=consensus hash=F671D562C7B9242900A286E1882EE64E5556FE9E +I[10-04|13:54:30.402] Signed and pushed vote module=consensus height=91 round=0 vote="Vote{0:125B0E3C5512 91/00/2(Precommit) F671D562C7B9 {/80533478E41A.../}}" err=null +I[10-04|13:54:30.404] Added to precommit module=consensus vote="Vote{0:125B0E3C5512 91/00/2(Precommit) F671D562C7B9 {/80533478E41A.../}}" precommits="VoteSet{H:91 R:0 T:2 +2/3:F671D562C7B9242900A286E1882EE64E5556FE9E:1:21B79872514F BA{1:X} map[]}" +I[10-04|13:54:30.404] enterCommit(91/0). Current: 91/0/RoundStepPrecommit module=consensus +I[10-04|13:54:30.405] Finalizing commit of block with 0 txs module=consensus height=91 hash=F671D562C7B9242900A286E1882EE64E5556FE9E root=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD +I[10-04|13:54:30.405] Block{ + Header{ + ChainID: test-chain-3MNw2N + Height: 91 + Time: 2017-10-04 13:54:30.393 +0000 UTC + NumTxs: 0 + LastBlockID: F15AB8BEF9A6AAB07E457A6E16BC410546AA4DC6:1:D505DA273544 + LastCommit: 56FEF2EFDB8B37E9C6E6D635749DF3169D5F005D + Data: + Validators: CE25FBFF2E10C0D51AA1A07C064A96931BC8B297 + App: E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD + }#F671D562C7B9242900A286E1882EE64E5556FE9E + Data{ + + }# + Commit{ + BlockID: F15AB8BEF9A6AAB07E457A6E16BC410546AA4DC6:1:D505DA273544 + Precommits: Vote{0:125B0E3C5512 90/00/2(Precommit) F15AB8BEF9A6 {/FE98E2B956F0.../}} + }#56FEF2EFDB8B37E9C6E6D635749DF3169D5F005D +}#F671D562C7B9242900A286E1882EE64E5556FE9E module=consensus +I[10-04|13:54:30.408] Executed block module=state height=91 validTxs=0 invalidTxs=0 +I[10-04|13:54:30.410] Committed state module=state height=91 txs=0 hash=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD +I[10-04|13:54:30.410] Recheck txs module=mempool numtxs=0 height=91 +``` + +## List of modules + +Here is the list of modules you may encounter in Tendermint's log and a +little overview what they do. + +- `abci-client` As mentioned in [Application Development Guide](./app-development.md), Tendermint acts as an ABCI + client with respect to the application and maintains 3 connections: + mempool, consensus and query. The code used by Tendermint Core can + be found [here](https://github.com/tendermint/tendermint/tree/develop/abci/client). +- `blockchain` Provides storage, pool (a group of peers), and reactor + for both storing and exchanging blocks between peers. +- `consensus` The heart of Tendermint core, which is the + implementation of the consensus algorithm. Includes two + "submodules": `wal` (write-ahead logging) for ensuring data + integrity and `replay` to replay blocks and messages on recovery + from a crash. +- `events` Simple event notification system. The list of events can be + found + [here](https://github.com/tendermint/tendermint/blob/master/types/events.go). + You can subscribe to them by calling `subscribe` RPC method. Refer + to [RPC docs](./specification/rpc.md) for additional information. +- `mempool` Mempool module handles all incoming transactions, whenever + they are coming from peers or the application. +- `p2p` Provides an abstraction around peer-to-peer communication. For + more details, please check out the + [README](https://github.com/tendermint/tendermint/blob/master/p2p/README.md). +- `rpc` [Tendermint's RPC](./specification/rpc.md). +- `rpc-server` RPC server. For implementation details, please read the + [README](https://github.com/tendermint/tendermint/blob/master/rpc/lib/README.md). +- `state` Represents the latest state and execution submodule, which + executes blocks against the application. +- `types` A collection of the publicly exposed types and methods to + work with them. diff --git a/docs/tendermint-core/light-client-protocol.md b/docs/tendermint-core/light-client-protocol.md new file mode 100644 index 000000000..6d905be32 --- /dev/null +++ b/docs/tendermint-core/light-client-protocol.md @@ -0,0 +1,30 @@ +# Light Client Protocol + +Light clients are an important part of the complete blockchain system +for most applications. Tendermint provides unique speed and security +properties for light client applications. + +See our [lite +package](https://godoc.org/github.com/tendermint/tendermint/lite). + +## Overview + +The objective of the light client protocol is to get a +[commit](./validators.md#committing-a-block) for a recent [block +hash](../spec/consensus/consensus.md.md#block-hash) where the commit includes a +majority of signatures from the last known validator set. From there, +all the application state is verifiable with [merkle +proofs](./merkle.md#iavl-tree). + +## Properties + +- You get the full collateralized security benefits of Tendermint; No + need to wait for confirmations. +- You get the full speed benefits of Tendermint; transactions + commit instantly. +- You can get the most recent version of the application state + non-interactively (without committing anything to the blockchain). + For example, this means that you can get the most recent value of a + name from the name-registry without worrying about fork censorship + attacks, without posting a commit and waiting for confirmations. + It's fast, secure, and free! diff --git a/docs/metrics.md b/docs/tendermint-core/metrics.md similarity index 100% rename from docs/metrics.md rename to docs/tendermint-core/metrics.md diff --git a/docs/specification/rpc.md b/docs/tendermint-core/rpc.md similarity index 100% rename from docs/specification/rpc.md rename to docs/tendermint-core/rpc.md diff --git a/docs/running-in-production.md b/docs/tendermint-core/running-in-production.md similarity index 72% rename from docs/running-in-production.md rename to docs/tendermint-core/running-in-production.md index 225a97853..094734320 100644 --- a/docs/running-in-production.md +++ b/docs/tendermint-core/running-in-production.md @@ -16,7 +16,7 @@ logging level, you can do so by running tendermint with Validators are supposed to setup [Sentry Node Architecture](https://blog.cosmos.network/tendermint-explained-bringing-bft-based-pos-to-the-public-blockchain-domain-f22e274a0fdb) to prevent Denial-of-service attacks. You can read more about it -[here](https://github.com/tendermint/aib-data/blob/develop/medium/TendermintBFT.md). +[here](../interviews/tendermint-bft.md). ### P2P @@ -49,21 +49,25 @@ second TODO is to query the /status RPC endpoint. It provides the necessary info: whenever the node is syncing or not, what height it is on, etc. - $ curl http(s)://{ip}:{rpcPort}/status +``` +curl http(s)://{ip}:{rpcPort}/status +``` `dump_consensus_state` will give you a detailed overview of the consensus state (proposer, lastest validators, peers states). From it, you should be able to figure out why, for example, the network had halted. - $ curl http(s)://{ip}:{rpcPort}/dump_consensus_state +``` +curl http(s)://{ip}:{rpcPort}/dump_consensus_state +``` There is a reduced version of this endpoint - `consensus_state`, which returns just the votes seen at the current height. -- [Github Issues](https://github.com/tendermint/tendermint/issues) -- [StackOverflow - questions](https://stackoverflow.com/questions/tagged/tendermint) +- [Github Issues](https://github.com/tendermint/tendermint/issues) +- [StackOverflow + questions](https://stackoverflow.com/questions/tagged/tendermint) ## Monitoring Tendermint @@ -100,6 +104,69 @@ signals we use the default behaviour in Go: [Default behavior of signals in Go programs](https://golang.org/pkg/os/signal/#hdr-Default_behavior_of_signals_in_Go_programs). +## Corruption + +**NOTE:** Make sure you have a backup of the Tendermint data directory. + +### Possible causes + +Remember that most corruption is caused by hardware issues: + +- RAID controllers with faulty / worn out battery backup, and an unexpected power loss +- Hard disk drives with write-back cache enabled, and an unexpected power loss +- Cheap SSDs with insufficient power-loss protection, and an unexpected power-loss +- Defective RAM +- Defective or overheating CPU(s) + +Other causes can be: + +- Database systems configured with fsync=off and an OS crash or power loss +- Filesystems configured to use write barriers plus a storage layer that ignores write barriers. LVM is a particular culprit. +- Tendermint bugs +- Operating system bugs +- Admin error (e.g., directly modifying Tendermint data-directory contents) + +(Source: https://wiki.postgresql.org/wiki/Corruption) + +### WAL Corruption + +If consensus WAL is corrupted at the lastest height and you are trying to start +Tendermint, replay will fail with panic. + +Recovering from data corruption can be hard and time-consuming. Here are two approaches you can take: + +1) Delete the WAL file and restart Tendermint. It will attempt to sync with other peers. +2) Try to repair the WAL file manually: + + 1. Create a backup of the corrupted WAL file: + +``` +cp "$TMHOME/data/cs.wal/wal" > /tmp/corrupted_wal_backup +``` + + 2. Use `./scripts/wal2json` to create a human-readable version + +``` +./scripts/wal2json/wal2json "$TMHOME/data/cs.wal/wal" > /tmp/corrupted_wal +``` + + 3. Search for a "CORRUPTED MESSAGE" line. + 4. By looking at the previous message and the message after the corrupted one + and looking at the logs, try to rebuild the message. If the consequent + messages are marked as corrupted too (this may happen if length header + got corrupted or some writes did not make it to the WAL ~ truncation), + then remove all the lines starting from the corrupted one and restart + Tendermint. + +``` +$EDITOR /tmp/corrupted_wal +``` + 5. After editing, convert this file back into binary form by running: + +``` +./scripts/json2wal/json2wal /tmp/corrupted_wal > "$TMHOME/data/cs.wal/wal" +``` + ## Hardware ### Processor and Memory @@ -107,18 +174,18 @@ programs](https://golang.org/pkg/os/signal/#hdr-Default_behavior_of_signals_in_G While actual specs vary depending on the load and validators count, minimal requirements are: -- 1GB RAM -- 25GB of disk space -- 1.4 GHz CPU +- 1GB RAM +- 25GB of disk space +- 1.4 GHz CPU SSD disks are preferable for applications with high transaction throughput. Recommended: -- 2GB RAM -- 100GB SSD -- x64 2.0 GHz 2v CPU +- 2GB RAM +- 100GB SSD +- x64 2.0 GHz 2v CPU While for now, Tendermint stores all the history and it may require significant disk space over time, we are planning to implement state @@ -145,21 +212,23 @@ Cosmos network. ## Configuration parameters -- `p2p.flush_throttle_timeout` `p2p.max_packet_msg_payload_size` - `p2p.send_rate` `p2p.recv_rate` +- `p2p.flush_throttle_timeout` `p2p.max_packet_msg_payload_size` + `p2p.send_rate` `p2p.recv_rate` If you are going to use Tendermint in a private domain and you have a private high-speed network among your peers, it makes sense to lower flush throttle timeout and increase other params. - [p2p] +``` +[p2p] - send_rate=20000000 # 2MB/s - recv_rate=20000000 # 2MB/s - flush_throttle_timeout=10 - max_packet_msg_payload_size=10240 # 10KB +send_rate=20000000 # 2MB/s +recv_rate=20000000 # 2MB/s +flush_throttle_timeout=10 +max_packet_msg_payload_size=10240 # 10KB +``` -- `mempool.recheck` +- `mempool.recheck` After every block, Tendermint rechecks every transaction left in the mempool to see if transactions committed in that block affected the @@ -167,13 +236,13 @@ application state, so some of the transactions left may become invalid. If that does not apply to your application, you can disable it by setting `mempool.recheck=false`. -- `mempool.broadcast` +- `mempool.broadcast` Setting this to false will stop the mempool from relaying transactions to other peers until they are included in a block. It means only the peer you send the tx to will see it until it is included in a block. -- `consensus.skip_timeout_commit` +- `consensus.skip_timeout_commit` We want `skip_timeout_commit=false` when there is economics on the line because proposers should wait to hear for more votes. But if you don't @@ -182,22 +251,17 @@ be kept false by default for public deployments (e.g. [Cosmos Hub](https://cosmos.network/intro/hub)) while for enterprise applications, setting it to true is not a problem. -- `consensus.peer_gossip_sleep_duration` +- `consensus.peer_gossip_sleep_duration` You can try to reduce the time your node sleeps before checking if theres something to send its peers. -- `consensus.timeout_commit` +- `consensus.timeout_commit` You can also try lowering `timeout_commit` (time we sleep before proposing the next block). -- `consensus.max_block_size_txs` - -By default, the maximum number of transactions per a block is 10_000. -Feel free to change it to suit your needs. - -- `p2p.addr_book_strict` +- `p2p.addr_book_strict` By default, Tendermint checks whenever a peer's address is routable before saving it to the address book. The address is considered as routable if the IP diff --git a/docs/specification/secure-p2p.rst b/docs/tendermint-core/secure-p2p.md similarity index 72% rename from docs/specification/secure-p2p.rst rename to docs/tendermint-core/secure-p2p.md index de95f0cf0..aad5eac41 100644 --- a/docs/specification/secure-p2p.rst +++ b/docs/tendermint-core/secure-p2p.md @@ -1,12 +1,11 @@ -Secure P2P -========== +# Secure P2P The Tendermint p2p protocol uses an authenticated encryption scheme -based on the `Station-to-Station -Protocol `__. +based on the [Station-to-Station +Protocol](https://en.wikipedia.org/wiki/Station-to-Station_protocol). The implementation uses -`golang's `__ `nacl -box `__ for the actual authenticated +[golang's](https://godoc.org/golang.org/x/crypto/nacl/box) [nacl +box](http://nacl.cr.yp.to/box.html) for the actual authenticated encryption algorithm. Each peer generates an ED25519 key-pair to use as a persistent @@ -19,10 +18,9 @@ their respective ephemeral public keys. This happens in the clear. They then each compute the shared secret. The shared secret is the multiplication of the peer's ephemeral private key by the other peer's ephemeral public key. The result is the same for both peers by the magic -of `elliptic -curves `__. -The shared secret is used as the symmetric key for the encryption -algorithm. +of [elliptic +curves](https://en.wikipedia.org/wiki/Elliptic_curve_cryptography). The +shared secret is used as the symmetric key for the encryption algorithm. The two ephemeral public keys are sorted to establish a canonical order. Then a 24-byte nonce is generated by concatenating the public keys and @@ -52,8 +50,7 @@ time it is used. The communications maintain Perfect Forward Secrecy, as the persistent key pair was not used for generating secrets - only for authenticating. -Caveat ------- +## Caveat This system is still vulnerable to a Man-In-The-Middle attack if the persistent public key of the remote node is not known in advance. The @@ -62,17 +59,15 @@ such as the Web-of-Trust or Certificate Authorities. In our case, we can use the blockchain itself as a certificate authority to ensure that we are connected to at least one validator. -Config ------- +## Config Authenticated encryption is enabled by default. -Additional Reading ------------------- +## Additional Reading -- `Implementation `__ -- `Original STS paper by Whitfield Diffie, Paul C. van Oorschot and - Michael J. - Wiener `__ -- `Further work on secret - handshakes `__ +- [Implementation](https://github.com/tendermint/tendermint/blob/64bae01d007b5bee0d0827ab53259ffd5910b4e6/p2p/conn/secret_connection.go#L47) +- [Original STS paper by Whitfield Diffie, Paul C. van Oorschot and + Michael J. + Wiener](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.216.6107&rep=rep1&type=pdf) +- [Further work on secret + handshakes](https://dominictarr.github.io/secret-handshake-paper/shs.pdf) diff --git a/docs/using-tendermint.md b/docs/tendermint-core/using-tendermint.md similarity index 70% rename from docs/using-tendermint.md rename to docs/tendermint-core/using-tendermint.md index 1cd910821..11949c798 100644 --- a/docs/using-tendermint.md +++ b/docs/tendermint-core/using-tendermint.md @@ -16,7 +16,9 @@ this by setting the `TMHOME` environment variable. Initialize the root directory by running: - tendermint init +``` +tendermint init +``` This will create a new private key (`priv_validator.json`), and a genesis file (`genesis.json`) containing the associated public key, in @@ -25,24 +27,97 @@ with one validator. For more elaborate initialization, see the tesnet command: - tendermint testnet --help +``` +tendermint testnet --help +``` + +### Genesis + +The `genesis.json` file in `$TMHOME/config/` defines the initial +TendermintCore state upon genesis of the blockchain ([see +definition](https://github.com/tendermint/tendermint/blob/master/types/genesis.go)). + +#### Fields + +- `genesis_time`: Official time of blockchain start. +- `chain_id`: ID of the blockchain. This must be unique for + every blockchain. If your testnet blockchains do not have unique + chain IDs, you will have a bad time. +- `validators`: +- `pub_key`: The first element specifies the `pub_key` type. 1 + == Ed25519. The second element are the pubkey bytes. +- `power`: The validator's voting power. +- `name`: Name of the validator (optional). +- `app_hash`: The expected application hash (as returned by the + `ResponseInfo` ABCI message) upon genesis. If the app's hash does + not match, Tendermint will panic. +- `app_state`: The application state (e.g. initial distribution + of tokens). + +#### Sample genesis.json + +``` +{ + "genesis_time": "2018-07-09T22:43:06.255718641Z", + "chain_id": "chain-IAkWsK", + "validators": [ + { + "pub_key": { + "type": "tendermint/PubKeyEd25519", + "value": "oX8HhKsErMluxI0QWNSR8djQMSupDvHdAYrHwP7n73k=" + }, + "power": "1", + "name": "node0" + }, + { + "pub_key": { + "type": "tendermint/PubKeyEd25519", + "value": "UZNSJA9zmeFQj36Rs296lY+WFQ4Rt6s7snPpuKypl5I=" + }, + "power": "1", + "name": "node1" + }, + { + "pub_key": { + "type": "tendermint/PubKeyEd25519", + "value": "i9GrM6/MHB4zjCelMZBUYHNXYIzl4n0RkDCVmmLhS/o=" + }, + "power": "1", + "name": "node2" + }, + { + "pub_key": { + "type": "tendermint/PubKeyEd25519", + "value": "0qq7954l87trEqbQV9c7d1gurnjTGMxreXc848ZZ5aw=" + }, + "power": "1", + "name": "node3" + } + ], + "app_hash": "" +} +``` ## Run To run a Tendermint node, use - tendermint node +``` +tendermint node +``` By default, Tendermint will try to connect to an ABCI application on [127.0.0.1:26658](127.0.0.1:26658). If you have the `kvstore` ABCI app installed, run it in another window. If you don't, kill Tendermint and run an in-process version of the `kvstore` app: - tendermint node --proxy_app=kvstore +``` +tendermint node --proxy_app=kvstore +``` After a few seconds you should see blocks start streaming in. Note that blocks are produced regularly, even if there are no transactions. See -*No Empty Blocks*, below, to modify this setting. +_No Empty Blocks_, below, to modify this setting. Tendermint supports in-process versions of the `counter`, `kvstore` and `nil` apps that ship as examples with `abci-cli`. It's easy to compile @@ -51,22 +126,30 @@ app is not written in Go, simply run it in another process, and use the `--proxy_app` flag to specify the address of the socket it is listening on, for instance: - tendermint node --proxy_app=/var/run/abci.sock +``` +tendermint node --proxy_app=/var/run/abci.sock +``` ## Transactions To send a transaction, use `curl` to make requests to the Tendermint RPC server, for example: - curl http://localhost:26657/broadcast_tx_commit?tx=\"abcd\" +``` +curl http://localhost:26657/broadcast_tx_commit?tx=\"abcd\" +``` We can see the chain's status at the `/status` end-point: - curl http://localhost:26657/status | json_pp +``` +curl http://localhost:26657/status | json_pp +``` and the `latest_app_hash` in particular: - curl http://localhost:26657/status | json_pp | grep latest_app_hash +``` +curl http://localhost:26657/status | json_pp | grep latest_app_hash +``` Visit http://localhost:26657> in your browser to see the list of other endpoints. Some take no arguments (like `/status`), while others specify @@ -81,30 +164,40 @@ With `GET`: To send a UTF8 string byte array, quote the value of the tx pramater: - curl 'http://localhost:26657/broadcast_tx_commit?tx="hello"' +``` +curl 'http://localhost:26657/broadcast_tx_commit?tx="hello"' +``` which sends a 5 byte transaction: "h e l l o" \[68 65 6c 6c 6f\]. Note the URL must be wrapped with single quoes, else bash will ignore the double quotes. To avoid the single quotes, escape the double quotes: - curl http://localhost:26657/broadcast_tx_commit?tx=\"hello\" +``` +curl http://localhost:26657/broadcast_tx_commit?tx=\"hello\" +``` Using a special character: - curl 'http://localhost:26657/broadcast_tx_commit?tx="€5"' +``` +curl 'http://localhost:26657/broadcast_tx_commit?tx="€5"' +``` sends a 4 byte transaction: "€5" (UTF8) \[e2 82 ac 35\]. To send as raw hex, omit quotes AND prefix the hex string with `0x`: - curl http://localhost:26657/broadcast_tx_commit?tx=0x01020304 +``` +curl http://localhost:26657/broadcast_tx_commit?tx=0x01020304 +``` which sends a 4 byte transaction: \[01 02 03 04\]. With `POST` (using `json`), the raw hex must be `base64` encoded: - curl --data-binary '{"jsonrpc":"2.0","id":"anything","method":"broadcast_tx_commit","params": {"tx": "AQIDBA=="}}' -H 'content-type:text/plain;' http://localhost:26657 +``` +curl --data-binary '{"jsonrpc":"2.0","id":"anything","method":"broadcast_tx_commit","params": {"tx": "AQIDBA=="}}' -H 'content-type:text/plain;' http://localhost:26657 +``` which sends the same 4 byte transaction: \[01 02 03 04\]. @@ -118,7 +211,9 @@ afford to lose all blockchain data! To reset a blockchain, stop the node, remove the `~/.tendermint/data` directory and run - tendermint unsafe_reset_priv_validator +``` +tendermint unsafe_reset_priv_validator +``` This final step is necessary to reset the `priv_validator.json`, which otherwise prevents you from making conflicting votes in the consensus @@ -150,21 +245,27 @@ To configure Tendermint to not produce empty blocks unless there are transactions or the app hash changes, run Tendermint with this additional flag: - tendermint node --consensus.create_empty_blocks=false +``` +tendermint node --consensus.create_empty_blocks=false +``` or set the configuration via the `config.toml` file: - [consensus] - create_empty_blocks = false +``` +[consensus] +create_empty_blocks = false +``` -Remember: because the default is to *create empty blocks*, avoiding +Remember: because the default is to _create empty blocks_, avoiding empty blocks requires the config option to be set to `false`. The block interval setting allows for a delay (in seconds) between the creation of each new empty block. It is set via the `config.toml`: - [consensus] - create_empty_blocks_interval = 5 +``` +[consensus] +create_empty_blocks_interval = 5 +``` With this setting, empty blocks will be produced every 5s if no block has been produced otherwise, regardless of the value of @@ -181,9 +282,11 @@ eventually included in a block. Since there are multiple phases to processing a transaction, we offer multiple endpoints to broadcast a transaction: - /broadcast_tx_async - /broadcast_tx_sync - /broadcast_tx_commit +``` +/broadcast_tx_async +/broadcast_tx_sync +/broadcast_tx_commit +``` These correspond to no-processing, processing through the mempool, and processing through a block, respectively. That is, `broadcast_tx_async`, @@ -208,38 +311,42 @@ When `tendermint init` is run, both a `genesis.json` and `priv_validator.json` are created in `~/.tendermint/config`. The `genesis.json` might look like: +``` +{ + "validators" : [ { - "validators" : [ - { - "pub_key" : { - "value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=", - "type" : "tendermint/PubKeyEd25519" - }, - "power" : 10, - "name" : "" - } - ], - "app_hash" : "", - "chain_id" : "test-chain-rDlYSN", - "genesis_time" : "0001-01-01T00:00:00Z" - } - -And the `priv_validator.json`: - - { - "last_step" : 0, - "last_round" : "0", - "address" : "B788DEDE4F50AD8BC9462DE76741CCAFF87D51E2", "pub_key" : { "value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=", "type" : "tendermint/PubKeyEd25519" }, - "last_height" : "0", - "priv_key" : { - "value" : "JPivl82x+LfVkp8i3ztoTjY6c6GJ4pBxQexErOCyhwqHeGT5ATxzpAtPJKnxNx/NyUnD8Ebv3OIYH+kgD4N88Q==", - "type" : "tendermint/PrivKeyEd25519" - } + "power" : 10, + "name" : "" } + ], + "app_hash" : "", + "chain_id" : "test-chain-rDlYSN", + "genesis_time" : "0001-01-01T00:00:00Z" +} +``` + +And the `priv_validator.json`: + +``` +{ + "last_step" : 0, + "last_round" : "0", + "address" : "B788DEDE4F50AD8BC9462DE76741CCAFF87D51E2", + "pub_key" : { + "value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=", + "type" : "tendermint/PubKeyEd25519" + }, + "last_height" : "0", + "priv_key" : { + "value" : "JPivl82x+LfVkp8i3ztoTjY6c6GJ4pBxQexErOCyhwqHeGT5ATxzpAtPJKnxNx/NyUnD8Ebv3OIYH+kgD4N88Q==", + "type" : "tendermint/PrivKeyEd25519" + } +} +``` The `priv_validator.json` actually contains a private key, and should thus be kept absolutely secret; for now we work with the plain text. @@ -272,6 +379,7 @@ with the consensus protocol. ### Peers #### Seed + A seed node is a node who relays the addresses of other peers which they know of. These nodes constantly crawl the network to try to get more peers. The addresses which the seed node relays get saved into a local address book. Once @@ -282,6 +390,7 @@ only need them on the first start. The seed node will immediately disconnect from you after sending you some addresses. #### Persistent Peer + Persistent peers are people you want to be constantly connected with. If you disconnect you will try to connect directly back to them as opposed to using another address from the address book. On restarts you will always try to @@ -302,12 +411,16 @@ persistent connections with. For example, - tendermint node --p2p.seeds "f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:26656,0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:26656" +``` +tendermint node --p2p.seeds "f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:26656,0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:26656" +``` Alternatively, you can use the `/dial_seeds` endpoint of the RPC to specify seeds for a running node to connect to: - curl 'localhost:26657/dial_seeds?seeds=\["f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:26656","0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:26656"\]' +``` +curl 'localhost:26657/dial_seeds?seeds=\["f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:26656","0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:26656"\]' +``` Note, with PeX enabled, you should not need seeds after the first start. @@ -318,8 +431,11 @@ maintain a persistent connection with each, you can use the `config.toml` or the `/dial_peers` RPC endpoint to do it without stopping Tendermint core instance. - tendermint node --p2p.persistent_peers "429fcf25974313b95673f58d77eacdd434402665@10.11.12.13:26656,96663a3dd0d7b9d17d4c8211b191af259621c693@10.11.12.14:26656" - curl 'localhost:26657/dial_peers?persistent=true&peers=\["429fcf25974313b95673f58d77eacdd434402665@10.11.12.13:26656","96663a3dd0d7b9d17d4c8211b191af259621c693@10.11.12.14:26656"\]' +``` +tendermint node --p2p.persistent_peers "429fcf25974313b95673f58d77eacdd434402665@10.11.12.13:26656,96663a3dd0d7b9d17d4c8211b191af259621c693@10.11.12.14:26656" + +curl 'localhost:26657/dial_peers?persistent=true&peers=\["429fcf25974313b95673f58d77eacdd434402665@10.11.12.13:26656","96663a3dd0d7b9d17d4c8211b191af259621c693@10.11.12.14:26656"\]' +``` ### Adding a Non-Validator @@ -338,51 +454,57 @@ before starting the network. For instance, we could make a new We can generate a new `priv_validator.json` with the command: - tendermint gen_validator +``` +tendermint gen_validator +``` Now we can update our genesis file. For instance, if the new `priv_validator.json` looks like: +``` +{ + "address" : "5AF49D2A2D4F5AD4C7C8C4CC2FB020131E9C4902", + "pub_key" : { + "value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=", + "type" : "tendermint/PubKeyEd25519" + }, + "priv_key" : { + "value" : "EDJY9W6zlAw+su6ITgTKg2nTZcHAH1NMTW5iwlgmNDuX1f35+OR4HMN88ZtQzsAwhETq4k3vzM3n6WTk5ii16Q==", + "type" : "tendermint/PrivKeyEd25519" + }, + "last_step" : 0, + "last_round" : "0", + "last_height" : "0" +} +``` + +then the new `genesis.json` will be: + +``` +{ + "validators" : [ { - "address" : "5AF49D2A2D4F5AD4C7C8C4CC2FB020131E9C4902", "pub_key" : { - "value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=", + "value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=", "type" : "tendermint/PubKeyEd25519" }, - "priv_key" : { - "value" : "EDJY9W6zlAw+su6ITgTKg2nTZcHAH1NMTW5iwlgmNDuX1f35+OR4HMN88ZtQzsAwhETq4k3vzM3n6WTk5ii16Q==", - "type" : "tendermint/PrivKeyEd25519" - }, - "last_step" : 0, - "last_round" : "0", - "last_height" : "0" - } - -then the new `genesis.json` will be: - + "power" : 10, + "name" : "" + }, { - "validators" : [ - { - "pub_key" : { - "value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=", - "type" : "tendermint/PubKeyEd25519" - }, - "power" : 10, - "name" : "" - }, - { - "pub_key" : { - "value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=", - "type" : "tendermint/PubKeyEd25519" - }, - "power" : 10, - "name" : "" - } - ], - "app_hash" : "", - "chain_id" : "test-chain-rDlYSN", - "genesis_time" : "0001-01-01T00:00:00Z" + "pub_key" : { + "value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=", + "type" : "tendermint/PubKeyEd25519" + }, + "power" : 10, + "name" : "" } + ], + "app_hash" : "", + "chain_id" : "test-chain-rDlYSN", + "genesis_time" : "0001-01-01T00:00:00Z" +} +``` Update the `genesis.json` in `~/.tendermint/config`. Copy the genesis file and the new `priv_validator.json` to the `~/.tendermint/config` on diff --git a/docs/specification/validators.rst b/docs/tendermint-core/validators.md similarity index 58% rename from docs/specification/validators.rst rename to docs/tendermint-core/validators.md index 085994f3d..0c1d7d89a 100644 --- a/docs/specification/validators.rst +++ b/docs/tendermint-core/validators.md @@ -1,5 +1,4 @@ -Validators -========== +# Validators Validators are responsible for committing new blocks in the blockchain. These validators participate in the consensus protocol by broadcasting @@ -19,25 +18,22 @@ to post any collateral at all. Validators have a cryptographic key-pair and an associated amount of "voting power". Voting power need not be the same. -Becoming a Validator --------------------- +## Becoming a Validator There are two ways to become validator. -1. They can be pre-established in the `genesis - state <./genesis.html>`__ -2. The ABCI app responds to the EndBlock message with changes to the - existing validator set. +1. They can be pre-established in the [genesis state](../../tendermint-core/using-tendermint.md#genesis) +2. The ABCI app responds to the EndBlock message with changes to the + existing validator set. -Committing a Block ------------------- +## Committing a Block *+2/3 is short for "more than 2/3"* -A block is committed when +2/3 of the validator set sign `precommit -votes <./block-structure.html#vote>`__ for that block at the same -``round``. The +2/3 set of precommit votes is -called a `*commit* <./block-structure.html#commit>`__. While any -+2/3 set of precommits for the same block at the same height&round can -serve as validation, the canonical commit is included in the next block -(see `LastCommit <./block-structure.html>`__). +A block is committed when +2/3 of the validator set sign [precommit +votes](../spec/blockchain/blockchain.md#vote) for that block at the same `round`. +The +2/3 set of precommit votes is called a +[*commit*](../spec/blockchain/blockchain.md#commit). While any +2/3 set of +precommits for the same block at the same height&round can serve as +validation, the canonical commit is included in the next block (see +[LastCommit](../spec/blockchain/blockchain.md#last-commit)). diff --git a/docs/tools/benchmarking.md b/docs/tools/benchmarking.md new file mode 100644 index 000000000..20c368e29 --- /dev/null +++ b/docs/tools/benchmarking.md @@ -0,0 +1,80 @@ +# tm-bench + +Tendermint blockchain benchmarking tool: + +- https://github.com/tendermint/tools/tree/master/tm-bench + +For example, the following: + +``` +tm-bench -T 10 -r 1000 localhost:26657 +``` + +will output: + +``` +Stats Avg StdDev Max Total +Txs/sec 818 532 1549 9000 +Blocks/sec 0.818 0.386 1 9 +``` + +## Quick Start + +[Install Tendermint](../introduction/install) +This currently is setup to work on tendermint's develop branch. Please ensure +you are on that. (If not, update `tendermint` and `tmlibs` in gopkg.toml to use + the master branch.) + +then run: + +``` +tendermint init +tendermint node --proxy_app=kvstore +``` + +``` +tm-bench localhost:26657 +``` + +with the last command being in a seperate window. + +## Usage + +``` +tm-bench [-c 1] [-T 10] [-r 1000] [-s 250] [endpoints] + +Examples: + tm-bench localhost:26657 +Flags: + -T int + Exit after the specified amount of time in seconds (default 10) + -c int + Connections to keep open per endpoint (default 1) + -r int + Txs per second to send in a connection (default 1000) + -s int + Size per tx in bytes + -v Verbose output +``` + +## How stats are collected + +These stats are derived by having each connection send transactions at the +specified rate (or as close as it can get) for the specified time. After the +specified time, it iterates over all of the blocks that were created in that +time. The average and stddev per second are computed based off of that, by +grouping the data by second. + +To send transactions at the specified rate in each connection, we loop +through the number of transactions. If its too slow, the loop stops at one second. +If its too fast, we wait until the one second mark ends. The transactions per +second stat is computed based off of what ends up in the block. + +Each of the connections is handled via two separate goroutines. + +## Development + +``` +make get_vendor_deps +make test +``` diff --git a/docs/tools/monitoring.md b/docs/tools/monitoring.md new file mode 100644 index 000000000..5cc2ad3b1 --- /dev/null +++ b/docs/tools/monitoring.md @@ -0,0 +1,92 @@ +# tm-monitor + +Tendermint blockchain monitoring tool; watches over one or more nodes, +collecting and providing various statistics to the user: + +- https://github.com/tendermint/tools/tree/master/tm-monitor + +## Quick Start + +### Docker + +Assuming your application is running in another container with the name +`app`: + +``` +docker run -it --rm -v "/tmp:/tendermint" tendermint/tendermint init +docker run -it --rm -v "/tmp:/tendermint" -p "26657:26657" --name=tm --link=app tendermint/tendermint node --proxy_app=tcp://app:26658 + +docker run -it --rm -p "26670:26670" --link=tm tendermint/monitor tm:26657 +``` + +If you don't have an application yet, but still want to try monitor out, +use `kvstore`: + +``` +docker run -it --rm -v "/tmp:/tendermint" tendermint/tendermint init +docker run -it --rm -v "/tmp:/tendermint" -p "26657:26657" --name=tm tendermint/tendermint node --proxy_app=kvstore +``` +``` +docker run -it --rm -p "26670:26670" --link=tm tendermint/monitor tm:26657 +``` + +### Using Binaries + +[Install Tendermint](https://github.com/tendermint/tendermint#install) + +then run: + +``` +tendermint init +tendermint node --proxy_app=kvstore +``` + +``` +tm-monitor localhost:26657 +``` + +with the last command being in a seperate window. + +## Usage + +``` +tm-monitor [-v] [-no-ton] [-listen-addr="tcp://0.0.0.0:26670"] [endpoints] + +Examples: + # monitor single instance + tm-monitor localhost:26657 + + # monitor a few instances by providing comma-separated list of RPC endpoints + tm-monitor host1:26657,host2:26657 +Flags: + -listen-addr string + HTTP and Websocket server listen address (default "tcp://0.0.0.0:26670") + -no-ton + Do not show ton (table of nodes) + -v verbose logging +``` + +### RPC UI + +Run `tm-monitor` and visit http://localhost:26670 You should see the +list of the available RPC endpoints: + +``` +http://localhost:26670/status +http://localhost:26670/status/network +http://localhost:26670/monitor?endpoint=_ +http://localhost:26670/status/node?name=_ +http://localhost:26670/unmonitor?endpoint=_ +``` + +The API is available as GET requests with URI encoded parameters, or as +JSONRPC POST requests. The JSONRPC methods are also exposed over +websocket. + +## Development + +``` +make get_tools +make get_vendor_deps +make test +``` diff --git a/docs/yarn.lock b/docs/yarn.lock new file mode 100644 index 000000000..5591b8fa0 --- /dev/null +++ b/docs/yarn.lock @@ -0,0 +1,2507 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@azu/format-text@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@azu/format-text/-/format-text-1.0.1.tgz#6967350a94640f6b02855169bd897ce54d6cebe2" + +"@azu/style-format@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@azu/style-format/-/style-format-1.0.0.tgz#e70187f8a862e191b1bce6c0268f13acd3a56b20" + dependencies: + "@azu/format-text" "^1.0.1" + +"@sindresorhus/is@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" + +"@textlint/ast-node-types@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@textlint/ast-node-types/-/ast-node-types-4.0.2.tgz#5386a15187798efb48eb71fa1cbf6ca2770b206a" + +"@textlint/ast-traverse@^2.0.8": + version "2.0.8" + resolved "https://registry.yarnpkg.com/@textlint/ast-traverse/-/ast-traverse-2.0.8.tgz#c180fe23dc3b8a6aa68539be70efb4ff17c38a3a" + dependencies: + "@textlint/ast-node-types" "^4.0.2" + +"@textlint/feature-flag@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@textlint/feature-flag/-/feature-flag-3.0.4.tgz#4290a4bb53da28c1f5f1d5ce0f4ae6630ab939ea" + dependencies: + map-like "^2.0.0" + +"@textlint/fixer-formatter@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@textlint/fixer-formatter/-/fixer-formatter-3.0.7.tgz#4ef15d5e606e2d32b89257afd382ed9dbb218846" + dependencies: + "@textlint/kernel" "^2.0.9" + chalk "^1.1.3" + debug "^2.1.0" + diff "^2.2.2" + interop-require "^1.0.0" + is-file "^1.0.0" + string-width "^1.0.1" + text-table "^0.2.0" + try-resolve "^1.0.1" + +"@textlint/kernel@^2.0.9": + version "2.0.9" + resolved "https://registry.yarnpkg.com/@textlint/kernel/-/kernel-2.0.9.tgz#a4471b7969e192551230c35ea9fae32d80128ee0" + dependencies: + "@textlint/ast-node-types" "^4.0.2" + "@textlint/ast-traverse" "^2.0.8" + "@textlint/feature-flag" "^3.0.4" + "@types/bluebird" "^3.5.18" + bluebird "^3.5.1" + debug "^2.6.6" + deep-equal "^1.0.1" + object-assign "^4.1.1" + structured-source "^3.0.2" + +"@textlint/linter-formatter@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@textlint/linter-formatter/-/linter-formatter-3.0.7.tgz#66716cac94c047d94627a7e6af427a0d199eda7c" + dependencies: + "@azu/format-text" "^1.0.1" + "@azu/style-format" "^1.0.0" + "@textlint/kernel" "^2.0.9" + chalk "^1.0.0" + concat-stream "^1.5.1" + js-yaml "^3.2.4" + optionator "^0.8.1" + pluralize "^2.0.0" + string-width "^1.0.1" + string.prototype.padstart "^3.0.0" + strip-ansi "^3.0.1" + table "^3.7.8" + text-table "^0.2.0" + try-resolve "^1.0.1" + xml-escape "^1.0.0" + +"@textlint/markdown-to-ast@^6.0.8": + version "6.0.8" + resolved "https://registry.yarnpkg.com/@textlint/markdown-to-ast/-/markdown-to-ast-6.0.8.tgz#baa509c42f842b4dba36ad91547a288c063396b8" + dependencies: + "@textlint/ast-node-types" "^4.0.2" + debug "^2.1.3" + remark-frontmatter "^1.2.0" + remark-parse "^5.0.0" + structured-source "^3.0.2" + traverse "^0.6.6" + unified "^6.1.6" + +"@textlint/text-to-ast@^3.0.8": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@textlint/text-to-ast/-/text-to-ast-3.0.8.tgz#6211977f369cec484447867f10dc155120f4c082" + dependencies: + "@textlint/ast-node-types" "^4.0.2" + +"@textlint/textlint-plugin-markdown@^4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@textlint/textlint-plugin-markdown/-/textlint-plugin-markdown-4.0.10.tgz#a99b4a308067597e89439a9e87bc1c4a7f4d076b" + dependencies: + "@textlint/markdown-to-ast" "^6.0.8" + +"@textlint/textlint-plugin-text@^3.0.10": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@textlint/textlint-plugin-text/-/textlint-plugin-text-3.0.10.tgz#619600bdc352d33a68e7a73d77d58b0c52b2a44f" + dependencies: + "@textlint/text-to-ast" "^3.0.8" + +"@types/bluebird@^3.5.18": + version "3.5.21" + resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.21.tgz#567615589cc913e84a28ecf9edb031732bdf2634" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +aggregate-error@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-1.0.0.tgz#888344dad0220a72e3af50906117f48771925fac" + dependencies: + clean-stack "^1.0.0" + indent-string "^3.0.0" + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv@^4.7.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + dependencies: + micromatch "^2.1.5" + normalize-path "^2.0.0" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +array-iterate@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/array-iterate/-/array-iterate-1.1.2.tgz#f66a57e84426f8097f4197fbb6c051b8e5cdf7d8" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" + +bail@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.3.tgz#63cfb9ddbac829b02a3128cd53224be78e6c21a3" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + dependencies: + tweetnacl "^0.14.3" + +binary-extensions@^1.0.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" + +bluebird@^3.0.5, bluebird@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + +boundary@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/boundary/-/boundary-1.0.1.tgz#4d67dc2602c0cc16dd9bce7ebf87e948290f5812" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +buffer-from@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04" + +builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +cacheable-request@^2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" + dependencies: + clone-response "1.0.2" + get-stream "3.0.0" + http-cache-semantics "3.8.1" + keyv "3.0.0" + lowercase-keys "1.0.0" + normalize-url "2.0.1" + responselike "1.0.2" + +camelcase@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + +capture-stack-trace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +ccount@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.3.tgz#f1cec43f332e2ea5a569fd46f9f5bde4e6102aff" + +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +character-entities-html4@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-1.1.2.tgz#c44fdde3ce66b52e8d321d6c1bf46101f0150610" + +character-entities-legacy@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz#7c6defb81648498222c9855309953d05f4d63a9c" + +character-entities@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.2.tgz#58c8f371c0774ef0ba9b2aca5f00d8f100e6e363" + +character-reference-invalid@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz#21e421ad3d84055952dab4a43a04e73cd425d3ed" + +charenc@~0.0.1: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + +chokidar@^1.5.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +chownr@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + +clean-stack@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31" + +clone-response@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + dependencies: + mimic-response "^1.0.0" + +co@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/co/-/co-3.1.0.tgz#4ea54ea5a08938153185e15210c68d9092bc1b78" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +collapse-white-space@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091" + +color-convert@^1.9.0: + version "1.9.2" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" + dependencies: + color-name "1.1.1" + +color-name@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" + +combined-stream@1.0.6, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + dependencies: + delayed-stream "~1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.5.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +create-error-class@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + dependencies: + capture-stack-trace "^1.0.0" + +crypt@~0.0.1: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +debug@^2.1.0, debug@^2.1.2, debug@^2.1.3, debug@^2.2.0, debug@^2.6.6: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + dependencies: + mimic-response "^1.0.0" + +deep-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + +diff@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/diff/-/diff-2.2.3.tgz#60eafd0d28ee906e4e8ff0a52c1229521033bf99" + +dns-packet@^1.1.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" + dependencies: + ip "^1.1.0" + safe-buffer "^5.0.1" + +dns-socket@^1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/dns-socket/-/dns-socket-1.6.3.tgz#5268724fad4aa46ad9c5ca4ffcd16e1de5342aab" + dependencies: + dns-packet "^1.1.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.4.3: + version "1.12.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.1" + has "^1.0.1" + is-callable "^1.1.3" + is-regex "^1.0.4" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +extend@^3.0.0, extend@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +fault@^1.0.0, fault@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.2.tgz#c3d0fec202f172a3a4d414042ad2bb5e2a3ffbaa" + dependencies: + format "^0.2.2" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +fill-range@^2.1.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^3.0.0" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +find-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +flat-cache@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +fn-name@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" + +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + +format@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + +from2@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + dependencies: + minipass "^2.2.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" + +function-bind@^1.0.2, function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +get-stdin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + +get-stream@3.0.0, get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +got@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + +got@^8.0.0: + version "8.3.2" + resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" + dependencies: + "@sindresorhus/is" "^0.7.0" + cacheable-request "^2.1.1" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + into-stream "^3.1.0" + is-retry-allowed "^1.1.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + mimic-response "^1.0.0" + p-cancelable "^0.4.0" + p-timeout "^2.0.1" + pify "^3.0.0" + safe-buffer "^5.1.1" + timed-out "^4.0.1" + url-parse-lax "^3.0.0" + url-to-options "^1.0.1" + +graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +has-symbol-support-x@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" + +has-to-string-tag-x@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + dependencies: + has-symbol-support-x "^1.4.1" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + dependencies: + function-bind "^1.1.1" + +hosted-git-info@^2.1.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.1.tgz#6e4cee78b01bb849dcf93527708c69fdbee410df" + +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +iconv-lite@^0.4.4: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" + +ignore@^3.2.0: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +interop-require@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/interop-require/-/interop-require-1.0.0.tgz#e53103679944c88d7e6105b62a9f4475c783971e" + +into-stream@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" + dependencies: + from2 "^2.1.1" + p-is-promise "^1.1.0" + +ip-regex@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + +ip@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + +is-alphabetical@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.2.tgz#1fa6e49213cb7885b75d15862fb3f3d96c884f41" + +is-alphanumeric@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-alphanumeric/-/is-alphanumeric-1.0.0.tgz#4a9cef71daf4c001c1d81d63d140cf53fd6889f4" + +is-alphanumerical@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.2.tgz#1138e9ae5040158dc6ff76b820acd6b7a181fd40" + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.4, is-buffer@^1.1.5, is-buffer@~1.1.1: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-decimal@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.2.tgz#894662d6a8709d307f3a276ca4339c8fa5dff0ff" + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + +is-empty@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-empty/-/is-empty-1.2.0.tgz#de9bb5b278738a05a0b09a57e1fb4d4a341a9f6b" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-file/-/is-file-1.0.0.tgz#28a44cfbd9d3db193045f22b65fce8edf9620596" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-hexadecimal@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835" + +is-hidden@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-hidden/-/is-hidden-1.1.1.tgz#82ee6a93aeef3fb007ad5b9457c0584d45329f38" + +is-ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-2.0.0.tgz#68eea07e8a0a0a94c2d080dd674c731ab2a461ab" + dependencies: + ip-regex "^2.0.0" + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + +is-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" + +is-online@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-online/-/is-online-7.0.0.tgz#7e2408c0ae1e7e37ba8d50bdb237260d32bfd96e" + dependencies: + got "^6.7.1" + p-any "^1.0.0" + p-timeout "^1.0.0" + public-ip "^2.3.0" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + dependencies: + path-is-inside "^1.0.1" + +is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-relative-url@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-relative-url/-/is-relative-url-2.0.0.tgz#72902d7fe04b3d4792e7db15f9db84b7204c9cef" + dependencies: + is-absolute-url "^2.0.0" + +is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + +is-stream@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +is-whitespace-character@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz#ede53b4c6f6fb3874533751ec9280d01928d03ed" + +is-word-character@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.2.tgz#46a5dac3f2a1840898b91e576cd40d493f3ae553" + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isemail@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.1.2.tgz#937cf919002077999a73ea8b1951d590e84e01dd" + dependencies: + punycode "2.x.x" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + +js-yaml@^3.2.4, js-yaml@^3.6.1: + version "3.12.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json5@^0.5.0, json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +keyv@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" + dependencies: + json-buffer "3.0.0" + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +link-check@^4.1.0: + version "4.4.4" + resolved "https://registry.yarnpkg.com/link-check/-/link-check-4.4.4.tgz#08dbb881b70c23f1c173889c3a34d682c2e68c1a" + dependencies: + is-relative-url "^2.0.0" + isemail "^3.1.2" + ms "^2.1.1" + request "^2.87.0" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + +load-plugin@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/load-plugin/-/load-plugin-2.2.2.tgz#ebc7599491ff33e5077719fbe051d5725a9f7a89" + dependencies: + npm-prefix "^1.2.0" + resolve-from "^4.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash@^4.0.0: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + dependencies: + chalk "^1.0.0" + +longest-streak@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e" + +lowercase-keys@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + +lowercase-keys@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + +map-like@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/map-like/-/map-like-2.0.0.tgz#94496d49ad333c0dc3234b27adbbd1e8535953b4" + +markdown-escapes@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122" + +markdown-extensions@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-1.1.1.tgz#fea03b539faeaee9b4ef02a3769b455b189f7fc3" + +markdown-table@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.2.tgz#c78db948fa879903a41bce522e3b96f801c63786" + +math-random@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" + +md5@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" + dependencies: + charenc "~0.0.1" + crypt "~0.0.1" + is-buffer "~1.1.1" + +mdast-util-compact@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-1.0.1.tgz#cdb5f84e2b6a2d3114df33bd05d9cb32e3c4083a" + dependencies: + unist-util-modify-children "^1.0.0" + unist-util-visit "^1.1.0" + +micromatch@^2.1.5: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + +mime-types@^2.1.12, mime-types@~2.1.17: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + dependencies: + mime-db "~1.33.0" + +mimic-response@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" + +minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minipass@^2.2.1, minipass@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + +mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + +nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +needle@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + +node-pre-gyp@^0.10.0: + version "0.10.2" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.2.tgz#e8945c20ef6795a20aac2b44f036eb13cf5146e3" + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.0" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-package-data@^2.3.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.0, normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-url@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" + dependencies: + prepend-http "^2.0.0" + query-string "^5.0.1" + sort-keys "^2.0.0" + +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + +npm-packlist@^1.1.6: + version "1.1.10" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-prefix@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/npm-prefix/-/npm-prefix-1.2.0.tgz#e619455f7074ba54cc66d6d0d37dd9f1be6bcbc0" + dependencies: + rc "^1.1.0" + shellsubstitute "^1.1.0" + untildify "^2.1.0" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-keys@^1.0.8, object-keys@^1.0.9: + version "1.0.12" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +optionator@^0.8.0, optionator@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-any@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-any/-/p-any-1.1.0.tgz#1d03835c7eed1e34b8e539c47b7b60d0d015d4e1" + dependencies: + p-some "^2.0.0" + +p-cancelable@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-is-promise@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +p-some@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-some/-/p-some-2.0.1.tgz#65d87c8b154edbcf5221d167778b6d2e150f6f06" + dependencies: + aggregate-error "^1.0.0" + +p-timeout@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" + dependencies: + p-finally "^1.0.0" + +p-timeout@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" + dependencies: + p-finally "^1.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + +parse-entities@^1.0.2, parse-entities@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.1.2.tgz#9eaf719b29dc3bd62246b4332009072e01527777" + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +path-exists@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-to-glob-pattern@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-to-glob-pattern/-/path-to-glob-pattern-1.0.2.tgz#473e6a3a292a9d13fbae3edccee72d3baba8c619" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + dependencies: + pify "^3.0.0" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pluralize@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-2.0.0.tgz#72b726aa6fac1edeee42256c7d8dc256b335677f" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +prettier@^1.13.7: + version "1.13.7" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281" + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +public-ip@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/public-ip/-/public-ip-2.4.0.tgz#f00c028a15366d8c798e47efab6acd09a17666da" + dependencies: + dns-socket "^1.6.2" + got "^8.0.0" + is-ip "^2.0.0" + pify "^3.0.0" + +punycode@2.x.x: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +randomatic@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.0.0.tgz#d35490030eb4f7578de292ce6dfb04a91a128923" + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + +rc-config-loader@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/rc-config-loader/-/rc-config-loader-2.0.1.tgz#8c8452f59bdd10d448a67762dccf7c1b247db860" + dependencies: + debug "^2.2.0" + js-yaml "^3.6.1" + json5 "^0.5.0" + object-assign "^4.1.0" + object-keys "^1.0.9" + path-exists "^2.1.0" + require-from-string "^2.0.1" + +rc@^1.1.0, rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + dependencies: + find-up "^2.0.0" + read-pkg "^3.0.0" + +read-pkg@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + +readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + dependencies: + is-equal-shallow "^0.1.3" + +remark-cli@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-cli/-/remark-cli-5.0.0.tgz#9feefd06474f3d0ff132df21b5334c546df12ab6" + dependencies: + markdown-extensions "^1.1.0" + remark "^9.0.0" + unified-args "^5.0.0" + +remark-frontmatter@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/remark-frontmatter/-/remark-frontmatter-1.2.0.tgz#67905d178c0fe531ed12c57b98759f101fc2c1b5" + dependencies: + fault "^1.0.1" + xtend "^4.0.1" + +remark-lint-no-dead-urls@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/remark-lint-no-dead-urls/-/remark-lint-no-dead-urls-0.3.0.tgz#b640ecbb4ccaf780afe28c8d13e79f5dc6769449" + dependencies: + is-online "^7.0.0" + is-relative-url "^2.0.0" + link-check "^4.1.0" + unified-lint-rule "^1.0.1" + unist-util-visit "^1.1.3" + +remark-parse@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-5.0.0.tgz#4c077f9e499044d1d5c13f80d7a98cf7b9285d95" + dependencies: + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^1.1.0" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^1.0.0" + vfile-location "^2.0.0" + xtend "^4.0.1" + +remark-stringify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/remark-stringify/-/remark-stringify-5.0.0.tgz#336d3a4d4a6a3390d933eeba62e8de4bd280afba" + dependencies: + ccount "^1.0.0" + is-alphanumeric "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + longest-streak "^2.0.1" + markdown-escapes "^1.0.0" + markdown-table "^1.1.0" + mdast-util-compact "^1.0.0" + parse-entities "^1.0.2" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + stringify-entities "^1.0.1" + unherit "^1.0.4" + xtend "^4.0.1" + +remark@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/remark/-/remark-9.0.0.tgz#c5cfa8ec535c73a67c4b0f12bfdbd3a67d8b2f60" + dependencies: + remark-parse "^5.0.0" + remark-stringify "^5.0.0" + unified "^6.0.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.0, repeat-string@^1.5.2, repeat-string@^1.5.4: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +replace-ext@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + +request@^2.87.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +require-from-string@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + +responselike@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + dependencies: + lowercase-keys "^1.0.0" + +rimraf@^2.2.8, rimraf@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + +"semver@2 || 3 || 4 || 5", semver@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + +shellsubstitute@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shellsubstitute/-/shellsubstitute-1.2.0.tgz#e4f702a50c518b0f6fe98451890d705af29b6b70" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + +sliced@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" + +sort-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" + dependencies: + is-plain-obj "^1.0.0" + +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.14.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + safer-buffer "^2.0.2" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +state-toggle@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.1.tgz#c3cb0974f40a6a0f8e905b96789eb41afa1cde3a" + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + +string-width@^1.0.0, string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string.prototype.padstart@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.padstart/-/string.prototype.padstart-3.0.0.tgz#5bcfad39f4649bb2d031292e19bcf0b510d4b242" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.4.3" + function-bind "^1.0.2" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +stringify-entities@^1.0.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-1.3.2.tgz#a98417e5471fd227b3e45d3db1861c11caf668f7" + dependencies: + character-entities-html4 "^1.0.0" + character-entities-legacy "^1.0.0" + is-alphanumerical "^1.0.0" + is-hexadecimal "^1.0.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +structured-source@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/structured-source/-/structured-source-3.0.2.tgz#dd802425e0f53dc4a6e7aca3752901a1ccda7af5" + dependencies: + boundary "^1.0.1" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^4.1.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + +supports-color@^5.3.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + +tar@^4: + version "4.4.4" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.3.3" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +textlint@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/textlint/-/textlint-10.2.1.tgz#ee22b7967d59cef7c74a04a5f4e8883134e5c79d" + dependencies: + "@textlint/ast-node-types" "^4.0.2" + "@textlint/ast-traverse" "^2.0.8" + "@textlint/feature-flag" "^3.0.4" + "@textlint/fixer-formatter" "^3.0.7" + "@textlint/kernel" "^2.0.9" + "@textlint/linter-formatter" "^3.0.7" + "@textlint/textlint-plugin-markdown" "^4.0.10" + "@textlint/textlint-plugin-text" "^3.0.10" + "@types/bluebird" "^3.5.18" + bluebird "^3.0.5" + debug "^2.1.0" + deep-equal "^1.0.1" + file-entry-cache "^2.0.0" + get-stdin "^5.0.1" + glob "^7.1.1" + interop-require "^1.0.0" + is-file "^1.0.0" + log-symbols "^1.0.2" + map-like "^2.0.0" + md5 "^2.2.1" + mkdirp "^0.5.0" + object-assign "^4.0.1" + optionator "^0.8.0" + path-to-glob-pattern "^1.0.2" + rc-config-loader "^2.0.1" + read-pkg "^1.1.0" + read-pkg-up "^3.0.0" + structured-source "^3.0.2" + try-resolve "^1.0.1" + unique-concat "^0.2.2" + +timed-out@^4.0.0, timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + +to-vfile@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/to-vfile/-/to-vfile-2.2.0.tgz#342d1705e6df526d569b1fc8bfa29f1f36d6c416" + dependencies: + is-buffer "^1.1.4" + vfile "^2.0.0" + x-is-function "^1.0.4" + +tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + +traverse@^0.6.6: + version "0.6.6" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" + +trim-trailing-lines@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz#e0ec0810fd3c3f1730516b45f49083caaf2774d9" + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + +trough@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.2.tgz#7f1663ec55c480139e2de5e486c6aef6cc24a535" + +try-resolve@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/try-resolve/-/try-resolve-1.0.1.tgz#cfde6fabd72d63e5797cfaab873abbe8e700e912" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +unherit@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c" + dependencies: + inherits "^2.0.1" + xtend "^4.0.1" + +unified-args@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/unified-args/-/unified-args-5.1.0.tgz#1889200e072998a662e6e84d817d6f4b5f448dd1" + dependencies: + camelcase "^4.0.0" + chalk "^2.0.0" + chokidar "^1.5.1" + json5 "^0.5.1" + minimist "^1.2.0" + text-table "^0.2.0" + unified-engine "^5.1.0" + +unified-engine@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/unified-engine/-/unified-engine-5.1.0.tgz#30db83bcc76c821f773bb5a8a491aa0e2471e3d1" + dependencies: + concat-stream "^1.5.1" + debug "^3.1.0" + fault "^1.0.0" + fn-name "^2.0.1" + glob "^7.0.3" + ignore "^3.2.0" + is-empty "^1.0.0" + is-hidden "^1.0.1" + is-object "^1.0.1" + js-yaml "^3.6.1" + load-plugin "^2.0.0" + parse-json "^4.0.0" + to-vfile "^2.0.0" + trough "^1.0.0" + unist-util-inspect "^4.1.2" + vfile-reporter "^4.0.0" + vfile-statistics "^1.1.0" + x-is-function "^1.0.4" + x-is-string "^0.1.0" + xtend "^4.0.1" + +unified-lint-rule@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/unified-lint-rule/-/unified-lint-rule-1.0.3.tgz#e302b0c4a7ac428c0980e049a500e59528001299" + dependencies: + wrapped "^1.0.1" + +unified@^6.0.0, unified@^6.1.6: + version "6.2.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-6.2.0.tgz#7fbd630f719126d67d40c644b7e3f617035f6dba" + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-plain-obj "^1.1.0" + trough "^1.0.0" + vfile "^2.0.0" + x-is-string "^0.1.0" + +unique-concat@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/unique-concat/-/unique-concat-0.2.2.tgz#9210f9bdcaacc5e1e3929490d7c019df96f18712" + +unist-util-inspect@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/unist-util-inspect/-/unist-util-inspect-4.1.3.tgz#39470e6d77485db285966df78431219aa1287822" + dependencies: + is-empty "^1.0.0" + +unist-util-is@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.1.2.tgz#1193fa8f2bfbbb82150633f3a8d2eb9a1c1d55db" + +unist-util-modify-children@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-modify-children/-/unist-util-modify-children-1.1.2.tgz#c7f1b91712554ee59c47a05b551ed3e052a4e2d1" + dependencies: + array-iterate "^1.0.0" + +unist-util-remove-position@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.2.tgz#86b5dad104d0bbfbeb1db5f5c92f3570575c12cb" + dependencies: + unist-util-visit "^1.1.0" + +unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" + +unist-util-visit@^1.1.0, unist-util-visit@^1.1.3: + version "1.3.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.3.1.tgz#c019ac9337a62486be58531bc27e7499ae7d55c7" + dependencies: + unist-util-is "^2.1.1" + +untildify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-2.1.0.tgz#17eb2807987f76952e9c0485fc311d06a826a2e0" + dependencies: + os-homedir "^1.0.0" + +unzip-response@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + dependencies: + prepend-http "^1.0.1" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + dependencies: + prepend-http "^2.0.0" + +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +uuid@^3.1.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + +validate-npm-package-license@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vfile-location@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.3.tgz#083ba80e50968e8d420be49dd1ea9a992131df77" + +vfile-message@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.0.1.tgz#51a2ccd8a6b97a7980bb34efb9ebde9632e93677" + dependencies: + unist-util-stringify-position "^1.1.1" + +vfile-reporter@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/vfile-reporter/-/vfile-reporter-4.0.0.tgz#ea6f0ae1342f4841573985e05f941736f27de9da" + dependencies: + repeat-string "^1.5.0" + string-width "^1.0.0" + supports-color "^4.1.0" + unist-util-stringify-position "^1.0.0" + vfile-statistics "^1.1.0" + +vfile-statistics@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/vfile-statistics/-/vfile-statistics-1.1.1.tgz#a22fd4eb844c9eaddd781ad3b3246db88375e2e3" + +vfile@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" + dependencies: + is-buffer "^1.1.4" + replace-ext "1.0.0" + unist-util-stringify-position "^1.0.0" + vfile-message "^1.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + dependencies: + string-width "^1.0.2 || 2" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wrapped@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wrapped/-/wrapped-1.0.1.tgz#c783d9d807b273e9b01e851680a938c87c907242" + dependencies: + co "3.1.0" + sliced "^1.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +x-is-function@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/x-is-function/-/x-is-function-1.0.4.tgz#5d294dc3d268cbdd062580e0c5df77a391d1fa1e" + +x-is-string@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" + +xml-escape@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xml-escape/-/xml-escape-1.1.0.tgz#3904c143fa8eb3a0030ec646d2902a2f1b706c44" + +xtend@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" diff --git a/evidence/reactor.go b/evidence/reactor.go index 7b22b8dba..bf11ac105 100644 --- a/evidence/reactor.go +++ b/evidence/reactor.go @@ -5,10 +5,10 @@ import ( "reflect" "time" - "github.com/tendermint/go-amino" + amino "github.com/tendermint/go-amino" + clist "github.com/tendermint/tendermint/libs/clist" "github.com/tendermint/tendermint/libs/log" - "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/types" ) @@ -73,7 +73,7 @@ func (evR *EvidenceReactor) RemovePeer(peer p2p.Peer, reason interface{}) { // Receive implements Reactor. // It adds any received evidence to the evpool. func (evR *EvidenceReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) { - msg, err := DecodeMessage(msgBytes) + msg, err := decodeMsg(msgBytes) if err != nil { evR.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes) evR.Switch.StopPeerForError(src, err) @@ -204,11 +204,9 @@ func RegisterEvidenceMessages(cdc *amino.Codec) { "tendermint/evidence/EvidenceListMessage", nil) } -// DecodeMessage decodes a byte-array into a EvidenceMessage. -func DecodeMessage(bz []byte) (msg EvidenceMessage, err error) { +func decodeMsg(bz []byte) (msg EvidenceMessage, err error) { if len(bz) > maxMsgSize { - return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", - len(bz), maxMsgSize) + return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", len(bz), maxMsgSize) } err = cdc.UnmarshalBinaryBare(bz, &msg) return diff --git a/evidence/wire.go b/evidence/wire.go index fb3a177cc..c61b86184 100644 --- a/evidence/wire.go +++ b/evidence/wire.go @@ -2,7 +2,7 @@ package evidence import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/tendermint/tendermint/types" ) @@ -10,7 +10,7 @@ var cdc = amino.NewCodec() func init() { RegisterEvidenceMessages(cdc) - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) types.RegisterEvidences(cdc) RegisterMockEvidences(cdc) // For testing } diff --git a/libs/CODEOWNERS b/libs/CODEOWNERS deleted file mode 100644 index d2dddf85a..000000000 --- a/libs/CODEOWNERS +++ /dev/null @@ -1,3 +0,0 @@ -* @melekes @ebuchman -*.md @zramsay -*.rst @zramsay diff --git a/libs/Gopkg.lock b/libs/Gopkg.lock deleted file mode 100644 index f0eaee18d..000000000 --- a/libs/Gopkg.lock +++ /dev/null @@ -1,281 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - name = "github.com/btcsuite/btcutil" - packages = ["bech32"] - revision = "d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4" - -[[projects]] - name = "github.com/davecgh/go-spew" - packages = ["spew"] - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" - -[[projects]] - branch = "master" - name = "github.com/fortytw2/leaktest" - packages = ["."] - revision = "3b724c3d7b8729a35bf4e577f71653aec6e53513" - -[[projects]] - name = "github.com/fsnotify/fsnotify" - packages = ["."] - revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" - version = "v1.4.7" - -[[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 = "817915b46b97fd7bb80e8ab6b69f01a53ac3eebf" - version = "v1.6.0" - -[[projects]] - name = "github.com/golang/protobuf" - packages = [ - "proto", - "ptypes", - "ptypes/any", - "ptypes/duration", - "ptypes/timestamp" - ] - revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" - version = "v1.1.0" - -[[projects]] - branch = "master" - name = "github.com/golang/snappy" - packages = ["."] - revision = "553a641470496b2327abcac10b36396bd98e45c9" - -[[projects]] - branch = "master" - name = "github.com/hashicorp/hcl" - packages = [ - ".", - "hcl/ast", - "hcl/parser", - "hcl/scanner", - "hcl/strconv", - "hcl/token", - "json/parser", - "json/scanner", - "json/token" - ] - revision = "23c074d0eceb2b8a5bfdbb271ab780cde70f05a8" - -[[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/magiconair/properties" - packages = ["."] - revision = "49d762b9817ba1c2e9d0c69183c2b4a8b8f1d934" - -[[projects]] - name = "github.com/mitchellh/mapstructure" - packages = ["."] - revision = "b4575eea38cca1123ec2dc90c26529b5c5acfcff" - -[[projects]] - name = "github.com/pelletier/go-toml" - packages = ["."] - revision = "acdc4509485b587f5e675510c4f2c63e90ff68a8" - version = "v1.1.0" - -[[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/afero" - packages = [ - ".", - "mem" - ] - revision = "bb8f1927f2a9d3ab41c9340aa034f6b803f4359c" - version = "v1.0.2" - -[[projects]] - name = "github.com/spf13/cast" - packages = ["."] - revision = "acbeb36b902d72a7a4c18e8f3241075e7ab763e4" - version = "v1.1.0" - -[[projects]] - name = "github.com/spf13/cobra" - packages = ["."] - revision = "7b2c5ac9fc04fc5efafb60700713d4fa609b777b" - version = "v0.0.1" - -[[projects]] - branch = "master" - name = "github.com/spf13/jwalterweatherman" - packages = ["."] - revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394" - -[[projects]] - name = "github.com/spf13/pflag" - packages = ["."] - revision = "97afa5e7ca8a08a383cb259e06636b5e2cc7897f" - -[[projects]] - name = "github.com/spf13/viper" - packages = ["."] - revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7" - version = "v1.0.0" - -[[projects]] - name = "github.com/stretchr/testify" - packages = [ - "assert", - "require" - ] - revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" - version = "v1.2.1" - -[[projects]] - 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 = "b89cc31ef7977104127d34c1bd31ebd1a9db2199" - -[[projects]] - branch = "master" - name = "golang.org/x/net" - packages = [ - "context", - "http/httpguts", - "http2", - "http2/hpack", - "idna", - "internal/timeseries", - "trace" - ] - revision = "d11bb6cd8e3c4e60239c9cb20ef68586d74500d0" - -[[projects]] - name = "golang.org/x/sys" - packages = ["unix"] - revision = "37707fdb30a5b38865cfb95e5aab41707daec7fd" - -[[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 = "c01e4764d870b77f8abe5096ee19ad20d80e8075" - -[[projects]] - branch = "master" - name = "google.golang.org/genproto" - packages = ["googleapis/rpc/status"] - revision = "86e600f69ee4704c6efbf6a2a40a5c10700e76c2" - -[[projects]] - name = "google.golang.org/grpc" - packages = [ - ".", - "balancer", - "balancer/base", - "balancer/roundrobin", - "codes", - "connectivity", - "credentials", - "encoding", - "encoding/proto", - "grpclb/grpc_lb_v1/messages", - "grpclog", - "internal", - "keepalive", - "metadata", - "naming", - "peer", - "resolver", - "resolver/dns", - "resolver/passthrough", - "stats", - "status", - "tap", - "transport" - ] - revision = "d11072e7ca9811b1100b80ca0269ac831f06d024" - version = "v1.11.3" - -[[projects]] - name = "gopkg.in/yaml.v2" - packages = ["."] - revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4" - version = "v2.0.0" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "e0c0af880b57928787ea78a820abefd2759e6aee4cba18e67ab36b80e62ad581" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/libs/Gopkg.toml b/libs/Gopkg.toml deleted file mode 100644 index ff42087f8..000000000 --- a/libs/Gopkg.toml +++ /dev/null @@ -1,69 +0,0 @@ -# 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 - - -[[constraint]] - branch = "master" - name = "github.com/fortytw2/leaktest" - -[[constraint]] - name = "github.com/go-kit/kit" - version = "0.6.0" - -[[constraint]] - name = "github.com/go-logfmt/logfmt" - version = "0.3.0" - -[[constraint]] - name = "github.com/gogo/protobuf" - version = "1.0.0" - -[[constraint]] - branch = "master" - name = "github.com/jmhodges/levigo" - -[[constraint]] - name = "github.com/pkg/errors" - version = "0.8.0" - -[[constraint]] - name = "github.com/spf13/cobra" - version = "0.0.1" - -[[constraint]] - name = "github.com/spf13/viper" - version = "1.0.0" - -[[constraint]] - name = "github.com/stretchr/testify" - version = "1.2.1" - -[[constraint]] - name = "github.com/btcsuite/btcutil" - branch ="master" -[prune] - go-tests = true - unused-packages = true diff --git a/libs/Makefile b/libs/Makefile deleted file mode 100644 index a55bc139c..000000000 --- a/libs/Makefile +++ /dev/null @@ -1,137 +0,0 @@ -GOTOOLS = \ - github.com/golang/dep/cmd/dep \ - github.com/golang/protobuf/protoc-gen-go \ - github.com/square/certstrap - # github.com/alecthomas/gometalinter.v2 \ - -GOTOOLS_CHECK = dep gometalinter.v2 protoc protoc-gen-go -INCLUDE = -I=. -I=${GOPATH}/src - -all: check get_vendor_deps protoc grpc_dbserver build test install metalinter - -check: check_tools - -######################################## -### Build - -protoc: - ## If you get the following error, - ## "error while loading shared libraries: libprotobuf.so.14: cannot open shared object file: No such file or directory" - ## See https://stackoverflow.com/a/25518702 - protoc $(INCLUDE) --go_out=plugins=grpc:. common/*.proto - @echo "--> adding nolint declarations to protobuf generated files" - @awk '/package common/ { print "//nolint: gas"; print; next }1' common/types.pb.go > common/types.pb.go.new - @mv common/types.pb.go.new common/types.pb.go - -build: - # Nothing to build! - -install: - # Nothing to install! - - -######################################## -### Tools & dependencies - -check_tools: - @# https://stackoverflow.com/a/25668869 - @echo "Found tools: $(foreach tool,$(GOTOOLS_CHECK),\ - $(if $(shell which $(tool)),$(tool),$(error "No $(tool) in PATH")))" - -get_tools: - @echo "--> Installing tools" - go get -u -v $(GOTOOLS) - # @gometalinter.v2 --install - -get_protoc: - @# https://github.com/google/protobuf/releases - curl -L https://github.com/google/protobuf/releases/download/v3.4.1/protobuf-cpp-3.4.1.tar.gz | tar xvz && \ - cd protobuf-3.4.1 && \ - DIST_LANG=cpp ./configure && \ - make && \ - make install && \ - cd .. && \ - rm -rf protobuf-3.4.1 - -update_tools: - @echo "--> Updating tools" - @go get -u $(GOTOOLS) - -get_vendor_deps: - @rm -rf vendor/ - @echo "--> Running dep ensure" - @dep ensure - - -######################################## -### Testing - -gen_certs: clean_certs - ## Generating certificates for TLS testing... - certstrap init --common-name "tendermint.com" --passphrase "" - certstrap request-cert -ip "::" --passphrase "" - certstrap sign "::" --CA "tendermint.com" --passphrase "" - mv out/::.crt out/::.key db/remotedb - -clean_certs: - ## Cleaning TLS testing certificates... - rm -rf out - rm -f db/remotedb/::.crt db/remotedb/::.key - -test: gen_certs - GOCACHE=off go test -tags gcc $(shell go list ./... | grep -v vendor) - make clean_certs - -test100: - @for i in {1..100}; do make test; done - - -######################################## -### Formatting, linting, and vetting - -fmt: - @go fmt ./... - -metalinter: - @echo "==> Running linter" - gometalinter.v2 --vendor --deadline=600s --disable-all \ - --enable=deadcode \ - --enable=goconst \ - --enable=goimports \ - --enable=gosimple \ - --enable=ineffassign \ - --enable=megacheck \ - --enable=misspell \ - --enable=staticcheck \ - --enable=safesql \ - --enable=structcheck \ - --enable=unconvert \ - --enable=unused \ - --enable=varcheck \ - --enable=vetshadow \ - ./... - - #--enable=maligned \ - #--enable=gas \ - #--enable=aligncheck \ - #--enable=dupl \ - #--enable=errcheck \ - #--enable=gocyclo \ - #--enable=golint \ <== comments on anything exported - #--enable=gotype \ - #--enable=interfacer \ - #--enable=unparam \ - #--enable=vet \ - -metalinter_all: - protoc $(INCLUDE) --lint_out=. types/*.proto - gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./... - - -# To avoid unintended conflicts with file names, always add to .PHONY -# unless there is a reason not to. -# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONY: check protoc build check_tools get_tools get_protoc update_tools get_vendor_deps test fmt metalinter metalinter_all gen_certs clean_certs - -grpc_dbserver: - protoc -I db/remotedb/proto/ db/remotedb/proto/defs.proto --go_out=plugins=grpc:db/remotedb/proto diff --git a/libs/clist/clist_test.go b/libs/clist/clist_test.go index 6171f1a39..dbdf2f028 100644 --- a/libs/clist/clist_test.go +++ b/libs/clist/clist_test.go @@ -2,11 +2,12 @@ package clist import ( "fmt" - "math/rand" "runtime" "sync/atomic" "testing" "time" + + cmn "github.com/tendermint/tendermint/libs/common" ) func TestSmall(t *testing.T) { @@ -131,7 +132,7 @@ func _TestGCRandom(t *testing.T) { els = append(els, el) } - for _, i := range rand.Perm(numElements) { + for _, i := range cmn.RandPerm(numElements) { el := els[i] l.Remove(el) _ = el.Next() @@ -189,7 +190,7 @@ func TestScanRightDeleteRandom(t *testing.T) { // Remove an element, push back an element. for i := 0; i < numTimes; i++ { // Pick an element to remove - rmElIdx := rand.Intn(len(els)) + rmElIdx := cmn.RandIntn(len(els)) rmEl := els[rmElIdx] // Remove it @@ -243,7 +244,7 @@ func TestWaitChan(t *testing.T) { for i := 1; i < 100; i++ { l.PushBack(i) pushed++ - time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) + time.Sleep(time.Duration(cmn.RandIntn(100)) * time.Millisecond) } close(done) }() diff --git a/libs/common/array.go b/libs/common/array.go deleted file mode 100644 index adedc42be..000000000 --- a/libs/common/array.go +++ /dev/null @@ -1,5 +0,0 @@ -package common - -func Arr(items ...interface{}) []interface{} { - return items -} diff --git a/libs/common/os_test.go b/libs/common/os_test.go index 973d68901..3edd6496e 100644 --- a/libs/common/os_test.go +++ b/libs/common/os_test.go @@ -3,17 +3,14 @@ package common import ( "bytes" "io/ioutil" - "math/rand" "os" "testing" - "time" ) func TestWriteFileAtomic(t *testing.T) { var ( - seed = rand.New(rand.NewSource(time.Now().UnixNano())) - data = []byte(RandStr(seed.Intn(2048))) - old = RandBytes(seed.Intn(2048)) + data = []byte(RandStr(RandIntn(2048))) + old = RandBytes(RandIntn(2048)) perm os.FileMode = 0600 ) diff --git a/libs/common/random.go b/libs/common/random.go index 389a32fc2..51bfd15c4 100644 --- a/libs/common/random.go +++ b/libs/common/random.go @@ -11,9 +11,13 @@ const ( strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters ) -// pseudo random number generator. -// seeded with OS randomness (crand) - +// Rand is a prng, that is seeded with OS randomness. +// The OS randomness is obtained from crypto/rand, however none of the provided +// methods are suitable for cryptographic usage. +// They all utilize math/rand's prng internally. +// +// All of the methods here are suitable for concurrent use. +// This is achieved by using a mutex lock on all of the provided methods. type Rand struct { sync.Mutex rand *mrand.Rand @@ -105,18 +109,6 @@ func RandInt63n(n int64) int64 { return grand.Int63n(n) } -func RandUint16Exp() uint16 { - return grand.Uint16Exp() -} - -func RandUint32Exp() uint32 { - return grand.Uint32Exp() -} - -func RandUint64Exp() uint64 { - return grand.Uint64Exp() -} - func RandFloat32() float32 { return grand.Float32() } @@ -150,8 +142,7 @@ func (r *Rand) Seed(seed int64) { r.Unlock() } -// Constructs an alphanumeric string of given length. -// It is not safe for cryptographic usage. +// Str constructs a random alphanumeric string of given length. func (r *Rand) Str(length int) string { chars := []byte{} MAIN_LOOP: @@ -175,12 +166,10 @@ MAIN_LOOP: return string(chars) } -// It is not safe for cryptographic usage. func (r *Rand) Uint16() uint16 { return uint16(r.Uint32() & (1<<16 - 1)) } -// It is not safe for cryptographic usage. func (r *Rand) Uint32() uint32 { r.Lock() u32 := r.rand.Uint32() @@ -188,12 +177,10 @@ func (r *Rand) Uint32() uint32 { return u32 } -// It is not safe for cryptographic usage. func (r *Rand) Uint64() uint64 { return uint64(r.Uint32())<<32 + uint64(r.Uint32()) } -// It is not safe for cryptographic usage. func (r *Rand) Uint() uint { r.Lock() i := r.rand.Int() @@ -201,22 +188,18 @@ func (r *Rand) Uint() uint { return uint(i) } -// It is not safe for cryptographic usage. func (r *Rand) Int16() int16 { return int16(r.Uint32() & (1<<16 - 1)) } -// It is not safe for cryptographic usage. func (r *Rand) Int32() int32 { return int32(r.Uint32()) } -// It is not safe for cryptographic usage. func (r *Rand) Int64() int64 { return int64(r.Uint64()) } -// It is not safe for cryptographic usage. func (r *Rand) Int() int { r.Lock() i := r.rand.Int() @@ -224,7 +207,6 @@ func (r *Rand) Int() int { return i } -// It is not safe for cryptographic usage. func (r *Rand) Int31() int32 { r.Lock() i31 := r.rand.Int31() @@ -232,7 +214,6 @@ func (r *Rand) Int31() int32 { return i31 } -// It is not safe for cryptographic usage. func (r *Rand) Int31n(n int32) int32 { r.Lock() i31n := r.rand.Int31n(n) @@ -240,7 +221,6 @@ func (r *Rand) Int31n(n int32) int32 { return i31n } -// It is not safe for cryptographic usage. func (r *Rand) Int63() int64 { r.Lock() i63 := r.rand.Int63() @@ -248,7 +228,6 @@ func (r *Rand) Int63() int64 { return i63 } -// It is not safe for cryptographic usage. func (r *Rand) Int63n(n int64) int64 { r.Lock() i63n := r.rand.Int63n(n) @@ -256,43 +235,6 @@ func (r *Rand) Int63n(n int64) int64 { return i63n } -// Distributed pseudo-exponentially to test for various cases -// It is not safe for cryptographic usage. -func (r *Rand) Uint16Exp() uint16 { - bits := r.Uint32() % 16 - if bits == 0 { - return 0 - } - n := uint16(1 << (bits - 1)) - n += uint16(r.Int31()) & ((1 << (bits - 1)) - 1) - return n -} - -// Distributed pseudo-exponentially to test for various cases -// It is not safe for cryptographic usage. -func (r *Rand) Uint32Exp() uint32 { - bits := r.Uint32() % 32 - if bits == 0 { - return 0 - } - n := uint32(1 << (bits - 1)) - n += uint32(r.Int31()) & ((1 << (bits - 1)) - 1) - return n -} - -// Distributed pseudo-exponentially to test for various cases -// It is not safe for cryptographic usage. -func (r *Rand) Uint64Exp() uint64 { - bits := r.Uint32() % 64 - if bits == 0 { - return 0 - } - n := uint64(1 << (bits - 1)) - n += uint64(r.Int63()) & ((1 << (bits - 1)) - 1) - return n -} - -// It is not safe for cryptographic usage. func (r *Rand) Float32() float32 { r.Lock() f32 := r.rand.Float32() @@ -300,7 +242,6 @@ func (r *Rand) Float32() float32 { return f32 } -// It is not safe for cryptographic usage. func (r *Rand) Float64() float64 { r.Lock() f64 := r.rand.Float64() @@ -308,13 +249,12 @@ func (r *Rand) Float64() float64 { return f64 } -// It is not safe for cryptographic usage. func (r *Rand) Time() time.Time { - return time.Unix(int64(r.Uint64Exp()), 0) + return time.Unix(int64(r.Uint64()), 0) } -// RandBytes returns n random bytes from the OS's source of entropy ie. via crypto/rand. -// It is not safe for cryptographic usage. +// Bytes returns n random bytes generated from the internal +// prng. func (r *Rand) Bytes(n int) []byte { // cRandBytes isn't guaranteed to be fast so instead // use random bytes generated from the internal PRNG @@ -325,9 +265,8 @@ func (r *Rand) Bytes(n int) []byte { return bs } -// RandIntn returns, as an int, a non-negative pseudo-random number in [0, n). +// Intn returns, as an int, a uniform pseudo-random number in the range [0, n). // It panics if n <= 0. -// It is not safe for cryptographic usage. func (r *Rand) Intn(n int) int { r.Lock() i := r.rand.Intn(n) @@ -335,8 +274,7 @@ func (r *Rand) Intn(n int) int { return i } -// RandPerm returns a pseudo-random permutation of n integers in [0, n). -// It is not safe for cryptographic usage. +// Perm returns a pseudo-random permutation of n integers in [0, n). func (r *Rand) Perm(n int) []int { r.Lock() perm := r.rand.Perm(n) diff --git a/libs/common/random_test.go b/libs/common/random_test.go index b58b4a13a..c59a577b8 100644 --- a/libs/common/random_test.go +++ b/libs/common/random_test.go @@ -73,9 +73,6 @@ func testThemAll() string { fmt.Fprintf(out, "randInt64: %d\n", RandInt64()) fmt.Fprintf(out, "randUint32: %d\n", RandUint32()) fmt.Fprintf(out, "randUint64: %d\n", RandUint64()) - fmt.Fprintf(out, "randUint16Exp: %d\n", RandUint16Exp()) - fmt.Fprintf(out, "randUint32Exp: %d\n", RandUint32Exp()) - fmt.Fprintf(out, "randUint64Exp: %d\n", RandUint64Exp()) return out.String() } diff --git a/libs/common/repeat_timer_test.go b/libs/common/repeat_timer_test.go index b81720c85..f2a7b16c3 100644 --- a/libs/common/repeat_timer_test.go +++ b/libs/common/repeat_timer_test.go @@ -1,7 +1,6 @@ package common import ( - "math/rand" "sync" "testing" "time" @@ -131,7 +130,7 @@ func TestRepeatTimerReset(t *testing.T) { // just random calls for i := 0; i < 100; i++ { - time.Sleep(time.Duration(rand.Intn(40)) * time.Millisecond) + time.Sleep(time.Duration(RandIntn(40)) * time.Millisecond) timer.Reset() } } diff --git a/libs/common/types.pb.go b/libs/common/types.pb.go index f6645602a..6442daeb4 100644 --- a/libs/common/types.pb.go +++ b/libs/common/types.pb.go @@ -1,25 +1,32 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: common/types.proto +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: libs/common/types.proto /* -Package common is a generated protocol buffer package. + Package common is a generated protocol buffer package. -It is generated from these files: - common/types.proto + It is generated from these files: + libs/common/types.proto -It has these top-level messages: - KVPair - KI64Pair + It has these top-level messages: + KVPair + KI64Pair */ -//nolint: gas +//nolint package common -import proto "github.com/golang/protobuf/proto" +import proto "github.com/gogo/protobuf/proto" +import golang_proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +import bytes "bytes" + +import io "io" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal +var _ = golang_proto.Marshal var _ = fmt.Errorf var _ = math.Inf @@ -27,7 +34,7 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package // Define these here for compatibility but use tmlibs/common.KVPair. type KVPair struct { @@ -38,7 +45,7 @@ type KVPair struct { func (m *KVPair) Reset() { *m = KVPair{} } func (m *KVPair) String() string { return proto.CompactTextString(m) } func (*KVPair) ProtoMessage() {} -func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*KVPair) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{0} } func (m *KVPair) GetKey() []byte { if m != nil { @@ -57,13 +64,13 @@ func (m *KVPair) GetValue() []byte { // Define these here for compatibility but use tmlibs/common.KI64Pair. type KI64Pair struct { Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Value int64 `protobuf:"varint,2,opt,name=value" json:"value,omitempty"` + Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` } func (m *KI64Pair) Reset() { *m = KI64Pair{} } func (m *KI64Pair) String() string { return proto.CompactTextString(m) } func (*KI64Pair) ProtoMessage() {} -func (*KI64Pair) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*KI64Pair) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{1} } func (m *KI64Pair) GetKey() []byte { if m != nil { @@ -81,18 +88,608 @@ func (m *KI64Pair) GetValue() int64 { func init() { proto.RegisterType((*KVPair)(nil), "common.KVPair") + golang_proto.RegisterType((*KVPair)(nil), "common.KVPair") proto.RegisterType((*KI64Pair)(nil), "common.KI64Pair") + golang_proto.RegisterType((*KI64Pair)(nil), "common.KI64Pair") +} +func (this *KVPair) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*KVPair) + if !ok { + that2, ok := that.(KVPair) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Key, that1.Key) { + return false + } + if !bytes.Equal(this.Value, that1.Value) { + return false + } + return true +} +func (this *KI64Pair) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*KI64Pair) + if !ok { + that2, ok := that.(KI64Pair) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Key, that1.Key) { + return false + } + if this.Value != that1.Value { + return false + } + return true +} +func (m *KVPair) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *KVPair) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Key) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Key))) + i += copy(dAtA[i:], m.Key) + } + if len(m.Value) > 0 { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Value))) + i += copy(dAtA[i:], m.Value) + } + return i, nil +} + +func (m *KI64Pair) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *KI64Pair) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Key) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Key))) + i += copy(dAtA[i:], m.Key) + } + if m.Value != 0 { + dAtA[i] = 0x10 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Value)) + } + return i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func NewPopulatedKVPair(r randyTypes, easy bool) *KVPair { + this := &KVPair{} + v1 := r.Intn(100) + this.Key = make([]byte, v1) + for i := 0; i < v1; i++ { + this.Key[i] = byte(r.Intn(256)) + } + v2 := r.Intn(100) + this.Value = make([]byte, v2) + for i := 0; i < v2; i++ { + this.Value[i] = byte(r.Intn(256)) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedKI64Pair(r randyTypes, easy bool) *KI64Pair { + this := &KI64Pair{} + v3 := r.Intn(100) + this.Key = make([]byte, v3) + for i := 0; i < v3; i++ { + this.Key[i] = byte(r.Intn(256)) + } + this.Value = int64(r.Int63()) + if r.Intn(2) == 0 { + this.Value *= -1 + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +type randyTypes interface { + Float32() float32 + Float64() float64 + Int63() int64 + Int31() int32 + Uint32() uint32 + Intn(n int) int +} + +func randUTF8RuneTypes(r randyTypes) rune { + ru := r.Intn(62) + if ru < 10 { + return rune(ru + 48) + } else if ru < 36 { + return rune(ru + 55) + } + return rune(ru + 61) +} +func randStringTypes(r randyTypes) string { + v4 := r.Intn(100) + tmps := make([]rune, v4) + for i := 0; i < v4; i++ { + tmps[i] = randUTF8RuneTypes(r) + } + return string(tmps) +} +func randUnrecognizedTypes(r randyTypes, maxFieldNumber int) (dAtA []byte) { + l := r.Intn(5) + for i := 0; i < l; i++ { + wire := r.Intn(4) + if wire == 3 { + wire = 5 + } + fieldNumber := maxFieldNumber + r.Intn(100) + dAtA = randFieldTypes(dAtA, r, fieldNumber, wire) + } + return dAtA +} +func randFieldTypes(dAtA []byte, r randyTypes, fieldNumber int, wire int) []byte { + key := uint32(fieldNumber)<<3 | uint32(wire) + switch wire { + case 0: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + v5 := r.Int63() + if r.Intn(2) == 0 { + v5 *= -1 + } + dAtA = encodeVarintPopulateTypes(dAtA, uint64(v5)) + case 1: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) + case 2: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + ll := r.Intn(100) + dAtA = encodeVarintPopulateTypes(dAtA, uint64(ll)) + for j := 0; j < ll; j++ { + dAtA = append(dAtA, byte(r.Intn(256))) + } + default: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) + } + return dAtA +} +func encodeVarintPopulateTypes(dAtA []byte, v uint64) []byte { + for v >= 1<<7 { + dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80)) + v >>= 7 + } + dAtA = append(dAtA, uint8(v)) + return dAtA } +func (m *KVPair) Size() (n int) { + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Value) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *KI64Pair) Size() (n int) { + var l int + _ = l + l = len(m.Key) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Value != 0 { + n += 1 + sovTypes(uint64(m.Value)) + } + return n +} + +func sovTypes(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *KVPair) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: KVPair: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: KVPair: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) + if m.Key == nil { + m.Key = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...) + if m.Value == nil { + m.Value = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *KI64Pair) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: KI64Pair: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: KI64Pair: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) + if m.Key == nil { + m.Key = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) + } + m.Value = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Value |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthTypes + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipTypes(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") +) -func init() { proto.RegisterFile("common/types.proto", fileDescriptor0) } +func init() { proto.RegisterFile("libs/common/types.proto", fileDescriptorTypes) } +func init() { golang_proto.RegisterFile("libs/common/types.proto", fileDescriptorTypes) } -var fileDescriptor0 = []byte{ - // 107 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4a, 0xce, 0xcf, 0xcd, - 0xcd, 0xcf, 0xd3, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, - 0x83, 0x88, 0x29, 0x19, 0x70, 0xb1, 0x79, 0x87, 0x05, 0x24, 0x66, 0x16, 0x09, 0x09, 0x70, 0x31, - 0x67, 0xa7, 0x56, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x81, 0x98, 0x42, 0x22, 0x5c, 0xac, - 0x65, 0x89, 0x39, 0xa5, 0xa9, 0x12, 0x4c, 0x60, 0x31, 0x08, 0x47, 0xc9, 0x88, 0x8b, 0xc3, 0xdb, - 0xd3, 0xcc, 0x84, 0x18, 0x3d, 0xcc, 0x50, 0x3d, 0x49, 0x6c, 0x60, 0x4b, 0x8d, 0x01, 0x01, 0x00, - 0x00, 0xff, 0xff, 0xd8, 0xf1, 0xc3, 0x8c, 0x8a, 0x00, 0x00, 0x00, +var fileDescriptorTypes = []byte{ + // 174 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcf, 0xc9, 0x4c, 0x2a, + 0xd6, 0x4f, 0xce, 0xcf, 0xcd, 0xcd, 0xcf, 0xd3, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, + 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x83, 0x88, 0x49, 0xe9, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, + 0x25, 0xe7, 0xe7, 0xea, 0xa7, 0xe7, 0xa7, 0xe7, 0xeb, 0x83, 0xa5, 0x93, 0x4a, 0xd3, 0xc0, 0x3c, + 0x30, 0x07, 0xcc, 0x82, 0x68, 0x53, 0x32, 0xe0, 0x62, 0xf3, 0x0e, 0x0b, 0x48, 0xcc, 0x2c, 0x12, + 0x12, 0xe0, 0x62, 0xce, 0x4e, 0xad, 0x94, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x09, 0x02, 0x31, 0x85, + 0x44, 0xb8, 0x58, 0xcb, 0x12, 0x73, 0x4a, 0x53, 0x25, 0x98, 0xc0, 0x62, 0x10, 0x8e, 0x92, 0x11, + 0x17, 0x87, 0xb7, 0xa7, 0x99, 0x09, 0x31, 0x7a, 0x98, 0xa1, 0x7a, 0x9c, 0x64, 0x7e, 0x3c, 0x94, + 0x63, 0x5c, 0xf1, 0x48, 0x8e, 0x71, 0xc7, 0x23, 0x39, 0xc6, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, + 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0xf1, 0xc0, 0x63, 0x39, 0xc6, 0x24, 0x36, 0xb0, 0x53, 0x8c, + 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb1, 0x39, 0xe1, 0xef, 0xdc, 0x00, 0x00, 0x00, } diff --git a/libs/common/types.proto b/libs/common/types.proto index 8406fcfdd..518e7ca09 100644 --- a/libs/common/types.proto +++ b/libs/common/types.proto @@ -1,6 +1,17 @@ syntax = "proto3"; package common; +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.goproto_registration) = true; +// Generate tests +option (gogoproto.populate_all) = true; +option (gogoproto.equal_all) = true; +option (gogoproto.testgen_all) = true; + //---------------------------------------- // Abstract types diff --git a/libs/common/typespb_test.go b/libs/common/typespb_test.go new file mode 100644 index 000000000..583c90502 --- /dev/null +++ b/libs/common/typespb_test.go @@ -0,0 +1,280 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: libs/common/types.proto + +/* +Package common is a generated protocol buffer package. + +It is generated from these files: + libs/common/types.proto + +It has these top-level messages: + KVPair + KI64Pair +*/ +package common + +import testing "testing" +import rand "math/rand" +import time "time" +import proto "github.com/gogo/protobuf/proto" +import jsonpb "github.com/gogo/protobuf/jsonpb" +import golang_proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = golang_proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +func TestKVPairProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKVPair(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &KVPair{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestKVPairMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKVPair(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &KVPair{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestKI64PairProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKI64Pair(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &KI64Pair{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestKI64PairMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKI64Pair(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &KI64Pair{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestKVPairJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKVPair(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &KVPair{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestKI64PairJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKI64Pair(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &KI64Pair{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestKVPairProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKVPair(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &KVPair{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestKVPairProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKVPair(popr, true) + dAtA := proto.CompactTextString(p) + msg := &KVPair{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestKI64PairProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKI64Pair(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &KI64Pair{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestKI64PairProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKI64Pair(popr, true) + dAtA := proto.CompactTextString(p) + msg := &KI64Pair{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestKVPairSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKVPair(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestKI64PairSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedKI64Pair(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +//These tests are generated by github.com/gogo/protobuf/plugin/testgen diff --git a/libs/events/events_test.go b/libs/events/events_test.go index 4995ae730..a01fbbb77 100644 --- a/libs/events/events_test.go +++ b/libs/events/events_test.go @@ -2,11 +2,11 @@ package events import ( "fmt" - "math/rand" "testing" "time" "github.com/stretchr/testify/assert" + cmn "github.com/tendermint/tendermint/libs/common" ) // TestAddListenerForEventFireOnce sets up an EventSwitch, subscribes a single @@ -306,8 +306,8 @@ func TestRemoveListenersAsync(t *testing.T) { // collect received events for event2 go sumReceivedNumbers(numbers2, doneSum2) addListenersStress := func() { - s1 := rand.NewSource(time.Now().UnixNano()) - r1 := rand.New(s1) + r1 := cmn.NewRand() + r1.Seed(time.Now().UnixNano()) for k := uint16(0); k < 400; k++ { listenerNumber := r1.Intn(100) + 3 eventNumber := r1.Intn(3) + 1 @@ -317,8 +317,8 @@ func TestRemoveListenersAsync(t *testing.T) { } } removeListenersStress := func() { - s2 := rand.NewSource(time.Now().UnixNano()) - r2 := rand.New(s2) + r2 := cmn.NewRand() + r2.Seed(time.Now().UnixNano()) for k := uint16(0); k < 80; k++ { listenerNumber := r2.Intn(100) + 3 go evsw.RemoveListener(fmt.Sprintf("listener%v", listenerNumber)) diff --git a/libs/glide.lock b/libs/glide.lock deleted file mode 100644 index a0ada5a4a..000000000 --- a/libs/glide.lock +++ /dev/null @@ -1,108 +0,0 @@ -hash: 98752078f39da926f655268b3b143f713d64edd379fc9fcb1210d9d8aa7ab4e0 -updated: 2018-02-03T01:28:00.221548057-05:00 -imports: -- name: github.com/fsnotify/fsnotify - version: c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9 -- 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: 817915b46b97fd7bb80e8ab6b69f01a53ac3eebf -- name: github.com/gogo/protobuf - version: 1adfc126b41513cc696b209667c8656ea7aac67c - subpackages: - - gogoproto - - proto - - protoc-gen-gogo/descriptor -- name: github.com/golang/snappy - version: 553a641470496b2327abcac10b36396bd98e45c9 -- name: github.com/hashicorp/hcl - version: 23c074d0eceb2b8a5bfdbb271ab780cde70f05a8 - subpackages: - - hcl/ast - - hcl/parser - - hcl/scanner - - hcl/strconv - - hcl/token - - json/parser - - json/scanner - - json/token -- name: github.com/inconshreveable/mousetrap - version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 -- name: github.com/jmhodges/levigo - version: c42d9e0ca023e2198120196f842701bb4c55d7b9 -- name: github.com/kr/logfmt - version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 -- name: github.com/magiconair/properties - version: 49d762b9817ba1c2e9d0c69183c2b4a8b8f1d934 -- name: github.com/mitchellh/mapstructure - version: b4575eea38cca1123ec2dc90c26529b5c5acfcff -- name: github.com/pelletier/go-toml - version: acdc4509485b587f5e675510c4f2c63e90ff68a8 -- name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/spf13/afero - version: bb8f1927f2a9d3ab41c9340aa034f6b803f4359c - subpackages: - - mem -- name: github.com/spf13/cast - version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4 -- name: github.com/spf13/cobra - version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b -- name: github.com/spf13/jwalterweatherman - version: 7c0cea34c8ece3fbeb2b27ab9b59511d360fb394 -- name: github.com/spf13/pflag - version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f -- name: github.com/spf13/viper - version: 25b30aa063fc18e48662b86996252eabdcf2f0c7 -- name: github.com/syndtr/goleveldb - version: b89cc31ef7977104127d34c1bd31ebd1a9db2199 - 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: golang.org/x/crypto - version: edd5e9b0879d13ee6970a50153d85b8fec9f7686 - subpackages: - - ripemd160 -- name: golang.org/x/sys - version: 37707fdb30a5b38865cfb95e5aab41707daec7fd - subpackages: - - unix -- name: golang.org/x/text - version: c01e4764d870b77f8abe5096ee19ad20d80e8075 - subpackages: - - transform - - unicode/norm -- name: gopkg.in/yaml.v2 - version: d670f9405373e636a5a2765eea47fac0c9bc91a4 -testImports: -- name: github.com/davecgh/go-spew - version: 346938d642f2ec3594ed81d874461961cd0faa76 - subpackages: - - spew -- name: github.com/fortytw2/leaktest - version: 3b724c3d7b8729a35bf4e577f71653aec6e53513 -- name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d - subpackages: - - difflib -- name: github.com/stretchr/testify - version: 12b6f73e6084dad08a7c6e575284b177ecafbc71 - subpackages: - - assert - - require diff --git a/libs/glide.yaml b/libs/glide.yaml deleted file mode 100644 index cf3da346b..000000000 --- a/libs/glide.yaml +++ /dev/null @@ -1,38 +0,0 @@ -package: github.com/tendermint/tmlibs -import: -- package: github.com/go-kit/kit - version: ^0.6.0 - subpackages: - - log - - log/level - - log/term -- package: github.com/go-logfmt/logfmt - version: ^0.3.0 -- package: github.com/gogo/protobuf - version: ^1.0.0 - subpackages: - - gogoproto - - proto -- package: github.com/jmhodges/levigo -- package: github.com/pkg/errors - version: ^0.8.0 -- package: github.com/spf13/cobra - version: ^0.0.1 -- package: github.com/spf13/viper - version: ^1.0.0 -- package: github.com/syndtr/goleveldb - subpackages: - - leveldb - - leveldb/errors - - leveldb/iterator - - leveldb/opt -- package: golang.org/x/crypto - subpackages: - - ripemd160 -testImport: -- package: github.com/stretchr/testify - version: ^1.2.1 - subpackages: - - assert - - require -- package: github.com/fortytw2/leaktest diff --git a/libs/merge.sh b/libs/merge.sh deleted file mode 100644 index 7ff0ed94e..000000000 --- a/libs/merge.sh +++ /dev/null @@ -1,54 +0,0 @@ -#! /bin/bash -set -e - -# NOTE: go-alert depends on go-common - -REPOS=("autofile" "clist" "db" "events" "flowrate" "logger" "process") - -mkdir common -git mv *.go common -git mv LICENSE common - -git commit -m "move all files to common/ to begin repo merge" - -for repo in "${REPOS[@]}"; do - # add and fetch the repo - git remote add -f "$repo" "https://github.com/tendermint/go-${repo}" - - # merge master and move into subdir - git merge "$repo/master" --no-edit - - if [[ "$repo" != "flowrate" ]]; then - mkdir "$repo" - git mv *.go "$repo/" - fi - - set +e # these might not exist - git mv *.md "$repo/" - git mv README "$repo/README.md" - git mv Makefile "$repo/Makefile" - git rm LICENSE - set -e - - # commit - git commit -m "merge go-${repo}" - - git remote rm "$repo" -done - -go get github.com/ebuchman/got -got replace "tendermint/go-common" "tendermint/go-common/common" -for repo in "${REPOS[@]}"; do - - if [[ "$repo" != "flowrate" ]]; then - got replace "tendermint/go-${repo}" "tendermint/go-common/${repo}" - else - got replace "tendermint/go-${repo}/flowrate" "tendermint/go-common/flowrate" - fi -done - -git add -u -git commit -m "update import paths" - -# TODO: change any paths in non-Go files -# TODO: add license diff --git a/libs/pubsub/pubsub.go b/libs/pubsub/pubsub.go index fb71a1652..c104439f8 100644 --- a/libs/pubsub/pubsub.go +++ b/libs/pubsub/pubsub.go @@ -163,6 +163,8 @@ func (s *Server) Subscribe(ctx context.Context, clientID string, query Query, ou return nil case <-ctx.Done(): return ctx.Err() + case <-s.Quit(): + return nil } } @@ -190,6 +192,8 @@ func (s *Server) Unsubscribe(ctx context.Context, clientID string, query Query) return nil case <-ctx.Done(): return ctx.Err() + case <-s.Quit(): + return nil } } @@ -211,6 +215,8 @@ func (s *Server) UnsubscribeAll(ctx context.Context, clientID string) error { return nil case <-ctx.Done(): return ctx.Err() + case <-s.Quit(): + return nil } } @@ -229,6 +235,8 @@ func (s *Server) PublishWithTags(ctx context.Context, msg interface{}, tags TagM return nil case <-ctx.Done(): return ctx.Err() + case <-s.Quit(): + return nil } } diff --git a/libs/pubsub/query/Makefile b/libs/pubsub/query/Makefile index 91030ef09..aef42b2df 100644 --- a/libs/pubsub/query/Makefile +++ b/libs/pubsub/query/Makefile @@ -1,10 +1,10 @@ gen_query_parser: - @go get github.com/pointlander/peg + go get -u -v github.com/pointlander/peg peg -inline -switch query.peg fuzzy_test: - @go get github.com/dvyukov/go-fuzz/go-fuzz - @go get github.com/dvyukov/go-fuzz/go-fuzz-build + go get -u -v github.com/dvyukov/go-fuzz/go-fuzz + go get -u -v github.com/dvyukov/go-fuzz/go-fuzz-build go-fuzz-build github.com/tendermint/tendermint/libs/pubsub/query/fuzz_test go-fuzz -bin=./fuzz_test-fuzz.zip -workdir=./fuzz_test/output diff --git a/libs/pubsub/query/query.peg.go b/libs/pubsub/query/query.peg.go index c86e4a47f..c1cc60aa9 100644 --- a/libs/pubsub/query/query.peg.go +++ b/libs/pubsub/query/query.peg.go @@ -1,6 +1,8 @@ // nolint package query +//go:generate peg -inline -switch query.peg + import ( "fmt" "math" diff --git a/lite/helpers.go b/lite/helpers.go index de02b739a..c6fe17602 100644 --- a/lite/helpers.go +++ b/lite/helpers.go @@ -4,6 +4,9 @@ import ( "time" crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" + "github.com/tendermint/tendermint/types" ) @@ -20,7 +23,7 @@ type privKeys []crypto.PrivKey func genPrivKeys(n int) privKeys { res := make(privKeys, n) for i := range res { - res[i] = crypto.GenPrivKeyEd25519() + res[i] = ed25519.GenPrivKey() } return res } @@ -29,7 +32,7 @@ func genPrivKeys(n int) privKeys { func (pkz privKeys) Change(i int) privKeys { res := make(privKeys, len(pkz)) copy(res, pkz) - res[i] = crypto.GenPrivKeyEd25519() + res[i] = ed25519.GenPrivKey() return res } @@ -39,6 +42,21 @@ func (pkz privKeys) Extend(n int) privKeys { return append(pkz, extra...) } +// GenSecpPrivKeys produces an array of secp256k1 private keys to generate commits. +func GenSecpPrivKeys(n int) privKeys { + res := make(privKey, n) + for i := range res { + res[i] = secp256k1.GenPrivKey() + } + return res +} + +// ExtendSecp adds n more secp256k1 keys (to remove, just take a slice). +func (pkz privKeys) ExtendSecp(n int) privKeys { + extra := GenSecpPrivKeys(n) + return append(v, extra...) +} + // ToValidators produces a valset from the set of keys. // The first key has weight `init` and it increases by `inc` every step // so we can have all the same weight, or a simple linear distribution diff --git a/lite/proxy/block.go b/lite/proxy/block.go index 663395fab..035871a11 100644 --- a/lite/proxy/block.go +++ b/lite/proxy/block.go @@ -12,14 +12,14 @@ func ValidateBlockMeta(meta *types.BlockMeta, sh types.SignedHeader) error { return errors.New("expecting a non-nil BlockMeta") } // TODO: check the BlockID?? - return ValidateHeader(meta.Header, sh) + return ValidateHeader(&meta.Header, sh) } func ValidateBlock(meta *types.Block, sh types.SignedHeader) error { if meta == nil { return errors.New("expecting a non-nil Block") } - err := ValidateHeader(meta.Header, sh) + err := ValidateHeader(&meta.Header, sh) if err != nil { return err } diff --git a/lite/proxy/validate_test.go b/lite/proxy/validate_test.go index af4fc26f4..6ca9035ce 100644 --- a/lite/proxy/validate_test.go +++ b/lite/proxy/validate_test.go @@ -17,7 +17,7 @@ var ( testTime2 = time.Date(2017, 1, 2, 1, 1, 1, 1, time.UTC) ) -var hdrHeight11 = &types.Header{ +var hdrHeight11 = types.Header{ Height: 11, Time: testTime1, ValidatorsHash: []byte("Tendermint"), @@ -41,13 +41,13 @@ func TestValidateBlock(t *testing.T) { // Start Header.Height mismatch test { - block: &types.Block{Header: &types.Header{Height: 10}}, + block: &types.Block{Header: types.Header{Height: 10}}, signedHeader: types.SignedHeader{Header: &types.Header{Height: 11}}, wantErr: "Header heights mismatched", }, { - block: &types.Block{Header: &types.Header{Height: 11}}, + block: &types.Block{Header: types.Header{Height: 11}}, signedHeader: types.SignedHeader{Header: &types.Header{Height: 11}}, }, // End Header.Height mismatch test @@ -61,15 +61,15 @@ func TestValidateBlock(t *testing.T) { { block: &types.Block{Header: hdrHeight11}, - signedHeader: types.SignedHeader{Header: hdrHeight11}, + signedHeader: types.SignedHeader{Header: &hdrHeight11}, }, // End Header.Hash mismatch test // Start Header.Data hash mismatch test { block: &types.Block{ - Header: &types.Header{Height: 11}, - Data: &types.Data{Txs: []types.Tx{[]byte("0xDE"), []byte("AD")}}, + Header: types.Header{Height: 11}, + Data: types.Data{Txs: []types.Tx{[]byte("0xDE"), []byte("AD")}}, }, signedHeader: types.SignedHeader{ Header: &types.Header{Height: 11}, @@ -79,8 +79,8 @@ func TestValidateBlock(t *testing.T) { }, { block: &types.Block{ - Header: &types.Header{Height: 11, DataHash: deadBeefHash}, - Data: &types.Data{Txs: deadBeefTxs}, + Header: types.Header{Height: 11, DataHash: deadBeefHash}, + Data: types.Data{Txs: deadBeefTxs}, }, signedHeader: types.SignedHeader{ Header: &types.Header{Height: 11}, @@ -119,17 +119,18 @@ func TestValidateBlockMeta(t *testing.T) { }, { meta: &types.BlockMeta{Header: new(types.Header)}, wantErr: "unexpected empty SignedHeader", + // meta: &types.BlockMeta{}, }, // Start Header.Height mismatch test { - meta: &types.BlockMeta{Header: &types.Header{Height: 10}}, + meta: &types.BlockMeta{Header: types.Header{Height: 10}}, signedHeader: types.SignedHeader{Header: &types.Header{Height: 11}}, wantErr: "Header heights mismatched", }, { - meta: &types.BlockMeta{Header: &types.Header{Height: 11}}, + meta: &types.BlockMeta{Header: types.Header{Height: 11}}, signedHeader: types.SignedHeader{Header: &types.Header{Height: 11}}, }, // End Header.Height mismatch test @@ -143,12 +144,12 @@ func TestValidateBlockMeta(t *testing.T) { { meta: &types.BlockMeta{Header: hdrHeight11}, - signedHeader: types.SignedHeader{Header: hdrHeight11}, + signedHeader: types.SignedHeader{Header: &hdrHeight11}, }, { meta: &types.BlockMeta{ - Header: &types.Header{ + Header: types.Header{ Height: 11, ValidatorsHash: []byte("lite-test"), // TODO: should be able to use empty time after Amino upgrade @@ -163,7 +164,7 @@ func TestValidateBlockMeta(t *testing.T) { { meta: &types.BlockMeta{ - Header: &types.Header{ + Header: types.Header{ Height: 11, DataHash: deadBeefHash, ValidatorsHash: []byte("Tendermint"), Time: testTime1, @@ -182,7 +183,7 @@ func TestValidateBlockMeta(t *testing.T) { { meta: &types.BlockMeta{ - Header: &types.Header{ + Header: types.Header{ Height: 11, DataHash: deadBeefHash, ValidatorsHash: []byte("Tendermint"), Time: testTime2, diff --git a/mempool/mempool.go b/mempool/mempool.go index 06852c9af..e1ed4f260 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -78,7 +78,7 @@ type Mempool struct { recheckCursor *clist.CElement // next expected response recheckEnd *clist.CElement // re-checking stops here notifiedTxsAvailable bool - txsAvailable chan int64 // fires the next height once for each height, when the mempool is not empty + txsAvailable chan struct{} // fires once for each height, when the mempool is not empty // Keep a cache of already-seen txs. // This reduces the pressure on the proxyApp. @@ -130,7 +130,7 @@ func NewMempool( // ensuring it will trigger once every height when transactions are available. // NOTE: not thread safe - should only be called once, on startup func (mem *Mempool) EnableTxsAvailable() { - mem.txsAvailable = make(chan int64, 1) + mem.txsAvailable = make(chan struct{}, 1) } // SetLogger sets the Logger. @@ -348,7 +348,7 @@ func (mem *Mempool) resCbRecheck(req *abci.Request, res *abci.Response) { // TxsAvailable returns a channel which fires once for every height, // and only when transactions are available in the mempool. // NOTE: the returned channel may be nil if EnableTxsAvailable was not called. -func (mem *Mempool) TxsAvailable() <-chan int64 { +func (mem *Mempool) TxsAvailable() <-chan struct{} { return mem.txsAvailable } @@ -358,11 +358,11 @@ func (mem *Mempool) notifyTxsAvailable() { } if mem.txsAvailable != nil && !mem.notifiedTxsAvailable { // channel cap is 1, so this will send once + mem.notifiedTxsAvailable = true select { - case mem.txsAvailable <- mem.height + 1: + case mem.txsAvailable <- struct{}{}: default: } - mem.notifiedTxsAvailable = true } } diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 1a91de4f9..acaa17eec 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -38,7 +38,7 @@ func newMempoolWithApp(cc proxy.ClientCreator) *Mempool { return mempool } -func ensureNoFire(t *testing.T, ch <-chan int64, timeoutMS int) { +func ensureNoFire(t *testing.T, ch <-chan struct{}, timeoutMS int) { timer := time.NewTimer(time.Duration(timeoutMS) * time.Millisecond) select { case <-ch: @@ -47,7 +47,7 @@ func ensureNoFire(t *testing.T, ch <-chan int64, timeoutMS int) { } } -func ensureFire(t *testing.T, ch <-chan int64, timeoutMS int) { +func ensureFire(t *testing.T, ch <-chan struct{}, timeoutMS int) { timer := time.NewTimer(time.Duration(timeoutMS) * time.Millisecond) select { case <-ch: diff --git a/mempool/reactor.go b/mempool/reactor.go index e63ff58e8..96988be78 100644 --- a/mempool/reactor.go +++ b/mempool/reactor.go @@ -78,7 +78,7 @@ func (memR *MempoolReactor) RemovePeer(peer p2p.Peer, reason interface{}) { // Receive implements Reactor. // It adds any received transactions to the mempool. func (memR *MempoolReactor) Receive(chID byte, src p2p.Peer, msgBytes []byte) { - msg, err := DecodeMessage(msgBytes) + msg, err := decodeMsg(msgBytes) if err != nil { memR.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes) memR.Switch.StopPeerForError(src, err) @@ -174,11 +174,9 @@ func RegisterMempoolMessages(cdc *amino.Codec) { cdc.RegisterConcrete(&TxMessage{}, "tendermint/mempool/TxMessage", nil) } -// DecodeMessage decodes a byte-array into a MempoolMessage. -func DecodeMessage(bz []byte) (msg MempoolMessage, err error) { +func decodeMsg(bz []byte) (msg MempoolMessage, err error) { if len(bz) > maxMsgSize { - return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", - len(bz), maxMsgSize) + return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", len(bz), maxMsgSize) } err = cdc.UnmarshalBinaryBare(bz, &msg) return diff --git a/node/node.go b/node/node.go index 0780891ef..e333c667a 100644 --- a/node/node.go +++ b/node/node.go @@ -8,10 +8,12 @@ import ( "net" "net/http" + "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" amino "github.com/tendermint/go-amino" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" @@ -19,7 +21,6 @@ import ( bc "github.com/tendermint/tendermint/blockchain" cfg "github.com/tendermint/tendermint/config" cs "github.com/tendermint/tendermint/consensus" - "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/evidence" mempl "github.com/tendermint/tendermint/mempool" "github.com/tendermint/tendermint/p2p" @@ -196,7 +197,7 @@ func NewNode(config *cfg.Config, var ( // TODO: persist this key so external signer // can actually authenticate us - privKey = crypto.GenPrivKeyEd25519() + privKey = ed25519.GenPrivKey() pvsc = privval.NewSocketPV( logger.With("module", "privval"), config.PrivValidatorListenAddr, @@ -321,9 +322,9 @@ func NewNode(config *cfg.Config, // TODO persistent peers ? so we can have their DNS addrs saved pexReactor := pex.NewPEXReactor(addrBook, &pex.PEXReactorConfig{ - Seeds: cmn.SplitAndTrim(config.P2P.Seeds, ",", " "), - SeedMode: config.P2P.SeedMode, - PrivatePeerIDs: cmn.SplitAndTrim(config.P2P.PrivatePeerIDs, ",", " ")}) + Seeds: cmn.SplitAndTrim(config.P2P.Seeds, ",", " "), + SeedMode: config.P2P.SeedMode, + }) pexReactor.SetLogger(p2pLogger) sw.AddReactor("PEX", pexReactor) } @@ -448,6 +449,9 @@ func (n *Node) OnStart() error { // Add ourselves to addrbook to prevent dialing ourselves n.addrBook.AddOurAddress(nodeInfo.NetAddress()) + // Add private IDs to addrbook to block those peers being added + n.addrBook.AddPrivateIDs(cmn.SplitAndTrim(n.config.P2P.PrivatePeerIDs, ",", " ")) + // Start the RPC server before the P2P server // so we can eg. receive txs for the first block if n.config.RPC.ListenAddress != "" { @@ -485,9 +489,16 @@ func (n *Node) OnStop() { n.BaseService.OnStop() n.Logger.Info("Stopping Node") + + // first stop the non-reactor services + n.eventBus.Stop() + n.indexerService.Stop() + + // now stop the reactors // TODO: gracefully disconnect from peers. n.sw.Stop() + // finally stop the listeners / external services for _, l := range n.rpcListeners { n.Logger.Info("Closing rpc listener", "listener", l) if err := l.Close(); err != nil { @@ -495,9 +506,6 @@ func (n *Node) OnStop() { } } - n.eventBus.Stop() - n.indexerService.Stop() - if pvsc, ok := n.privValidator.(*privval.SocketPV); ok { if err := pvsc.Stop(); err != nil { n.Logger.Error("Error stopping priv validator socket client", "err", err) @@ -599,8 +607,13 @@ func (n *Node) startRPC() ([]net.Listener, error) { // collectors on addr. func (n *Node) startPrometheusServer(addr string) *http.Server { srv := &http.Server{ - Addr: addr, - Handler: promhttp.Handler(), + Addr: addr, + Handler: promhttp.InstrumentMetricHandler( + prometheus.DefaultRegisterer, promhttp.HandlerFor( + prometheus.DefaultGatherer, + promhttp.HandlerOpts{MaxRequestsInFlight: n.config.Instrumentation.MaxOpenConnections}, + ), + ), } go func() { if err := srv.ListenAndServe(); err != http.ErrServerClosed { diff --git a/node/node_test.go b/node/node_test.go index 80f6f02c2..ca074e1bc 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -2,6 +2,9 @@ package node import ( "context" + "fmt" + "os" + "syscall" "testing" "time" @@ -43,6 +46,13 @@ func TestNodeStartStop(t *testing.T) { select { case <-n.Quit(): case <-time.After(5 * time.Second): + pid := os.Getpid() + p, err := os.FindProcess(pid) + if err != nil { + panic(err) + } + err = p.Signal(syscall.SIGABRT) + fmt.Println(err) t.Fatal("timed out waiting for shutdown") } } diff --git a/node/wire.go b/node/wire.go index 8b3ae8950..3bd6de2fc 100644 --- a/node/wire.go +++ b/node/wire.go @@ -2,11 +2,11 @@ package node import ( amino "github.com/tendermint/go-amino" - crypto "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) var cdc = amino.NewCodec() func init() { - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) } diff --git a/p2p/conn/secret_connection_test.go b/p2p/conn/secret_connection_test.go index 7274dfaf7..27dca034a 100644 --- a/p2p/conn/secret_connection_test.go +++ b/p2p/conn/secret_connection_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" ) @@ -35,9 +35,9 @@ func makeKVStoreConnPair() (fooConn, barConn kvstoreConn) { func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection) { var fooConn, barConn = makeKVStoreConnPair() - var fooPrvKey = crypto.GenPrivKeyEd25519() + var fooPrvKey = ed25519.GenPrivKey() var fooPubKey = fooPrvKey.PubKey() - var barPrvKey = crypto.GenPrivKeyEd25519() + var barPrvKey = ed25519.GenPrivKey() var barPubKey = barPrvKey.PubKey() // Make connections from both sides in parallel. @@ -105,7 +105,7 @@ func TestSecretConnectionReadWrite(t *testing.T) { genNodeRunner := func(id string, nodeConn kvstoreConn, nodeWrites []string, nodeReads *[]string) cmn.Task { return func(_ int) (interface{}, error, bool) { // Initiate cryptographic private key and secret connection trhough nodeConn. - nodePrvKey := crypto.GenPrivKeyEd25519() + nodePrvKey := ed25519.GenPrivKey() nodeSecretConn, err := MakeSecretConnection(nodeConn, nodePrvKey) if err != nil { t.Errorf("Failed to establish SecretConnection for node: %v", err) diff --git a/p2p/conn/wire.go b/p2p/conn/wire.go index 3182fde38..4bd778c74 100644 --- a/p2p/conn/wire.go +++ b/p2p/conn/wire.go @@ -2,12 +2,12 @@ package conn import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) var cdc *amino.Codec = amino.NewCodec() func init() { - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) RegisterPacket(cdc) } diff --git a/p2p/dummy/peer.go b/p2p/dummy/peer.go index d18a9f99d..bb6e822fc 100644 --- a/p2p/dummy/peer.go +++ b/p2p/dummy/peer.go @@ -3,9 +3,9 @@ package dummy import ( "net" + cmn "github.com/tendermint/tendermint/libs/common" p2p "github.com/tendermint/tendermint/p2p" tmconn "github.com/tendermint/tendermint/p2p/conn" - cmn "github.com/tendermint/tendermint/libs/common" ) type peer struct { @@ -78,3 +78,8 @@ func (p *peer) Get(key string) interface{} { } return nil } + +// OriginalAddr always returns nil. +func (p *peer) OriginalAddr() *p2p.NetAddress { + return nil +} diff --git a/p2p/key.go b/p2p/key.go index 9548d34f0..4d1ecd82f 100644 --- a/p2p/key.go +++ b/p2p/key.go @@ -7,6 +7,7 @@ import ( "io/ioutil" crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" ) @@ -70,7 +71,7 @@ func LoadNodeKey(filePath string) (*NodeKey, error) { } func genNodeKey(filePath string) (*NodeKey, error) { - privKey := crypto.GenPrivKeyEd25519() + privKey := ed25519.GenPrivKey() nodeKey := &NodeKey{ PrivKey: privKey, } diff --git a/p2p/node_info.go b/p2p/node_info.go index 5e8160a3b..fa1333b27 100644 --- a/p2p/node_info.go +++ b/p2p/node_info.go @@ -2,8 +2,9 @@ package p2p import ( "fmt" - cmn "github.com/tendermint/tendermint/libs/common" "strings" + + cmn "github.com/tendermint/tendermint/libs/common" ) const ( @@ -81,8 +82,8 @@ func (info NodeInfo) Validate() error { // CONTRACT: two nodes are compatible if the major version matches and network match // and they have at least one channel in common. func (info NodeInfo) CompatibleWith(other NodeInfo) error { - iMajor, iMinor, _, iErr := splitVersion(info.Version) - oMajor, oMinor, _, oErr := splitVersion(other.Version) + iMajor, _, _, iErr := splitVersion(info.Version) + oMajor, _, _, oErr := splitVersion(other.Version) // if our own version number is not formatted right, we messed up if iErr != nil { @@ -99,11 +100,6 @@ func (info NodeInfo) CompatibleWith(other NodeInfo) error { return fmt.Errorf("Peer is on a different major version. Got %v, expected %v", oMajor, iMajor) } - // minor version can differ - if iMinor != oMinor { - // ok - } - // nodes must be on the same network if info.Network != other.Network { return fmt.Errorf("Peer is on a different network. Got %v, expected %v", other.Network, info.Network) diff --git a/p2p/peer.go b/p2p/peer.go index 5c615275b..4f59fef76 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -26,6 +26,7 @@ type Peer interface { IsPersistent() bool // do we redial this peer when we disconnect NodeInfo() NodeInfo // peer's info Status() tmconn.ConnectionStatus + OriginalAddr() *NetAddress Send(byte, []byte) bool TrySend(byte, []byte) bool @@ -38,11 +39,12 @@ type Peer interface { // peerConn contains the raw connection and its config. type peerConn struct { - outbound bool - persistent bool - config *config.P2PConfig - conn net.Conn // source connection - ip net.IP + outbound bool + persistent bool + config *config.P2PConfig + conn net.Conn // source connection + ip net.IP + originalAddr *NetAddress // nil for inbound connections } // ID only exists for SecretConnection. @@ -139,7 +141,7 @@ func newOutboundPeerConn( return peerConn{}, cmn.ErrorWrap(err, "Error creating peer") } - pc, err := newPeerConn(conn, config, true, persistent, ourNodePrivKey) + pc, err := newPeerConn(conn, config, true, persistent, ourNodePrivKey, addr) if err != nil { if cerr := conn.Close(); cerr != nil { return peerConn{}, cmn.ErrorWrap(err, cerr.Error()) @@ -166,7 +168,7 @@ func newInboundPeerConn( // TODO: issue PoW challenge - return newPeerConn(conn, config, false, false, ourNodePrivKey) + return newPeerConn(conn, config, false, false, ourNodePrivKey, nil) } func newPeerConn( @@ -174,6 +176,7 @@ func newPeerConn( cfg *config.P2PConfig, outbound, persistent bool, ourNodePrivKey crypto.PrivKey, + originalAddr *NetAddress, ) (pc peerConn, err error) { conn := rawConn @@ -200,10 +203,11 @@ func newPeerConn( // Only the information we already have return peerConn{ - config: cfg, - outbound: outbound, - persistent: persistent, - conn: conn, + config: cfg, + outbound: outbound, + persistent: persistent, + conn: conn, + originalAddr: originalAddr, }, nil } @@ -254,6 +258,15 @@ func (p *peer) NodeInfo() NodeInfo { return p.nodeInfo } +// OriginalAddr returns the original address, which was used to connect with +// the peer. Returns nil for inbound peers. +func (p *peer) OriginalAddr() *NetAddress { + if p.peerConn.outbound { + return p.peerConn.originalAddr + } + return nil +} + // Status returns the peer's ConnectionStatus. func (p *peer) Status() tmconn.ConnectionStatus { return p.mconn.Status() diff --git a/p2p/peer_set_test.go b/p2p/peer_set_test.go index aa63ef949..4582ab644 100644 --- a/p2p/peer_set_test.go +++ b/p2p/peer_set_test.go @@ -1,14 +1,13 @@ package p2p import ( - "math/rand" "net" "sync" "testing" "github.com/stretchr/testify/assert" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" ) @@ -18,11 +17,11 @@ func randPeer(ip net.IP) *peer { ip = net.IP{127, 0, 0, 1} } - nodeKey := NodeKey{PrivKey: crypto.GenPrivKeyEd25519()} + nodeKey := NodeKey{PrivKey: ed25519.GenPrivKey()} p := &peer{ nodeInfo: NodeInfo{ ID: nodeKey.ID(), - ListenAddr: cmn.Fmt("%v.%v.%v.%v:26656", rand.Int()%256, rand.Int()%256, rand.Int()%256, rand.Int()%256), + ListenAddr: cmn.Fmt("%v.%v.%v.%v:26656", cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256), }, } diff --git a/p2p/peer_test.go b/p2p/peer_test.go index 281b218d9..f0e915328 100644 --- a/p2p/peer_test.go +++ b/p2p/peer_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" @@ -23,7 +24,7 @@ func TestPeerBasic(t *testing.T) { assert, require := assert.New(t), require.New(t) // simulate remote peer - rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: cfg} + rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} rp.Start() defer rp.Stop() @@ -49,7 +50,7 @@ func TestPeerSend(t *testing.T) { config := cfg // simulate remote peer - rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: config} + rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: config} rp.Start() defer rp.Stop() @@ -74,7 +75,7 @@ func createOutboundPeerAndPerformHandshake( {ID: testCh, Priority: 1}, } reactorsByCh := map[byte]Reactor{testCh: NewTestReactor(chDescs, true)} - pk := crypto.GenPrivKeyEd25519() + pk := ed25519.GenPrivKey() pc, err := newOutboundPeerConn(addr, config, false, pk) if err != nil { return nil, err diff --git a/p2p/pex/addrbook.go b/p2p/pex/addrbook.go index 421aa135a..c630d14c3 100644 --- a/p2p/pex/addrbook.go +++ b/p2p/pex/addrbook.go @@ -13,8 +13,8 @@ import ( "time" crypto "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/p2p" cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/p2p" ) const ( @@ -34,6 +34,8 @@ type AddrBook interface { // Check if it is our address OurAddress(*p2p.NetAddress) bool + AddPrivateIDs([]string) + // Add and remove an address AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error RemoveAddress(*p2p.NetAddress) @@ -82,6 +84,7 @@ type addrBook struct { mtx sync.Mutex rand *cmn.Rand ourAddrs map[string]struct{} + privateIDs map[p2p.ID]struct{} addrLookup map[p2p.ID]*knownAddress // new & old bucketsOld []map[string]*knownAddress bucketsNew []map[string]*knownAddress @@ -97,6 +100,7 @@ func NewAddrBook(filePath string, routabilityStrict bool) *addrBook { am := &addrBook{ rand: cmn.NewRand(), ourAddrs: make(map[string]struct{}), + privateIDs: make(map[p2p.ID]struct{}), addrLookup: make(map[p2p.ID]*knownAddress), filePath: filePath, routabilityStrict: routabilityStrict, @@ -168,6 +172,14 @@ func (a *addrBook) OurAddress(addr *p2p.NetAddress) bool { return ok } +func (a *addrBook) AddPrivateIDs(IDs []string) { + a.mtx.Lock() + defer a.mtx.Unlock() + for _, id := range IDs { + a.privateIDs[p2p.ID(id)] = struct{}{} + } +} + // AddAddress implements AddrBook // Add address to a "new" bucket. If it's already in one, only add it probabilistically. // Returns error if the addr is non-routable. Does not add self. @@ -631,6 +643,10 @@ func (a *addrBook) addAddress(addr, src *p2p.NetAddress) error { return ErrAddrBookSelf{addr} } + if _, ok := a.privateIDs[addr.ID]; ok { + return ErrAddrBookPrivate{addr} + } + ka := a.addrLookup[addr.ID] if ka != nil { // If its already old and the addr is the same, ignore it. diff --git a/p2p/pex/addrbook_test.go b/p2p/pex/addrbook_test.go index dd983f76f..8b64c380f 100644 --- a/p2p/pex/addrbook_test.go +++ b/p2p/pex/addrbook_test.go @@ -4,14 +4,15 @@ import ( "encoding/hex" "fmt" "io/ioutil" - "math/rand" "os" "testing" "github.com/stretchr/testify/assert" - "github.com/tendermint/tendermint/p2p" + "github.com/stretchr/testify/require" + cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/p2p" ) func createTempFileName(prefix string) string { @@ -202,12 +203,12 @@ func randNetAddressPairs(t *testing.T, n int) []netAddressPair { func randIPv4Address(t *testing.T) *p2p.NetAddress { for { ip := fmt.Sprintf("%v.%v.%v.%v", - rand.Intn(254)+1, - rand.Intn(255), - rand.Intn(255), - rand.Intn(255), + cmn.RandIntn(254)+1, + cmn.RandIntn(255), + cmn.RandIntn(255), + cmn.RandIntn(255), ) - port := rand.Intn(65535-1) + 1 + port := cmn.RandIntn(65535-1) + 1 id := p2p.ID(hex.EncodeToString(cmn.RandBytes(p2p.IDByteLength))) idAddr := p2p.IDAddressString(id, fmt.Sprintf("%v:%v", ip, port)) addr, err := p2p.NewNetAddressString(idAddr) @@ -354,3 +355,29 @@ func TestAddrBookHasAddress(t *testing.T) { assert.False(t, book.HasAddress(addr)) } + +func TestPrivatePeers(t *testing.T) { + fname := createTempFileName("addrbook_test") + defer deleteTempFile(fname) + + book := NewAddrBook(fname, true) + book.SetLogger(log.TestingLogger()) + + addrs := make([]*p2p.NetAddress, 10) + for i := 0; i < 10; i++ { + addrs[i] = randIPv4Address(t) + } + + private := make([]string, 10) + for i, addr := range addrs { + private[i] = string(addr.ID) + } + book.AddPrivateIDs(private) + + for _, addr := range addrs { + err := book.AddAddress(addr, addr) + require.Error(t, err, "AddAddress should have failed with private peer %s", addr) + _, ok := err.(ErrAddrBookPrivate) + require.True(t, ok, "Wrong error type, wanted ErrAddrBookPrivate, got error: %s", err) + } +} diff --git a/p2p/pex/errors.go b/p2p/pex/errors.go index 0b8bf4715..34bfb5ab1 100644 --- a/p2p/pex/errors.go +++ b/p2p/pex/errors.go @@ -22,6 +22,14 @@ func (err ErrAddrBookSelf) Error() string { return fmt.Sprintf("Cannot add ourselves with address %v", err.Addr) } +type ErrAddrBookPrivate struct { + Addr *p2p.NetAddress +} + +func (err ErrAddrBookPrivate) Error() string { + return fmt.Sprintf("Cannot add private peer with address %v", err.Addr) +} + type ErrAddrBookNilAddr struct { Addr *p2p.NetAddress Src *p2p.NetAddress diff --git a/p2p/pex/pex_reactor.go b/p2p/pex/pex_reactor.go index 2d93783df..5c4894ce4 100644 --- a/p2p/pex/pex_reactor.go +++ b/p2p/pex/pex_reactor.go @@ -91,10 +91,6 @@ type PEXReactorConfig struct { // Seeds is a list of addresses reactor may use // if it can't connect to peers in the addrbook. Seeds []string - - // PrivatePeerIDs is a list of peer IDs, which must not be gossiped to other - // peers. - PrivatePeerIDs []string } type _attemptsToDial struct { @@ -173,11 +169,6 @@ func (r *PEXReactor) AddPeer(p Peer) { addr := p.NodeInfo().NetAddress() src := addr - // ignore private addrs - if isAddrPrivate(addr, r.config.PrivatePeerIDs) { - return - } - // add to book. dont RequestAddrs right away because // we don't trust inbound as much - let ensurePeersRoutine handle it. err := r.book.AddAddress(addr, src) @@ -191,7 +182,7 @@ func (r *PEXReactor) logErrAddrBook(err error) { case ErrAddrBookNilAddr: r.Logger.Error("Failed to add new address", "err", err) default: - // non-routable, self, full book, etc. + // non-routable, self, full book, private, etc. r.Logger.Debug("Failed to add new address", "err", err) } } @@ -206,7 +197,7 @@ func (r *PEXReactor) RemovePeer(p Peer, reason interface{}) { // Receive implements Reactor by handling incoming PEX messages. func (r *PEXReactor) Receive(chID byte, src Peer, msgBytes []byte) { - msg, err := DecodeMessage(msgBytes) + msg, err := decodeMsg(msgBytes) if err != nil { r.Logger.Error("Error decoding message", "src", src, "chId", chID, "msg", msg, "err", err, "bytes", msgBytes) r.Switch.StopPeerForError(src, err) @@ -287,7 +278,7 @@ func (r *PEXReactor) RequestAddrs(p Peer) { return } r.requestsSent.Set(id, struct{}{}) - p.Send(PexChannel, cdc.MustMarshalBinary(&pexRequestMessage{})) + p.Send(PexChannel, cdc.MustMarshalBinaryBare(&pexRequestMessage{})) } // ReceiveAddrs adds the given addrs to the addrbook if theres an open @@ -308,14 +299,6 @@ func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error { return cmn.NewError("received nil addr") } - // ignore private peers - // TODO: give private peers to AddrBook so it can enforce this on AddAddress. - // We'd then have to check for ErrPrivatePeer on AddAddress here, which is - // an error we just ignore (maybe peer is probing us for our private peers :P) - if isAddrPrivate(netAddr, r.config.PrivatePeerIDs) { - continue - } - err := r.book.AddAddress(netAddr, srcAddr) r.logErrAddrBook(err) } @@ -324,7 +307,7 @@ func (r *PEXReactor) ReceiveAddrs(addrs []*p2p.NetAddress, src Peer) error { // SendAddrs sends addrs to the peer. func (r *PEXReactor) SendAddrs(p Peer, netAddrs []*p2p.NetAddress) { - p.Send(PexChannel, cdc.MustMarshalBinary(&pexAddrsMessage{Addrs: netAddrs})) + p.Send(PexChannel, cdc.MustMarshalBinaryBare(&pexAddrsMessage{Addrs: netAddrs})) } // SetEnsurePeersPeriod sets period to ensure peers connected. @@ -647,16 +630,6 @@ func (r *PEXReactor) attemptDisconnects() { } } -// isAddrPrivate returns true if addr.ID is a private ID. -func isAddrPrivate(addr *p2p.NetAddress, privatePeerIDs []string) bool { - for _, id := range privatePeerIDs { - if string(addr.ID) == id { - return true - } - } - return false -} - //----------------------------------------------------------------------------- // Messages @@ -670,13 +643,11 @@ func RegisterPexMessage(cdc *amino.Codec) { cdc.RegisterConcrete(&pexAddrsMessage{}, "tendermint/p2p/PexAddrsMessage", nil) } -// DecodeMessage implements interface registered above. -func DecodeMessage(bz []byte) (msg PexMessage, err error) { +func decodeMsg(bz []byte) (msg PexMessage, err error) { if len(bz) > maxMsgSize { - return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", - len(bz), maxMsgSize) + return msg, fmt.Errorf("Msg exceeds max size (%d > %d)", len(bz), maxMsgSize) } - err = cdc.UnmarshalBinary(bz, &msg) + err = cdc.UnmarshalBinaryBare(bz, &msg) return } diff --git a/p2p/pex/pex_reactor_test.go b/p2p/pex/pex_reactor_test.go index 6d6e91c38..8d54693fe 100644 --- a/p2p/pex/pex_reactor_test.go +++ b/p2p/pex/pex_reactor_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/require" crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" @@ -134,11 +135,11 @@ func TestPEXReactorReceive(t *testing.T) { size := book.Size() addrs := []*p2p.NetAddress{peer.NodeInfo().NetAddress()} - msg := cdc.MustMarshalBinary(&pexAddrsMessage{Addrs: addrs}) + msg := cdc.MustMarshalBinaryBare(&pexAddrsMessage{Addrs: addrs}) r.Receive(PexChannel, peer, msg) assert.Equal(t, size+1, book.Size()) - msg = cdc.MustMarshalBinary(&pexRequestMessage{}) + msg = cdc.MustMarshalBinaryBare(&pexRequestMessage{}) r.Receive(PexChannel, peer, msg) // should not panic. } @@ -154,7 +155,7 @@ func TestPEXReactorRequestMessageAbuse(t *testing.T) { assert.True(t, sw.Peers().Has(peer.ID())) id := string(peer.ID()) - msg := cdc.MustMarshalBinary(&pexRequestMessage{}) + msg := cdc.MustMarshalBinaryBare(&pexRequestMessage{}) // first time creates the entry r.Receive(PexChannel, peer, msg) @@ -191,7 +192,7 @@ func TestPEXReactorAddrsMessageAbuse(t *testing.T) { assert.True(t, sw.Peers().Has(peer.ID())) addrs := []*p2p.NetAddress{peer.NodeInfo().NetAddress()} - msg := cdc.MustMarshalBinary(&pexAddrsMessage{Addrs: addrs}) + msg := cdc.MustMarshalBinaryBare(&pexAddrsMessage{Addrs: addrs}) // receive some addrs. should clear the request r.Receive(PexChannel, peer, msg) @@ -295,7 +296,8 @@ func TestPEXReactorCrawlStatus(t *testing.T) { func TestPEXReactorDoesNotAddPrivatePeersToAddrBook(t *testing.T) { peer := p2p.CreateRandomPeer(false) - pexR, book := createReactor(&PEXReactorConfig{PrivatePeerIDs: []string{string(peer.NodeInfo().ID)}}) + pexR, book := createReactor(&PEXReactorConfig{}) + book.AddPrivateIDs([]string{string(peer.NodeInfo().ID)}) defer teardownReactor(book) // we have to send a request to receive responses @@ -303,7 +305,7 @@ func TestPEXReactorDoesNotAddPrivatePeersToAddrBook(t *testing.T) { size := book.Size() addrs := []*p2p.NetAddress{peer.NodeInfo().NetAddress()} - msg := cdc.MustMarshalBinary(&pexAddrsMessage{Addrs: addrs}) + msg := cdc.MustMarshalBinaryBare(&pexAddrsMessage{Addrs: addrs}) pexR.Receive(PexChannel, peer, msg) assert.Equal(t, size, book.Size()) @@ -355,7 +357,7 @@ func newMockPeer() mockPeer { _, netAddr := p2p.CreateRoutableAddr() mp := mockPeer{ addr: netAddr, - pubKey: crypto.GenPrivKeyEd25519().PubKey(), + pubKey: ed25519.GenPrivKey().PubKey(), } mp.BaseService = cmn.NewBaseService(nil, "MockPeer", mp) mp.Start() @@ -371,12 +373,13 @@ func (mp mockPeer) NodeInfo() p2p.NodeInfo { ListenAddr: mp.addr.DialString(), } } -func (mp mockPeer) RemoteIP() net.IP { return net.ParseIP("127.0.0.1") } -func (mp mockPeer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{} } -func (mp mockPeer) Send(byte, []byte) bool { return false } -func (mp mockPeer) TrySend(byte, []byte) bool { return false } -func (mp mockPeer) Set(string, interface{}) {} -func (mp mockPeer) Get(string) interface{} { return nil } +func (mockPeer) RemoteIP() net.IP { return net.ParseIP("127.0.0.1") } +func (mockPeer) Status() conn.ConnectionStatus { return conn.ConnectionStatus{} } +func (mockPeer) Send(byte, []byte) bool { return false } +func (mockPeer) TrySend(byte, []byte) bool { return false } +func (mockPeer) Set(string, interface{}) {} +func (mockPeer) Get(string) interface{} { return nil } +func (mockPeer) OriginalAddr() *p2p.NetAddress { return nil } func assertPeersWithTimeout( t *testing.T, diff --git a/p2p/switch.go b/p2p/switch.go index d1e2ef23b..636ca6d8e 100644 --- a/p2p/switch.go +++ b/p2p/switch.go @@ -8,8 +8,8 @@ import ( "time" "github.com/tendermint/tendermint/config" - "github.com/tendermint/tendermint/p2p/conn" cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/p2p/conn" ) const ( @@ -281,8 +281,13 @@ func (sw *Switch) StopPeerForError(peer Peer, reason interface{}) { sw.stopAndRemovePeer(peer, reason) if peer.IsPersistent() { - // NOTE: this is the self-reported addr, not the original we dialed - go sw.reconnectToPeer(peer.NodeInfo().NetAddress()) + addr := peer.OriginalAddr() + if addr == nil { + // FIXME: persistent peers can't be inbound right now. + // self-reported address for inbound persistent peers + addr = peer.NodeInfo().NetAddress() + } + go sw.reconnectToPeer(addr) } } diff --git a/p2p/switch_test.go b/p2p/switch_test.go index 97539112e..2ce297761 100644 --- a/p2p/switch_test.go +++ b/p2p/switch_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/config" @@ -259,7 +259,7 @@ func TestSwitchStopsNonPersistentPeerOnError(t *testing.T) { defer sw.Stop() // simulate remote peer - rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: cfg} + rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} rp.Start() defer rp.Stop() @@ -289,7 +289,7 @@ func TestSwitchReconnectsToPersistentPeer(t *testing.T) { defer sw.Stop() // simulate remote peer - rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: cfg} + rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} rp.Start() defer rp.Stop() @@ -319,7 +319,7 @@ func TestSwitchReconnectsToPersistentPeer(t *testing.T) { // simulate another remote peer rp = &remotePeer{ - PrivKey: crypto.GenPrivKeyEd25519(), + PrivKey: ed25519.GenPrivKey(), Config: cfg, // Use different interface to prevent duplicate IP filter, this will break // beyond two peers. diff --git a/p2p/test_util.go b/p2p/test_util.go index 467532f0f..fdf9ae764 100644 --- a/p2p/test_util.go +++ b/p2p/test_util.go @@ -4,7 +4,7 @@ import ( "fmt" "net" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" @@ -135,7 +135,7 @@ func MakeSwitch(cfg *config.P2PConfig, i int, network, version string, initSwitc // new switch, add reactors // TODO: let the config be passed in? nodeKey := &NodeKey{ - PrivKey: crypto.GenPrivKeyEd25519(), + PrivKey: ed25519.GenPrivKey(), } sw := NewSwitch(cfg) sw.SetLogger(log.TestingLogger()) diff --git a/p2p/wire.go b/p2p/wire.go index b7ae41253..40176e3af 100644 --- a/p2p/wire.go +++ b/p2p/wire.go @@ -2,11 +2,11 @@ package p2p import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) var cdc = amino.NewCodec() func init() { - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) } diff --git a/privval/priv_validator.go b/privval/priv_validator.go index 2abcf5590..5b056d8a0 100644 --- a/privval/priv_validator.go +++ b/privval/priv_validator.go @@ -9,8 +9,9 @@ import ( "time" "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/types" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/types" ) // TODO: type ? @@ -67,7 +68,7 @@ func (pv *FilePV) GetPubKey() crypto.PubKey { // GenFilePV generates a new validator with randomly generated private key // and sets the filePath, but does not call Save(). func GenFilePV(filePath string) *FilePV { - privKey := crypto.GenPrivKeyEd25519() + privKey := ed25519.GenPrivKey() return &FilePV{ Address: privKey.PubKey().Address(), PubKey: privKey.PubKey(), @@ -91,6 +92,10 @@ func LoadFilePV(filePath string) *FilePV { cmn.Exit(cmn.Fmt("Error reading PrivValidator from %v: %v\n", filePath, err)) } + // overwrite pubkey and address for convenience + pv.PubKey = pv.PrivKey.PubKey() + pv.Address = pv.PubKey.Address() + pv.filePath = filePath return pv } diff --git a/privval/priv_validator_test.go b/privval/priv_validator_test.go index 0135cce8c..7c9c93fcf 100644 --- a/privval/priv_validator_test.go +++ b/privval/priv_validator_test.go @@ -10,8 +10,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/types" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/types" ) func TestGenLoadValidator(t *testing.T) { @@ -47,10 +48,10 @@ func TestUnmarshalValidator(t *testing.T) { assert, require := assert.New(t), require.New(t) // create some fixed values - privKey := crypto.GenPrivKeyEd25519() + privKey := ed25519.GenPrivKey() pubKey := privKey.PubKey() addr := pubKey.Address() - pubArray := [32]byte(pubKey.(crypto.PubKeyEd25519)) + pubArray := [32]byte(pubKey.(ed25519.PubKeyEd25519)) pubBytes := pubArray[:] privArray := [64]byte(privKey) privBytes := privArray[:] diff --git a/privval/socket.go b/privval/socket.go index 1e8a3807b..c33443eda 100644 --- a/privval/socket.go +++ b/privval/socket.go @@ -9,6 +9,7 @@ import ( "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" @@ -74,7 +75,7 @@ type SocketPV struct { connDeadline time.Duration connHeartbeat time.Duration connWaitTimeout time.Duration - privKey crypto.PrivKeyEd25519 + privKey ed25519.PrivKeyEd25519 conn net.Conn listener net.Listener @@ -87,7 +88,7 @@ var _ types.PrivValidator = (*SocketPV)(nil) func NewSocketPV( logger log.Logger, socketAddr string, - privKey crypto.PrivKeyEd25519, + privKey ed25519.PrivKeyEd25519, ) *SocketPV { sc := &SocketPV{ addr: socketAddr, @@ -343,7 +344,7 @@ type RemoteSigner struct { chainID string connDeadline time.Duration connRetries int - privKey crypto.PrivKeyEd25519 + privKey ed25519.PrivKeyEd25519 privVal types.PrivValidator conn net.Conn @@ -354,7 +355,7 @@ func NewRemoteSigner( logger log.Logger, chainID, socketAddr string, privVal types.PrivValidator, - privKey crypto.PrivKeyEd25519, + privKey ed25519.PrivKeyEd25519, ) *RemoteSigner { rs := &RemoteSigner{ addr: socketAddr, diff --git a/privval/socket_test.go b/privval/socket_test.go index 7bcacd6e1..461ce3f85 100644 --- a/privval/socket_test.go +++ b/privval/socket_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" @@ -112,7 +112,7 @@ func TestSocketPVAcceptDeadline(t *testing.T) { sc = NewSocketPV( log.TestingLogger(), "127.0.0.1:0", - crypto.GenPrivKeyEd25519(), + ed25519.GenPrivKey(), ) ) defer sc.Stop() @@ -129,7 +129,7 @@ func TestSocketPVDeadline(t *testing.T) { sc = NewSocketPV( log.TestingLogger(), addr, - crypto.GenPrivKeyEd25519(), + ed25519.GenPrivKey(), ) ) @@ -152,7 +152,7 @@ func TestSocketPVDeadline(t *testing.T) { _, err = p2pconn.MakeSecretConnection( conn, - crypto.GenPrivKeyEd25519(), + ed25519.GenPrivKey(), ) if err == nil { break @@ -172,7 +172,7 @@ func TestSocketPVWait(t *testing.T) { sc := NewSocketPV( log.TestingLogger(), "127.0.0.1:0", - crypto.GenPrivKeyEd25519(), + ed25519.GenPrivKey(), ) defer sc.Stop() @@ -214,7 +214,7 @@ func TestRemoteSignerRetry(t *testing.T) { cmn.RandStr(12), ln.Addr().String(), types.NewMockPV(), - crypto.GenPrivKeyEd25519(), + ed25519.GenPrivKey(), ) defer rs.Stop() @@ -245,12 +245,12 @@ func testSetupSocketPair( chainID, addr, privVal, - crypto.GenPrivKeyEd25519(), + ed25519.GenPrivKey(), ) sc = NewSocketPV( logger, addr, - crypto.GenPrivKeyEd25519(), + ed25519.GenPrivKey(), ) ) diff --git a/privval/wire.go b/privval/wire.go index c42ba40d6..50660ff34 100644 --- a/privval/wire.go +++ b/privval/wire.go @@ -2,12 +2,12 @@ package privval import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) var cdc = amino.NewCodec() func init() { - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) RegisterSocketPVMsg(cdc) } diff --git a/rpc/client/localclient.go b/rpc/client/localclient.go index df3daf907..b3c5e3090 100644 --- a/rpc/client/localclient.go +++ b/rpc/client/localclient.go @@ -3,12 +3,12 @@ package client import ( "context" + cmn "github.com/tendermint/tendermint/libs/common" tmpubsub "github.com/tendermint/tendermint/libs/pubsub" nm "github.com/tendermint/tendermint/node" "github.com/tendermint/tendermint/rpc/core" ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/types" - cmn "github.com/tendermint/tendermint/libs/common" ) /* diff --git a/rpc/core/blocks.go b/rpc/core/blocks.go index b74312011..af061c93c 100644 --- a/rpc/core/blocks.go +++ b/rpc/core/blocks.go @@ -3,10 +3,10 @@ package core import ( "fmt" + cmn "github.com/tendermint/tendermint/libs/common" ctypes "github.com/tendermint/tendermint/rpc/core/types" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" - cmn "github.com/tendermint/tendermint/libs/common" ) // Get block headers for minHeight <= height <= maxHeight. @@ -288,12 +288,12 @@ func Commit(heightPtr *int64) (*ctypes.ResultCommit, error) { // use a non-canonical commit if height == storeHeight { commit := blockStore.LoadSeenCommit(height) - return ctypes.NewResultCommit(header, commit, false), nil + return ctypes.NewResultCommit(&header, commit, false), nil } // Return the canonical commit (comes from the block at height+1) commit := blockStore.LoadBlockCommit(height) - return ctypes.NewResultCommit(header, commit, true), nil + return ctypes.NewResultCommit(&header, commit, true), nil } // BlockResults gets ABCIResults at a given height. diff --git a/rpc/core/doc.go b/rpc/core/doc.go index d076b3ecd..75f6ac82e 100644 --- a/rpc/core/doc.go +++ b/rpc/core/doc.go @@ -39,8 +39,6 @@ curl 'localhost:26657/broadcast_tx_sync?tx="abc"' } ``` -The first entry in the result-array (`96`) is the method this response correlates with. `96` refers to "ResultTypeBroadcastTx", see [responses.go](https://github.com/tendermint/tendermint/blob/master/rpc/core/types/responses.go) for a complete overview. - ## JSONRPC/HTTP JSONRPC requests can be POST'd to the root RPC endpoint via HTTP (e.g. `http://localhost:26657/`). diff --git a/rpc/core/status.go b/rpc/core/status.go index 45b5a905e..0228fd869 100644 --- a/rpc/core/status.go +++ b/rpc/core/status.go @@ -4,10 +4,10 @@ import ( "bytes" "time" + cmn "github.com/tendermint/tendermint/libs/common" ctypes "github.com/tendermint/tendermint/rpc/core/types" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" - cmn "github.com/tendermint/tendermint/libs/common" ) // Get Tendermint status including node info, pubkey, latest block @@ -109,8 +109,17 @@ func Status() (*ctypes.ResultStatus, error) { return result, nil } +const consensusTimeout = time.Second + func validatorAtHeight(h int64) *types.Validator { - lastBlockHeight, vals := consensusState.GetValidators() + lastBlockHeight, vals := getValidatorsWithTimeout( + consensusState, + consensusTimeout, + ) + + if lastBlockHeight == -1 { + return nil + } privValAddress := pubKey.Address() @@ -135,3 +144,32 @@ func validatorAtHeight(h int64) *types.Validator { return nil } + +type validatorRetriever interface { + GetValidators() (int64, []*types.Validator) +} + +// NOTE: Consensus might halt, but we still need to process RPC requests (at +// least for endpoints whole output does not depend on consensus state). +func getValidatorsWithTimeout( + vr validatorRetriever, + t time.Duration, +) (int64, []*types.Validator) { + resultCh := make(chan struct { + lastBlockHeight int64 + vals []*types.Validator + }) + go func() { + h, v := vr.GetValidators() + resultCh <- struct { + lastBlockHeight int64 + vals []*types.Validator + }{h, v} + }() + select { + case res := <-resultCh: + return res.lastBlockHeight, res.vals + case <-time.After(t): + return -1, []*types.Validator{} + } +} diff --git a/rpc/core/status_test.go b/rpc/core/status_test.go new file mode 100644 index 000000000..e44ffed0f --- /dev/null +++ b/rpc/core/status_test.go @@ -0,0 +1,39 @@ +package core + +import ( + "testing" + "time" + + "github.com/tendermint/tendermint/types" +) + +func TestGetValidatorsWithTimeout(t *testing.T) { + height, vs := getValidatorsWithTimeout( + testValidatorReceiver{}, + time.Millisecond, + ) + + if height != -1 { + t.Errorf("expected negative height") + } + + if len(vs) != 0 { + t.Errorf("expected no validators") + } +} + +type testValidatorReceiver struct{} + +func (tr testValidatorReceiver) GetValidators() (int64, []*types.Validator) { + vs := []*types.Validator{} + + for i := 0; i < 3; i++ { + v, _ := types.RandValidator(true, 10) + + vs = append(vs, v) + } + + time.Sleep(time.Millisecond) + + return 10, vs +} diff --git a/rpc/core/types/wire.go b/rpc/core/types/wire.go index d3a31dc35..d49b977eb 100644 --- a/rpc/core/types/wire.go +++ b/rpc/core/types/wire.go @@ -2,12 +2,12 @@ package core_types import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/tendermint/tendermint/types" ) func RegisterAmino(cdc *amino.Codec) { types.RegisterEventDatas(cdc) types.RegisterEvidences(cdc) - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) } diff --git a/rpc/grpc/compile.sh b/rpc/grpc/compile.sh deleted file mode 100644 index 2c4629c8e..000000000 --- a/rpc/grpc/compile.sh +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/bash - -protoc --go_out=plugins=grpc:. -I $GOPATH/src/ -I . types.proto diff --git a/rpc/grpc/types.pb.go b/rpc/grpc/types.pb.go index be16b711a..8bc9761a4 100644 --- a/rpc/grpc/types.pb.go +++ b/rpc/grpc/types.pb.go @@ -1,34 +1,38 @@ -// Code generated by protoc-gen-go. -// source: types.proto -// DO NOT EDIT! +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: rpc/grpc/types.proto /* -Package core_grpc is a generated protocol buffer package. + Package core_grpc is a generated protocol buffer package. -It is generated from these files: - types.proto + It is generated from these files: + rpc/grpc/types.proto -It has these top-level messages: - RequestPing - RequestBroadcastTx - ResponsePing - ResponseBroadcastTx + It has these top-level messages: + RequestPing + RequestBroadcastTx + ResponsePing + ResponseBroadcastTx */ +//nolint package core_grpc -import proto "github.com/golang/protobuf/proto" +import proto "github.com/gogo/protobuf/proto" +import golang_proto "github.com/golang/protobuf/proto" import fmt "fmt" import math "math" +import _ "github.com/gogo/protobuf/gogoproto" import types "github.com/tendermint/tendermint/abci/types" -import ( - "context" +import bytes "bytes" - grpc "google.golang.org/grpc" -) +import context "golang.org/x/net/context" +import grpc "google.golang.org/grpc" + +import io "io" // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal +var _ = golang_proto.Marshal var _ = fmt.Errorf var _ = math.Inf @@ -36,7 +40,7 @@ var _ = math.Inf // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package type RequestPing struct { } @@ -44,7 +48,7 @@ type RequestPing struct { func (m *RequestPing) Reset() { *m = RequestPing{} } func (m *RequestPing) String() string { return proto.CompactTextString(m) } func (*RequestPing) ProtoMessage() {} -func (*RequestPing) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } +func (*RequestPing) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{0} } type RequestBroadcastTx struct { Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"` @@ -53,7 +57,7 @@ type RequestBroadcastTx struct { func (m *RequestBroadcastTx) Reset() { *m = RequestBroadcastTx{} } func (m *RequestBroadcastTx) String() string { return proto.CompactTextString(m) } func (*RequestBroadcastTx) ProtoMessage() {} -func (*RequestBroadcastTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*RequestBroadcastTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{1} } func (m *RequestBroadcastTx) GetTx() []byte { if m != nil { @@ -68,7 +72,7 @@ type ResponsePing struct { func (m *ResponsePing) Reset() { *m = ResponsePing{} } func (m *ResponsePing) String() string { return proto.CompactTextString(m) } func (*ResponsePing) ProtoMessage() {} -func (*ResponsePing) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*ResponsePing) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{2} } type ResponseBroadcastTx struct { CheckTx *types.ResponseCheckTx `protobuf:"bytes,1,opt,name=check_tx,json=checkTx" json:"check_tx,omitempty"` @@ -78,7 +82,7 @@ type ResponseBroadcastTx struct { func (m *ResponseBroadcastTx) Reset() { *m = ResponseBroadcastTx{} } func (m *ResponseBroadcastTx) String() string { return proto.CompactTextString(m) } func (*ResponseBroadcastTx) ProtoMessage() {} -func (*ResponseBroadcastTx) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*ResponseBroadcastTx) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{3} } func (m *ResponseBroadcastTx) GetCheckTx() *types.ResponseCheckTx { if m != nil { @@ -96,9 +100,106 @@ func (m *ResponseBroadcastTx) GetDeliverTx() *types.ResponseDeliverTx { func init() { proto.RegisterType((*RequestPing)(nil), "core_grpc.RequestPing") + golang_proto.RegisterType((*RequestPing)(nil), "core_grpc.RequestPing") proto.RegisterType((*RequestBroadcastTx)(nil), "core_grpc.RequestBroadcastTx") + golang_proto.RegisterType((*RequestBroadcastTx)(nil), "core_grpc.RequestBroadcastTx") proto.RegisterType((*ResponsePing)(nil), "core_grpc.ResponsePing") + golang_proto.RegisterType((*ResponsePing)(nil), "core_grpc.ResponsePing") proto.RegisterType((*ResponseBroadcastTx)(nil), "core_grpc.ResponseBroadcastTx") + golang_proto.RegisterType((*ResponseBroadcastTx)(nil), "core_grpc.ResponseBroadcastTx") +} +func (this *RequestPing) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*RequestPing) + if !ok { + that2, ok := that.(RequestPing) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (this *RequestBroadcastTx) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*RequestBroadcastTx) + if !ok { + that2, ok := that.(RequestBroadcastTx) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !bytes.Equal(this.Tx, that1.Tx) { + return false + } + return true +} +func (this *ResponsePing) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponsePing) + if !ok { + that2, ok := that.(ResponsePing) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + return true +} +func (this *ResponseBroadcastTx) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*ResponseBroadcastTx) + if !ok { + that2, ok := that.(ResponseBroadcastTx) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if !this.CheckTx.Equal(that1.CheckTx) { + return false + } + if !this.DeliverTx.Equal(that1.DeliverTx) { + return false + } + return true } // Reference imports to suppress errors if they are not otherwise used. @@ -203,28 +304,702 @@ var _BroadcastAPI_serviceDesc = grpc.ServiceDesc{ }, }, Streams: []grpc.StreamDesc{}, - Metadata: "types.proto", -} - -func init() { proto.RegisterFile("types.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 264 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2e, 0xa9, 0x2c, 0x48, - 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4c, 0xce, 0x2f, 0x4a, 0x8d, 0x4f, 0x2f, - 0x2a, 0x48, 0x96, 0xd2, 0x49, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x2f, - 0x49, 0xcd, 0x4b, 0x49, 0x2d, 0xca, 0xcd, 0xcc, 0x2b, 0xd1, 0x4f, 0x4c, 0x4a, 0xce, 0xd4, 0x07, - 0x6b, 0xd1, 0x47, 0xd2, 0xa8, 0xc4, 0xcb, 0xc5, 0x1d, 0x94, 0x5a, 0x58, 0x9a, 0x5a, 0x5c, 0x12, - 0x90, 0x99, 0x97, 0xae, 0xa4, 0xc2, 0x25, 0x04, 0xe5, 0x3a, 0x15, 0xe5, 0x27, 0xa6, 0x24, 0x27, - 0x16, 0x97, 0x84, 0x54, 0x08, 0xf1, 0x71, 0x31, 0x95, 0x54, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0xf0, - 0x04, 0x31, 0x95, 0x54, 0x28, 0xf1, 0x71, 0xf1, 0x04, 0xa5, 0x16, 0x17, 0xe4, 0xe7, 0x15, 0xa7, - 0x82, 0x75, 0x35, 0x32, 0x72, 0x09, 0xc3, 0x04, 0x90, 0xf5, 0x19, 0x72, 0x71, 0x24, 0x67, 0xa4, - 0x26, 0x67, 0xc7, 0x43, 0x75, 0x73, 0x1b, 0x89, 0xe9, 0x41, 0x2c, 0x87, 0xa9, 0x76, 0x06, 0x49, - 0x87, 0x54, 0x04, 0xb1, 0x27, 0x43, 0x18, 0x42, 0xe6, 0x5c, 0x5c, 0x29, 0xa9, 0x39, 0x99, 0x65, - 0xa9, 0x45, 0x20, 0x4d, 0x4c, 0x60, 0x4d, 0x12, 0x68, 0x9a, 0x5c, 0x20, 0x0a, 0x42, 0x2a, 0x82, - 0x38, 0x53, 0x60, 0x4c, 0xa3, 0xa9, 0x8c, 0x5c, 0x3c, 0x70, 0xbb, 0x1d, 0x03, 0x3c, 0x85, 0xcc, - 0xb9, 0x58, 0x40, 0x8e, 0x13, 0x12, 0xd3, 0x83, 0x87, 0x8d, 0x1e, 0x92, 0x57, 0xa5, 0xc4, 0x51, - 0xc4, 0x11, 0xbe, 0x11, 0xf2, 0xe1, 0xe2, 0x46, 0xf6, 0x84, 0x2c, 0xa6, 0x7e, 0x24, 0x69, 0x29, - 0x39, 0x2c, 0xc6, 0x20, 0xc9, 0x27, 0xb1, 0x81, 0xc3, 0xd9, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, - 0x92, 0x29, 0xd9, 0x42, 0xaf, 0x01, 0x00, 0x00, + Metadata: "rpc/grpc/types.proto", +} + +func (m *RequestPing) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestPing) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func (m *RequestBroadcastTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RequestBroadcastTx) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if len(m.Tx) > 0 { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Tx))) + i += copy(dAtA[i:], m.Tx) + } + return i, nil +} + +func (m *ResponsePing) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponsePing) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + return i, nil +} + +func (m *ResponseBroadcastTx) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalTo(dAtA) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ResponseBroadcastTx) MarshalTo(dAtA []byte) (int, error) { + var i int + _ = i + var l int + _ = l + if m.CheckTx != nil { + dAtA[i] = 0xa + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.CheckTx.Size())) + n1, err := m.CheckTx.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n1 + } + if m.DeliverTx != nil { + dAtA[i] = 0x12 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.DeliverTx.Size())) + n2, err := m.DeliverTx.MarshalTo(dAtA[i:]) + if err != nil { + return 0, err + } + i += n2 + } + return i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return offset + 1 +} +func NewPopulatedRequestPing(r randyTypes, easy bool) *RequestPing { + this := &RequestPing{} + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedRequestBroadcastTx(r randyTypes, easy bool) *RequestBroadcastTx { + this := &RequestBroadcastTx{} + v1 := r.Intn(100) + this.Tx = make([]byte, v1) + for i := 0; i < v1; i++ { + this.Tx[i] = byte(r.Intn(256)) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponsePing(r randyTypes, easy bool) *ResponsePing { + this := &ResponsePing{} + if !easy && r.Intn(10) != 0 { + } + return this +} + +func NewPopulatedResponseBroadcastTx(r randyTypes, easy bool) *ResponseBroadcastTx { + this := &ResponseBroadcastTx{} + if r.Intn(10) != 0 { + this.CheckTx = types.NewPopulatedResponseCheckTx(r, easy) + } + if r.Intn(10) != 0 { + this.DeliverTx = types.NewPopulatedResponseDeliverTx(r, easy) + } + if !easy && r.Intn(10) != 0 { + } + return this +} + +type randyTypes interface { + Float32() float32 + Float64() float64 + Int63() int64 + Int31() int32 + Uint32() uint32 + Intn(n int) int +} + +func randUTF8RuneTypes(r randyTypes) rune { + ru := r.Intn(62) + if ru < 10 { + return rune(ru + 48) + } else if ru < 36 { + return rune(ru + 55) + } + return rune(ru + 61) +} +func randStringTypes(r randyTypes) string { + v2 := r.Intn(100) + tmps := make([]rune, v2) + for i := 0; i < v2; i++ { + tmps[i] = randUTF8RuneTypes(r) + } + return string(tmps) +} +func randUnrecognizedTypes(r randyTypes, maxFieldNumber int) (dAtA []byte) { + l := r.Intn(5) + for i := 0; i < l; i++ { + wire := r.Intn(4) + if wire == 3 { + wire = 5 + } + fieldNumber := maxFieldNumber + r.Intn(100) + dAtA = randFieldTypes(dAtA, r, fieldNumber, wire) + } + return dAtA +} +func randFieldTypes(dAtA []byte, r randyTypes, fieldNumber int, wire int) []byte { + key := uint32(fieldNumber)<<3 | uint32(wire) + switch wire { + case 0: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + v3 := r.Int63() + if r.Intn(2) == 0 { + v3 *= -1 + } + dAtA = encodeVarintPopulateTypes(dAtA, uint64(v3)) + case 1: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) + case 2: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + ll := r.Intn(100) + dAtA = encodeVarintPopulateTypes(dAtA, uint64(ll)) + for j := 0; j < ll; j++ { + dAtA = append(dAtA, byte(r.Intn(256))) + } + default: + dAtA = encodeVarintPopulateTypes(dAtA, uint64(key)) + dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256))) + } + return dAtA +} +func encodeVarintPopulateTypes(dAtA []byte, v uint64) []byte { + for v >= 1<<7 { + dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80)) + v >>= 7 + } + dAtA = append(dAtA, uint8(v)) + return dAtA +} +func (m *RequestPing) Size() (n int) { + var l int + _ = l + return n +} + +func (m *RequestBroadcastTx) Size() (n int) { + var l int + _ = l + l = len(m.Tx) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *ResponsePing) Size() (n int) { + var l int + _ = l + return n +} + +func (m *ResponseBroadcastTx) Size() (n int) { + var l int + _ = l + if m.CheckTx != nil { + l = m.CheckTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + if m.DeliverTx != nil { + l = m.DeliverTx.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func sovTypes(x uint64) (n int) { + for { + n++ + x >>= 7 + if x == 0 { + break + } + } + return n +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *RequestPing) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestPing: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestPing: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RequestBroadcastTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RequestBroadcastTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RequestBroadcastTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Tx", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Tx = append(m.Tx[:0], dAtA[iNdEx:postIndex]...) + if m.Tx == nil { + m.Tx = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponsePing) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponsePing: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponsePing: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ResponseBroadcastTx) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ResponseBroadcastTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ResponseBroadcastTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field CheckTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.CheckTx == nil { + m.CheckTx = &types.ResponseCheckTx{} + } + if err := m.CheckTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeliverTx", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DeliverTx == nil { + m.DeliverTx = &types.ResponseDeliverTx{} + } + if err := m.DeliverTx.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + return iNdEx, nil + case 1: + iNdEx += 8 + return iNdEx, nil + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + iNdEx += length + if length < 0 { + return 0, ErrInvalidLengthTypes + } + return iNdEx, nil + case 3: + for { + var innerWire uint64 + var start int = iNdEx + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + innerWire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + innerWireType := int(innerWire & 0x7) + if innerWireType == 4 { + break + } + next, err := skipTypes(dAtA[start:]) + if err != nil { + return 0, err + } + iNdEx = start + next + } + return iNdEx, nil + case 4: + return iNdEx, nil + case 5: + iNdEx += 4 + return iNdEx, nil + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + } + panic("unreachable") +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") +) + +func init() { proto.RegisterFile("rpc/grpc/types.proto", fileDescriptorTypes) } +func init() { golang_proto.RegisterFile("rpc/grpc/types.proto", fileDescriptorTypes) } + +var fileDescriptorTypes = []byte{ + // 321 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x29, 0x2a, 0x48, 0xd6, + 0x4f, 0x07, 0x11, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0x9c, + 0xc9, 0xf9, 0x45, 0xa9, 0xf1, 0x20, 0x61, 0x29, 0xdd, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, + 0xe4, 0xfc, 0x5c, 0xfd, 0xf4, 0xfc, 0xf4, 0x7c, 0x7d, 0xb0, 0x8a, 0xa4, 0xd2, 0x34, 0x30, 0x0f, + 0xcc, 0x01, 0xb3, 0x20, 0x3a, 0xa5, 0xcc, 0x91, 0x94, 0x97, 0xa4, 0xe6, 0xa5, 0xa4, 0x16, 0xe5, + 0x66, 0xe6, 0x95, 0x20, 0x33, 0x13, 0x93, 0x92, 0x33, 0x21, 0x96, 0x21, 0x5b, 0xa9, 0xc4, 0xcb, + 0xc5, 0x1d, 0x94, 0x5a, 0x58, 0x9a, 0x5a, 0x5c, 0x12, 0x90, 0x99, 0x97, 0xae, 0xa4, 0xc2, 0x25, + 0x04, 0xe5, 0x3a, 0x15, 0xe5, 0x27, 0xa6, 0x24, 0x27, 0x16, 0x97, 0x84, 0x54, 0x08, 0xf1, 0x71, + 0x31, 0x95, 0x54, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x31, 0x95, 0x54, 0x28, 0xf1, 0x71, + 0xf1, 0x04, 0xa5, 0x16, 0x17, 0xe4, 0xe7, 0x15, 0xa7, 0x82, 0x75, 0x35, 0x32, 0x72, 0x09, 0xc3, + 0x04, 0x90, 0xf5, 0x19, 0x72, 0x71, 0x24, 0x67, 0xa4, 0x26, 0x67, 0xc7, 0x43, 0x75, 0x73, 0x1b, + 0x89, 0xe9, 0x41, 0x2c, 0x87, 0xa9, 0x76, 0x06, 0x49, 0x87, 0x54, 0x04, 0xb1, 0x27, 0x43, 0x18, + 0x42, 0xe6, 0x5c, 0x5c, 0x29, 0xa9, 0x39, 0x99, 0x65, 0xa9, 0x45, 0x20, 0x4d, 0x4c, 0x60, 0x4d, + 0x12, 0x68, 0x9a, 0x5c, 0x20, 0x0a, 0x42, 0x2a, 0x82, 0x38, 0x53, 0x60, 0x4c, 0xa3, 0xa9, 0x8c, + 0x5c, 0x3c, 0x70, 0xbb, 0x1d, 0x03, 0x3c, 0x85, 0xcc, 0xb9, 0x58, 0x40, 0x8e, 0x13, 0x12, 0xd3, + 0x83, 0x87, 0xaa, 0x1e, 0x92, 0x57, 0xa5, 0xc4, 0x51, 0xc4, 0x11, 0xbe, 0x11, 0xf2, 0xe1, 0xe2, + 0x46, 0xf6, 0x84, 0x2c, 0xa6, 0x7e, 0x24, 0x69, 0x29, 0x39, 0x2c, 0xc6, 0x20, 0xc9, 0x3b, 0xc9, + 0xfc, 0x78, 0x28, 0xc7, 0xb8, 0xe2, 0x91, 0x1c, 0xe3, 0x8e, 0x47, 0x72, 0x8c, 0x27, 0x1e, 0xc9, + 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x81, 0xc7, 0x72, 0x8c, 0x49, 0x6c, + 0xe0, 0x58, 0x30, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xd5, 0xa8, 0xe4, 0xd9, 0x10, 0x02, 0x00, + 0x00, } diff --git a/rpc/grpc/types.proto b/rpc/grpc/types.proto index d7980d5e0..beb6442a2 100644 --- a/rpc/grpc/types.proto +++ b/rpc/grpc/types.proto @@ -1,8 +1,17 @@ syntax = "proto3"; package core_grpc; +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; import "github.com/tendermint/tendermint/abci/types/types.proto"; +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; +option (gogoproto.sizer_all) = true; +option (gogoproto.goproto_registration) = true; +// Generate tests +option (gogoproto.populate_all) = true; +option (gogoproto.equal_all) = true; +option (gogoproto.testgen_all) = true; //---------------------------------------- // Message types diff --git a/rpc/grpc/typespb_test.go b/rpc/grpc/typespb_test.go new file mode 100644 index 000000000..3d28002b1 --- /dev/null +++ b/rpc/grpc/typespb_test.go @@ -0,0 +1,531 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: rpc/grpc/types.proto + +/* +Package core_grpc is a generated protocol buffer package. + +It is generated from these files: + rpc/grpc/types.proto + +It has these top-level messages: + RequestPing + RequestBroadcastTx + ResponsePing + ResponseBroadcastTx +*/ +package core_grpc + +import testing "testing" +import rand "math/rand" +import time "time" +import proto "github.com/gogo/protobuf/proto" +import jsonpb "github.com/gogo/protobuf/jsonpb" +import golang_proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" +import _ "github.com/gogo/protobuf/gogoproto" +import _ "github.com/tendermint/tendermint/abci/types" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = golang_proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +func TestRequestPingProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestPing(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestPing{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestPingMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestPing(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestPing{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestBroadcastTxProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBroadcastTx(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestBroadcastTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestRequestBroadcastTxMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBroadcastTx(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestBroadcastTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponsePingProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponsePing(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponsePing{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponsePingMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponsePing(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponsePing{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseBroadcastTxProto(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBroadcastTx(popr, false) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseBroadcastTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + littlefuzz := make([]byte, len(dAtA)) + copy(littlefuzz, dAtA) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } + if len(littlefuzz) > 0 { + fuzzamount := 100 + for i := 0; i < fuzzamount; i++ { + littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256)) + littlefuzz = append(littlefuzz, byte(popr.Intn(256))) + } + // shouldn't panic + _ = proto.Unmarshal(littlefuzz, msg) + } +} + +func TestResponseBroadcastTxMarshalTo(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBroadcastTx(popr, false) + size := p.Size() + dAtA := make([]byte, size) + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + _, err := p.MarshalTo(dAtA) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseBroadcastTx{} + if err := proto.Unmarshal(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + for i := range dAtA { + dAtA[i] = byte(popr.Intn(256)) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestPingJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestPing(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestPing{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestBroadcastTxJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBroadcastTx(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &RequestBroadcastTx{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponsePingJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponsePing(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponsePing{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestResponseBroadcastTxJSON(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBroadcastTx(popr, true) + marshaler := jsonpb.Marshaler{} + jsondata, err := marshaler.MarshalToString(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + msg := &ResponseBroadcastTx{} + err = jsonpb.UnmarshalString(jsondata, msg) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p) + } +} +func TestRequestPingProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestPing(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestPing{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestPingProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestPing(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestPing{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestBroadcastTxProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBroadcastTx(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &RequestBroadcastTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestBroadcastTxProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBroadcastTx(popr, true) + dAtA := proto.CompactTextString(p) + msg := &RequestBroadcastTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponsePingProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponsePing(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponsePing{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponsePingProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponsePing(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponsePing{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseBroadcastTxProtoText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBroadcastTx(popr, true) + dAtA := proto.MarshalTextString(p) + msg := &ResponseBroadcastTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestResponseBroadcastTxProtoCompactText(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBroadcastTx(popr, true) + dAtA := proto.CompactTextString(p) + msg := &ResponseBroadcastTx{} + if err := proto.UnmarshalText(dAtA, msg); err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + if !p.Equal(msg) { + t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p) + } +} + +func TestRequestPingSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestPing(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestRequestBroadcastTxSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedRequestBroadcastTx(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponsePingSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponsePing(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +func TestResponseBroadcastTxSize(t *testing.T) { + seed := time.Now().UnixNano() + popr := rand.New(rand.NewSource(seed)) + p := NewPopulatedResponseBroadcastTx(popr, true) + size2 := proto.Size(p) + dAtA, err := proto.Marshal(p) + if err != nil { + t.Fatalf("seed = %d, err = %v", seed, err) + } + size := p.Size() + if len(dAtA) != size { + t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA)) + } + if size2 != size { + t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2) + } + size3 := proto.Size(p) + if size3 != size { + t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3) + } +} + +//These tests are generated by github.com/gogo/protobuf/plugin/testgen diff --git a/rpc/lib/doc.go b/rpc/lib/doc.go index 2bc438593..b96b9123c 100644 --- a/rpc/lib/doc.go +++ b/rpc/lib/doc.go @@ -98,6 +98,6 @@ Each route is available as a GET request, as a JSONRPCv2 POST request, and via J # Examples * [Tendermint](https://github.com/tendermint/tendermint/blob/master/rpc/core/routes.go) -* [tm-monitor](https://github.com/tendermint/tools/blob/master/tm-monitor/rpc.go) +* [tm-monitor](https://github.com/tendermint/tendermint/blob/master/tools/tm-monitor/rpc.go) */ package rpc diff --git a/rpc/lib/rpc_test.go b/rpc/lib/rpc_test.go index 31839dcab..3d76db323 100644 --- a/rpc/lib/rpc_test.go +++ b/rpc/lib/rpc_test.go @@ -6,7 +6,6 @@ import ( crand "crypto/rand" "encoding/json" "fmt" - "math/rand" "net/http" "os" "os/exec" @@ -206,7 +205,7 @@ func testWithHTTPClient(t *testing.T, cl client.HTTPClient) { require.Nil(t, err) assert.Equal(t, got3, val3) - val4 := rand.Intn(10000) + val4 := cmn.RandIntn(10000) got4, err := echoIntViaHTTP(cl, val4) require.Nil(t, err) assert.Equal(t, got4, val4) @@ -370,7 +369,7 @@ func TestWSClientPingPong(t *testing.T) { } func randBytes(t *testing.T) []byte { - n := rand.Intn(10) + 2 + n := cmn.RandIntn(10) + 2 buf := make([]byte, n) _, err := crand.Read(buf) require.Nil(t, err) diff --git a/rpc/lib/server/handlers.go b/rpc/lib/server/handlers.go index 1bfe52536..3ec5f81e3 100644 --- a/rpc/lib/server/handlers.go +++ b/rpc/lib/server/handlers.go @@ -18,9 +18,9 @@ import ( "github.com/pkg/errors" amino "github.com/tendermint/go-amino" - types "github.com/tendermint/tendermint/rpc/lib/types" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" + types "github.com/tendermint/tendermint/rpc/lib/types" ) // RegisterRPCFuncs adds a route for each function in the funcMap, as well as general jsonrpc and websocket handlers for all functions. @@ -294,7 +294,7 @@ func httpParamsToArgs(rpcFunc *RPCFunc, cdc *amino.Codec, r *http.Request) ([]re continue } - v, err, ok := nonJSONToArg(cdc, argType, arg) + v, err, ok := nonJSONStringToArg(cdc, argType, arg) if err != nil { return nil, err } @@ -303,7 +303,7 @@ func httpParamsToArgs(rpcFunc *RPCFunc, cdc *amino.Codec, r *http.Request) ([]re continue } - values[i], err = _jsonStringToArg(cdc, argType, arg) + values[i], err = jsonStringToArg(cdc, argType, arg) if err != nil { return nil, err } @@ -312,26 +312,64 @@ func httpParamsToArgs(rpcFunc *RPCFunc, cdc *amino.Codec, r *http.Request) ([]re return values, nil } -func _jsonStringToArg(cdc *amino.Codec, ty reflect.Type, arg string) (reflect.Value, error) { - v := reflect.New(ty) - err := cdc.UnmarshalJSON([]byte(arg), v.Interface()) +func jsonStringToArg(cdc *amino.Codec, rt reflect.Type, arg string) (reflect.Value, error) { + rv := reflect.New(rt) + err := cdc.UnmarshalJSON([]byte(arg), rv.Interface()) if err != nil { - return v, err + return rv, err + } + rv = rv.Elem() + return rv, nil +} + +func nonJSONStringToArg(cdc *amino.Codec, rt reflect.Type, arg string) (reflect.Value, error, bool) { + if rt.Kind() == reflect.Ptr { + rv_, err, ok := nonJSONStringToArg(cdc, rt.Elem(), arg) + if err != nil { + return reflect.Value{}, err, false + } else if ok { + rv := reflect.New(rt.Elem()) + rv.Elem().Set(rv_) + return rv, nil, true + } else { + return reflect.Value{}, nil, false + } + } else { + return _nonJSONStringToArg(cdc, rt, arg) } - v = v.Elem() - return v, nil } -func nonJSONToArg(cdc *amino.Codec, ty reflect.Type, arg string) (reflect.Value, error, bool) { +// NOTE: rt.Kind() isn't a pointer. +func _nonJSONStringToArg(cdc *amino.Codec, rt reflect.Type, arg string) (reflect.Value, error, bool) { + isIntString := RE_INT.Match([]byte(arg)) isQuotedString := strings.HasPrefix(arg, `"`) && strings.HasSuffix(arg, `"`) isHexString := strings.HasPrefix(strings.ToLower(arg), "0x") - expectingString := ty.Kind() == reflect.String - expectingByteSlice := ty.Kind() == reflect.Slice && ty.Elem().Kind() == reflect.Uint8 + + var expectingString, expectingByteSlice, expectingInt bool + switch rt.Kind() { + case reflect.Int, reflect.Uint, reflect.Int8, reflect.Uint8, reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64: + expectingInt = true + case reflect.String: + expectingString = true + case reflect.Slice: + expectingByteSlice = rt.Elem().Kind() == reflect.Uint8 + } + + if isIntString && expectingInt { + qarg := `"` + arg + `"` + // jsonStringToArg + rv, err := jsonStringToArg(cdc, rt, qarg) + if err != nil { + return rv, err, false + } else { + return rv, nil, true + } + } if isHexString { if !expectingString && !expectingByteSlice { err := errors.Errorf("Got a hex string arg, but expected '%s'", - ty.Kind().String()) + rt.Kind().String()) return reflect.ValueOf(nil), err, false } @@ -340,7 +378,7 @@ func nonJSONToArg(cdc *amino.Codec, ty reflect.Type, arg string) (reflect.Value, if err != nil { return reflect.ValueOf(nil), err, false } - if ty.Kind() == reflect.String { + if rt.Kind() == reflect.String { return reflect.ValueOf(string(value)), nil, true } return reflect.ValueOf([]byte(value)), nil, true diff --git a/rpc/lib/server/http_params.go b/rpc/lib/server/http_params.go index 565060678..3c948c0ba 100644 --- a/rpc/lib/server/http_params.go +++ b/rpc/lib/server/http_params.go @@ -15,6 +15,7 @@ var ( dotAtom = atom + `(?:\.` + atom + `)*` domain = `[A-Z0-9.-]+\.[A-Z]{2,4}` + RE_INT = regexp.MustCompile(`^-?[0-9]+$`) RE_HEX = regexp.MustCompile(`^(?i)[a-f0-9]+$`) RE_EMAIL = regexp.MustCompile(`^(?i)(` + dotAtom + `)@(` + dotAtom + `)$`) RE_ADDRESS = regexp.MustCompile(`^(?i)[a-z0-9]{25,34}$`) diff --git a/rpc/lib/server/parse_test.go b/rpc/lib/server/parse_test.go index f71316906..7b0aacdbe 100644 --- a/rpc/lib/server/parse_test.go +++ b/rpc/lib/server/parse_test.go @@ -2,6 +2,8 @@ package rpcserver import ( "encoding/json" + "fmt" + "net/http" "strconv" "testing" @@ -134,7 +136,7 @@ func TestParseJSONArray(t *testing.T) { } } -func TestParseRPC(t *testing.T) { +func TestParseJSONRPC(t *testing.T) { assert := assert.New(t) demo := func(height int, name string) {} @@ -172,5 +174,48 @@ func TestParseRPC(t *testing.T) { } } +} + +func TestParseURI(t *testing.T) { + + demo := func(height int, name string) {} + call := NewRPCFunc(demo, "height,name") + cdc := amino.NewCodec() + + cases := []struct { + raw []string + height int64 + name string + fail bool + }{ + // can parse numbers unquoted and strings quoted + {[]string{"7", `"flew"`}, 7, "flew", false}, + {[]string{"22", `"john"`}, 22, "john", false}, + {[]string{"-10", `"bob"`}, -10, "bob", false}, + // can parse numbers quoted, too + {[]string{`"7"`, `"flew"`}, 7, "flew", false}, + {[]string{`"-10"`, `"bob"`}, -10, "bob", false}, + // cant parse strings uquoted + {[]string{`"-10"`, `bob`}, -10, "bob", true}, + } + for idx, tc := range cases { + i := strconv.Itoa(idx) + // data := []byte(tc.raw) + url := fmt.Sprintf( + "test.com/method?height=%v&name=%v", + tc.raw[0], tc.raw[1]) + req, err := http.NewRequest("GET", url, nil) + assert.NoError(t, err) + vals, err := httpParamsToArgs(call, cdc, req) + if tc.fail { + assert.NotNil(t, err, i) + } else { + assert.Nil(t, err, "%s: %+v", i, err) + if assert.Equal(t, 2, len(vals), i) { + assert.Equal(t, tc.height, vals[0].Int(), i) + assert.Equal(t, tc.name, vals[1].String(), i) + } + } + } } diff --git a/scripts/install/install_tendermint_osx.sh b/scripts/install/install_tendermint_osx.sh new file mode 100644 index 000000000..b4107ab01 --- /dev/null +++ b/scripts/install/install_tendermint_osx.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# XXX: this script is intended to be run from +# an MacOS machine + +# as written, this script will install +# tendermint core from master branch +REPO=github.com/tendermint/tendermint + +# change this to a specific release or branch +BRANCH=master + +if ! [ -x "$(command -v brew)" ]; then + echo 'Error: brew is not installed, to install brew' >&2 + echo 'follow the instructions here: https://docs.brew.sh/Installation' >&2 + exit 1 +fi + +if ! [ -x "$(command -v go)" ]; then + echo 'Error: go is not installed, to install go follow' >&2 + echo 'the instructions here: https://golang.org/doc/install#tarball' >&2 + echo 'ALSO MAKE SURE TO SETUP YOUR $GOPATH and $GOBIN in your ~/.profile: https://github.com/golang/go/wiki/SettingGOPATH' >&2 + exit 1 +fi + +if ! [ -x "$(command -v make)" ]; then + echo 'Make not installed, installing using brew...' + brew install make +fi + +# get the code and move into repo +go get $REPO +cd $GOPATH/src/$REPO + +# build & install +git checkout $BRANCH +# XXX: uncomment if branch isn't master +# git fetch origin $BRANCH +make get_tools +make get_vendor_deps +make install diff --git a/scripts/slate.sh b/scripts/slate.sh deleted file mode 100644 index e18babea7..000000000 --- a/scripts/slate.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -if [ "$CIRCLE_BRANCH" == "" ]; then - echo "this script is meant to be run on CircleCI, exiting" - echo 1 -fi - -# check for changes in the `rpc/core` directory -did_rpc_change=$(git diff --name-status $CIRCLE_BRANCH origin/master | grep rpc/core) - -if [ "$did_rpc_change" == "" ]; then - echo "no changes detected in rpc/core, exiting" - exit 0 -else - echo "changes detected in rpc/core, continuing" -fi - -# only run this script on changes to rpc/core committed to develop -if [ "$CIRCLE_BRANCH" != "master" ]; then - echo "the branch being built isn't master, exiting" - exit 0 -else - echo "on master, building the RPC docs" -fi - -# godoc2md used to convert the go documentation from -# `rpc/core` into a markdown file consumed by Slate -go get github.com/davecheney/godoc2md - -# slate works via forks, and we'll be committing to -# master branch, which will trigger our fork to run -# the `./deploy.sh` and publish via the `gh-pages` branch -slate_repo=github.com/tendermint/slate -slate_path="$GOPATH"/src/"$slate_repo" - -if [ ! -d "$slate_path" ]; then - git clone https://"$slate_repo".git $slate_path -fi - -# the main file we need to update if rpc/core changed -destination="$slate_path"/source/index.html.md - -# we remove it then re-create it with the latest changes -rm $destination - -header="--- -title: RPC Reference - -language_tabs: - - shell - - go - -toc_footers: - - Tendermint - - Documentation Powered by Slate - -search: true ----" - -# write header to the main slate file -echo "$header" > "$destination" - -# generate a markdown from the godoc comments, using a template -rpc_docs=$(godoc2md -template rpc/core/doc_template.txt github.com/tendermint/tendermint/rpc/core | grep -v -e "pipe.go" -e "routes.go" -e "dev.go" | sed 's$/src/target$https://github.com/tendermint/tendermint/tree/master/rpc/core$') - -# append core RPC docs -echo "$rpc_docs" >> "$destination" - -# commit the changes -cd $slate_path - -git config --global user.email "github@tendermint.com" -git config --global user.name "tenderbot" - -git commit -a -m "Update tendermint RPC docs via CircleCI" -git push -q https://${GITHUB_ACCESS_TOKEN}@github.com/tendermint/slate.git master diff --git a/scripts/wire2amino.go b/scripts/wire2amino.go index 867c5735a..26069b505 100644 --- a/scripts/wire2amino.go +++ b/scripts/wire2amino.go @@ -9,7 +9,9 @@ import ( "time" "github.com/tendermint/go-amino" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" + cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/p2p" @@ -29,9 +31,8 @@ type Genesis struct { ConsensusParams *types.ConsensusParams `json:"consensus_params,omitempty"` Validators []GenesisValidator `json:"validators"` AppHash cmn.HexBytes `json:"app_hash"` - AppStateJSON json.RawMessage `json:"app_state,omitempty"` + AppState json.RawMessage `json:"app_state,omitempty"` AppOptions json.RawMessage `json:"app_options,omitempty"` // DEPRECATED - } type NodeKey struct { @@ -59,7 +60,7 @@ func convertNodeKey(cdc *amino.Codec, jsonBytes []byte) ([]byte, error) { return nil, err } - var privKey crypto.PrivKeyEd25519 + var privKey ed25519.PrivKeyEd25519 copy(privKey[:], nodeKey.PrivKey.Data) nodeKeyNew := p2p.NodeKey{privKey} @@ -78,10 +79,10 @@ func convertPrivVal(cdc *amino.Codec, jsonBytes []byte) ([]byte, error) { return nil, err } - var privKey crypto.PrivKeyEd25519 + var privKey ed25519.PrivKeyEd25519 copy(privKey[:], privVal.PrivKey.Data) - var pubKey crypto.PubKeyEd25519 + var pubKey ed25519.PubKeyEd25519 copy(pubKey[:], privVal.PubKey.Data) privValNew := privval.FilePV{ @@ -112,16 +113,16 @@ func convertGenesis(cdc *amino.Codec, jsonBytes []byte) ([]byte, error) { ChainID: genesis.ChainID, ConsensusParams: genesis.ConsensusParams, // Validators - AppHash: genesis.AppHash, - AppStateJSON: genesis.AppStateJSON, + AppHash: genesis.AppHash, + AppState: genesis.AppState, } if genesis.AppOptions != nil { - genesisNew.AppStateJSON = genesis.AppOptions + genesisNew.AppState = genesis.AppOptions } for _, v := range genesis.Validators { - var pubKey crypto.PubKeyEd25519 + var pubKey ed25519.PubKeyEd25519 copy(pubKey[:], v.PubKey.Data) genesisNew.Validators = append( genesisNew.Validators, @@ -143,7 +144,7 @@ func convertGenesis(cdc *amino.Codec, jsonBytes []byte) ([]byte, error) { func main() { cdc := amino.NewCodec() - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) args := os.Args[1:] if len(args) != 1 { diff --git a/state/execution.go b/state/execution.go index 6e1898e20..abecb138e 100644 --- a/state/execution.go +++ b/state/execution.go @@ -5,10 +5,10 @@ import ( fail "github.com/ebuchman/fail-test" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/proxy" - "github.com/tendermint/tendermint/types" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/proxy" + "github.com/tendermint/tendermint/types" ) //----------------------------------------------------------------------------- @@ -86,7 +86,7 @@ func (blockExec *BlockExecutor) ApplyBlock(state State, blockID types.BlockID, b fail.Fail() // XXX // Update the state with the block and responses. - state, err = updateState(state, blockID, block.Header, abciResponses) + state, err = updateState(state, blockID, &block.Header, abciResponses) if err != nil { return state, fmt.Errorf("Commit failed for application: %v", err) } @@ -189,7 +189,7 @@ func execBlockOnProxyApp(logger log.Logger, proxyAppConn proxy.AppConnConsensus, // Begin block. _, err := proxyAppConn.BeginBlockSync(abci.RequestBeginBlock{ Hash: block.Hash(), - Header: types.TM2PB.Header(block.Header), + Header: types.TM2PB.Header(&block.Header), Validators: signVals, ByzantineValidators: byzVals, }) @@ -278,20 +278,24 @@ func updateValidators(currentSet *types.ValidatorSet, abciUpdates []abci.Validat // these are tendermint types now for _, valUpdate := range updates { + if valUpdate.VotingPower < 0 { + return fmt.Errorf("Voting power can't be negative %v", valUpdate) + } + address := valUpdate.Address _, val := currentSet.GetByAddress(address) - if val == nil { - // add val - added := currentSet.Add(valUpdate) - if !added { - return fmt.Errorf("Failed to add new validator %v", valUpdate) - } - } else if valUpdate.VotingPower == 0 { + if valUpdate.VotingPower == 0 { // remove val _, removed := currentSet.Remove(address) if !removed { return fmt.Errorf("Failed to remove validator %X", address) } + } else if val == nil { + // add val + added := currentSet.Add(valUpdate) + if !added { + return fmt.Errorf("Failed to add new validator %v", valUpdate) + } } else { // update val updated := currentSet.Update(valUpdate) diff --git a/state/execution_test.go b/state/execution_test.go index 9c0635dcc..81510fb9f 100644 --- a/state/execution_test.go +++ b/state/execution_test.go @@ -10,7 +10,7 @@ import ( "github.com/tendermint/tendermint/abci/example/kvstore" abci "github.com/tendermint/tendermint/abci/types" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" "github.com/tendermint/tendermint/libs/log" @@ -149,6 +149,89 @@ func TestBeginBlockByzantineValidators(t *testing.T) { } } +func TestUpdateValidators(t *testing.T) { + pubkey1 := ed25519.GenPrivKey().PubKey() + val1 := types.NewValidator(pubkey1, 10) + pubkey2 := ed25519.GenPrivKey().PubKey() + val2 := types.NewValidator(pubkey2, 20) + + testCases := []struct { + name string + + currentSet *types.ValidatorSet + abciUpdates []abci.Validator + + resultingSet *types.ValidatorSet + shouldErr bool + }{ + { + "adding a validator is OK", + + types.NewValidatorSet([]*types.Validator{val1}), + []abci.Validator{{[]byte{}, types.TM2PB.PubKey(pubkey2), 20}}, + + types.NewValidatorSet([]*types.Validator{val1, val2}), + false, + }, + { + "updating a validator is OK", + + types.NewValidatorSet([]*types.Validator{val1}), + []abci.Validator{{[]byte{}, types.TM2PB.PubKey(pubkey1), 20}}, + + types.NewValidatorSet([]*types.Validator{types.NewValidator(pubkey1, 20)}), + false, + }, + { + "removing a validator is OK", + + types.NewValidatorSet([]*types.Validator{val1, val2}), + []abci.Validator{{[]byte{}, types.TM2PB.PubKey(pubkey2), 0}}, + + types.NewValidatorSet([]*types.Validator{val1}), + false, + }, + + { + "removing a non-existing validator results in error", + + types.NewValidatorSet([]*types.Validator{val1}), + []abci.Validator{{[]byte{}, types.TM2PB.PubKey(pubkey2), 0}}, + + types.NewValidatorSet([]*types.Validator{val1}), + true, + }, + + { + "adding a validator with negative power results in error", + + types.NewValidatorSet([]*types.Validator{val1}), + []abci.Validator{{[]byte{}, types.TM2PB.PubKey(pubkey2), -100}}, + + types.NewValidatorSet([]*types.Validator{val1}), + true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := updateValidators(tc.currentSet, tc.abciUpdates) + if tc.shouldErr { + assert.Error(t, err) + } else { + require.Equal(t, tc.resultingSet.Size(), tc.currentSet.Size()) + + assert.Equal(t, tc.resultingSet.TotalVotingPower(), tc.currentSet.TotalVotingPower()) + + assert.Equal(t, tc.resultingSet.Validators[0].Address, tc.currentSet.Validators[0].Address) + if tc.resultingSet.Size() > 1 { + assert.Equal(t, tc.resultingSet.Validators[1].Address, tc.currentSet.Validators[1].Address) + } + } + }) + } +} + //---------------------------------------------------------------------------- // make some bogus txs @@ -163,7 +246,7 @@ func state(nVals, height int) (State, dbm.DB) { vals := make([]types.GenesisValidator, nVals) for i := 0; i < nVals; i++ { secret := []byte(fmt.Sprintf("test%d", i)) - pk := crypto.GenPrivKeyEd25519FromSecret(secret) + pk := ed25519.GenPrivKeyFromSecret(secret) vals[i] = types.GenesisValidator{ pk.PubKey(), 1000, fmt.Sprintf("test%d", i), } diff --git a/state/services.go b/state/services.go index bf0b1a6f4..c51fa9752 100644 --- a/state/services.go +++ b/state/services.go @@ -27,7 +27,7 @@ type Mempool interface { Flush() FlushAppConn() error - TxsAvailable() <-chan int64 + TxsAvailable() <-chan struct{} EnableTxsAvailable() } @@ -43,7 +43,7 @@ func (m MockMempool) Reap(n int) types.Txs { retur func (m MockMempool) Update(height int64, txs types.Txs) error { return nil } func (m MockMempool) Flush() {} func (m MockMempool) FlushAppConn() error { return nil } -func (m MockMempool) TxsAvailable() <-chan int64 { return make(chan int64) } +func (m MockMempool) TxsAvailable() <-chan struct{} { return make(chan struct{}) } func (m MockMempool) EnableTxsAvailable() {} //------------------------------------------------------ diff --git a/state/state_test.go b/state/state_test.go index 6c23a7e4b..ad28b0a9d 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" @@ -78,7 +79,7 @@ func TestABCIResponsesSaveLoad1(t *testing.T) { abciResponses.DeliverTx[0] = &abci.ResponseDeliverTx{Data: []byte("foo"), Tags: nil} abciResponses.DeliverTx[1] = &abci.ResponseDeliverTx{Data: []byte("bar"), Log: "ok", Tags: nil} abciResponses.EndBlock = &abci.ResponseEndBlock{ValidatorUpdates: []abci.Validator{ - types.TM2PB.ValidatorFromPubKeyAndPower(crypto.GenPrivKeyEd25519().PubKey(), 10), + types.TM2PB.ValidatorFromPubKeyAndPower(ed25519.GenPrivKey().PubKey(), 10), }} saveABCIResponses(stateDB, block.Height, abciResponses) @@ -213,8 +214,8 @@ func TestOneValidatorChangesSaveLoad(t *testing.T) { changeIndex++ power++ } - header, blockID, responses := makeHeaderPartsResponsesValPowerChange(state, power) - state, err = updateState(state, blockID, header, responses) + header, blockID, responses := makeHeaderPartsResponsesValPowerChange(state, i, power) + state, err = updateState(state, blockID, &header, responses) assert.Nil(t, err) nextHeight := state.LastBlockHeight + 1 saveValidatorsInfo(stateDB, nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators) @@ -258,14 +259,15 @@ func TestManyValidatorChangesSaveLoad(t *testing.T) { _, valOld := state.Validators.GetByIndex(0) var pubkeyOld = valOld.PubKey - var pubkey = crypto.GenPrivKeyEd25519().PubKey() + pubkey := ed25519.GenPrivKey().PubKey() + const height = 1 // Swap the first validator with a new one (validator set size stays the same). - header, blockID, responses := makeHeaderPartsResponsesValPubKeyChange(state, pubkey) + header, blockID, responses := makeHeaderPartsResponsesValPubKeyChange(state, height, pubkey) // Save state etc. var err error - state, err = updateState(state, blockID, header, responses) + state, err = updateState(state, blockID, &header, responses) require.Nil(t, err) nextHeight := state.LastBlockHeight + 1 saveValidatorsInfo(stateDB, nextHeight+1, state.LastHeightValidatorsChanged, state.NextValidators) @@ -294,7 +296,7 @@ func TestManyValidatorChangesSaveLoad(t *testing.T) { func genValSet(size int) *types.ValidatorSet { vals := make([]*types.Validator, size) for i := 0; i < size; i++ { - vals[i] = types.NewValidator(crypto.GenPrivKeyEd25519().PubKey(), 10) + vals[i] = types.NewValidator(ed25519.GenPrivKey().PubKey(), 10) } return types.NewValidatorSet(vals) } @@ -330,8 +332,8 @@ func TestConsensusParamsChangesSaveLoad(t *testing.T) { changeIndex++ cp = params[changeIndex] } - header, blockID, responses := makeHeaderPartsResponsesParams(state, cp) - state, err = updateState(state, blockID, header, responses) + header, blockID, responses := makeHeaderPartsResponsesParams(state, i, cp) + state, err = updateState(state, blockID, &header, responses) require.Nil(t, err) nextHeight := state.LastBlockHeight + 1 @@ -380,7 +382,7 @@ func makeParams(blockBytes, blockTx, blockGas, txBytes, } func pk() []byte { - return crypto.GenPrivKeyEd25519().PubKey().Bytes() + return ed25519.GenPrivKey().PubKey().Bytes() } func TestApplyUpdates(t *testing.T) { @@ -429,8 +431,8 @@ func TestApplyUpdates(t *testing.T) { } } -func makeHeaderPartsResponsesValPubKeyChange(state State, pubkey crypto.PubKey) ( - *types.Header, types.BlockID, *ABCIResponses) { +func makeHeaderPartsResponsesValPubKeyChange(state State, height int64, + pubkey crypto.PubKey) (types.Header, types.BlockID, *ABCIResponses) { block := makeBlock(state, state.LastBlockHeight+1) abciResponses := &ABCIResponses{ @@ -451,8 +453,8 @@ func makeHeaderPartsResponsesValPubKeyChange(state State, pubkey crypto.PubKey) return block.Header, types.BlockID{block.Hash(), types.PartSetHeader{}}, abciResponses } -func makeHeaderPartsResponsesValPowerChange(state State, power int64) ( - *types.Header, types.BlockID, *ABCIResponses) { +func makeHeaderPartsResponsesValPowerChange(state State, height int64, + power int64) (types.Header, types.BlockID, *ABCIResponses) { block := makeBlock(state, state.LastBlockHeight+1) abciResponses := &ABCIResponses{ @@ -472,8 +474,8 @@ func makeHeaderPartsResponsesValPowerChange(state State, power int64) ( return block.Header, types.BlockID{block.Hash(), types.PartSetHeader{}}, abciResponses } -func makeHeaderPartsResponsesParams(state State, params types.ConsensusParams) ( - *types.Header, types.BlockID, *ABCIResponses) { +func makeHeaderPartsResponsesParams(state State, height int64, + params types.ConsensusParams) (types.Header, types.BlockID, *ABCIResponses) { block := makeBlock(state, state.LastBlockHeight+1) abciResponses := &ABCIResponses{ diff --git a/state/store.go b/state/store.go index c701a94aa..ea10b27c1 100644 --- a/state/store.go +++ b/state/store.go @@ -4,9 +4,9 @@ import ( "fmt" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/types" cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" + "github.com/tendermint/tendermint/types" ) //------------------------------------------------------------------------ @@ -80,6 +80,7 @@ func loadState(db dbm.DB, key []byte) (state State) { } // SaveState persists the State, the ValidatorsInfo, and the ConsensusParamsInfo to the database. +// This flushes the writes (e.g. calls SetSync). func SaveState(db dbm.DB, state State) { saveState(db, state, stateKey) } @@ -182,8 +183,13 @@ func LoadValidators(db dbm.DB, height int64) (*types.ValidatorSet, error) { if valInfo.ValidatorSet == nil { valInfo2 := loadValidatorsInfo(db, valInfo.LastHeightChanged) if valInfo2 == nil { - cmn.PanicSanity(fmt.Sprintf(`Couldn't find validators at height %d as - last changed from height %d`, valInfo.LastHeightChanged, height)) + panic( + fmt.Sprintf( + "Couldn't find validators at height %d as last changed from height %d", + valInfo.LastHeightChanged, + height, + ), + ) } valInfo = valInfo2 } @@ -220,7 +226,7 @@ func saveValidatorsInfo(db dbm.DB, nextHeight, changeHeight int64, valSet *types if changeHeight == nextHeight { valInfo.ValidatorSet = valSet } - db.SetSync(calcValidatorsKey(nextHeight), valInfo.Bytes()) + db.Set(calcValidatorsKey(nextHeight), valInfo.Bytes()) } //----------------------------------------------------------------------------- @@ -246,11 +252,17 @@ func LoadConsensusParams(db dbm.DB, height int64) (types.ConsensusParams, error) } if paramsInfo.ConsensusParams == empty { - paramsInfo = loadConsensusParamsInfo(db, paramsInfo.LastHeightChanged) - if paramsInfo == nil { - cmn.PanicSanity(fmt.Sprintf(`Couldn't find consensus params at height %d as - last changed from height %d`, paramsInfo.LastHeightChanged, height)) + paramsInfo2 := loadConsensusParamsInfo(db, paramsInfo.LastHeightChanged) + if paramsInfo2 == nil { + panic( + fmt.Sprintf( + "Couldn't find consensus params at height %d as last changed from height %d", + paramsInfo.LastHeightChanged, + height, + ), + ) } + paramsInfo = paramsInfo2 } return paramsInfo.ConsensusParams, nil @@ -285,5 +297,5 @@ func saveConsensusParamsInfo(db dbm.DB, nextHeight, changeHeight int64, params t if changeHeight == nextHeight { paramsInfo.ConsensusParams = params } - db.SetSync(calcConsensusParamsKey(nextHeight), paramsInfo.Bytes()) + db.Set(calcConsensusParamsKey(nextHeight), paramsInfo.Bytes()) } diff --git a/state/wire.go b/state/wire.go index af743c7b8..eeb156d67 100644 --- a/state/wire.go +++ b/state/wire.go @@ -2,11 +2,11 @@ package state import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) var cdc = amino.NewCodec() func init() { - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) } diff --git a/test/docker/Dockerfile b/test/docker/Dockerfile index 70570e752..7351ec9d1 100644 --- a/test/docker/Dockerfile +++ b/test/docker/Dockerfile @@ -29,6 +29,7 @@ COPY . $REPO RUN cd abci && make install && cd - RUN go install ./cmd/tendermint +RUN go install ./abci/cmd/abci-cli # expose the volume for debugging VOLUME $REPO diff --git a/test/test_cover.sh b/test/test_cover.sh index 5f2dea3ee..17df139e6 100644 --- a/test/test_cover.sh +++ b/test/test_cover.sh @@ -1,6 +1,6 @@ #! /bin/bash -PKGS=$(go list github.com/tendermint/tendermint/... | grep -v /vendor/) +PKGS=$(go list github.com/tendermint/tendermint/...) set -e diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 000000000..aeb411410 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,3 @@ +# tools + +Tools for working with tendermint and associated technologies. Documentation can be found in the `README.md` of each the `tm-bench/` and `tm-monitor/` directories. diff --git a/tools/build/.gitignore b/tools/build/.gitignore new file mode 100644 index 000000000..9974388f1 --- /dev/null +++ b/tools/build/.gitignore @@ -0,0 +1,4 @@ +BUILD +RPMS +SPECS +tmp diff --git a/crypto/LICENSE b/tools/build/LICENSE similarity index 93% rename from crypto/LICENSE rename to tools/build/LICENSE index 3beb77b13..bb66bb350 100644 --- a/crypto/LICENSE +++ b/tools/build/LICENSE @@ -1,11 +1,9 @@ -Tendermint Go-Crypto -Copyright (C) 2015 Tendermint - - +Tendermint Core +License: Apache2.0 Apache License Version 2.0, January 2004 - https://www.apache.org/licenses/ + http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION @@ -180,11 +178,24 @@ Copyright (C) 2015 Tendermint END OF TERMS AND CONDITIONS + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 All in Bits, Inc + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - https://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/tools/build/Makefile b/tools/build/Makefile new file mode 100644 index 000000000..a47644b63 --- /dev/null +++ b/tools/build/Makefile @@ -0,0 +1,289 @@ +## +# Extra checks, because we do not use autoconf. +## + +requirements_check = true +gpg_check = false +go_min_version = 1.9.4 +gpg_key = 2122CBE9 + +ifeq ($(requirements_check),true) +ifndef GOPATH +$(error GOPATH not set) +else +go_version := $(shell go version | sed "s/^.* go\([0-9\.]*\) .*$$/\1/" ) +$(info Found go version $(go_version)) +go_version_check := $(shell echo -e "$(go_min_version)\n$(go_version)" | sort -V | head -1) +ifneq ($(go_min_version),$(go_version_check)) +$(error go version go_min_version or above is required) +endif +endif +ifeq ($(gpg_check),true) +gpg_check := $(shell gpg -K | grep '/$(gpg_key) ' | sed 's,^.*/\($(gpg_key)\) .*$$,\1,') +ifneq ($(gpg_check),$(gpg_key)) +$(error GPG key $(gpg_key) not found.) +else +$(info GPG key $(gpg_key) found) +endif +ifndef GPG_PASSPHRASE +$(error GPG_PASSPHRASE not set) +endif +endif +endif + +### +# Here comes the real deal +### + +binaries = tendermint basecoind ethermint gaia +build-binaries = build-tendermint build-basecoind build-ethermint build-gaia +package-rpm = package-rpm-tendermint package-rpm-basecoind package-rpm-ethermint package-rpm-gaia +install-rpm = install-rpm-tendermint install-rpm-basecoind install-rpm-ethermint install-rpm-gaia +package-deb = package-deb-tendermint package-deb-basecoind package-deb-ethermint package-deb-gaia +install-deb = install-deb-tendermint install-deb-basecoind install-deb-ethermint install-deb-gaia + +all: $(binaries) +build: $(build-binaries) +package: $(package-rpm) $(package-deb) +install: $(install-rpm) $(install-deb) +$(binaries): %: build-% package-rpm-% package-deb-% + +### +# Build the binaries +### + +git-branch: + $(eval GIT_BRANCH=$(shell echo $${GIT_BRANCH:-master})) + +gopath-setup: + test -d $(GOPATH) || mkdir -p $(GOPATH) + test -d $(GOPATH)/bin || mkdir -p $(GOPATH)/bin + test -d $(GOPATH)/src || mkdir -p $(GOPATH)/src + +build-tendermint: git-branch gopath-setup + @echo "*** Building tendermint" + go get -d -u github.com/tendermint/tendermint/cmd/tendermint + cd $(GOPATH)/src/github.com/tendermint/tendermint && git checkout "$(GIT_BRANCH)" && git pull + export PATH=$(GOPATH)/bin:$(PATH) && $(MAKE) -C $(GOPATH)/src/github.com/tendermint/tendermint get_tools get_vendor_deps build + cp $(GOPATH)/src/github.com/tendermint/tendermint/build/tendermint $(GOPATH)/bin + @echo "*** Built tendermint" + +build-ethermint: git-branch gopath-setup + @echo "*** Building ethermint" + go get -d -u github.com/tendermint/ethermint/cmd/ethermint + cd $(GOPATH)/src/github.com/tendermint/ethermint && git checkout "$(GIT_BRANCH)" && git pull + export PATH=$(GOPATH)/bin:$(PATH) && $(MAKE) -C $(GOPATH)/src/github.com/tendermint/ethermint get_vendor_deps build + cp $(GOPATH)/src/github.com/tendermint/ethermint/build/ethermint $(GOPATH)/bin + @echo "*** Built ethermint" + +build-gaia: git-branch gopath-setup + @echo "*** Building gaia" + go get -d -u go github.com/cosmos/gaia || echo "Workaround for go downloads." + cd $(GOPATH)/src/github.com/cosmos/gaia && git checkout "$(GIT_BRANCH)" && git pull + export PATH=$(GOPATH)/bin:$(PATH) && $(MAKE) -C $(GOPATH)/src/github.com/cosmos/gaia get_vendor_deps install + @echo "*** Built gaia" + +build-basecoind: git-branch gopath-setup + @echo "*** Building basecoind from cosmos-sdk" + go get -d -u github.com/cosmos/cosmos-sdk/examples/basecoin/cmd/basecoind + cd $(GOPATH)/src/github.com/cosmos/cosmos-sdk && git checkout "$(GIT_BRANCH)" && git pull + export PATH=$(GOPATH)/bin:$(PATH) && $(MAKE) -C $(GOPATH)/src/github.com/cosmos/cosmos-sdk get_tools get_vendor_deps build + cp $(GOPATH)/src/github.com/cosmos/cosmos-sdk/build/basecoind $(GOPATH)/bin/basecoind + @echo "*** Built basecoind from cosmos-sdk" + +### +# Prepare package files +### + +# set app_version +version-%: + @echo "Checking if binary exists" + test -f $(GOPATH)/bin/$* + @echo "BUILD_NUMBER is $(BUILD_NUMBER)" + test -n "$(BUILD_NUMBER)" + $(eval $*_version=$(shell $(GOPATH)/bin/$* version | head -1 | cut -d- -f1 | sed 's/^\(ethermint:\s*\|\)\(v\|\)//' | tr -d '\t ' )) + +# set build_folder +folder-%: version-% + $(eval build_folder=BUILD/$*-$($*_version)-$(BUILD_NUMBER)) + +# clean up folder structure for package files +prepare-files = rm -rf $(build_folder) && mkdir -p $(build_folder) && cp -r ./$(1)/* $(build_folder) && mkdir -p $(build_folder)/usr/bin && cp $(GOPATH)/bin/$(1) $(build_folder)/usr/bin + +## +## Package customizations for the different applications +## + +prepare-tendermint = +prepare-ethermint = mkdir -p $(build_folder)/etc/ethermint && \ + cp $(GOPATH)/src/github.com/tendermint/ethermint/setup/genesis.json $(build_folder)/etc/ethermint/genesis.json && \ + cp -r $(GOPATH)/src/github.com/tendermint/ethermint/setup/keystore $(build_folder)/etc/ethermint +prepare-gaia = +prepare-basecoind = cp $(GOPATH)/bin/basecoind $(build_folder)/usr/bin + +### +# Package the binary for CentOS/RedHat (RPM) and Debian/Ubuntu (DEB) +### + +# Depends on rpmbuild, sorry, this can only be built on CentOS/RedHat machines. +package-rpm-%: folder-% + @echo "*** Packaging RPM $* version $($*_version)" + + $(call prepare-files,$*) + $(call prepare-$*) + + rm -rf $(build_folder)/DEBIAN + mkdir -p $(build_folder)/usr/share/licenses/$* + cp ./LICENSE $(build_folder)/usr/share/licenses/$*/LICENSE + chmod -Rf a+rX,u+w,g-w,o-w $(build_folder) + + mkdir -p {SPECS,tmp} + + ./generate-spec $* spectemplates SPECS + sed -i "s/@VERSION@/$($*_version)/" SPECS/$*.spec + sed -i "s/@BUILD_NUMBER@/$(BUILD_NUMBER)/" SPECS/$*.spec + sed -i "s/@PACKAGE_NAME@/$*/" SPECS/$*.spec + + rpmbuild -bb SPECS/$*.spec --define "_topdir `pwd`" --define "_tmppath `pwd`/tmp" + ./sign RPMS/x86_64/$*-$($*_version)-$(BUILD_NUMBER).x86_64.rpm "$(gpg_key)" "`which gpg`" + rpm -Kv RPMS/x86_64/$*-$($*_version)-$(BUILD_NUMBER).x86_64.rpm || echo "rpm returns non-zero exist for some reason. ($?)" + @echo "*** Packaged RPM $* version $($*_version)" + +package-deb-%: folder-% + @echo "*** Packaging DEB $* version $($*_version)-$(BUILD_NUMBER)" + + $(call prepare-files,$*) + $(call prepare-$*) + + mkdir -p $(build_folder)/usr/share/doc/$* + cp $(build_folder)/DEBIAN/copyright $(build_folder)/usr/share/doc/$* + chmod -Rf a+rX,u+w,g-w,o-w $(build_folder) + + sed -i "s/@VERSION@/$($*_version)-$(BUILD_NUMBER)/" $(build_folder)/DEBIAN/changelog + sed -i "s/@STABILITY@/stable/" $(build_folder)/DEBIAN/changelog + sed -i "s/@DATETIMESTAMP@/`date +%a,\ %d\ %b\ %Y\ %T\ %z`/" $(build_folder)/DEBIAN/changelog + sed -i "s/@VERSION@/$($*_version)-$(BUILD_NUMBER)/" $(build_folder)/DEBIAN/control + + gzip -c $(build_folder)/DEBIAN/changelog > $(build_folder)/usr/share/doc/$*/changelog.Debian.gz + gzip -c $(build_folder)/DEBIAN/changelog > $(build_folder)/usr/share/doc/$*/changelog.Debian.amd64.gz + sed -i "s/@INSTALLEDSIZE@/`du -ks $(build_folder) | cut -f 1`/" $(build_folder)/DEBIAN/control + + cd $(build_folder) && tar --owner=root --group=root -cvJf ../../tmp/data.tar.xz --exclude DEBIAN * + cd $(build_folder)/DEBIAN && tar --owner=root --group=root -cvzf ../../../tmp/control.tar.gz * + echo "2.0" > tmp/debian-binary + + cp ./_gpg tmp/ + cd tmp && sed -i "s/@DATETIMESTAMP@/`date +%a\ %b\ %d\ %T\ %Y`/" _gpg + cd tmp && sed -i "s/@BINMD5@/`md5sum debian-binary | cut -d\ -f1`/" _gpg + cd tmp && sed -i "s/@BINSHA1@/`sha1sum debian-binary | cut -d\ -f1`/" _gpg + cd tmp && sed -i "s/@BINSIZE@/`stat -c %s debian-binary | cut -d\ -f1`/" _gpg + cd tmp && sed -i "s/@CONMD5@/`md5sum control.tar.gz | cut -d\ -f1`/" _gpg + cd tmp && sed -i "s/@CONSHA1@/`sha1sum control.tar.gz | cut -d\ -f1`/" _gpg + cd tmp && sed -i "s/@CONSIZE@/`stat -c %s control.tar.gz | cut -d\ -f1`/" _gpg + cd tmp && sed -i "s/@DATMD5@/`md5sum data.tar.xz | cut -d\ -f1`/" _gpg + cd tmp && sed -i "s/@DATSHA1@/`sha1sum data.tar.xz | cut -d\ -f1`/" _gpg + cd tmp && sed -i "s/@DATSIZE@/`stat -c %s data.tar.xz | cut -d\ -f1`/" _gpg + gpg --batch --passphrase "$(GPG_PASSPHRASE)" --clearsign tmp/_gpg + mv tmp/_gpg.asc tmp/_gpgbuilder + ar r tmp/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb tmp/debian-binary tmp/control.tar.gz tmp/data.tar.xz tmp/_gpgbuilder + mv tmp/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb RPMS/ + rm tmp/debian-binary tmp/control.tar.gz tmp/data.tar.xz tmp/_gpgbuilder tmp/_gpg + @echo "*** Packaged DEB $* version $($*_version)-$(BUILD_NUMBER)" + +install-rpm-%: version-% +#Make sure your host has the IAM role to read/write the S3 bucket OR that you set up ~/.boto + @echo "*** Uploading $*-$($*_version)-$(BUILD_NUMBER).x86_64.rpm to AWS $(DEVOPS_PATH)CentOS repository" + aws s3 sync s3://tendermint-packages/$(DEVOPS_PATH)centos/ tmp/s3/ --delete + mkdir -p tmp/s3/7/os/x86_64/Packages + cp RPMS/x86_64/$*-$($*_version)-$(BUILD_NUMBER).x86_64.rpm tmp/s3/7/os/x86_64/Packages + cp ./RPM-GPG-KEY-Tendermint tmp/s3/7/os/x86_64/ + cp ./tendermint.repo tmp/s3/7/os/x86_64/ + rm -f tmp/s3/7/os/x86_64/repodata/*.bz2 tmp/s3/7/os/x86_64/repodata/*.gz tmp/s3/7/os/x86_64/repodata/repomd.xml.asc + createrepo tmp/s3/7/os/x86_64/Packages -u https://tendermint-packages.interblock.io/$(DEVOPS_PATH)centos/7/os/x86_64/Packages -o tmp/s3/7/os/x86_64 --update -S --repo Tendermint --content tendermint --content basecoind --content ethermint + gpg --batch --passphrase "$(GPG_PASSPHRASE)" --detach-sign -a tmp/s3/7/os/x86_64/repodata/repomd.xml + aws s3 sync tmp/s3/ s3://tendermint-packages/$(DEVOPS_PATH)centos/ --delete --acl public-read + @echo "*** Uploaded $* to AWS $(DEVOPS_PATH)CentOS repository" + +install-deb-%: version-% + @echo "*** Uploading $*-$($*_version)-$(BUILD_NUMBER)_amd64.deb to AWS $(DEVOPS_PATH)Debian repository" + @echo "Testing if $*-$($*_version)-$(BUILD_NUMBER)_amd64.deb is already uploaded" + test ! -f tmp/debian-s3/pool/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb + aws s3 sync s3://tendermint-packages/$(DEVOPS_PATH)debian/ tmp/debian-s3/ --delete + @echo "Testing if $*-$($*_version)-$(BUILD_NUMBER)_amd64.deb is already uploaded" + test ! -f tmp/debian-s3/pool/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb + cp ./tendermint.list tmp/debian-s3/ + mkdir -p tmp/debian-s3/pool tmp/debian-s3/dists/stable/main/binary-amd64 + cp RPMS/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb tmp/debian-s3/pool + cp ./Release_amd64 tmp/debian-s3/dists/stable/main/binary-amd64/Release + + #Packages / Packages.gz + + echo > tmp/Package + echo "Filename: pool/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb" >> tmp/Package + echo "MD5sum: `md5sum RPMS/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb | cut -d\ -f 1`" >> tmp/Package + echo "SHA1: `sha1sum RPMS/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb | cut -d\ -f 1`" >> tmp/Package + echo "SHA256: `sha256sum RPMS/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb | cut -d\ -f 1`" >> tmp/Package + echo "Size: `stat -c %s RPMS/$*-$($*_version)-$(BUILD_NUMBER)_amd64.deb | cut -d\ -f 1`" >> tmp/Package + cat BUILD/$*-$($*_version)-$(BUILD_NUMBER)/DEBIAN/control >> tmp/Package + + cat tmp/Package >> tmp/debian-s3/dists/stable/main/binary-amd64/Packages + rm -f tmp/debian-s3/dists/stable/main/binary-amd64/Packages.gz + gzip -c tmp/debian-s3/dists/stable/main/binary-amd64/Packages > tmp/debian-s3/dists/stable/main/binary-amd64/Packages.gz + rm -f tmp/Package + + #main / Release / InRelease / Release.gpg + + cp ./Release tmp/debian-s3/dists/stable/main/Release + rm -f tmp/debian-s3/dists/stable/main/InRelease + rm -f tmp/debian-s3/dists/stable/main/Release.gpg + + echo "MD5Sum:" >> tmp/debian-s3/dists/stable/main/Release + cd tmp/debian-s3/dists/stable/main && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; md5sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release + echo "SHA1:" >> tmp/debian-s3/dists/stable/main/Release + cd tmp/debian-s3/dists/stable/main && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; sha1sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release + echo "SHA256:" >> tmp/debian-s3/dists/stable/main/Release + cd tmp/debian-s3/dists/stable/main && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; sha256sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release + + gpg --batch --passphrase "$(GPG_PASSPHRASE)" --digest-algo SHA256 -b -a tmp/debian-s3/dists/stable/main/Release + mv tmp/debian-s3/dists/stable/main/Release.asc tmp/debian-s3/dists/stable/main/Release.gpg + gpg --batch --passphrase "$(GPG_PASSPHRASE)" --digest-algo SHA512 --clearsign tmp/debian-s3/dists/stable/main/Release + mv tmp/debian-s3/dists/stable/main/Release.asc tmp/debian-s3/dists/stable/main/InRelease + + #stable / Release / InRelease / Release.gpg + + cp ./Release tmp/debian-s3/dists/stable/Release + rm -f tmp/debian-s3/dists/stable/InRelease + rm -f tmp/debian-s3/dists/stable/Release.gpg + + echo "MD5Sum:" >> tmp/debian-s3/dists/stable/Release + cd tmp/debian-s3/dists/stable && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; md5sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release + echo "SHA1:" >> tmp/debian-s3/dists/stable/Release + cd tmp/debian-s3/dists/stable && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; sha1sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release + echo "SHA256:" >> tmp/debian-s3/dists/stable/Release + cd tmp/debian-s3/dists/stable && for f in `find . -type f | sed 's/^.\///'` ; do test "$$f" == "Release" && continue ; echo -n " " ; sha256sum $$f | sed "s/ / `stat -c %s $$f` /" ; done >> Release + + gpg --batch --passphrase "$(GPG_PASSPHRASE)" --digest-algo SHA256 -b -a tmp/debian-s3/dists/stable/Release + mv tmp/debian-s3/dists/stable/Release.asc tmp/debian-s3/dists/stable/Release.gpg + gpg --batch --passphrase "$(GPG_PASSPHRASE)" --digest-algo SHA512 --clearsign tmp/debian-s3/dists/stable/Release + mv tmp/debian-s3/dists/stable/Release.asc tmp/debian-s3/dists/stable/InRelease + + aws s3 sync tmp/debian-s3/ s3://tendermint-packages/$(DEVOPS_PATH)debian/ --delete --acl public-read + @echo "*** Uploaded $*-$($*_version)-$(BUILD_NUMBER)_amd64.deb to AWS $(DEVOPS_PATH)Debian repository" + +mostlyclean: + rm -rf {BUILDROOT,SOURCES,SPECS,SRPMS,tmp} + +clean: mostlyclean + rm -rf {BUILD,RPMS} + +distclean: clean + rm -rf $(GOPATH)/src/github.com/tendermint/tendermint + rm -rf $(GOPATH)/src/github.com/cosmos/cosmos-sdk + rm -rf $(GOPATH)/src/github.com/tendermint/ethermint + rm -rf $(GOPATH)/bin/tendermint + rm -rf $(GOPATH)/bin/basecoind + rm -rf $(GOPATH)/bin/ethermint + rm -rf $(GOPATH)/bin/gaia + +.PHONY : clean + diff --git a/tools/build/RPM-GPG-KEY-Tendermint b/tools/build/RPM-GPG-KEY-Tendermint new file mode 100644 index 000000000..e6f200d87 --- /dev/null +++ b/tools/build/RPM-GPG-KEY-Tendermint @@ -0,0 +1,19 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.22 (GNU/Linux) + +mQENBFk97ngBCADaiPQFKJI7zWYdUKqC490DzY9g9LatsWoJErK5LuMXwEnF5i+a +UkygueukA4C5U7L71l5EeOB9rtb6AbkF4IEZsmmp93APec/3Vfbac9xvK4dBdiht +F8SrazPdHeR6AKcZH8ZpG/+mdONvGb/gEgtxVjaeIJFpCbjKLlKEXazh2zamhhth +q+Nn/17QmI3KBiaGqQK5w4kGZ4mZPy6fXMQhW5dDMq9f4anlGIAYi9O53dVxsx2S +5d+NHuGer5Ps0u6WMJi/e+UT2EGwzP6ygOxkIjyhMFuVftabOtSSrRHHetw8UAaI +N/RPn2gSbQtOQ7unzHDXp3/o6/r2nDEErPyJABEBAAG0LkdyZWcgU3phYm8gKFRl +bmRlcm1pbnQpIDxncmVnQHBoaWxvc29iZWFyLmNvbT6JATkEEwECACMFAlk97ngC +GwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRDIkIHIISLL6bX/CACXTKmO +u5XgvJICH0pHNeVS5/4Om1Rsg1xNmEkGFBP8N2fqn576exbOLgWLSyNHTEyrJNoc +iTeUtod2qqbVGwRgWm1zeiP8NBYiQ9SUbqskIqcPavJNGWIxsCB0p/odoZah8xSj +tGrkoyoxrc+7z2JgKYK8SVSkJXQkzuc5/ZlY85ci5gPKQhlo5YDqGo+4U9n/Ieo5 +nkF8LBalFC2j7A7sQNroEicpulpGhIq3jyUHtadX01z3pNzuX+wfHX9futoet0YS +tG2007WoPGV0whGnoKxmk0JhwzhscC2XNtJl1GZcwqOOlPU9eGtZuPKj/HBAlRtz +4xTOAcklpg8soqRA +=jNDW +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tools/build/Release b/tools/build/Release new file mode 100644 index 000000000..9003d1320 --- /dev/null +++ b/tools/build/Release @@ -0,0 +1,7 @@ +Origin: Tendermint +Label: Tendermint +Suite: stable +Date: Fri, 16 Jun 2017 19:44:00 UTC +Architectures: amd64 +Components: main +Description: Tendermint repository diff --git a/tools/build/Release_amd64 b/tools/build/Release_amd64 new file mode 100644 index 000000000..1f2ecbfe2 --- /dev/null +++ b/tools/build/Release_amd64 @@ -0,0 +1,5 @@ +Archive: stable +Component: main +Origin: Tendermint +Label: Tendermint +Architecture: amd64 diff --git a/tools/build/_gpg b/tools/build/_gpg new file mode 100644 index 000000000..73742b5d8 --- /dev/null +++ b/tools/build/_gpg @@ -0,0 +1,8 @@ +Version: 4 +Signer: +Date: @DATETIMESTAMP@ +Role: builder +Files: + @BINMD5@ @BINSHA1@ @BINSIZE@ debian-binary + @CONMD5@ @CONSHA1@ @CONSIZE@ control.tar.gz + @DATMD5@ @DATSHA1@ @DATSIZE@ data.tar.xz diff --git a/tools/build/basecoind/DEBIAN/changelog b/tools/build/basecoind/DEBIAN/changelog new file mode 100644 index 000000000..260718eaf --- /dev/null +++ b/tools/build/basecoind/DEBIAN/changelog @@ -0,0 +1,6 @@ +basecoind (@VERSION@) @STABILITY@; urgency=medium + + * Automatic build. See https://github.com/cosmos/cosmos-sdk for more information. + + -- Greg Szabo @DATETIMESTAMP@ + diff --git a/tools/build/basecoind/DEBIAN/compat b/tools/build/basecoind/DEBIAN/compat new file mode 100644 index 000000000..ec635144f --- /dev/null +++ b/tools/build/basecoind/DEBIAN/compat @@ -0,0 +1 @@ +9 diff --git a/tools/build/basecoind/DEBIAN/control b/tools/build/basecoind/DEBIAN/control new file mode 100644 index 000000000..c15d49110 --- /dev/null +++ b/tools/build/basecoind/DEBIAN/control @@ -0,0 +1,14 @@ +Source: basecoind +Section: net +Priority: optional +Maintainer: Greg Szabo +Build-Depends: debhelper (>=9) +Standards-Version: 3.9.6 +Homepage: https://tendermint.com +Package: basecoind +Architecture: amd64 +Version: @VERSION@ +Installed-Size: @INSTALLEDSIZE@ +Description: basecoind is a Proof-of-Stake cryptocurrency and framework + Basecoind is an ABCI application designed to be used with the Tendermint consensus engine to form a Proof-of-Stake cryptocurrency. It also provides a general purpose framework for extending the feature-set of the cryptocurrency by implementing plugins. + diff --git a/tools/build/basecoind/DEBIAN/copyright b/tools/build/basecoind/DEBIAN/copyright new file mode 100644 index 000000000..fe449650c --- /dev/null +++ b/tools/build/basecoind/DEBIAN/copyright @@ -0,0 +1,21 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: basecoind +Source: https://github.com/cosmos/cosmos-sdk + +Files: * +Copyright: 2017 All In Bits, Inc. +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian systems, the full text of the Apache License 2.0 can be found + in the file `/usr/share/common-licenses/Apache-2.0'. diff --git a/tools/build/basecoind/DEBIAN/postinst b/tools/build/basecoind/DEBIAN/postinst new file mode 100644 index 000000000..d7d8f4413 --- /dev/null +++ b/tools/build/basecoind/DEBIAN/postinst @@ -0,0 +1,41 @@ +#!/bin/sh +# postinst script for basecoind +# + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + chown basecoind.basecoind /etc/basecoind + sudo -Hu basecoind basecoind node init --home /etc/basecoind 2B24DEE2364762300168DF19B6C18BCE2D399EA2 + systemctl daemon-reload + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/basecoind/DEBIAN/postrm b/tools/build/basecoind/DEBIAN/postrm new file mode 100644 index 000000000..b84c9f2a4 --- /dev/null +++ b/tools/build/basecoind/DEBIAN/postrm @@ -0,0 +1,41 @@ +#!/bin/sh +# postrm script for basecoin +# + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + upgrade|failed-upgrade|abort-upgrade) + systemctl daemon-reload + ;; + + purge|remove|abort-install|disappear) + systemctl daemon-reload + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/basecoind/DEBIAN/preinst b/tools/build/basecoind/DEBIAN/preinst new file mode 100644 index 000000000..53124c0ce --- /dev/null +++ b/tools/build/basecoind/DEBIAN/preinst @@ -0,0 +1,38 @@ +#!/bin/sh +# preinst script for basecoind +# + +set -e + +# summary of how this script can be called: +# * `install' +# * `install' +# * `upgrade' +# * `abort-upgrade' +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + install|upgrade) + if ! grep -q '^basecoind:' /etc/passwd ; then + useradd -k /dev/null -r -m -b /etc basecoind + chmod 755 /etc/basecoind + fi + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/basecoind/DEBIAN/prerm b/tools/build/basecoind/DEBIAN/prerm new file mode 100644 index 000000000..18ef42079 --- /dev/null +++ b/tools/build/basecoind/DEBIAN/prerm @@ -0,0 +1,38 @@ +#!/bin/sh +# prerm script for basecoin +# + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + systemctl stop basecoind 2> /dev/null || : + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/basecoind/etc/systemd/system-preset/50-basecoind.preset b/tools/build/basecoind/etc/systemd/system-preset/50-basecoind.preset new file mode 100644 index 000000000..358334fc3 --- /dev/null +++ b/tools/build/basecoind/etc/systemd/system-preset/50-basecoind.preset @@ -0,0 +1,2 @@ +disable basecoind.service + diff --git a/tools/build/basecoind/etc/systemd/system/basecoind.service b/tools/build/basecoind/etc/systemd/system/basecoind.service new file mode 100644 index 000000000..68b46d84f --- /dev/null +++ b/tools/build/basecoind/etc/systemd/system/basecoind.service @@ -0,0 +1,18 @@ +[Unit] +Description=Basecoind +Requires=network-online.target +After=network-online.target + +[Service] +Environment="BCHOME=/etc/basecoind" +Restart=on-failure +User=basecoind +Group=basecoind +PermissionsStartOnly=true +ExecStart=/usr/bin/basecoind start +ExecReload=/bin/kill -HUP $MAINPID +KillSignal=SIGTERM + +[Install] +WantedBy=multi-user.target + diff --git a/tools/build/basecoind/usr/share/basecoind/key.json b/tools/build/basecoind/usr/share/basecoind/key.json new file mode 100644 index 000000000..bdefe8fd4 --- /dev/null +++ b/tools/build/basecoind/usr/share/basecoind/key.json @@ -0,0 +1,12 @@ +{ + "address": "1B1BE55F969F54064628A63B9559E7C21C925165", + "priv_key": { + "type": "ed25519", + "data": "C70D6934B4F55F1B7BC33B56B9CA8A2061384AFC19E91E44B40C4BBA182953D1619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279" + }, + "pub_key": { + "type": "ed25519", + "data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279" + } +} + diff --git a/tools/build/basecoind/usr/share/basecoind/key2.json b/tools/build/basecoind/usr/share/basecoind/key2.json new file mode 100644 index 000000000..ddfc6809b --- /dev/null +++ b/tools/build/basecoind/usr/share/basecoind/key2.json @@ -0,0 +1,12 @@ +{ + "address": "1DA7C74F9C219229FD54CC9F7386D5A3839F0090", + "priv_key": { + "type": "ed25519", + "data": "34BAE9E65CE8245FAD035A0E3EED9401BDE8785FFB3199ACCF8F5B5DDF7486A8352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8" + }, + "pub_key": { + "type": "ed25519", + "data": "352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8" + } +} + diff --git a/tools/build/ethermint/DEBIAN/changelog b/tools/build/ethermint/DEBIAN/changelog new file mode 100644 index 000000000..76a1fb154 --- /dev/null +++ b/tools/build/ethermint/DEBIAN/changelog @@ -0,0 +1,6 @@ +ethermint (@VERSION@) @STABILITY@; urgency=medium + + * Automatic build. See https://github.com/tendermint/tendermint for more information. + + -- Greg Szabo @DATETIMESTAMP@ + diff --git a/tools/build/ethermint/DEBIAN/compat b/tools/build/ethermint/DEBIAN/compat new file mode 100644 index 000000000..ec635144f --- /dev/null +++ b/tools/build/ethermint/DEBIAN/compat @@ -0,0 +1 @@ +9 diff --git a/tools/build/ethermint/DEBIAN/control b/tools/build/ethermint/DEBIAN/control new file mode 100644 index 000000000..2d8b3b002 --- /dev/null +++ b/tools/build/ethermint/DEBIAN/control @@ -0,0 +1,15 @@ +Source: ethermint +Section: net +Priority: optional +Maintainer: Greg Szabo +Build-Depends: debhelper (>=9) +Depends: tendermint (>=0.11.0) +Standards-Version: 3.9.6 +Homepage: https://tendermint.com +Package: ethermint +Architecture: amd64 +Version: @VERSION@ +Installed-Size: @INSTALLEDSIZE@ +Description: ethermint enables ethereum as an ABCI application on tendermint and the COSMOS hub + Ethermint enables ethereum to run as an ABCI application on tendermint and the COSMOS hub. This application allows you to get all the benefits of ethereum without having to run your own miners. + diff --git a/tools/build/ethermint/DEBIAN/copyright b/tools/build/ethermint/DEBIAN/copyright new file mode 100644 index 000000000..6d1bab01b --- /dev/null +++ b/tools/build/ethermint/DEBIAN/copyright @@ -0,0 +1,21 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: ethermint +Source: https://github.com/tendermint/ethermint + +Files: * +Copyright: 2017 All In Bits, Inc. +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian systems, the full text of the Apache License 2.0 can be found + in the file `/usr/share/common-licenses/Apache-2.0'. diff --git a/tools/build/ethermint/DEBIAN/postinst b/tools/build/ethermint/DEBIAN/postinst new file mode 100644 index 000000000..439fdc395 --- /dev/null +++ b/tools/build/ethermint/DEBIAN/postinst @@ -0,0 +1,46 @@ +#!/bin/sh +# postinst script for ethermint +# + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + chown ethermint.ethermint /etc/ethermint + chown ethermint.ethermint /etc/ethermint/genesis.json + chown ethermint.ethermint /etc/ethermint/keystore + chown ethermint.ethermint /etc/ethermint/keystore/UTC--2016-10-21T22-30-03.071787745Z--7eff122b94897ea5b0e2a9abf47b86337fafebdc + + sudo -Hu ethermint /usr/bin/ethermint --datadir /etc/ethermint init /etc/ethermint/genesis.json + sudo -Hu ethermint tendermint init --home /etc/ethermint + systemctl daemon-reload + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/ethermint/DEBIAN/postrm b/tools/build/ethermint/DEBIAN/postrm new file mode 100644 index 000000000..f1d9d6afc --- /dev/null +++ b/tools/build/ethermint/DEBIAN/postrm @@ -0,0 +1,41 @@ +#!/bin/sh +# postrm script for ethermint +# + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + upgrade|failed-upgrade|abort-upgrade) + systemctl daemon-reload + ;; + + purge|remove|abort-install|disappear) + systemctl daemon-reload + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/ethermint/DEBIAN/preinst b/tools/build/ethermint/DEBIAN/preinst new file mode 100644 index 000000000..829112e6b --- /dev/null +++ b/tools/build/ethermint/DEBIAN/preinst @@ -0,0 +1,38 @@ +#!/bin/sh +# preinst script for ethermint +# + +set -e + +# summary of how this script can be called: +# * `install' +# * `install' +# * `upgrade' +# * `abort-upgrade' +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + install|upgrade) + if ! grep -q '^ethermint:' /etc/passwd ; then + useradd -k /dev/null -r -m -b /etc ethermint + chmod 755 /etc/ethermint + fi + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/ethermint/DEBIAN/prerm b/tools/build/ethermint/DEBIAN/prerm new file mode 100644 index 000000000..00a775cef --- /dev/null +++ b/tools/build/ethermint/DEBIAN/prerm @@ -0,0 +1,38 @@ +#!/bin/sh +# prerm script for ethermint +# + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + systemctl stop ethermint 2> /dev/null || : + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/ethermint/etc/systemd/system-preset/50-ethermint.preset b/tools/build/ethermint/etc/systemd/system-preset/50-ethermint.preset new file mode 100644 index 000000000..836a28c30 --- /dev/null +++ b/tools/build/ethermint/etc/systemd/system-preset/50-ethermint.preset @@ -0,0 +1,2 @@ +disable ethermint.service + diff --git a/tools/build/ethermint/etc/systemd/system/ethermint.service b/tools/build/ethermint/etc/systemd/system/ethermint.service new file mode 100644 index 000000000..f71a074ea --- /dev/null +++ b/tools/build/ethermint/etc/systemd/system/ethermint.service @@ -0,0 +1,17 @@ +[Unit] +Description=Ethermint +Requires=network-online.target +After=network-online.target + +[Service] +Restart=on-failure +User=ethermint +Group=ethermint +PermissionsStartOnly=true +ExecStart=/usr/bin/ethermint --datadir /etc/ethermint +ExecReload=/bin/kill -HUP $MAINPID +KillSignal=SIGTERM + +[Install] +WantedBy=multi-user.target + diff --git a/tools/build/gaia/DEBIAN/changelog b/tools/build/gaia/DEBIAN/changelog new file mode 100644 index 000000000..eca5fbc3d --- /dev/null +++ b/tools/build/gaia/DEBIAN/changelog @@ -0,0 +1,6 @@ +gaia (@VERSION@) @STABILITY@; urgency=medium + + * Automatic build. See https://github.com/tendermint/basecoin for more information. + + -- Greg Szabo @DATETIMESTAMP@ + diff --git a/tools/build/gaia/DEBIAN/compat b/tools/build/gaia/DEBIAN/compat new file mode 100644 index 000000000..ec635144f --- /dev/null +++ b/tools/build/gaia/DEBIAN/compat @@ -0,0 +1 @@ +9 diff --git a/tools/build/gaia/DEBIAN/control b/tools/build/gaia/DEBIAN/control new file mode 100644 index 000000000..55d1cd5dd --- /dev/null +++ b/tools/build/gaia/DEBIAN/control @@ -0,0 +1,14 @@ +Source: gaia +Section: net +Priority: optional +Maintainer: Greg Szabo +Build-Depends: debhelper (>=9) +Standards-Version: 3.9.6 +Homepage: https://cosmos.network +Package: gaia +Architecture: amd64 +Version: @VERSION@ +Installed-Size: @INSTALLEDSIZE@ +Description: gaia - Tendermint Cosmos delegation game chain + Gaia description comes later. + diff --git a/tools/build/gaia/DEBIAN/copyright b/tools/build/gaia/DEBIAN/copyright new file mode 100644 index 000000000..ffc230134 --- /dev/null +++ b/tools/build/gaia/DEBIAN/copyright @@ -0,0 +1,21 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: gaia +Source: https://github.com/cosmos/gaia + +Files: * +Copyright: 2017 All In Bits, Inc. +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian systems, the full text of the Apache License 2.0 can be found + in the file `/usr/share/common-licenses/Apache-2.0'. diff --git a/tools/build/gaia/DEBIAN/postinst b/tools/build/gaia/DEBIAN/postinst new file mode 100644 index 000000000..427b7c493 --- /dev/null +++ b/tools/build/gaia/DEBIAN/postinst @@ -0,0 +1,41 @@ +#!/bin/sh +# postinst script for gaia +# + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + chown gaia.gaia /etc/gaia + sudo -Hu gaia gaia node init --home /etc/gaia 2B24DEE2364762300168DF19B6C18BCE2D399EA2 + systemctl daemon-reload + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/gaia/DEBIAN/postrm b/tools/build/gaia/DEBIAN/postrm new file mode 100644 index 000000000..da526ec30 --- /dev/null +++ b/tools/build/gaia/DEBIAN/postrm @@ -0,0 +1,41 @@ +#!/bin/sh +# postrm script for gaia +# + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + upgrade|failed-upgrade|abort-upgrade) + systemctl daemon-reload + ;; + + purge|remove|abort-install|disappear) + systemctl daemon-reload + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/gaia/DEBIAN/preinst b/tools/build/gaia/DEBIAN/preinst new file mode 100644 index 000000000..382fa419f --- /dev/null +++ b/tools/build/gaia/DEBIAN/preinst @@ -0,0 +1,38 @@ +#!/bin/sh +# preinst script for gaia +# + +set -e + +# summary of how this script can be called: +# * `install' +# * `install' +# * `upgrade' +# * `abort-upgrade' +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + install|upgrade) + if ! grep -q '^gaia:' /etc/passwd ; then + useradd -k /dev/null -r -m -b /etc gaia + chmod 755 /etc/gaia + fi + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/gaia/DEBIAN/prerm b/tools/build/gaia/DEBIAN/prerm new file mode 100644 index 000000000..165c1ab6a --- /dev/null +++ b/tools/build/gaia/DEBIAN/prerm @@ -0,0 +1,38 @@ +#!/bin/sh +# prerm script for gaia +# + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see https://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + systemctl stop gaia 2> /dev/null || : + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 diff --git a/tools/build/gaia/etc/systemd/system-preset/50-gaia.preset b/tools/build/gaia/etc/systemd/system-preset/50-gaia.preset new file mode 100644 index 000000000..dfbf0bc06 --- /dev/null +++ b/tools/build/gaia/etc/systemd/system-preset/50-gaia.preset @@ -0,0 +1,2 @@ +disable gaia.service + diff --git a/tools/build/gaia/etc/systemd/system/gaia.service b/tools/build/gaia/etc/systemd/system/gaia.service new file mode 100644 index 000000000..372fe9343 --- /dev/null +++ b/tools/build/gaia/etc/systemd/system/gaia.service @@ -0,0 +1,17 @@ +[Unit] +Description=Gaia +Requires=network-online.target +After=network-online.target + +[Service] +Restart=on-failure +User=gaia +Group=gaia +PermissionsStartOnly=true +ExecStart=/usr/bin/gaia node start --home=/etc/gaia +ExecReload=/bin/kill -HUP $MAINPID +KillSignal=SIGTERM + +[Install] +WantedBy=multi-user.target + diff --git a/tools/build/gaia/usr/share/gaia/key.json b/tools/build/gaia/usr/share/gaia/key.json new file mode 100644 index 000000000..bdefe8fd4 --- /dev/null +++ b/tools/build/gaia/usr/share/gaia/key.json @@ -0,0 +1,12 @@ +{ + "address": "1B1BE55F969F54064628A63B9559E7C21C925165", + "priv_key": { + "type": "ed25519", + "data": "C70D6934B4F55F1B7BC33B56B9CA8A2061384AFC19E91E44B40C4BBA182953D1619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279" + }, + "pub_key": { + "type": "ed25519", + "data": "619D3678599971ED29C7529DDD4DA537B97129893598A17C82E3AC9A8BA95279" + } +} + diff --git a/tools/build/gaia/usr/share/gaia/key2.json b/tools/build/gaia/usr/share/gaia/key2.json new file mode 100644 index 000000000..ddfc6809b --- /dev/null +++ b/tools/build/gaia/usr/share/gaia/key2.json @@ -0,0 +1,12 @@ +{ + "address": "1DA7C74F9C219229FD54CC9F7386D5A3839F0090", + "priv_key": { + "type": "ed25519", + "data": "34BAE9E65CE8245FAD035A0E3EED9401BDE8785FFB3199ACCF8F5B5DDF7486A8352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8" + }, + "pub_key": { + "type": "ed25519", + "data": "352195DA90CB0B90C24295B90AEBA25A5A71BC61BAB2FE2387241D439698B7B8" + } +} + diff --git a/tools/build/generate-spec b/tools/build/generate-spec new file mode 100755 index 000000000..4ca60a1d4 --- /dev/null +++ b/tools/build/generate-spec @@ -0,0 +1,36 @@ +#!/bin/bash + +if [ $# -ne 3 ]; then + echo "Usage: $0 " + exit 1 +fi + +app=$1 +src=$2 +dst=$3 + +# Find spectemplate +if [ ! -f "$src/$app.spec" ]; then + if [ ! -f "$src/app-template.spec" ]; then + echo "Source template not found." + exit 1 + else + srcfile="$src/app-template.spec" + fi +else + srcfile="$src/$app.spec" +fi + +# Copy spectemplate to SPECS +cp "$srcfile" "$dst/$app.spec" + +# Apply any variables defined in .data +if [ -f "$src/$app.data" ]; then + srcdata="$src/$app.data" + source "$srcdata" + for var in `grep -v -e ^# -e ^\s*$ "$srcdata" | grep = | sed 's/\s*=.*$//'` + do + sed -i "s\\@${var}@\\${!var}\\g" "$dst/$app.spec" + done +fi + diff --git a/tools/build/sign b/tools/build/sign new file mode 100755 index 000000000..0371b5d4b --- /dev/null +++ b/tools/build/sign @@ -0,0 +1,26 @@ +#!/usr/bin/expect -f +set timeout 3 +set PACKAGE [lindex $argv 0] +set GPG_NAME [lindex $argv 1] +set GPG_PATH [lindex $argv 2] +set GPG_PASSPHRASE $env(GPG_PASSPHRASE) + +if {[llength $argv] == 0} { + send_user "Usage: ./sign \n" + exit 1 +} + +send_user "\nSigning $PACKAGE\n" +spawn rpmsign --resign $PACKAGE --define "_signature gpg" --define "_gpg_name $GPG_NAME" --define "_gpgbin $GPG_PATH" +expect { + timeout { send_user "\nTimeout signing $PACKAGE\n"; exit 1 } + "Enter pass phrase:" +} +send "$GPG_PASSPHRASE\r" +expect { + timeout { send_user "\nTimeout signing $PACKAGE\n"; exit 1 } + "Pass phrase is good." +} +interact +sleep 3 + diff --git a/tools/build/spectemplates/app-template.spec b/tools/build/spectemplates/app-template.spec new file mode 100644 index 000000000..6cb8145bb --- /dev/null +++ b/tools/build/spectemplates/app-template.spec @@ -0,0 +1,55 @@ +Version: @VERSION@ +Release: @BUILD_NUMBER@ + +%define __spec_install_post %{nil} +%define debug_package %{nil} +%define __os_install_post %{nil} + +Name: @PACKAGE_NAME@ +Summary: @PACKAGE_SUMMARY@ +License: Apache 2.0 +URL: @PACKAGE_URL@ +Packager: Greg Szabo +@PACKAGE_ADDITIONAL_HEADER@ + +%description +@PACKAGE_DESCRIPTION@ + +%pre +if ! %{__grep} -q '^%{name}:' /etc/passwd ; then + useradd -r -b %{_sysconfdir} %{name} + mkdir -p %{_sysconfdir}/%{name} + chmod 755 %{_sysconfdir}/%{name} + chown %{name}.%{name} %{_sysconfdir}/%{name} +fi + +%prep +# Nothing to do here. - It is done in the Makefile. + +%build +# Nothing to do here. + +%install +cd %{name}-%{version}-%{release} +%{__cp} -a * %{buildroot} + +%post +sudo -Hu %{name} %{name} node init --home %{_sysconfdir}/%{name} 2B24DEE2364762300168DF19B6C18BCE2D399EA2 +systemctl daemon-reload + +%preun +systemctl stop %{name} 2> /dev/null || : + +%postun +systemctl daemon-reload + +%files +%ghost %attr(0755, %{name}, %{name}) %dir %{_sysconfdir}/%{name} +%{_bindir}/* +%{_sysconfdir}/systemd/system/* +%{_sysconfdir}/systemd/system-preset/* +%dir %{_datadir}/%{name} +%{_datadir}/%{name}/* +%dir %{_defaultlicensedir}/%{name} +%doc %{_defaultlicensedir}/%{name}/LICENSE + diff --git a/tools/build/spectemplates/basecoind.data b/tools/build/spectemplates/basecoind.data new file mode 100644 index 000000000..36b172ecf --- /dev/null +++ b/tools/build/spectemplates/basecoind.data @@ -0,0 +1,5 @@ +PACKAGE_SUMMARY="basecoind is a Proof-of-Stake cryptocurrency and framework" +PACKAGE_URL="https://cosmos.network/" +PACKAGE_ADDITIONAL_HEADER="Provides: basecoind" +PACKAGE_DESCRIPTION="Basecoind is an ABCI application designed to be used with the Tendermint consensus engine to form a Proof-of-Stake cryptocurrency. It also provides a general purpose framework for extending the feature-set of the cryptocurrency by implementing plugins." + diff --git a/tools/build/spectemplates/ethermint.data b/tools/build/spectemplates/ethermint.data new file mode 100644 index 000000000..e9d403db7 --- /dev/null +++ b/tools/build/spectemplates/ethermint.data @@ -0,0 +1,5 @@ +PACKAGE_SUMMARY="ethermint enables ethereum as an ABCI application on tendermint and the COSMOS hub" +PACKAGE_URL="https://tendermint.com/" +PACKAGE_ADDITIONAL_HEADER="Provides: ethermint" +PACKAGE_DESCRIPTION="Ethermint enables ethereum to run as an ABCI application on tendermint and the COSMOS hub. This application allows you to get all the benefits of ethereum without having to run your own miners." + diff --git a/tools/build/spectemplates/ethermint.spec b/tools/build/spectemplates/ethermint.spec new file mode 100644 index 000000000..fc443e35b --- /dev/null +++ b/tools/build/spectemplates/ethermint.spec @@ -0,0 +1,60 @@ +Version: @VERSION@ +Release: @BUILD_NUMBER@ + +%define __spec_install_post %{nil} +%define debug_package %{nil} +%define __os_install_post %{nil} + +Name: @PACKAGE_NAME@ +Summary: @PACKAGE_SUMMARY@ +License: Apache 2.0 +URL: @PACKAGE_URL@ +Packager: Greg Szabo +Requires: tendermint >= 0.11.0 +@PACKAGE_ADDITIONAL_HEADER@ + +%description +@PACKAGE_DESCRIPTION@ + +%pre +if ! %{__grep} -q '^%{name}:' /etc/passwd ; then + useradd -r -b %{_sysconfdir} %{name} + mkdir -p %{_sysconfdir}/%{name} + chmod 755 %{_sysconfdir}/%{name} + chown %{name}.%{name} %{_sysconfdir}/%{name} +fi + +%prep +# Nothing to do here. - It is done in the Makefile. + +%build +# Nothing to do here. + +%install +cd %{name}-%{version}-%{release} +%{__cp} -a * %{buildroot} + +%post +sudo -Hu %{name} tendermint init --home %{_sysconfdir}/%{name} +sudo -Hu %{name} %{name} --datadir %{_sysconfdir}/%{name} init %{_sysconfdir}/%{name}/genesis.json + +systemctl daemon-reload + +%preun +systemctl stop %{name} 2> /dev/null || : +systemctl stop %{name}-service 2> /dev/null || : + +%postun +systemctl daemon-reload + +%files +%attr(0755, %{name}, %{name}) %dir %{_sysconfdir}/%{name} +%config(noreplace) %attr(0644, %{name}, %{name}) %{_sysconfdir}/%{name}/genesis.json +%attr(0755, %{name}, %{name}) %dir %{_sysconfdir}/%{name}/keystore +%attr(0644, %{name}, %{name}) %{_sysconfdir}/%{name}/keystore/* +%{_bindir}/* +%{_sysconfdir}/systemd/system/* +%{_sysconfdir}/systemd/system-preset/* +%dir %{_defaultlicensedir}/%{name} +%doc %{_defaultlicensedir}/%{name}/LICENSE + diff --git a/tools/build/spectemplates/gaia.data b/tools/build/spectemplates/gaia.data new file mode 100644 index 000000000..7152b1b51 --- /dev/null +++ b/tools/build/spectemplates/gaia.data @@ -0,0 +1,5 @@ +PACKAGE_SUMMARY="gaia - Tendermint Cosmos delegation game chain" +PACKAGE_URL="https://cosmos.network/" +PACKAGE_ADDITIONAL_HEADER="" +PACKAGE_DESCRIPTION="Gaia description comes later." + diff --git a/tools/build/spectemplates/tendermint.spec b/tools/build/spectemplates/tendermint.spec new file mode 100644 index 000000000..68902a170 --- /dev/null +++ b/tools/build/spectemplates/tendermint.spec @@ -0,0 +1,31 @@ +Version: @VERSION@ +Release: @BUILD_NUMBER@ + +%define __spec_install_post %{nil} +%define debug_package %{nil} +%define __os_install_post %{nil} + +Name: tendermint +Summary: securely and consistently replicate an application on many machines +License: Apache 2.0 +URL: https://tendermint.com/ +Packager: Greg Szabo + +%description +Tendermint is software for securely and consistently replicating an application on many machines. By securely, we mean that Tendermint works even if up to 1/3 of machines fail in arbitrary ways. By consistently, we mean that every non-faulty machine sees the same transaction log and computes the same state. + +%prep +# Nothing to do here. - It is done in the Makefile. + +%build +# Nothing to do here. + +%install +cd %{name}-%{version}-%{release} +%{__cp} -a * %{buildroot} + +%files +%{_bindir}/tendermint +%dir %{_defaultlicensedir}/%{name} +%doc %{_defaultlicensedir}/%{name}/LICENSE + diff --git a/tools/build/tendermint.list b/tools/build/tendermint.list new file mode 100644 index 000000000..bba521af5 --- /dev/null +++ b/tools/build/tendermint.list @@ -0,0 +1 @@ +deb http://tendermint-packages.s3-website-us-west-1.amazonaws.com/debian stable main diff --git a/tools/build/tendermint.repo b/tools/build/tendermint.repo new file mode 100644 index 000000000..439f98ecb --- /dev/null +++ b/tools/build/tendermint.repo @@ -0,0 +1,12 @@ +#This is the .repo file for the Tendermint CentOS repositories. +#Although it has only been tested under CentOS 7, it should work under Fedora and RedHat 7 too. +#Currently only 64-bit packages are built. + +[tendermint] +name=Tendermint stable releases repository +baseurl=https://do9rmxapsag1v.cloudfront.net/centos/7/os/x86_64 +gpgcheck=1 +gpgkey=https://do9rmxapsag1v.cloudfront.net/centos/7/os/x86_64/RPM-GPG-KEY-Tendermint +enabled=1 +#sslverify = 1 + diff --git a/tools/build/tendermint/DEBIAN/changelog b/tools/build/tendermint/DEBIAN/changelog new file mode 100644 index 000000000..4b016f845 --- /dev/null +++ b/tools/build/tendermint/DEBIAN/changelog @@ -0,0 +1,6 @@ +tendermint (@VERSION@) @STABILITY@; urgency=medium + + * Automatic build. See https://github.com/tendermint/tendermint for more information. + + -- Greg Szabo @DATETIMESTAMP@ + diff --git a/tools/build/tendermint/DEBIAN/compat b/tools/build/tendermint/DEBIAN/compat new file mode 100644 index 000000000..ec635144f --- /dev/null +++ b/tools/build/tendermint/DEBIAN/compat @@ -0,0 +1 @@ +9 diff --git a/tools/build/tendermint/DEBIAN/control b/tools/build/tendermint/DEBIAN/control new file mode 100644 index 000000000..d9da17dd1 --- /dev/null +++ b/tools/build/tendermint/DEBIAN/control @@ -0,0 +1,14 @@ +Source: tendermint +Section: net +Priority: optional +Maintainer: Greg Szabo +Build-Depends: debhelper (>=9) +Standards-Version: 3.9.6 +Homepage: https://tendermint.com +Package: tendermint +Architecture: amd64 +Version: @VERSION@ +Installed-Size: @INSTALLEDSIZE@ +Description: securely and consistently replicate an application on many machines + Tendermint is software for securely and consistently replicating an application on many machines. By securely, we mean that Tendermint works even if up to 1/3 of machines fail in arbitrary ways. By consistently, we mean that every non-faulty machine sees the same transaction log and computes the same state. + diff --git a/tools/build/tendermint/DEBIAN/copyright b/tools/build/tendermint/DEBIAN/copyright new file mode 100644 index 000000000..15ee960dd --- /dev/null +++ b/tools/build/tendermint/DEBIAN/copyright @@ -0,0 +1,21 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: tendermint +Source: https://github.com/tendermint/tendermint + +Files: * +Copyright: 2017 All In Bits, Inc. +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian systems, the full text of the Apache License 2.0 can be found + in the file `/usr/share/common-licenses/Apache-2.0'. diff --git a/libs/LICENSE b/tools/mintnet-kubernetes/LICENSE similarity index 99% rename from libs/LICENSE rename to tools/mintnet-kubernetes/LICENSE index 06bc5e1c6..64a33ddf1 100644 --- a/libs/LICENSE +++ b/tools/mintnet-kubernetes/LICENSE @@ -1,4 +1,3 @@ -Tendermint Libraries Copyright (C) 2017 Tendermint diff --git a/tools/mintnet-kubernetes/README.rst b/tools/mintnet-kubernetes/README.rst new file mode 100644 index 000000000..9cfdbb8eb --- /dev/null +++ b/tools/mintnet-kubernetes/README.rst @@ -0,0 +1,290 @@ +Using Kubernetes +================ + +.. figure:: assets/t_plus_k.png + :alt: Tendermint plus Kubernetes + + Tendermint plus Kubernetes + +This should primarily be used for testing purposes or for +tightly-defined chains operated by a single stakeholder (see `the +security precautions <#security>`__). If your desire is to launch an +application with many stakeholders, consider using our set of Ansible +scripts. + +Quick Start +----------- + +For either platform, see the `requirements `__ + +MacOS +^^^^^ + +:: + + curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/kubectl + curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.18.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/ + minikube start + + git clone https://github.com/tendermint/tools.git && cd tools/mintnet-kubernetes/examples/basecoin && make create + +Linux +^^^^^ + +:: + + curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/kubectl + curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.18.0/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/ + minikube start + + git clone https://github.com/tendermint/tools.git && cd tools/mintnet-kubernetes/examples/basecoin && make create + +Verify it worked +~~~~~~~~~~~~~~~~ + +**Using a shell:** + +First wait until all the pods are ``Running``: + +``kubectl get pods -w -o wide -L tm`` + +then query the Tendermint app logs from the first pod: + +``kubectl logs -c tm -f tm-0`` + +finally, use our `Rest API <../specification/rpc.html>`__ to fetch the status of the second pod's Tendermint app. + +Note we are using ``kubectl exec`` because pods are not exposed (and should not be) to the +outer network: + +``kubectl exec -c tm tm-0 -- curl -s http://tm-1.basecoin:26657/status | json_pp`` + +**Using the dashboard:** + +:: + + minikube dashboard + +Clean up +~~~~~~~~ + +:: + + make destroy + +Usage +----- + +Setup a Kubernetes cluster +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- locally using `Minikube `__ +- on GCE with a single click in the web UI +- on AWS using `Kubernetes + Operations `__ +- on Linux machines (Digital Ocean) using + `kubeadm `__ +- on AWS, Azure, GCE or bare metal using `Kargo + (Ansible) `__ + +Please refer to `the official +documentation `__ +for overview and comparison of different options. + +Kubernetes on Digital Ocean +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Available options: + +- `kubeadm (alpha) `__ +- `kargo `__ +- `rancher `__ +- `terraform `__ + +As you can see, there is no single tool for creating a cluster on DO. +Therefore, choose the one you know and comfortable working with. If you know +and used `terraform `__ before, then choose it. If you +know Ansible, then pick kargo. If none of these seem familiar to you, go with +``kubeadm``. Rancher is a beautiful UI for deploying and managing containers in +production. + +Kubernetes on Google Cloud Engine +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Review the `Official Documentation `__ for Kubernetes on Google Compute +Engine. + +**Create a cluster** + +The recommended way is to use `Google Container +Engine `__. You should be able +to create a fully fledged cluster with just a few clicks. + +**Connect to it** + +Install ``gcloud`` as a part of `Google Cloud SDK `__. + +Make sure you have credentials for GCloud by running ``gcloud auth login``. + +In order to make API calls against GCE, you must also run ``gcloud auth +application-default login``. + +Press ``Connect``: + +.. figure:: assets/gce1.png + +and execute the first command in your shell. Then start a proxy by +executing ``kubectl` proxy``. + +.. figure:: assets/gce2.png + +Now you should be able to run ``kubectl`` command to create resources, get +resource info, logs, etc. + +**Make sure you have Kubernetes >= 1.5, because you will be using +StatefulSets, which is a beta feature in 1.5.** + +Create a configuration file +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Download a template: + +:: + + curl -Lo app.yaml https://github.com/tendermint/tools/raw/master/mintnet-kubernetes/app.template.yaml + +Open ``app.yaml`` in your favorite editor and configure your app +container (navigate to ``- name: app``). Kubernetes DSL (Domain Specific +Language) is very simple, so it should be easy. You will need to set +Docker image, command and/or run arguments. Replace variables prefixed +with ``YOUR_APP`` with corresponding values. Set genesis time to now and +preferable chain ID in ConfigMap. + +Please note if you are changing ``replicas`` number, do not forget to +update ``validators`` set in ConfigMap. You will be able to scale the +cluster up or down later, but new pods (nodes) won't become validators +automatically. + +Deploy your application +^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + kubectl create -f ./app.yaml + +Observe your cluster +^^^^^^^^^^^^^^^^^^^^ + +`web UI `__ + +The easiest way to access Dashboard is to use ``kubectl``. Run the following +command in your desktop environment: + +:: + + kubectl proxy + +``kubectl`` will handle authentication with apiserver and make Dashboard +available at http://localhost:8001/ui + +**shell** + +List all the pods: + +:: + + kubectl get pods -o wide -L tm + +StatefulSet details: + +:: + + kubectl describe statefulsets tm + +First pod details: + +:: + + kubectl describe pod tm-0 + +Tendermint app logs from the first pod: + +:: + + kubectl logs tm-0 -c tm -f + +App logs from the first pod: + +:: + + kubectl logs tm-0 -c app -f + +Status of the second pod's Tendermint app: + +:: + + kubectl exec -c tm tm-0 -- curl -s http://tm-1.:26657/status | json_pp + +Security +-------- + +Due to the nature of Kubernetes, where you typically have a single +master, the master could be a SPOF (Single Point Of Failure). Therefore, +you need to make sure only authorized people can access it. And these +people themselves had taken basic measures in order not to get hacked. + +These are the best practices: + +- all access to the master is over TLS +- access to the API Server is X.509 certificate or token based +- etcd is not exposed directly to the cluster +- ensure that images are free of vulnerabilities + (`1 `__) +- ensure that only authorized images are used in your environment +- disable direct access to Kubernetes nodes (no SSH) +- define resource quota + +Resources: + +- https://kubernetes.io/docs/admin/accessing-the-api/ +- http://blog.kubernetes.io/2016/08/security-best-practices-kubernetes-deployment.html +- https://blog.openshift.com/securing-kubernetes/ + +Fault tolerance +--------------- + +Having a single master (API server) is a bad thing also because if +something happens to it, you risk being left without an access to the +application. + +To avoid that you can `run Kubernetes in multiple +zones `__, each zone +running an `API +server `__ and load +balance requests between them. Do not forget to make sure only one +instance of scheduler and controller-manager are running at once. + +Running in multiple zones is a lightweight version of a broader `Cluster +Federation feature `__. +Federated deployments could span across multiple regions (not zones). We +haven't tried this feature yet, so any feedback is highly appreciated! +Especially, related to additional latency and cost of exchanging data +between the regions. + +Resources: + +- https://kubernetes.io/docs/admin/high-availability/ + +Starting process +---------------- + +.. figure:: assets/statefulset.png + :alt: StatefulSet + + StatefulSet + +Init containers (``tm-gen-validator``) are run before all other +containers, creating public-private key pair for each pod. Every ``tm`` +container then asks other pods for their public keys, which are served +with nginx (``pub-key`` container). When ``tm`` container have all the +keys, it forms a genesis file and starts the Tendermint process. diff --git a/tools/mintnet-kubernetes/app.template.yaml b/tools/mintnet-kubernetes/app.template.yaml new file mode 100644 index 000000000..826b2e97f --- /dev/null +++ b/tools/mintnet-kubernetes/app.template.yaml @@ -0,0 +1,265 @@ +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" + name: YOUR_APP_NAME + labels: + app: YOUR_APP_NAME +spec: + ports: + - port: 26656 + name: p2p + - port: 26657 + name: rpc + clusterIP: None + selector: + app: tm +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: tm-config +data: + seeds: "tm-0,tm-1,tm-2,tm-3" + validators: "tm-0,tm-1,tm-2,tm-3" + validator.power: "10" + genesis.json: |- + { + "genesis_time": "2017-01-02T10:10:10.164Z", + "chain_id": "chain-B5XXm5", + "validators": [], + "app_hash": "" + } + pub_key_nginx.conf: |- + server { + listen 80 default_server; + listen [::]:80 default_server ipv6only=on; + location /pub_key.json { root /usr/share/nginx/; } + } +--- +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: tm-budget +spec: + selector: + matchLabels: + app: tm + minAvailable: 2 +--- +apiVersion: apps/v1beta1 +kind: StatefulSet +metadata: + name: tm +spec: + serviceName: YOUR_APP_NAME + replicas: 4 + template: + metadata: + labels: + app: tm + version: v1 + annotations: + pod.beta.kubernetes.io/init-containers: '[{ + "name": "tm-gen-validator", + "image": "tendermint/tendermint:0.10.0", + "imagePullPolicy": "IfNotPresent", + "command": ["bash", "-c", " + set -ex\n + if [ ! -f /tendermint/priv_validator.json ]; then\n + tendermint gen_validator > /tendermint/priv_validator.json\n + # pub_key.json will be served by pub-key container\n + cat /tendermint/priv_validator.json | jq \".pub_key\" > /tendermint/pub_key.json\n + fi\n + "], + "volumeMounts": [ + {"name": "tmdir", "mountPath": "/tendermint"} + ] + }]' + spec: + containers: + - name: tm + imagePullPolicy: IfNotPresent + image: tendermint/tendermint:0.10.0 + resources: + requests: + cpu: 50m + memory: 128Mi + limits: + cpu: 100m + memory: 256Mi + ports: + - containerPort: 26656 + name: p2p + - containerPort: 26657 + name: rpc + env: + - name: SEEDS + valueFrom: + configMapKeyRef: + name: tm-config + key: seeds + - name: VALIDATOR_POWER + valueFrom: + configMapKeyRef: + name: tm-config + key: validator.power + - name: VALIDATORS + valueFrom: + configMapKeyRef: + name: tm-config + key: validators + - name: TMHOME + value: /tendermint + command: + - bash + - "-c" + - | + set -ex + + # copy template + cp /etc/tendermint/genesis.json /tendermint/genesis.json + + # fill genesis file with validators + IFS=',' read -ra VALS_ARR <<< "$VALIDATORS" + fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#') + for v in "${VALS_ARR[@]}"; do + # wait until validator generates priv/pub key pair + set +e + + curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null + ERR=$? + while [ "$ERR" != 0 ]; do + sleep 5 + curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null + ERR=$? + done + set -e + + # add validator to genesis file along with its pub_key + curl -s "http://$v.$fqdn_suffix/pub_key.json" | jq ". as \$k | {pub_key: \$k, amount: $VALIDATOR_POWER, name: \"$v\"}" > pub_validator.json + cat /tendermint/genesis.json | jq ".validators |= .+ [$(cat pub_validator.json)]" > tmpgenesis && mv tmpgenesis /tendermint/genesis.json + rm pub_validator.json + done + + # construct seeds + IFS=',' read -ra SEEDS_ARR <<< "$SEEDS" + seeds=() + for s in "${SEEDS_ARR[@]}"; do + seeds+=("$s.$fqdn_suffix:26656") + done + seeds=$(IFS=','; echo "${seeds[*]}") + + tendermint node --p2p.seeds="$seeds" --moniker="`hostname`" --proxy_app="unix:///socks/app.sock" + volumeMounts: + - name: tmdir + mountPath: /tendermint + - mountPath: /etc/tendermint/genesis.json + name: configdir + subPath: genesis.json + - name: socksdir + mountPath: /socks + + - name: app + imagePullPolicy: IfNotPresent + image: YOUR_APP_IMAGE + args: ["--addr=\"unix:///socks/app.sock\""] + volumeMounts: + - name: socksdir + mountPath: /socks + + ######## OR ######## + # + # - name: app + # imagePullPolicy: IfNotPresent + # image: golang:1.7.5 + # resources: + # requests: + # cpu: YOUR_APP_CPU_REQ + # memory: YOUR_APP_MEM_REQ + # limits: + # cpu: YOUR_APP_CPU_LIMIT + # memory: YOUR_APP_MEM_LIMIT + # command: + # - bash + # - "-c" + # - | + # set -ex + + # go get -d YOUR_APP_PACKAGE + # cd $GOPATH/YOUR_APP_PACKAGE + # make install + # + # rm -f /socks/app.sock # remove old socket + + # YOUR_APP_EXEC --addr="unix:///socks/app.sock" + # volumeMounts: + # - name: socksdir + # mountPath: /socks + + ######## OPTIONALLY ######## + # + # - name: data + # imagePullPolicy: IfNotPresent + # image: golang:1.7.5 + # command: + # - bash + # - "-c" + # - | + # set -ex + # go get github.com/tendermint/merkleeyes/cmd/merkleeyes + # rm -f /socks/data.sock # remove old socket + # merkleeyes server --address="unix:///socks/data.sock" + # volumeMounts: + # - name: socksdir + # mountPath: /socks + + - name: pub-key + imagePullPolicy: IfNotPresent + image: nginx:1.11.9 + resources: + requests: + cpu: 10m + memory: 12Mi + limits: + cpu: 20m + memory: 24Mi + ports: + - containerPort: 80 + name: pub-key + command: + - bash + - "-c" + - | + set -ex + # fixes 403 Permission Denied (open() "/tendermint/pub_key.json" failed (13: Permission denied)) + # => we cannot serve from /tendermint, so we copy the file + mkdir -p /usr/share/nginx + cp /tendermint/pub_key.json /usr/share/nginx/pub_key.json + nginx -g "daemon off;" + volumeMounts: + - name: tmdir + mountPath: /tendermint + - mountPath: /etc/nginx/conf.d/pub_key.conf + name: configdir + subPath: pub_key_nginx.conf + + volumes: + - name: configdir + configMap: + name: tm-config + - name: socksdir + emptyDir: {} + + volumeClaimTemplates: + - metadata: + name: tmdir + annotations: + volume.alpha.kubernetes.io/storage-class: anything + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 2Gi diff --git a/tools/mintnet-kubernetes/assets/gce1.png b/tools/mintnet-kubernetes/assets/gce1.png new file mode 100644 index 000000000..3bf3ad005 Binary files /dev/null and b/tools/mintnet-kubernetes/assets/gce1.png differ diff --git a/tools/mintnet-kubernetes/assets/gce2.png b/tools/mintnet-kubernetes/assets/gce2.png new file mode 100644 index 000000000..358dcc04b Binary files /dev/null and b/tools/mintnet-kubernetes/assets/gce2.png differ diff --git a/tools/mintnet-kubernetes/assets/statefulset.png b/tools/mintnet-kubernetes/assets/statefulset.png new file mode 100644 index 000000000..ac68d22b7 Binary files /dev/null and b/tools/mintnet-kubernetes/assets/statefulset.png differ diff --git a/tools/mintnet-kubernetes/assets/t_plus_k.png b/tools/mintnet-kubernetes/assets/t_plus_k.png new file mode 100644 index 000000000..bee9fe56e Binary files /dev/null and b/tools/mintnet-kubernetes/assets/t_plus_k.png differ diff --git a/tools/mintnet-kubernetes/examples/basecoin/Makefile b/tools/mintnet-kubernetes/examples/basecoin/Makefile new file mode 100644 index 000000000..6d54d57d6 --- /dev/null +++ b/tools/mintnet-kubernetes/examples/basecoin/Makefile @@ -0,0 +1,10 @@ +create: + @echo "==> Creating deployment" + @kubectl create -f app.yaml + +destroy: + @echo "==> Destroying deployment" + @kubectl delete -f app.yaml + @kubectl delete pvc -l app=tm + +.PHONY: create destroy diff --git a/tools/mintnet-kubernetes/examples/basecoin/README.md b/tools/mintnet-kubernetes/examples/basecoin/README.md new file mode 100644 index 000000000..46911a096 --- /dev/null +++ b/tools/mintnet-kubernetes/examples/basecoin/README.md @@ -0,0 +1,42 @@ +# Basecoin example + +This is an example of using [basecoin](https://github.com/tendermint/basecoin). + +## Usage + +``` +make create +``` + +### Check account balance and send a transaction + +1. wait until all the pods are `Running`. + + ``` + kubectl get pods -w -o wide -L tm + ``` + +2. wait until app starts. + + ``` + kubectl logs -c app -f tm-0 + ``` + +3. get account's address of the second pod + + ``` + ADDR=`kubectl exec -c app tm-1 -- cat /app/key.json | jq ".address" | tr -d "\""` + ``` + +4. send 5 coins to it from the first pod + + ``` + kubectl exec -c app tm-0 -- basecoin tx send --to "0x$ADDR" --amount 5mycoin --from /app/key.json --chain_id chain-tTH4mi + ``` + + +## Clean up + +``` +make destroy +``` diff --git a/tools/mintnet-kubernetes/examples/basecoin/app.yaml b/tools/mintnet-kubernetes/examples/basecoin/app.yaml new file mode 100644 index 000000000..6206b1cdb --- /dev/null +++ b/tools/mintnet-kubernetes/examples/basecoin/app.yaml @@ -0,0 +1,334 @@ +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" + name: basecoin + labels: + app: basecoin +spec: + ports: + - port: 26656 + name: p2p + - port: 26657 + name: rpc + clusterIP: None + selector: + app: tm +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: tm-config +data: + seeds: "tm-0,tm-1,tm-2,tm-3" + validators: "tm-0,tm-1,tm-2,tm-3" + validator.power: "10" + genesis.json: |- + { + "genesis_time": "2016-02-05T06:02:31.526Z", + "chain_id": "chain-tTH4mi", + "validators": [], + "app_hash": "" + } + pub_key_nginx.conf: |- + server { + listen 80 default_server; + listen [::]:80 default_server ipv6only=on; + location /pub_key.json { root /usr/share/nginx/; } + location /app_pub_key.json { root /usr/share/nginx/; } + } +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: app-config +data: + genesis.json: |- + { + "chain_id": "chain-tTH4mi", + "app_options": { + "accounts": [ + { + "pub_key": "tm-0", + "coins": [ + { + "denom": "mycoin", + "amount": 1000000000 + } + ] + }, + { + "pub_key": "tm-1", + "coins": [ + { + "denom": "mycoin", + "amount": 1000000000 + } + ] + }, + { + "pub_key": "tm-2", + "coins": [ + { + "denom": "mycoin", + "amount": 1000000000 + } + ] + }, + { + "pub_key": "tm-3", + "coins": [ + { + "denom": "mycoin", + "amount": 1000000000 + } + ] + } + ] + } + } +--- +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: tm-budget +spec: + selector: + matchLabels: + app: tm + minAvailable: 2 +--- +apiVersion: apps/v1beta1 +kind: StatefulSet +metadata: + name: tm +spec: + serviceName: basecoin + replicas: 4 + template: + metadata: + labels: + app: tm + annotations: + pod.beta.kubernetes.io/init-containers: '[{ + "name": "tm-gen-validator", + "image": "tendermint/tendermint:0.10.0", + "imagePullPolicy": "IfNotPresent", + "command": ["bash", "-c", " + set -ex\n + if [ ! -f /tendermint/priv_validator.json ]; then\n + tendermint gen_validator > /tendermint/priv_validator.json\n + # pub_key.json will be served by pub-key container\n + cat /tendermint/priv_validator.json | jq \".pub_key\" > /tendermint/pub_key.json\n + fi\n + "], + "volumeMounts": [ + {"name": "tmdir", "mountPath": "/tendermint"} + ] + }, + { + "name": "app-gen-key", + "image": "tendermint/basecoin:0.5.1", + "imagePullPolicy": "IfNotPresent", + "command": ["bash", "-c", " + set -ex\n + if [ ! -f /app/key.json ]; then\n + basecoin key new > /app/key.json\n + # pub_key.json will be served by app-pub-key container\n + cat /app/key.json | jq \".pub_key\" > /app/pub_key.json\n + fi\n + "], + "volumeMounts": [ + {"name": "appdir", "mountPath": "/app"} + ] + }]' + spec: + containers: + - name: tm + imagePullPolicy: IfNotPresent + image: tendermint/tendermint:0.10.0 + ports: + - containerPort: 26656 + name: p2p + - containerPort: 26657 + name: rpc + env: + - name: SEEDS + valueFrom: + configMapKeyRef: + name: tm-config + key: seeds + - name: VALIDATOR_POWER + valueFrom: + configMapKeyRef: + name: tm-config + key: validator.power + - name: VALIDATORS + valueFrom: + configMapKeyRef: + name: tm-config + key: validators + - name: TMHOME + value: /tendermint + command: + - bash + - "-c" + - | + set -ex + + # copy template + cp /etc/tendermint/genesis.json /tendermint/genesis.json + + # fill genesis file with validators + IFS=',' read -ra VALS_ARR <<< "$VALIDATORS" + fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#') + for v in "${VALS_ARR[@]}"; do + # wait until validator generates priv/pub key pair + set +e + + curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null + ERR=$? + while [ "$ERR" != 0 ]; do + sleep 5 + curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null + ERR=$? + done + set -e + + # add validator to genesis file along with its pub_key + curl -s "http://$v.$fqdn_suffix/pub_key.json" | jq ". as \$k | {pub_key: \$k, amount: $VALIDATOR_POWER, name: \"$v\"}" > pub_validator.json + cat /tendermint/genesis.json | jq ".validators |= .+ [$(cat pub_validator.json)]" > tmpgenesis && mv tmpgenesis /tendermint/genesis.json + rm pub_validator.json + done + + # construct seeds + IFS=',' read -ra SEEDS_ARR <<< "$SEEDS" + seeds=() + for s in "${SEEDS_ARR[@]}"; do + seeds+=("$s.$fqdn_suffix:26656") + done + seeds=$(IFS=','; echo "${seeds[*]}") + + tendermint node --p2p.seeds="$seeds" --moniker="`hostname`" --proxy_app="unix:///socks/app.sock" + volumeMounts: + - name: tmdir + mountPath: /tendermint + - mountPath: /etc/tendermint/genesis.json + name: tmconfigdir + subPath: genesis.json + - name: socksdir + mountPath: /socks + + - name: app + imagePullPolicy: IfNotPresent + image: tendermint/basecoin:0.5.1 + env: + - name: BCHOME + value: /app + workingDir: /app + command: + - bash + - "-c" + - | + set -ex + + # replace "tm-N" with public keys in genesis file + cp /etc/app/genesis.json genesis.json + fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#') + # for every "base/account" + i=0 + length=$(cat genesis.json | jq ".app_options.accounts | length") + while [[ $i -lt $length ]]; do + # extract pod name ("tm-0") + pod=$(cat genesis.json | jq -r ".app_options.accounts[$i].pub_key") + + # wait until pod starts to serve its pub_key + set +e + + curl -s --fail "http://$pod.$fqdn_suffix/app_pub_key.json" > /dev/null + ERR=$? + while [ "$ERR" != 0 ]; do + sleep 5 + curl -s --fail "http://$pod.$fqdn_suffix/app_pub_key.json" > /dev/null + ERR=$? + done + set -e + + # get its pub_key + curl -s "http://$pod.$fqdn_suffix/app_pub_key.json" | jq "." > k.json + + # replace pod name with it ("tm-0" => "{"type": ..., "data": ...}") + cat genesis.json | jq ".app_options.accounts[$i].pub_key = $(cat k.json | jq '.')" > tmpgenesis && mv tmpgenesis genesis.json + rm -f k.json + + i=$((i+1)) + done + + rm -f /socks/app.sock # remove old socket + + basecoin start --address="unix:///socks/app.sock" --without-tendermint + volumeMounts: + - name: appdir + mountPath: /app + - mountPath: /etc/app/genesis.json + name: appconfigdir + subPath: genesis.json + - name: socksdir + mountPath: /socks + + - name: pub-key + imagePullPolicy: IfNotPresent + image: nginx:latest + ports: + - containerPort: 80 + command: + - bash + - "-c" + - | + set -ex + # fixes 403 Permission Denied (open() "/tendermint/pub_key.json" failed (13: Permission denied)) + # => we cannot serve from /tendermint, so we copy the file + mkdir -p /usr/share/nginx + cp /tendermint/pub_key.json /usr/share/nginx/pub_key.json + cp /app/pub_key.json /usr/share/nginx/app_pub_key.json + nginx -g "daemon off;" + volumeMounts: + - name: tmdir + mountPath: /tendermint + - name: appdir + mountPath: /app + - mountPath: /etc/nginx/conf.d/pub_key.conf + name: tmconfigdir + subPath: pub_key_nginx.conf + + volumes: + - name: tmconfigdir + configMap: + name: tm-config + - name: appconfigdir + configMap: + name: app-config + - name: socksdir + emptyDir: {} + + volumeClaimTemplates: + - metadata: + name: tmdir + annotations: + volume.alpha.kubernetes.io/storage-class: anything + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 2Gi + - metadata: + name: appdir + annotations: + volume.alpha.kubernetes.io/storage-class: anything + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 12Mi diff --git a/tools/mintnet-kubernetes/examples/basecoin/lightclient.md b/tools/mintnet-kubernetes/examples/basecoin/lightclient.md new file mode 100644 index 000000000..11d07af1f --- /dev/null +++ b/tools/mintnet-kubernetes/examples/basecoin/lightclient.md @@ -0,0 +1,100 @@ +**OUTDATED** + +# Using with lightclient + +We have an awesome cluster running, let's try to test this out without +relying on executing commands on the cluster. Rather, we can connect to the +rpc interface with the `light-client` package and execute commands locally, +or even proxy our webapp to the kubernetes backend. + +## Setup + +In order to get this working, we need to know a few pieces of info, +the chain id of tendermint, the chain id of basecoin, and an account +with a bit of cash.... + +### Tendermint Chain ID + +`kubectl exec -c tm tm-0 -- curl -s http://tm-1.basecoin:26657/status | json_pp | grep network` + +set TM_CHAIN with the value there + +### Basecoin Chain ID + +`kubectl exec -c app tm-1 -- grep -A1 chainID /app/genesis.json` + +set BC_CHAIN with the value there + +### Expose tendermint rpc + +We need to be able to reach the tendermint rpc interface from our shell. + +`kubectl port-forward tm-0 26657:26657` + +### Start basecoin-proxy + +Using this info, let's connect our proxy and get going + +`proxy-basecoin -tmchain=$TM_CHAIN -chain=$BC_CHAIN -rpc=localhost:26657` + +## Basecoin accounts + +Well, we can connect, but we don't have a registered account yet... +Let's look around, then use the cli to send some money from one of +the validators to our client's address so we can play. + +**TODO** we can add some of our known accounts (from `/keys`) into +the genesis file, so we can skip all the kubectl money fiddling here. +We will want to start with money on some known non-validators. + +### Getting validator info (kubectl) + +The basecoin app deployment starts with 1000 "blank" coin in an account of +each validator. Let's get the address of the first validator + +`kubectl exec -c app tm-1 -- grep address /app/key.json` + +Store this info as VAL1_ADDR + +### Querying state (proxy) + +The proxy can read any public info via the tendermint rpc, so let's check +out this account. + +`curl localhost:8108/query/account/$VAL1_ADDR` + +Now, let's make out own account.... + +`curl -XPOST http://localhost:8108/keys/ -d '{"name": "k8demo", "passphrase": "1234567890"}'` + +(or pick your own user and password). Remember the address you get here. You can +always find it out later by calling: + +`curl http://localhost:8108/keys/k8demo` + +and store it in DEMO_ADDR, which is empty at first + +`curl localhost:8108/query/account/$DEMO_ADDR` + + +### "Stealing" validator cash (kubectl) + +Run one command, that will be signed, now we have money + +`kubectl exec -c app tm-0 -- basecoin tx send --to --amount 500` + +### Using our money + +Returning to our remote shell, we have a remote account with some money. +Let's see that. + +`curl localhost:8108/query/account/$DEMO_ADDR` + +Cool. Now we need to send it to a second account. + +`curl -XPOST http://localhost:8108/keys/ -d '{"name": "buddy", "passphrase": "1234567890"}'` + +and store the resulting address in BUDDY_ADDR + +**TODO** finish this + diff --git a/tools/mintnet-kubernetes/examples/counter/Makefile b/tools/mintnet-kubernetes/examples/counter/Makefile new file mode 100644 index 000000000..6d54d57d6 --- /dev/null +++ b/tools/mintnet-kubernetes/examples/counter/Makefile @@ -0,0 +1,10 @@ +create: + @echo "==> Creating deployment" + @kubectl create -f app.yaml + +destroy: + @echo "==> Destroying deployment" + @kubectl delete -f app.yaml + @kubectl delete pvc -l app=tm + +.PHONY: create destroy diff --git a/tools/mintnet-kubernetes/examples/counter/app.yaml b/tools/mintnet-kubernetes/examples/counter/app.yaml new file mode 100644 index 000000000..fed35f102 --- /dev/null +++ b/tools/mintnet-kubernetes/examples/counter/app.yaml @@ -0,0 +1,214 @@ +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" + name: counter + labels: + app: counter +spec: + ports: + - port: 26656 + name: p2p + - port: 26657 + name: rpc + clusterIP: None + selector: + app: tm +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: tm-config +data: + seeds: "tm-0,tm-1,tm-2,tm-3" + validators: "tm-0,tm-1,tm-2,tm-3" + validator.power: "10" + genesis.json: |- + { + "genesis_time": "2016-02-05T23:17:31.164Z", + "chain_id": "chain-B5XXm5", + "validators": [], + "app_hash": "" + } + pub_key_nginx.conf: |- + server { + listen 80 default_server; + listen [::]:80 default_server ipv6only=on; + location /pub_key.json { root /usr/share/nginx/; } + } +--- +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: tm-budget +spec: + selector: + matchLabels: + app: tm + minAvailable: 2 +--- +apiVersion: apps/v1beta1 +kind: StatefulSet +metadata: + name: tm +spec: + serviceName: counter + replicas: 4 + template: + metadata: + labels: + app: tm + annotations: + pod.beta.kubernetes.io/init-containers: '[{ + "name": "tm-gen-validator", + "image": "tendermint/tendermint:0.10.0", + "imagePullPolicy": "IfNotPresent", + "command": ["bash", "-c", " + set -ex\n + if [ ! -f /tendermint/priv_validator.json ]; then\n + tendermint gen_validator > /tendermint/priv_validator.json\n + # pub_key.json will be served by pub-key container\n + cat /tendermint/priv_validator.json | jq \".pub_key\" > /tendermint/pub_key.json\n + fi\n + "], + "volumeMounts": [ + {"name": "tmdir", "mountPath": "/tendermint"} + ] + }]' + spec: + containers: + - name: tm + imagePullPolicy: IfNotPresent + image: tendermint/tendermint:0.10.0 + ports: + - containerPort: 26656 + name: p2p + - containerPort: 26657 + name: rpc + env: + - name: SEEDS + valueFrom: + configMapKeyRef: + name: tm-config + key: seeds + - name: VALIDATOR_POWER + valueFrom: + configMapKeyRef: + name: tm-config + key: validator.power + - name: VALIDATORS + valueFrom: + configMapKeyRef: + name: tm-config + key: validators + - name: TMHOME + value: /tendermint + command: + - bash + - "-c" + - | + set -ex + + # copy template + cp /etc/tendermint/genesis.json /tendermint/genesis.json + + # fill genesis file with validators + IFS=',' read -ra VALS_ARR <<< "$VALIDATORS" + fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#') + for v in "${VALS_ARR[@]}"; do + # wait until validator generates priv/pub key pair + set +e + + curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null + ERR=$? + while [ "$ERR" != 0 ]; do + sleep 5 + curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null + ERR=$? + done + set -e + + # add validator to genesis file along with its pub_key + curl -s "http://$v.$fqdn_suffix/pub_key.json" | jq ". as \$k | {pub_key: \$k, amount: $VALIDATOR_POWER, name: \"$v\"}" > pub_validator.json + cat /tendermint/genesis.json | jq ".validators |= .+ [$(cat pub_validator.json)]" > tmpgenesis && mv tmpgenesis /tendermint/genesis.json + rm pub_validator.json + done + + # construct seeds + IFS=',' read -ra SEEDS_ARR <<< "$SEEDS" + seeds=() + for s in "${SEEDS_ARR[@]}"; do + seeds+=("$s.$fqdn_suffix:26656") + done + seeds=$(IFS=','; echo "${seeds[*]}") + + tendermint node --p2p.seeds="$seeds" --moniker="`hostname`" --proxy_app="unix:///socks/app.sock" + volumeMounts: + - name: tmdir + mountPath: /tendermint + - mountPath: /etc/tendermint/genesis.json + name: tmconfigdir + subPath: genesis.json + - name: socksdir + mountPath: /socks + + - name: app + imagePullPolicy: IfNotPresent + image: golang:latest + command: + - bash + - "-c" + - | + set -ex + + go get github.com/tendermint/abci/cmd/counter + + rm -f /socks/app.sock # remove old socket + + counter --serial --addr="unix:///socks/app.sock" + volumeMounts: + - name: socksdir + mountPath: /socks + + - name: pub-key + imagePullPolicy: IfNotPresent + image: nginx:latest + ports: + - containerPort: 80 + name: pub-key + command: + - bash + - "-c" + - | + set -ex + # fixes 403 Permission Denied (open() "/tendermint/pub_key.json" failed (13: Permission denied)) + # => we cannot serve from /tendermint, so we copy the file + mkdir -p /usr/share/nginx + cp /tendermint/pub_key.json /usr/share/nginx/pub_key.json + nginx -g "daemon off;" + volumeMounts: + - name: tmdir + mountPath: /tendermint + - mountPath: /etc/nginx/conf.d/pub_key.conf + name: tmconfigdir + subPath: pub_key_nginx.conf + + volumes: + - name: tmconfigdir + configMap: + name: tm-config + - name: socksdir + emptyDir: {} + + volumeClaimTemplates: + - metadata: + name: tmdir + annotations: + volume.alpha.kubernetes.io/storage-class: anything + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 2Gi diff --git a/tools/mintnet-kubernetes/examples/dummy/Makefile b/tools/mintnet-kubernetes/examples/dummy/Makefile new file mode 100644 index 000000000..825487fcd --- /dev/null +++ b/tools/mintnet-kubernetes/examples/dummy/Makefile @@ -0,0 +1,17 @@ +create: + @echo "==> Creating deployment" + @kubectl create -f app.yaml + @echo "==> Waiting 10s until it is probably ready" + @sleep 10 + @echo "==> Creating monitor and transacter pods" + @kubectl create -f tm-monitor-pod.yaml + @kubectl create -f transacter-pod.yaml + +destroy: + @echo "==> Destroying deployment" + @kubectl delete -f transacter-pod.yaml + @kubectl delete -f tm-monitor-pod.yaml + @kubectl delete -f app.yaml + @kubectl delete pvc -l app=tm + +.PHONY: create destroy diff --git a/tools/mintnet-kubernetes/examples/dummy/app.yaml b/tools/mintnet-kubernetes/examples/dummy/app.yaml new file mode 100644 index 000000000..5413bd501 --- /dev/null +++ b/tools/mintnet-kubernetes/examples/dummy/app.yaml @@ -0,0 +1,196 @@ +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" + name: dummy + labels: + app: dummy +spec: + ports: + - port: 26656 + name: p2p + - port: 26657 + name: rpc + clusterIP: None + selector: + app: tm +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: tm-config +data: + seeds: "tm-0,tm-1,tm-2,tm-3" + validators: "tm-0,tm-1,tm-2,tm-3" + validator.power: "10" + genesis.json: |- + { + "genesis_time": "2016-02-05T23:17:31.164Z", + "chain_id": "chain-B5XXm5", + "validators": [], + "app_hash": "" + } + pub_key_nginx.conf: |- + server { + listen 80 default_server; + listen [::]:80 default_server ipv6only=on; + location /pub_key.json { root /usr/share/nginx/; } + } +--- +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: tm-budget +spec: + selector: + matchLabels: + app: tm + minAvailable: 2 +--- +apiVersion: apps/v1beta1 +kind: StatefulSet +metadata: + name: tm +spec: + serviceName: dummy + replicas: 4 + template: + metadata: + labels: + app: tm + annotations: + pod.beta.kubernetes.io/init-containers: '[{ + "name": "tm-gen-validator", + "image": "tendermint/tendermint:0.10.0", + "imagePullPolicy": "IfNotPresent", + "command": ["bash", "-c", " + set -ex\n + if [ ! -f /tendermint/priv_validator.json ]; then\n + tendermint gen_validator > /tendermint/priv_validator.json\n + # pub_key.json will be served by pub-key container\n + cat /tendermint/priv_validator.json | jq \".pub_key\" > /tendermint/pub_key.json\n + fi\n + "], + "volumeMounts": [ + {"name": "tmdir", "mountPath": "/tendermint"} + ] + }]' + spec: + containers: + - name: tm + imagePullPolicy: IfNotPresent + image: tendermint/tendermint:0.10.0 + ports: + - containerPort: 26656 + name: p2p + - containerPort: 26657 + name: rpc + env: + - name: SEEDS + valueFrom: + configMapKeyRef: + name: tm-config + key: seeds + - name: VALIDATOR_POWER + valueFrom: + configMapKeyRef: + name: tm-config + key: validator.power + - name: VALIDATORS + valueFrom: + configMapKeyRef: + name: tm-config + key: validators + - name: TMHOME + value: /tendermint + command: + - bash + - "-c" + - | + set -ex + + # copy template + cp /etc/tendermint/genesis.json /tendermint/genesis.json + + # fill genesis file with validators + IFS=',' read -ra VALS_ARR <<< "$VALIDATORS" + fqdn_suffix=$(hostname -f | sed 's#[^.]*\.\(\)#\1#') + for v in "${VALS_ARR[@]}"; do + # wait until validator generates priv/pub key pair + set +e + + curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null + ERR=$? + while [ "$ERR" != 0 ]; do + sleep 5 + curl -s --fail "http://$v.$fqdn_suffix/pub_key.json" > /dev/null + ERR=$? + done + set -e + + # add validator to genesis file along with its pub_key + curl -s "http://$v.$fqdn_suffix/pub_key.json" | jq ". as \$k | {pub_key: \$k, amount: $VALIDATOR_POWER, name: \"$v\"}" > pub_validator.json + cat /tendermint/genesis.json | jq ".validators |= .+ [$(cat pub_validator.json)]" > tmpgenesis && mv tmpgenesis /tendermint/genesis.json + rm pub_validator.json + done + + # construct seeds + IFS=',' read -ra SEEDS_ARR <<< "$SEEDS" + seeds=() + for s in "${SEEDS_ARR[@]}"; do + seeds+=("$s.$fqdn_suffix:26656") + done + seeds=$(IFS=','; echo "${seeds[*]}") + + tendermint node --p2p.seeds="$seeds" --moniker="`hostname`" --proxy_app="dummy" + volumeMounts: + - name: tmdir + mountPath: /tendermint + - mountPath: /etc/tendermint/genesis.json + name: tmconfigdir + subPath: genesis.json + - name: socksdir + mountPath: /socks + + - name: pub-key + imagePullPolicy: IfNotPresent + image: nginx:latest + ports: + - containerPort: 80 + name: pub-key + command: + - bash + - "-c" + - | + set -ex + # fixes 403 Permission Denied (open() "/tendermint/pub_key.json" failed (13: Permission denied)) + # => we cannot serve from /tendermint, so we copy the file + mkdir -p /usr/share/nginx + cp /tendermint/pub_key.json /usr/share/nginx/pub_key.json + nginx -g "daemon off;" + volumeMounts: + - name: tmdir + mountPath: /tendermint + - mountPath: /etc/nginx/conf.d/pub_key.conf + name: tmconfigdir + subPath: pub_key_nginx.conf + + volumes: + - name: tmconfigdir + configMap: + name: tm-config + - name: socksdir + emptyDir: {} + + volumeClaimTemplates: + - metadata: + name: tmdir + annotations: + volume.alpha.kubernetes.io/storage-class: anything + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 2Gi diff --git a/tools/mintnet-kubernetes/examples/dummy/tm-monitor-pod.yaml b/tools/mintnet-kubernetes/examples/dummy/tm-monitor-pod.yaml new file mode 100644 index 000000000..fb0bf7236 --- /dev/null +++ b/tools/mintnet-kubernetes/examples/dummy/tm-monitor-pod.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: v1 +kind: Pod +metadata: + name: monitor +spec: + containers: + - name: monitor + image: tendermint/monitor + args: ["-listen-addr=tcp://0.0.0.0:26670", "tm-0.dummy:26657,tm-1.dummy:26657,tm-2.dummy:26657,tm-3.dummy:26657"] + ports: + - containerPort: 26670 + name: rpc diff --git a/tools/mintnet-kubernetes/examples/dummy/transacter-pod.yaml b/tools/mintnet-kubernetes/examples/dummy/transacter-pod.yaml new file mode 100644 index 000000000..6598e2a8b --- /dev/null +++ b/tools/mintnet-kubernetes/examples/dummy/transacter-pod.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: v1 +kind: Pod +metadata: + name: transacter +spec: + containers: + - name: transacter + image: tendermint/transacter + command: + - bash + - "-c" + - | + set -ex + while true + do + ./transact 100 "tm-0.dummy:26657" + sleep 1 + done diff --git a/tools/tm-bench/Dockerfile b/tools/tm-bench/Dockerfile new file mode 100644 index 000000000..9adb2936e --- /dev/null +++ b/tools/tm-bench/Dockerfile @@ -0,0 +1,6 @@ +FROM alpine:3.7 + +WORKDIR /app +COPY tm-bench /app/tm-bench + +ENTRYPOINT ["./tm-bench"] diff --git a/tools/tm-bench/Dockerfile.dev b/tools/tm-bench/Dockerfile.dev new file mode 100644 index 000000000..469bb8150 --- /dev/null +++ b/tools/tm-bench/Dockerfile.dev @@ -0,0 +1,12 @@ +FROM golang:latest + +RUN mkdir -p /go/src/github.com/tendermint/tendermint/tools/tm-bench +WORKDIR /go/src/github.com/tendermint/tendermint/tools/tm-bench + +COPY Makefile /go/src/github.com/tendermint/tendermint/tools/tm-bench/ + +RUN make get_tools + +COPY . /go/src/github.com/tendermint/tendermint/tools/tm-bench + +RUN make get_vendor_deps diff --git a/tools/tm-bench/LICENSE b/tools/tm-bench/LICENSE new file mode 100644 index 000000000..f48913967 --- /dev/null +++ b/tools/tm-bench/LICENSE @@ -0,0 +1,204 @@ +Tendermint Bench +Copyright 2017 Tendermint + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/tools/tm-bench/Makefile b/tools/tm-bench/Makefile new file mode 100644 index 000000000..2d427dbc1 --- /dev/null +++ b/tools/tm-bench/Makefile @@ -0,0 +1,50 @@ +DIST_DIRS := find * -type d -exec +VERSION := $(shell perl -ne '/^var version.*"([^"]+)".*$$/ && print "v$$1\n"' main.go) + +all: build test install + +######################################## +### Build + +build: + @go build + +install: + @go install + +test: + @go test -race + +build-all: check_tools + rm -rf ./dist + gox -verbose \ + -ldflags "-s -w" \ + -arch="amd64 386 arm arm64" \ + -os="linux darwin windows freebsd" \ + -osarch="!darwin/arm !darwin/arm64" \ + -output="dist/{{.OS}}-{{.Arch}}/{{.Dir}}" . + +dist: build-all + cd dist && \ + $(DIST_DIRS) cp ../LICENSE {} \; && \ + $(DIST_DIRS) cp ../README.rst {} \; && \ + $(DIST_DIRS) tar -zcf tm-bench-${VERSION}-{}.tar.gz {} \; && \ + shasum -a256 ./*.tar.gz > "./tm-bench_${VERSION}_SHA256SUMS" && \ + cd .. + +######################################## +### Docker + +build-docker: + rm -f ./tm-bench + docker run -it --rm -v "$(PWD):/go/src/app" -w "/go/src/app" -e "CGO_ENABLED=0" golang:alpine go build -ldflags "-s -w" -o tm-bench + docker build -t "tendermint/bench" . + +clean: + rm -f ./tm-bench + rm -rf ./dist + +# To avoid unintended conflicts with file names, always add to .PHONY +# unless there is a reason not to. +# https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html +.PHONY: check check_tools get_tools update_tools get_vendor_deps build install test build-all dist fmt metalinter metalinter_all build-docker clean diff --git a/tools/tm-bench/README.md b/tools/tm-bench/README.md new file mode 100644 index 000000000..000f20f37 --- /dev/null +++ b/tools/tm-bench/README.md @@ -0,0 +1,80 @@ +# tm-bench + +Tendermint blockchain benchmarking tool: + +- https://github.com/tendermint/tools/tree/master/tm-bench + +For example, the following: + + tm-bench -T 10 -r 1000 localhost:26657 + +will output: + + Stats Avg StdDev Max Total + Txs/sec 818 532 1549 9000 + Blocks/sec 0.818 0.386 1 9 + + +## Quick Start + +[Install Tendermint](https://github.com/tendermint/tendermint#install) +This currently is setup to work on tendermint's develop branch. Please ensure +you are on that. (If not, update `tendermint` and `tmlibs` in gopkg.toml to use + the master branch.) + +then run: + + tendermint init + tendermint node --proxy_app=kvstore + + tm-bench localhost:26657 + +with the last command being in a seperate window. + +## Usage + + tm-bench [-c 1] [-T 10] [-r 1000] [-s 250] [endpoints] + + Examples: + tm-bench localhost:26657 + Flags: + -T int + Exit after the specified amount of time in seconds (default 10) + -c int + Connections to keep open per endpoint (default 1) + -r int + Txs per second to send in a connection (default 1000) + -s int + Size per tx in bytes + -v Verbose output + +## How stats are collected + +These stats are derived by having each connection send transactions at the +specified rate (or as close as it can get) for the specified time. +After the specified time, it iterates over all of the blocks that were created +in that time. +The average and stddev per second are computed based off of that, by +grouping the data by second. + +To send transactions at the specified rate in each connection, we loop +through the number of transactions. +If its too slow, the loop stops at one second. +If its too fast, we wait until the one second mark ends. +The transactions per second stat is computed based off of what ends up in the +block. + +Note that there will be edge effects on the number of transactions in the first +and last blocks. +This is because transactions may start sending midway through when tendermint +starts building the next block, so it only has half as much time to gather txs +that tm-bench sends. +Similarly the end of the duration will likely end mid-way through tendermint +trying to build the next block. + +Each of the connections is handled via two separate goroutines. + +## Development + + make get_vendor_deps + make test diff --git a/tools/tm-bench/main.go b/tools/tm-bench/main.go new file mode 100644 index 000000000..a8ede4a0c --- /dev/null +++ b/tools/tm-bench/main.go @@ -0,0 +1,175 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + "sync" + "time" + + "github.com/go-kit/kit/log/term" + + "github.com/tendermint/tendermint/libs/log" + tmrpc "github.com/tendermint/tendermint/rpc/client" +) + +var logger = log.NewNopLogger() + +func main() { + var durationInt, txsRate, connections, txSize int + var verbose bool + var outputFormat, broadcastTxMethod string + + flagSet := flag.NewFlagSet("tm-bench", flag.ExitOnError) + flagSet.IntVar(&connections, "c", 1, "Connections to keep open per endpoint") + flagSet.IntVar(&durationInt, "T", 10, "Exit after the specified amount of time in seconds") + flagSet.IntVar(&txsRate, "r", 1000, "Txs per second to send in a connection") + flagSet.IntVar(&txSize, "s", 250, "The size of a transaction in bytes.") + flagSet.StringVar(&outputFormat, "output-format", "plain", "Output format: plain or json") + flagSet.StringVar(&broadcastTxMethod, "broadcast-tx-method", "async", "Broadcast method: async (no guarantees; fastest), sync (ensures tx is checked) or commit (ensures tx is checked and committed; slowest)") + flagSet.BoolVar(&verbose, "v", false, "Verbose output") + + flagSet.Usage = func() { + fmt.Println(`Tendermint blockchain benchmarking tool. + +Usage: + tm-bench [-c 1] [-T 10] [-r 1000] [-s 250] [endpoints] [-output-format [-broadcast-tx-method ]] + +Examples: + tm-bench localhost:26657`) + fmt.Println("Flags:") + flagSet.PrintDefaults() + } + + flagSet.Parse(os.Args[1:]) + + if flagSet.NArg() == 0 { + flagSet.Usage() + os.Exit(1) + } + + if verbose { + if outputFormat == "json" { + fmt.Fprintln(os.Stderr, "Verbose mode not supported with json output.") + os.Exit(1) + } + // Color errors red + colorFn := func(keyvals ...interface{}) term.FgBgColor { + for i := 1; i < len(keyvals); i += 2 { + if _, ok := keyvals[i].(error); ok { + return term.FgBgColor{Fg: term.White, Bg: term.Red} + } + } + return term.FgBgColor{} + } + logger = log.NewTMLoggerWithColorFn(log.NewSyncWriter(os.Stdout), colorFn) + + fmt.Printf("Running %ds test @ %s\n", durationInt, flagSet.Arg(0)) + } + + if broadcastTxMethod != "async" && + broadcastTxMethod != "sync" && + broadcastTxMethod != "commit" { + fmt.Fprintln( + os.Stderr, + "broadcast-tx-method should be either 'sync', 'async' or 'commit'.", + ) + os.Exit(1) + } + + var ( + endpoints = strings.Split(flagSet.Arg(0), ",") + client = tmrpc.NewHTTP(endpoints[0], "/websocket") + initialHeight = latestBlockHeight(client) + ) + logger.Info("Latest block height", "h", initialHeight) + + transacters := startTransacters( + endpoints, + connections, + txsRate, + txSize, + "broadcast_tx_"+broadcastTxMethod, + ) + + // Wait until transacters have begun until we get the start time + timeStart := time.Now() + logger.Info("Time last transacter started", "t", timeStart) + + duration := time.Duration(durationInt) * time.Second + + timeEnd := timeStart.Add(duration) + logger.Info("End time for calculation", "t", timeEnd) + + <-time.After(duration) + for i, t := range transacters { + t.Stop() + numCrashes := countCrashes(t.connsBroken) + if numCrashes != 0 { + fmt.Printf("%d connections crashed on transacter #%d\n", numCrashes, i) + } + } + + logger.Debug("Time all transacters stopped", "t", time.Now()) + + stats, err := calculateStatistics( + client, + initialHeight, + timeStart, + durationInt, + ) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + printStatistics(stats, outputFormat) +} + +func latestBlockHeight(client tmrpc.Client) int64 { + status, err := client.Status() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + return status.SyncInfo.LatestBlockHeight +} + +func countCrashes(crashes []bool) int { + count := 0 + for i := 0; i < len(crashes); i++ { + if crashes[i] { + count++ + } + } + return count +} + +func startTransacters( + endpoints []string, + connections, + txsRate int, + txSize int, + broadcastTxMethod string, +) []*transacter { + transacters := make([]*transacter, len(endpoints)) + + wg := sync.WaitGroup{} + wg.Add(len(endpoints)) + for i, e := range endpoints { + t := newTransacter(e, connections, txsRate, txSize, broadcastTxMethod) + t.SetLogger(logger) + go func(i int) { + defer wg.Done() + if err := t.Start(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + transacters[i] = t + }(i) + } + wg.Wait() + + return transacters +} diff --git a/tools/tm-bench/statistics.go b/tools/tm-bench/statistics.go new file mode 100644 index 000000000..5a8f60578 --- /dev/null +++ b/tools/tm-bench/statistics.go @@ -0,0 +1,150 @@ +package main + +import ( + "encoding/json" + "fmt" + "math" + "os" + "text/tabwriter" + "time" + + metrics "github.com/rcrowley/go-metrics" + tmrpc "github.com/tendermint/tendermint/rpc/client" + "github.com/tendermint/tendermint/types" +) + +type statistics struct { + TxsThroughput metrics.Histogram `json:"txs_per_sec"` + BlocksThroughput metrics.Histogram `json:"blocks_per_sec"` +} + +// calculateStatistics calculates the tx / second, and blocks / second based +// off of the number the transactions and number of blocks that occurred from +// the start block, and the end time. +func calculateStatistics( + client tmrpc.Client, + minHeight int64, + timeStart time.Time, + duration int, +) (*statistics, error) { + timeEnd := timeStart.Add(time.Duration(duration) * time.Second) + + stats := &statistics{ + BlocksThroughput: metrics.NewHistogram(metrics.NewUniformSample(1000)), + TxsThroughput: metrics.NewHistogram(metrics.NewUniformSample(1000)), + } + + var ( + numBlocksPerSec = make(map[int64]int64) + numTxsPerSec = make(map[int64]int64) + ) + + // because during some seconds blocks won't be created... + for i := int64(0); i < int64(duration); i++ { + numBlocksPerSec[i] = 0 + numTxsPerSec[i] = 0 + } + + blockMetas, err := getBlockMetas(client, minHeight, timeStart, timeEnd) + if err != nil { + return nil, err + } + + // iterates from max height to min height + for _, blockMeta := range blockMetas { + // check if block was created after timeStart + if blockMeta.Header.Time.Before(timeStart) { + break + } + + // check if block was created before timeEnd + if blockMeta.Header.Time.After(timeEnd) { + continue + } + sec := secondsSinceTimeStart(timeStart, blockMeta.Header.Time) + + // increase number of blocks for that second + numBlocksPerSec[sec]++ + + // increase number of txs for that second + numTxsPerSec[sec] += blockMeta.Header.NumTxs + logger.Debug(fmt.Sprintf("%d txs at block height %d", blockMeta.Header.NumTxs, blockMeta.Header.Height)) + } + + for i := int64(0); i < int64(duration); i++ { + stats.BlocksThroughput.Update(numBlocksPerSec[i]) + stats.TxsThroughput.Update(numTxsPerSec[i]) + } + + return stats, nil +} + +func getBlockMetas(client tmrpc.Client, minHeight int64, timeStart, timeEnd time.Time) ([]*types.BlockMeta, error) { + // get blocks between minHeight and last height + // This returns max(minHeight,(last_height - 20)) to last_height + info, err := client.BlockchainInfo(minHeight, 0) + if err != nil { + return nil, err + } + + var ( + blockMetas = info.BlockMetas + lastHeight = info.LastHeight + diff = lastHeight - minHeight + offset = len(blockMetas) + ) + + for offset < int(diff) { + // get blocks between minHeight and last height + info, err := client.BlockchainInfo(minHeight, lastHeight-int64(offset)) + if err != nil { + return nil, err + } + blockMetas = append(blockMetas, info.BlockMetas...) + offset = len(blockMetas) + } + + return blockMetas, nil +} + +func secondsSinceTimeStart(timeStart, timePassed time.Time) int64 { + return int64(math.Round(timePassed.Sub(timeStart).Seconds())) +} + +func printStatistics(stats *statistics, outputFormat string) { + if outputFormat == "json" { + result, err := json.Marshal(struct { + TxsThroughput float64 `json:"txs_per_sec_avg"` + BlocksThroughput float64 `json:"blocks_per_sec_avg"` + }{stats.TxsThroughput.Mean(), stats.BlocksThroughput.Mean()}) + + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + fmt.Println(string(result)) + } else { + w := tabwriter.NewWriter(os.Stdout, 0, 0, 5, ' ', 0) + fmt.Fprintln(w, "Stats\tAvg\tStdDev\tMax\tTotal\t") + fmt.Fprintln( + w, + fmt.Sprintf( + "Txs/sec\t%.0f\t%.0f\t%d\t%d\t", + stats.TxsThroughput.Mean(), + stats.TxsThroughput.StdDev(), + stats.TxsThroughput.Max(), + stats.TxsThroughput.Sum(), + ), + ) + fmt.Fprintln( + w, + fmt.Sprintf("Blocks/sec\t%.3f\t%.3f\t%d\t%d\t", + stats.BlocksThroughput.Mean(), + stats.BlocksThroughput.StdDev(), + stats.BlocksThroughput.Max(), + stats.BlocksThroughput.Sum(), + ), + ) + w.Flush() + } +} diff --git a/tools/tm-bench/transacter.go b/tools/tm-bench/transacter.go new file mode 100644 index 000000000..36cc761e5 --- /dev/null +++ b/tools/tm-bench/transacter.go @@ -0,0 +1,284 @@ +package main + +import ( + "crypto/md5" + "encoding/binary" + "encoding/hex" + "encoding/json" + "fmt" + "math/rand" + "net" + "net/http" + "net/url" + "os" + "sync" + "time" + + "github.com/gorilla/websocket" + "github.com/pkg/errors" + + "github.com/tendermint/tendermint/libs/log" + rpctypes "github.com/tendermint/tendermint/rpc/lib/types" +) + +const ( + sendTimeout = 10 * time.Second + // see https://github.com/tendermint/tendermint/blob/master/rpc/lib/server/handlers.go + pingPeriod = (30 * 9 / 10) * time.Second +) + +type transacter struct { + Target string + Rate int + Size int + Connections int + BroadcastTxMethod string + + conns []*websocket.Conn + connsBroken []bool + startingWg sync.WaitGroup + endingWg sync.WaitGroup + stopped bool + + logger log.Logger +} + +func newTransacter(target string, connections, rate int, size int, broadcastTxMethod string) *transacter { + return &transacter{ + Target: target, + Rate: rate, + Size: size, + Connections: connections, + BroadcastTxMethod: broadcastTxMethod, + conns: make([]*websocket.Conn, connections), + connsBroken: make([]bool, connections), + logger: log.NewNopLogger(), + } +} + +// SetLogger lets you set your own logger +func (t *transacter) SetLogger(l log.Logger) { + t.logger = l +} + +// Start opens N = `t.Connections` connections to the target and creates read +// and write goroutines for each connection. +func (t *transacter) Start() error { + t.stopped = false + + rand.Seed(time.Now().Unix()) + + for i := 0; i < t.Connections; i++ { + c, _, err := connect(t.Target) + if err != nil { + return err + } + t.conns[i] = c + } + + t.startingWg.Add(t.Connections) + t.endingWg.Add(2 * t.Connections) + for i := 0; i < t.Connections; i++ { + go t.sendLoop(i) + go t.receiveLoop(i) + } + + t.startingWg.Wait() + + return nil +} + +// Stop closes the connections. +func (t *transacter) Stop() { + t.stopped = true + t.endingWg.Wait() + for _, c := range t.conns { + c.Close() + } +} + +// receiveLoop reads messages from the connection (empty in case of +// `broadcast_tx_async`). +func (t *transacter) receiveLoop(connIndex int) { + c := t.conns[connIndex] + defer t.endingWg.Done() + for { + _, _, err := c.ReadMessage() + if err != nil { + if !websocket.IsCloseError(err, websocket.CloseNormalClosure) { + t.logger.Error( + fmt.Sprintf("failed to read response on conn %d", connIndex), + "err", + err, + ) + } + return + } + if t.stopped || t.connsBroken[connIndex] { + return + } + } +} + +// sendLoop generates transactions at a given rate. +func (t *transacter) sendLoop(connIndex int) { + started := false + // Close the starting waitgroup, in the event that this fails to start + defer func() { + if !started { + t.startingWg.Done() + } + }() + c := t.conns[connIndex] + + c.SetPingHandler(func(message string) error { + err := c.WriteControl(websocket.PongMessage, []byte(message), time.Now().Add(sendTimeout)) + if err == websocket.ErrCloseSent { + return nil + } else if e, ok := err.(net.Error); ok && e.Temporary() { + return nil + } + return err + }) + + logger := t.logger.With("addr", c.RemoteAddr()) + + var txNumber = 0 + + pingsTicker := time.NewTicker(pingPeriod) + txsTicker := time.NewTicker(1 * time.Second) + defer func() { + pingsTicker.Stop() + txsTicker.Stop() + t.endingWg.Done() + }() + + // hash of the host name is a part of each tx + var hostnameHash [md5.Size]byte + hostname, err := os.Hostname() + if err != nil { + hostname = "127.0.0.1" + } + hostnameHash = md5.Sum([]byte(hostname)) + // each transaction embeds connection index, tx number and hash of the hostname + // we update the tx number between successive txs + tx := generateTx(connIndex, txNumber, t.Size, hostnameHash) + txHex := make([]byte, len(tx)*2) + hex.Encode(txHex, tx) + + for { + select { + case <-txsTicker.C: + startTime := time.Now() + endTime := startTime.Add(time.Second) + numTxSent := t.Rate + if !started { + t.startingWg.Done() + started = true + } + + now := time.Now() + for i := 0; i < t.Rate; i++ { + // update tx number of the tx, and the corresponding hex + updateTx(tx, txHex, txNumber) + paramsJSON, err := json.Marshal(map[string]interface{}{"tx": txHex}) + if err != nil { + fmt.Printf("failed to encode params: %v\n", err) + os.Exit(1) + } + rawParamsJSON := json.RawMessage(paramsJSON) + + c.SetWriteDeadline(now.Add(sendTimeout)) + err = c.WriteJSON(rpctypes.RPCRequest{ + JSONRPC: "2.0", + ID: "tm-bench", + Method: t.BroadcastTxMethod, + Params: rawParamsJSON, + }) + if err != nil { + err = errors.Wrap(err, + fmt.Sprintf("txs send failed on connection #%d", connIndex)) + t.connsBroken[connIndex] = true + logger.Error(err.Error()) + return + } + + // cache the time.Now() reads to save time. + if i%5 == 0 { + now = time.Now() + if now.After(endTime) { + // Plus one accounts for sending this tx + numTxSent = i + 1 + break + } + } + + txNumber++ + } + + timeToSend := time.Since(startTime) + logger.Info(fmt.Sprintf("sent %d transactions", numTxSent), "took", timeToSend) + if timeToSend < 1*time.Second { + sleepTime := time.Second - timeToSend + logger.Debug(fmt.Sprintf("connection #%d is sleeping for %f seconds", connIndex, sleepTime.Seconds())) + time.Sleep(sleepTime) + } + + case <-pingsTicker.C: + // go-rpc server closes the connection in the absence of pings + c.SetWriteDeadline(time.Now().Add(sendTimeout)) + if err := c.WriteMessage(websocket.PingMessage, []byte{}); err != nil { + err = errors.Wrap(err, + fmt.Sprintf("failed to write ping message on conn #%d", connIndex)) + logger.Error(err.Error()) + t.connsBroken[connIndex] = true + } + } + + if t.stopped { + // To cleanly close a connection, a client should send a close + // frame and wait for the server to close the connection. + c.SetWriteDeadline(time.Now().Add(sendTimeout)) + err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) + if err != nil { + err = errors.Wrap(err, + fmt.Sprintf("failed to write close message on conn #%d", connIndex)) + logger.Error(err.Error()) + t.connsBroken[connIndex] = true + } + + return + } + } +} + +func connect(host string) (*websocket.Conn, *http.Response, error) { + u := url.URL{Scheme: "ws", Host: host, Path: "/websocket"} + return websocket.DefaultDialer.Dial(u.String(), nil) +} + +func generateTx(connIndex int, txNumber int, txSize int, hostnameHash [md5.Size]byte) []byte { + tx := make([]byte, txSize) + + binary.PutUvarint(tx[:8], uint64(connIndex)) + binary.PutUvarint(tx[8:16], uint64(txNumber)) + copy(tx[16:32], hostnameHash[:16]) + binary.PutUvarint(tx[32:40], uint64(time.Now().Unix())) + + // 40-* random data + if _, err := rand.Read(tx[40:]); err != nil { + panic(errors.Wrap(err, "failed to read random bytes")) + } + + return tx +} + +// warning, mutates input byte slice +func updateTx(tx []byte, txHex []byte, txNumber int) { + binary.PutUvarint(tx[8:16], uint64(txNumber)) + hexUpdate := make([]byte, 16) + hex.Encode(hexUpdate, tx[8:16]) + for i := 16; i < 32; i++ { + txHex[i] = hexUpdate[i-16] + } +} diff --git a/tools/tm-bench/transacter_test.go b/tools/tm-bench/transacter_test.go new file mode 100644 index 000000000..086a43c31 --- /dev/null +++ b/tools/tm-bench/transacter_test.go @@ -0,0 +1,104 @@ +package main + +import ( + "crypto/md5" + "encoding/hex" + "encoding/json" + "fmt" + "os" + "testing" + "time" + + "github.com/pkg/errors" + "github.com/stretchr/testify/require" +) + +// This test tests that the output of generate tx and update tx is consistent +func TestGenerateTxUpdateTxConsistentency(t *testing.T) { + cases := []struct { + connIndex int + startingTxNumber int + txSize int + hostname string + numTxsToTest int + }{ + {0, 0, 50, "localhost:26657", 1000}, + {70, 300, 10000, "localhost:26657", 1000}, + {0, 50, 100000, "localhost:26657", 1000}, + } + + for tcIndex, tc := range cases { + hostnameHash := md5.Sum([]byte(tc.hostname)) + // Tx generated from update tx. This is defined outside of the loop, since we have + // to a have something initially to update + updatedTx := generateTx(tc.connIndex, tc.startingTxNumber, tc.txSize, hostnameHash) + updatedHex := make([]byte, len(updatedTx)*2) + hex.Encode(updatedHex, updatedTx) + for i := 0; i < tc.numTxsToTest; i++ { + expectedTx := generateTx(tc.connIndex, tc.startingTxNumber+i, tc.txSize, hostnameHash) + expectedHex := make([]byte, len(expectedTx)*2) + hex.Encode(expectedHex, expectedTx) + + updateTx(updatedTx, updatedHex, tc.startingTxNumber+i) + + // after first 32 bytes is 8 bytes of time, then purely random bytes + require.Equal(t, expectedTx[:32], updatedTx[:32], + "First 32 bytes of the txs differed. tc #%d, i #%d", tcIndex, i) + require.Equal(t, expectedHex[:64], updatedHex[:64], + "First 64 bytes of the hex differed. tc #%d, i #%d", tcIndex, i) + // Test the lengths of the txs are as expected + require.Equal(t, tc.txSize, len(expectedTx), + "Length of expected Tx differed. tc #%d, i #%d", tcIndex, i) + require.Equal(t, tc.txSize, len(updatedTx), + "Length of expected Tx differed. tc #%d, i #%d", tcIndex, i) + require.Equal(t, tc.txSize*2, len(expectedHex), + "Length of expected hex differed. tc #%d, i #%d", tcIndex, i) + require.Equal(t, tc.txSize*2, len(updatedHex), + "Length of updated hex differed. tc #%d, i #%d", tcIndex, i) + } + } +} + +func BenchmarkIterationOfSendLoop(b *testing.B) { + var ( + connIndex = 0 + txSize = 25000 + ) + + now := time.Now() + // something too far away to matter + endTime := now.Add(time.Hour) + txNumber := 0 + hostnameHash := md5.Sum([]byte{0}) + tx := generateTx(connIndex, txNumber, txSize, hostnameHash) + txHex := make([]byte, len(tx)*2) + hex.Encode(txHex, tx) + b.ResetTimer() + for i := 0; i < b.N; i++ { + updateTx(tx, txHex, txNumber) + paramsJSON, err := json.Marshal(map[string]interface{}{"tx": txHex}) + if err != nil { + fmt.Printf("failed to encode params: %v\n", err) + os.Exit(1) + } + _ = json.RawMessage(paramsJSON) + _ = now.Add(sendTimeout) + + if err != nil { + err = errors.Wrap(err, + fmt.Sprintf("txs send failed on connection #%d", connIndex)) + logger.Error(err.Error()) + return + } + + // Cache the now operations + if i%5 == 0 { + now = time.Now() + if now.After(endTime) { + break + } + } + + txNumber++ + } +} diff --git a/tools/tm-monitor/Dockerfile b/tools/tm-monitor/Dockerfile new file mode 100644 index 000000000..7edfaca66 --- /dev/null +++ b/tools/tm-monitor/Dockerfile @@ -0,0 +1,6 @@ +FROM alpine:3.6 + +WORKDIR /app +COPY tm-monitor /app/tm-monitor + +ENTRYPOINT ["./tm-monitor"] diff --git a/tools/tm-monitor/Dockerfile.dev b/tools/tm-monitor/Dockerfile.dev new file mode 100644 index 000000000..5bfbbfd5a --- /dev/null +++ b/tools/tm-monitor/Dockerfile.dev @@ -0,0 +1,12 @@ +FROM golang:latest + +RUN mkdir -p /go/src/github.com/tendermint/tools/tm-monitor +WORKDIR /go/src/github.com/tendermint/tools/tm-monitor + +COPY Makefile /go/src/github.com/tendermint/tools/tm-monitor/ + +RUN make get_tools + +COPY . /go/src/github.com/tendermint/tools/tm-monitor + +RUN make get_vendor_deps diff --git a/tools/tm-monitor/LICENSE b/tools/tm-monitor/LICENSE new file mode 100644 index 000000000..20728d318 --- /dev/null +++ b/tools/tm-monitor/LICENSE @@ -0,0 +1,204 @@ +Tendermint Monitor +Copyright 2017 Tendermint + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/crypto/Makefile b/tools/tm-monitor/Makefile similarity index 52% rename from crypto/Makefile rename to tools/tm-monitor/Makefile index a4fd3c37f..3371a0c19 100644 --- a/crypto/Makefile +++ b/tools/tm-monitor/Makefile @@ -1,41 +1,27 @@ +DIST_DIRS := find * -type d -exec +VERSION := $(shell perl -ne '/^var version.*"([^"]+)".*$$/ && print "v$$1\n"' main.go) GOTOOLS = \ - github.com/golang/dep/cmd/dep \ - # gopkg.in/alecthomas/gometalinter.v2 \ + github.com/mitchellh/gox \ + github.com/golang/dep/cmd/dep \ + gopkg.in/alecthomas/gometalinter.v2 +PACKAGES=$(shell go list ./... | grep -v '/vendor/') -GOTOOLS_CHECK = dep #gometalinter.v2 - -all: check get_vendor_deps build test install +all: check get_vendor_deps build test install metalinter check: check_tools - -######################################## -### Build - -# Command to generate the workd list (kept here for documentation purposes only): -wordlist: - # To re-generate wordlist.go run: - # go-bindata -ignore ".*\.go" -o keys/words/bip39/wordlist.go -pkg "wordlist" keys/bip39/wordlist/... - -build: wordlist - # Nothing else to build! - -install: - # Nothing to install! - - ######################################## ### Tools & dependencies check_tools: @# https://stackoverflow.com/a/25668869 @echo "Found tools: $(foreach tool,$(GOTOOLS_CHECK),\ - $(if $(shell which $(tool)),$(tool),$(error "No $(tool) in PATH")))" + $(if $(shell which $(tool)),$(tool),$(error "No $(tool) in PATH")))" get_tools: @echo "--> Installing tools" go get -u -v $(GOTOOLS) - #@gometalinter.v2 --install + @gometalinter.v2 --install update_tools: @echo "--> Updating tools" @@ -46,12 +32,45 @@ get_vendor_deps: @echo "--> Running dep ensure" @dep ensure - ######################################## -### Testing +### Build + +build: + @go build + +install: + @go install test: - CGO_ENABLED=0 go test -p 1 $(shell go list ./... | grep -v vendor) + @go test -race $(PACKAGES) + +build-all: check_tools + rm -rf ./dist + gox -verbose \ + -ldflags "-s -w" \ + -arch="amd64 386 arm arm64" \ + -os="linux darwin windows freebsd" \ + -osarch="!darwin/arm !darwin/arm64" \ + -output="dist/{{.OS}}-{{.Arch}}/{{.Dir}}" . + +dist: build-all + cd dist && \ + $(DIST_DIRS) cp ../LICENSE {} \; && \ + $(DIST_DIRS) tar -zcf tm-monitor-${VERSION}-{}.tar.gz {} \; && \ + shasum -a256 ./*.tar.gz > "./tm-monitor_${VERSION}_SHA256SUMS" && \ + cd .. + +######################################## +### Docker + +build-docker: + rm -f ./tm-monitor + docker run -it --rm -v "$(PWD):/go/src/github.com/tendermint/tools/tm-monitor" -w "/go/src/github.com/tendermint/tools/tm-monitor" -e "CGO_ENABLED=0" golang:alpine go build -ldflags "-s -w" -o tm-monitor + docker build -t "tendermint/monitor" . + +clean: + rm -f ./tm-monitor + rm -rf ./dist ######################################## ### Formatting, linting, and vetting @@ -89,11 +108,9 @@ metalinter: #--enable=vet \ metalinter_all: - protoc $(INCLUDE) --lint_out=. types/*.proto gometalinter.v2 --vendor --deadline=600s --enable-all --disable=lll ./... - # To avoid unintended conflicts with file names, always add to .PHONY # unless there is a reason not to. # https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html -.PHONEY: check build install check_tools get_tools update_tools get_vendor_deps test fmt metalinter metalinter_all +.PHONY: check check_tools get_tools update_tools get_vendor_deps build install test build-all dist fmt metalinter metalinter_all build-docker clean diff --git a/tools/tm-monitor/README.md b/tools/tm-monitor/README.md new file mode 100644 index 000000000..4c49775e3 --- /dev/null +++ b/tools/tm-monitor/README.md @@ -0,0 +1,77 @@ +# tm-monitor + +Tendermint blockchain monitoring tool; watches over one or more nodes, +collecting and providing various statistics to the user: + +- https://github.com/tendermint/tools/tree/master/tm-monitor + +## Quick Start + +### Docker + +Assuming your application is running in another container with the name +`app`: + + docker run -it --rm -v "/tmp:/tendermint" tendermint/tendermint init + docker run -it --rm -v "/tmp:/tendermint" -p "26657:26657" --name=tm --link=app tendermint/tendermint node --proxy_app=tcp://app:26658 + + docker run -it --rm -p "26670:26670" --link=tm tendermint/monitor tm:26657 + +If you don't have an application yet, but still want to try monitor out, +use `kvstore`: + + docker run -it --rm -v "/tmp:/tendermint" tendermint/tendermint init + docker run -it --rm -v "/tmp:/tendermint" -p "26657:26657" --name=tm tendermint/tendermint node --proxy_app=kvstore + + docker run -it --rm -p "26670:26670" --link=tm tendermint/monitor tm:26657 + +### Using Binaries + +[Install Tendermint](https://github.com/tendermint/tendermint#install) + +then run: + + tendermint init + tendermint node --proxy_app=kvstore + + tm-monitor localhost:26657 + +with the last command being in a seperate window. + +## Usage + + tm-monitor [-v] [-no-ton] [-listen-addr="tcp://0.0.0.0:26670"] [endpoints] + + Examples: + # monitor single instance + tm-monitor localhost:26657 + + # monitor a few instances by providing comma-separated list of RPC endpoints + tm-monitor host1:26657,host2:26657 + Flags: + -listen-addr string + HTTP and Websocket server listen address (default "tcp://0.0.0.0:26670") + -no-ton + Do not show ton (table of nodes) + -v verbose logging + +### RPC UI + +Run `tm-monitor` and visit http://localhost:26670 You should see the +list of the available RPC endpoints: + + http://localhost:26670/status + http://localhost:26670/status/network + http://localhost:26670/monitor?endpoint=_ + http://localhost:26670/status/node?name=_ + http://localhost:26670/unmonitor?endpoint=_ + +The API is available as GET requests with URI encoded parameters, or as +JSONRPC POST requests. The JSONRPC methods are also exposed over +websocket. + +## Development + + make get_tools + make get_vendor_deps + make test diff --git a/tools/tm-monitor/eventmeter/eventmeter.go b/tools/tm-monitor/eventmeter/eventmeter.go new file mode 100644 index 000000000..185f37749 --- /dev/null +++ b/tools/tm-monitor/eventmeter/eventmeter.go @@ -0,0 +1,296 @@ +// eventmeter - generic system to subscribe to events and record their frequency. +package eventmeter + +import ( + "context" + "encoding/json" + "fmt" + "sync" + "time" + + metrics "github.com/rcrowley/go-metrics" + + "github.com/tendermint/tendermint/libs/events" + "github.com/tendermint/tendermint/libs/log" + client "github.com/tendermint/tendermint/rpc/lib/client" +) + +const ( + // Get ping/pong latency and call LatencyCallbackFunc with this period. + latencyPeriod = 1 * time.Second + + // Check if the WS client is connected every + connectionCheckPeriod = 100 * time.Millisecond +) + +// EventMetric exposes metrics for an event. +type EventMetric struct { + ID string `json:"id"` + Started time.Time `json:"start_time"` + LastHeard time.Time `json:"last_heard"` + MinDuration int64 `json:"min_duration"` + MaxDuration int64 `json:"max_duration"` + + // tracks event count and rate + meter metrics.Meter + + // filled in from the Meter + Count int64 `json:"count"` + Rate1 float64 `json:"rate_1" amino:"unsafe"` + Rate5 float64 `json:"rate_5" amino:"unsafe"` + Rate15 float64 `json:"rate_15" amino:"unsafe"` + RateMean float64 `json:"rate_mean" amino:"unsafe"` + + // so the event can have effects in the eventmeter's consumer. runs in a go + // routine. + callback EventCallbackFunc +} + +func (metric *EventMetric) Copy() *EventMetric { + metricCopy := *metric + metricCopy.meter = metric.meter.Snapshot() + return &metricCopy +} + +// called on GetMetric +func (metric *EventMetric) fillMetric() *EventMetric { + metric.Count = metric.meter.Count() + metric.Rate1 = metric.meter.Rate1() + metric.Rate5 = metric.meter.Rate5() + metric.Rate15 = metric.meter.Rate15() + metric.RateMean = metric.meter.RateMean() + return metric +} + +// EventCallbackFunc is a closure to enable side effects from receiving an +// event. +type EventCallbackFunc func(em *EventMetric, data interface{}) + +// EventUnmarshalFunc is a closure to get the query and data out of the raw +// JSON received over the RPC WebSocket. +type EventUnmarshalFunc func(b json.RawMessage) (string, events.EventData, error) + +// LatencyCallbackFunc is a closure to enable side effects from receiving a latency. +type LatencyCallbackFunc func(meanLatencyNanoSeconds float64) + +// DisconnectCallbackFunc is a closure to notify a consumer that the connection +// has died. +type DisconnectCallbackFunc func() + +// EventMeter tracks events, reports latency and disconnects. +type EventMeter struct { + wsc *client.WSClient + + mtx sync.Mutex + queryToMetricMap map[string]*EventMetric + + unmarshalEvent EventUnmarshalFunc + latencyCallback LatencyCallbackFunc + disconnectCallback DisconnectCallbackFunc + subscribed bool + + quit chan struct{} + + logger log.Logger +} + +func NewEventMeter(addr string, unmarshalEvent EventUnmarshalFunc) *EventMeter { + return &EventMeter{ + wsc: client.NewWSClient(addr, "/websocket", client.PingPeriod(1*time.Second)), + queryToMetricMap: make(map[string]*EventMetric), + unmarshalEvent: unmarshalEvent, + logger: log.NewNopLogger(), + } +} + +// SetLogger lets you set your own logger. +func (em *EventMeter) SetLogger(l log.Logger) { + em.logger = l + em.wsc.SetLogger(l.With("module", "rpcclient")) +} + +// String returns a string representation of event meter. +func (em *EventMeter) String() string { + return em.wsc.Address +} + +// Start boots up event meter. +func (em *EventMeter) Start() error { + if err := em.wsc.Start(); err != nil { + return err + } + + em.quit = make(chan struct{}) + go em.receiveRoutine() + go em.disconnectRoutine() + + err := em.subscribe() + if err != nil { + return err + } + em.subscribed = true + return nil +} + +// Stop stops event meter. +func (em *EventMeter) Stop() { + close(em.quit) + + if em.wsc.IsRunning() { + em.wsc.Stop() + } +} + +// Subscribe for the given query. Callback function will be called upon +// receiving an event. +func (em *EventMeter) Subscribe(query string, cb EventCallbackFunc) error { + em.mtx.Lock() + defer em.mtx.Unlock() + + if err := em.wsc.Subscribe(context.TODO(), query); err != nil { + return err + } + + metric := &EventMetric{ + meter: metrics.NewMeter(), + callback: cb, + } + em.queryToMetricMap[query] = metric + return nil +} + +// Unsubscribe from the given query. +func (em *EventMeter) Unsubscribe(query string) error { + em.mtx.Lock() + defer em.mtx.Unlock() + + return em.wsc.Unsubscribe(context.TODO(), query) +} + +// GetMetric fills in the latest data for an query and return a copy. +func (em *EventMeter) GetMetric(query string) (*EventMetric, error) { + em.mtx.Lock() + defer em.mtx.Unlock() + metric, ok := em.queryToMetricMap[query] + if !ok { + return nil, fmt.Errorf("unknown query: %s", query) + } + return metric.fillMetric().Copy(), nil +} + +// RegisterLatencyCallback allows you to set latency callback. +func (em *EventMeter) RegisterLatencyCallback(f LatencyCallbackFunc) { + em.mtx.Lock() + defer em.mtx.Unlock() + em.latencyCallback = f +} + +// RegisterDisconnectCallback allows you to set disconnect callback. +func (em *EventMeter) RegisterDisconnectCallback(f DisconnectCallbackFunc) { + em.mtx.Lock() + defer em.mtx.Unlock() + em.disconnectCallback = f +} + +/////////////////////////////////////////////////////////////////////////////// +// Private + +func (em *EventMeter) subscribe() error { + for query, _ := range em.queryToMetricMap { + if err := em.wsc.Subscribe(context.TODO(), query); err != nil { + return err + } + } + return nil +} + +func (em *EventMeter) receiveRoutine() { + latencyTicker := time.NewTicker(latencyPeriod) + for { + select { + case resp := <-em.wsc.ResponsesCh: + if resp.Error != nil { + em.logger.Error("expected some event, got error", "err", resp.Error.Error()) + continue + } + query, data, err := em.unmarshalEvent(resp.Result) + if err != nil { + em.logger.Error("failed to unmarshal event", "err", err) + continue + } + if query != "" { // FIXME how can it be an empty string? + em.updateMetric(query, data) + } + case <-latencyTicker.C: + if em.wsc.IsActive() { + em.callLatencyCallback(em.wsc.PingPongLatencyTimer.Mean()) + } + case <-em.wsc.Quit(): + return + case <-em.quit: + return + } + } +} + +func (em *EventMeter) disconnectRoutine() { + ticker := time.NewTicker(connectionCheckPeriod) + for { + select { + case <-ticker.C: + if em.wsc.IsReconnecting() && em.subscribed { // notify user about disconnect only once + em.callDisconnectCallback() + em.subscribed = false + } else if !em.wsc.IsReconnecting() && !em.subscribed { // resubscribe + em.subscribe() + em.subscribed = true + } + case <-em.wsc.Quit(): + return + case <-em.quit: + return + } + } +} + +func (em *EventMeter) updateMetric(query string, data events.EventData) { + em.mtx.Lock() + defer em.mtx.Unlock() + + metric, ok := em.queryToMetricMap[query] + if !ok { + // we already unsubscribed, or got an unexpected query + return + } + + last := metric.LastHeard + metric.LastHeard = time.Now() + metric.meter.Mark(1) + dur := int64(metric.LastHeard.Sub(last)) + if dur < metric.MinDuration { + metric.MinDuration = dur + } + if !last.IsZero() && dur > metric.MaxDuration { + metric.MaxDuration = dur + } + + if metric.callback != nil { + go metric.callback(metric.Copy(), data) + } +} + +func (em *EventMeter) callDisconnectCallback() { + em.mtx.Lock() + if em.disconnectCallback != nil { + go em.disconnectCallback() + } + em.mtx.Unlock() +} + +func (em *EventMeter) callLatencyCallback(meanLatencyNanoSeconds float64) { + em.mtx.Lock() + if em.latencyCallback != nil { + go em.latencyCallback(meanLatencyNanoSeconds) + } + em.mtx.Unlock() +} diff --git a/tools/tm-monitor/main.go b/tools/tm-monitor/main.go new file mode 100644 index 000000000..32897b978 --- /dev/null +++ b/tools/tm-monitor/main.go @@ -0,0 +1,86 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + cmn "github.com/tendermint/tendermint/libs/common" + "github.com/tendermint/tendermint/libs/log" + monitor "github.com/tendermint/tendermint/tools/tm-monitor/monitor" +) + +var logger = log.NewNopLogger() + +func main() { + var listenAddr string + var noton bool + + flag.StringVar(&listenAddr, "listen-addr", "tcp://0.0.0.0:26670", "HTTP and Websocket server listen address") + flag.BoolVar(¬on, "no-ton", false, "Do not show ton (table of nodes)") + + flag.Usage = func() { + fmt.Println(`Tendermint monitor watches over one or more Tendermint core +applications, collecting and providing various statistics to the user. + +Usage: + tm-monitor [-no-ton] [-listen-addr="tcp://0.0.0.0:26670"] [endpoints] + +Examples: + # monitor single instance + tm-monitor localhost:26657 + + # monitor a few instances by providing comma-separated list of RPC endpoints + tm-monitor host1:26657,host2:26657`) + fmt.Println("Flags:") + flag.PrintDefaults() + } + + flag.Parse() + + if flag.NArg() == 0 { + flag.Usage() + os.Exit(1) + } + + if noton { + logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + } + + m := startMonitor(flag.Arg(0)) + + startRPC(listenAddr, m, logger) + + var ton *Ton + if !noton { + ton = NewTon(m) + ton.Start() + } + + cmn.TrapSignal(func() { + if !noton { + ton.Stop() + } + m.Stop() + }) +} + +func startMonitor(endpoints string) *monitor.Monitor { + m := monitor.NewMonitor() + m.SetLogger(logger.With("component", "monitor")) + + for _, e := range strings.Split(endpoints, ",") { + n := monitor.NewNode(e) + n.SetLogger(logger.With("node", e)) + if err := m.Monitor(n); err != nil { + panic(err) + } + } + + if err := m.Start(); err != nil { + panic(err) + } + + return m +} diff --git a/tools/tm-monitor/mock/eventmeter.go b/tools/tm-monitor/mock/eventmeter.go new file mode 100644 index 000000000..271297581 --- /dev/null +++ b/tools/tm-monitor/mock/eventmeter.go @@ -0,0 +1,69 @@ +package mock + +import ( + stdlog "log" + "reflect" + + "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/libs/log" + em "github.com/tendermint/tendermint/tools/tm-monitor/eventmeter" +) + +type EventMeter struct { + latencyCallback em.LatencyCallbackFunc + disconnectCallback em.DisconnectCallbackFunc + eventCallback em.EventCallbackFunc +} + +func (e *EventMeter) Start() error { return nil } +func (e *EventMeter) Stop() {} +func (e *EventMeter) SetLogger(l log.Logger) {} +func (e *EventMeter) RegisterLatencyCallback(cb em.LatencyCallbackFunc) { e.latencyCallback = cb } +func (e *EventMeter) RegisterDisconnectCallback(cb em.DisconnectCallbackFunc) { + e.disconnectCallback = cb +} +func (e *EventMeter) Subscribe(query string, cb em.EventCallbackFunc) error { + e.eventCallback = cb + return nil +} +func (e *EventMeter) Unsubscribe(query string) error { + e.eventCallback = nil + return nil +} + +func (e *EventMeter) Call(callback string, args ...interface{}) { + switch callback { + case "latencyCallback": + e.latencyCallback(args[0].(float64)) + case "disconnectCallback": + e.disconnectCallback() + case "eventCallback": + e.eventCallback(args[0].(*em.EventMetric), args[1]) + } +} + +type RpcClient struct { + Stubs map[string]interface{} + cdc *amino.Codec +} + +func (c *RpcClient) Call(method string, params map[string]interface{}, result interface{}) (interface{}, error) { + s, ok := c.Stubs[method] + if !ok { + stdlog.Fatalf("Call to %s, but no stub is defined for it", method) + } + + rv, rt := reflect.ValueOf(result), reflect.TypeOf(result) + rv, rt = rv.Elem(), rt.Elem() + rv.Set(reflect.ValueOf(s)) + + return s, nil +} + +func (c *RpcClient) Codec() *amino.Codec { + return c.cdc +} + +func (c *RpcClient) SetCodec(cdc *amino.Codec) { + c.cdc = cdc +} diff --git a/tools/tm-monitor/monitor/monitor.go b/tools/tm-monitor/monitor/monitor.go new file mode 100644 index 000000000..764f281ff --- /dev/null +++ b/tools/tm-monitor/monitor/monitor.go @@ -0,0 +1,251 @@ +package monitor + +import ( + "fmt" + "math/rand" + "sync" + "time" + + "github.com/pkg/errors" + "github.com/tendermint/tendermint/libs/log" + tmtypes "github.com/tendermint/tendermint/types" +) + +// waiting more than this many seconds for a block means we're unhealthy +const nodeLivenessTimeout = 5 * time.Second + +// Monitor keeps track of the nodes and updates common statistics upon +// receiving new events from nodes. +// +// Common statistics is stored in Network struct. +type Monitor struct { + mtx sync.Mutex + Nodes []*Node + + Network *Network + + monitorQuit chan struct{} // monitor exitting + nodeQuit map[string]chan struct{} // node is being stopped and removed from under the monitor + + recalculateNetworkUptimeEvery time.Duration + numValidatorsUpdateInterval time.Duration + + logger log.Logger +} + +// NewMonitor creates new instance of a Monitor. You can provide options to +// change some default values. +// +// Example: +// NewMonitor(monitor.SetNumValidatorsUpdateInterval(1 * time.Second)) +func NewMonitor(options ...func(*Monitor)) *Monitor { + m := &Monitor{ + Nodes: make([]*Node, 0), + Network: NewNetwork(), + monitorQuit: make(chan struct{}), + nodeQuit: make(map[string]chan struct{}), + recalculateNetworkUptimeEvery: 10 * time.Second, + numValidatorsUpdateInterval: 5 * time.Second, + logger: log.NewNopLogger(), + } + + for _, option := range options { + option(m) + } + + return m +} + +// RecalculateNetworkUptimeEvery lets you change network uptime update interval. +func RecalculateNetworkUptimeEvery(d time.Duration) func(m *Monitor) { + return func(m *Monitor) { + m.recalculateNetworkUptimeEvery = d + } +} + +// SetNumValidatorsUpdateInterval lets you change num validators update interval. +func SetNumValidatorsUpdateInterval(d time.Duration) func(m *Monitor) { + return func(m *Monitor) { + m.numValidatorsUpdateInterval = d + } +} + +// SetLogger lets you set your own logger +func (m *Monitor) SetLogger(l log.Logger) { + m.logger = l +} + +// Monitor begins to monitor the node `n`. The node will be started and added +// to the monitor. +func (m *Monitor) Monitor(n *Node) error { + m.mtx.Lock() + m.Nodes = append(m.Nodes, n) + m.mtx.Unlock() + + blockCh := make(chan tmtypes.Header, 10) + n.SendBlocksTo(blockCh) + blockLatencyCh := make(chan float64, 10) + n.SendBlockLatenciesTo(blockLatencyCh) + disconnectCh := make(chan bool, 10) + n.NotifyAboutDisconnects(disconnectCh) + + if err := n.Start(); err != nil { + return err + } + + m.Network.NewNode(n.Name) + + m.nodeQuit[n.Name] = make(chan struct{}) + go m.listen(n.Name, blockCh, blockLatencyCh, disconnectCh, m.nodeQuit[n.Name]) + + return nil +} + +// Unmonitor stops monitoring node `n`. The node will be stopped and removed +// from the monitor. +func (m *Monitor) Unmonitor(n *Node) { + m.Network.NodeDeleted(n.Name) + + n.Stop() + close(m.nodeQuit[n.Name]) + delete(m.nodeQuit, n.Name) + i, _ := m.NodeByName(n.Name) + + m.mtx.Lock() + m.Nodes[i] = m.Nodes[len(m.Nodes)-1] + m.Nodes = m.Nodes[:len(m.Nodes)-1] + m.mtx.Unlock() +} + +// NodeByName returns the node and its index if such node exists within the +// monitor. Otherwise, -1 and nil are returned. +func (m *Monitor) NodeByName(name string) (index int, node *Node) { + m.mtx.Lock() + defer m.mtx.Unlock() + + for i, n := range m.Nodes { + if name == n.Name { + return i, n + } + } + return -1, nil +} + +// NodeIsOnline is called when connection to the node is restored. +// Must be safe to call multiple times. +func (m *Monitor) NodeIsOnline(name string) { + + _, node := m.NodeByName(name) + if nil != node { + if online, ok := m.Network.nodeStatusMap[name]; ok && online { + m.mtx.Lock() + node.Online = online + m.mtx.Unlock() + } + } + +} + +// Start starts the monitor's routines: recalculating network uptime and +// updating number of validators. +func (m *Monitor) Start() error { + go m.recalculateNetworkUptimeLoop() + go m.updateNumValidatorLoop() + + return nil +} + +// Stop stops the monitor's routines. +func (m *Monitor) Stop() { + close(m.monitorQuit) + + for _, n := range m.Nodes { + m.Unmonitor(n) + } +} + +// main loop where we listen for events from the node +func (m *Monitor) listen(nodeName string, blockCh <-chan tmtypes.Header, blockLatencyCh <-chan float64, disconnectCh <-chan bool, quit <-chan struct{}) { + logger := m.logger.With("node", nodeName) + + for { + select { + case <-quit: + return + case b := <-blockCh: + m.Network.NewBlock(b) + m.Network.NodeIsOnline(nodeName) + m.NodeIsOnline(nodeName) + case l := <-blockLatencyCh: + m.Network.NewBlockLatency(l) + m.Network.NodeIsOnline(nodeName) + m.NodeIsOnline(nodeName) + case disconnected := <-disconnectCh: + if disconnected { + m.Network.NodeIsDown(nodeName) + } else { + m.Network.NodeIsOnline(nodeName) + m.NodeIsOnline(nodeName) + } + case <-time.After(nodeLivenessTimeout): + logger.Info("event", fmt.Sprintf("node was not responding for %v", nodeLivenessTimeout)) + m.Network.NodeIsDown(nodeName) + } + } +} + +// recalculateNetworkUptimeLoop every N seconds. +func (m *Monitor) recalculateNetworkUptimeLoop() { + for { + select { + case <-m.monitorQuit: + return + case <-time.After(m.recalculateNetworkUptimeEvery): + m.Network.RecalculateUptime() + } + } +} + +// updateNumValidatorLoop sends a request to a random node once every N seconds, +// which in turn makes an RPC call to get the latest validators. +func (m *Monitor) updateNumValidatorLoop() { + rand.Seed(time.Now().Unix()) + + var height int64 + var num int + var err error + + for { + m.mtx.Lock() + nodesCount := len(m.Nodes) + m.mtx.Unlock() + if 0 == nodesCount { + time.Sleep(m.numValidatorsUpdateInterval) + continue + } + + randomNodeIndex := rand.Intn(nodesCount) + + select { + case <-m.monitorQuit: + return + case <-time.After(m.numValidatorsUpdateInterval): + i := 0 + + m.mtx.Lock() + for _, n := range m.Nodes { + if i == randomNodeIndex { + height, num, err = n.NumValidators() + if err != nil { + m.logger.Info("err", errors.Wrap(err, "update num validators failed")) + } + break + } + i++ + } + m.mtx.Unlock() + + m.Network.UpdateNumValidatorsForHeight(num, height) + } + } +} diff --git a/tools/tm-monitor/monitor/monitor_test.go b/tools/tm-monitor/monitor/monitor_test.go new file mode 100644 index 000000000..9694e5771 --- /dev/null +++ b/tools/tm-monitor/monitor/monitor_test.go @@ -0,0 +1,72 @@ +package monitor_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/crypto/ed25519" + ctypes "github.com/tendermint/tendermint/rpc/core/types" + mock "github.com/tendermint/tendermint/tools/tm-monitor/mock" + monitor "github.com/tendermint/tendermint/tools/tm-monitor/monitor" + tmtypes "github.com/tendermint/tendermint/types" +) + +func TestMonitorUpdatesNumberOfValidators(t *testing.T) { + m := startMonitor(t) + defer m.Stop() + + n, _ := createValidatorNode(t) + m.Monitor(n) + assert.Equal(t, 1, m.Network.NumNodesMonitored) + assert.Equal(t, 1, m.Network.NumNodesMonitoredOnline) + + time.Sleep(1 * time.Second) + + // DATA RACE + // assert.Equal(t, 1, m.Network.NumValidators()) +} + +func TestMonitorRecalculatesNetworkUptime(t *testing.T) { + m := startMonitor(t) + defer m.Stop() + assert.Equal(t, 100.0, m.Network.Uptime()) + + n, _ := createValidatorNode(t) + m.Monitor(n) + + m.Network.NodeIsDown(n.Name) // simulate node failure + time.Sleep(200 * time.Millisecond) + m.Network.NodeIsOnline(n.Name) + time.Sleep(1 * time.Second) + + assert.True(t, m.Network.Uptime() < 100.0, "Uptime should be less than 100%") +} + +func startMonitor(t *testing.T) *monitor.Monitor { + m := monitor.NewMonitor( + monitor.SetNumValidatorsUpdateInterval(200*time.Millisecond), + monitor.RecalculateNetworkUptimeEvery(200*time.Millisecond), + ) + err := m.Start() + require.Nil(t, err) + return m +} + +func createValidatorNode(t *testing.T) (n *monitor.Node, emMock *mock.EventMeter) { + emMock = &mock.EventMeter{} + + stubs := make(map[string]interface{}) + pubKey := ed25519.GenPrivKey().PubKey() + stubs["validators"] = ctypes.ResultValidators{BlockHeight: blockHeight, Validators: []*tmtypes.Validator{tmtypes.NewValidator(pubKey, 0)}} + stubs["status"] = ctypes.ResultStatus{ValidatorInfo: ctypes.ValidatorInfo{PubKey: pubKey}} + cdc := amino.NewCodec() + rpcClientMock := &mock.RpcClient{Stubs: stubs} + rpcClientMock.SetCodec(cdc) + + n = monitor.NewNodeWithEventMeterAndRpcClient("tcp://127.0.0.1:26657", emMock, rpcClientMock) + return +} diff --git a/tools/tm-monitor/monitor/network.go b/tools/tm-monitor/monitor/network.go new file mode 100644 index 000000000..9b147c06b --- /dev/null +++ b/tools/tm-monitor/monitor/network.go @@ -0,0 +1,199 @@ +package monitor + +import ( + "sync" + "time" + + metrics "github.com/rcrowley/go-metrics" + tmtypes "github.com/tendermint/tendermint/types" +) + +// UptimeData stores data for how long network has been running. +type UptimeData struct { + StartTime time.Time `json:"start_time"` + Uptime float64 `json:"uptime" amino:"unsafe"` // percentage of time we've been healthy, ever + + totalDownTime time.Duration // total downtime (only updated when we come back online) + wentDown time.Time +} + +// Health describes the health of the network. Note that this applies only to +// the observed nodes, and not to the entire cluster, which may consist of +// thousands of machines. It may change in the future. +type Health int + +const ( + // FullHealth means all nodes online, synced, validators making blocks + FullHealth = Health(0) + // ModerateHealth means we're making blocks + ModerateHealth = Health(1) + // Dead means we're not making blocks due to all validators freezing or crashing + Dead = Health(2) +) + +// Common statistics for network of nodes +type Network struct { + Height int64 `json:"height"` + + AvgBlockTime float64 `json:"avg_block_time" amino:"unsafe"` // ms (avg over last minute) + blockTimeMeter metrics.Meter + AvgTxThroughput float64 `json:"avg_tx_throughput" amino:"unsafe"` // tx/s (avg over last minute) + txThroughputMeter metrics.Meter + AvgBlockLatency float64 `json:"avg_block_latency" amino:"unsafe"` // ms (avg over last minute) + blockLatencyMeter metrics.Meter + + NumValidators int `json:"num_validators"` + NumNodesMonitored int `json:"num_nodes_monitored"` + NumNodesMonitoredOnline int `json:"num_nodes_monitored_online"` + + Health Health `json:"health"` + + UptimeData *UptimeData `json:"uptime_data"` + + nodeStatusMap map[string]bool + + mu sync.Mutex +} + +func NewNetwork() *Network { + return &Network{ + blockTimeMeter: metrics.NewMeter(), + txThroughputMeter: metrics.NewMeter(), + blockLatencyMeter: metrics.NewMeter(), + Health: FullHealth, + UptimeData: &UptimeData{ + StartTime: time.Now(), + Uptime: 100.0, + }, + nodeStatusMap: make(map[string]bool), + } +} + +func (n *Network) NewBlock(b tmtypes.Header) { + n.mu.Lock() + defer n.mu.Unlock() + + if n.Height >= b.Height { + return + } + + n.Height = b.Height + + n.blockTimeMeter.Mark(1) + if n.blockTimeMeter.Rate1() > 0.0 { + n.AvgBlockTime = (1.0 / n.blockTimeMeter.Rate1()) * 1000 // 1/s to ms + } else { + n.AvgBlockTime = 0.0 + } + n.txThroughputMeter.Mark(int64(b.NumTxs)) + n.AvgTxThroughput = n.txThroughputMeter.Rate1() +} + +func (n *Network) NewBlockLatency(l float64) { + n.mu.Lock() + defer n.mu.Unlock() + + n.blockLatencyMeter.Mark(int64(l)) + n.AvgBlockLatency = n.blockLatencyMeter.Rate1() / 1000000.0 // ns to ms +} + +// RecalculateUptime calculates uptime on demand. +func (n *Network) RecalculateUptime() { + n.mu.Lock() + defer n.mu.Unlock() + + since := time.Since(n.UptimeData.StartTime) + uptime := since - n.UptimeData.totalDownTime + if n.Health != FullHealth { + uptime -= time.Since(n.UptimeData.wentDown) + } + n.UptimeData.Uptime = (float64(uptime) / float64(since)) * 100.0 +} + +// NodeIsDown is called when the node disconnects for whatever reason. +// Must be safe to call multiple times. +func (n *Network) NodeIsDown(name string) { + n.mu.Lock() + defer n.mu.Unlock() + + if online, ok := n.nodeStatusMap[name]; !ok || online { + n.nodeStatusMap[name] = false + n.NumNodesMonitoredOnline-- + n.UptimeData.wentDown = time.Now() + n.updateHealth() + } +} + +// NodeIsOnline is called when connection to the node is restored. +// Must be safe to call multiple times. +func (n *Network) NodeIsOnline(name string) { + n.mu.Lock() + defer n.mu.Unlock() + + if online, ok := n.nodeStatusMap[name]; ok && !online { + n.nodeStatusMap[name] = true + n.NumNodesMonitoredOnline++ + n.UptimeData.totalDownTime += time.Since(n.UptimeData.wentDown) + n.updateHealth() + } +} + +// NewNode is called when the new node is added to the monitor. +func (n *Network) NewNode(name string) { + n.NumNodesMonitored++ + n.NumNodesMonitoredOnline++ +} + +// NodeDeleted is called when the node is deleted from under the monitor. +func (n *Network) NodeDeleted(name string) { + n.NumNodesMonitored-- + n.NumNodesMonitoredOnline-- +} + +func (n *Network) updateHealth() { + // if we are connected to all validators, we're at full health + // TODO: make sure they're all at the same height (within a block) + // and all proposing (and possibly validating ) Alternatively, just + // check there hasn't been a new round in numValidators rounds + if n.NumValidators != 0 && n.NumNodesMonitoredOnline == n.NumValidators { + n.Health = FullHealth + } else if n.NumNodesMonitoredOnline > 0 && n.NumNodesMonitoredOnline <= n.NumNodesMonitored { + n.Health = ModerateHealth + } else { + n.Health = Dead + } +} + +func (n *Network) UpdateNumValidatorsForHeight(num int, height int64) { + n.mu.Lock() + defer n.mu.Unlock() + + if n.Height <= height { + n.NumValidators = num + } +} + +func (n *Network) GetHealthString() string { + switch n.Health { + case FullHealth: + return "full" + case ModerateHealth: + return "moderate" + case Dead: + return "dead" + default: + return "undefined" + } +} + +// Uptime returns network's uptime in percentages. +func (n *Network) Uptime() float64 { + n.mu.Lock() + defer n.mu.Unlock() + return n.UptimeData.Uptime +} + +// StartTime returns time we started monitoring. +func (n *Network) StartTime() time.Time { + return n.UptimeData.StartTime +} diff --git a/tools/tm-monitor/monitor/network_test.go b/tools/tm-monitor/monitor/network_test.go new file mode 100644 index 000000000..df2d42813 --- /dev/null +++ b/tools/tm-monitor/monitor/network_test.go @@ -0,0 +1,80 @@ +package monitor_test + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + + monitor "github.com/tendermint/tendermint/tools/tm-monitor/monitor" + tmtypes "github.com/tendermint/tendermint/types" +) + +func TestNetworkNewBlock(t *testing.T) { + n := monitor.NewNetwork() + + n.NewBlock(tmtypes.Header{Height: 5, NumTxs: 100}) + assert.Equal(t, int64(5), n.Height) + assert.Equal(t, 0.0, n.AvgBlockTime) + assert.Equal(t, 0.0, n.AvgTxThroughput) +} + +func TestNetworkNewBlockLatency(t *testing.T) { + n := monitor.NewNetwork() + + n.NewBlockLatency(9000000.0) // nanoseconds + assert.Equal(t, 0.0, n.AvgBlockLatency) +} + +func TestNetworkNodeIsDownThenOnline(t *testing.T) { + n := monitor.NewNetwork() + n.NewNode("test") + + n.NodeIsDown("test") + assert.Equal(t, 0, n.NumNodesMonitoredOnline) + assert.Equal(t, monitor.Dead, n.Health) + n.NodeIsDown("test") + assert.Equal(t, 0, n.NumNodesMonitoredOnline) + + n.NodeIsOnline("test") + assert.Equal(t, 1, n.NumNodesMonitoredOnline) + assert.Equal(t, monitor.ModerateHealth, n.Health) + n.NodeIsOnline("test") + assert.Equal(t, 1, n.NumNodesMonitoredOnline) +} + +func TestNetworkNewNode(t *testing.T) { + n := monitor.NewNetwork() + assert.Equal(t, 0, n.NumNodesMonitored) + assert.Equal(t, 0, n.NumNodesMonitoredOnline) + n.NewNode("test") + assert.Equal(t, 1, n.NumNodesMonitored) + assert.Equal(t, 1, n.NumNodesMonitoredOnline) +} + +func TestNetworkNodeDeleted(t *testing.T) { + n := monitor.NewNetwork() + n.NewNode("test") + n.NodeDeleted("test") + assert.Equal(t, 0, n.NumNodesMonitored) + assert.Equal(t, 0, n.NumNodesMonitoredOnline) +} + +func TestNetworkGetHealthString(t *testing.T) { + n := monitor.NewNetwork() + assert.Equal(t, "full", n.GetHealthString()) + n.Health = monitor.ModerateHealth + assert.Equal(t, "moderate", n.GetHealthString()) + n.Health = monitor.Dead + assert.Equal(t, "dead", n.GetHealthString()) +} + +func TestNetworkUptime(t *testing.T) { + n := monitor.NewNetwork() + assert.Equal(t, 100.0, n.Uptime()) +} + +func TestNetworkStartTime(t *testing.T) { + n := monitor.NewNetwork() + assert.True(t, n.StartTime().Before(time.Now())) +} diff --git a/tools/tm-monitor/monitor/node.go b/tools/tm-monitor/monitor/node.go new file mode 100644 index 000000000..b99870207 --- /dev/null +++ b/tools/tm-monitor/monitor/node.go @@ -0,0 +1,261 @@ +package monitor + +import ( + "encoding/json" + "math" + "time" + + "github.com/pkg/errors" + + crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/events" + "github.com/tendermint/tendermint/libs/log" + ctypes "github.com/tendermint/tendermint/rpc/core/types" + rpc_client "github.com/tendermint/tendermint/rpc/lib/client" + em "github.com/tendermint/tendermint/tools/tm-monitor/eventmeter" + tmtypes "github.com/tendermint/tendermint/types" +) + +const maxRestarts = 25 + +type Node struct { + rpcAddr string + + IsValidator bool `json:"is_validator"` // validator or non-validator? + pubKey crypto.PubKey `json:"pub_key"` + + Name string `json:"name"` + Online bool `json:"online"` + Height int64 `json:"height"` + BlockLatency float64 `json:"block_latency" amino:"unsafe"` // ms, interval between block commits + + // em holds the ws connection. Each eventMeter callback is called in a separate go-routine. + em eventMeter + + // rpcClient is an client for making RPC calls to TM + rpcClient rpc_client.HTTPClient + + blockCh chan<- tmtypes.Header + blockLatencyCh chan<- float64 + disconnectCh chan<- bool + + checkIsValidatorInterval time.Duration + + quit chan struct{} + + logger log.Logger +} + +func NewNode(rpcAddr string, options ...func(*Node)) *Node { + em := em.NewEventMeter(rpcAddr, UnmarshalEvent) + rpcClient := rpc_client.NewURIClient(rpcAddr) // HTTP client by default + rpcClient.SetCodec(cdc) + return NewNodeWithEventMeterAndRpcClient(rpcAddr, em, rpcClient, options...) +} + +func NewNodeWithEventMeterAndRpcClient(rpcAddr string, em eventMeter, rpcClient rpc_client.HTTPClient, options ...func(*Node)) *Node { + n := &Node{ + rpcAddr: rpcAddr, + em: em, + rpcClient: rpcClient, + Name: rpcAddr, + quit: make(chan struct{}), + checkIsValidatorInterval: 5 * time.Second, + logger: log.NewNopLogger(), + } + + for _, option := range options { + option(n) + } + + return n +} + +// SetCheckIsValidatorInterval lets you change interval for checking whenever +// node is still a validator or not. +func SetCheckIsValidatorInterval(d time.Duration) func(n *Node) { + return func(n *Node) { + n.checkIsValidatorInterval = d + } +} + +func (n *Node) SendBlocksTo(ch chan<- tmtypes.Header) { + n.blockCh = ch +} + +func (n *Node) SendBlockLatenciesTo(ch chan<- float64) { + n.blockLatencyCh = ch +} + +func (n *Node) NotifyAboutDisconnects(ch chan<- bool) { + n.disconnectCh = ch +} + +// SetLogger lets you set your own logger +func (n *Node) SetLogger(l log.Logger) { + n.logger = l + n.em.SetLogger(l) +} + +func (n *Node) Start() error { + if err := n.em.Start(); err != nil { + return err + } + + n.em.RegisterLatencyCallback(latencyCallback(n)) + err := n.em.Subscribe(tmtypes.EventQueryNewBlockHeader.String(), newBlockCallback(n)) + if err != nil { + return err + } + n.em.RegisterDisconnectCallback(disconnectCallback(n)) + + n.Online = true + + n.checkIsValidator() + go n.checkIsValidatorLoop() + + return nil +} + +func (n *Node) Stop() { + n.Online = false + + n.em.Stop() + + close(n.quit) +} + +// implements eventmeter.EventCallbackFunc +func newBlockCallback(n *Node) em.EventCallbackFunc { + return func(metric *em.EventMetric, data interface{}) { + block := data.(tmtypes.TMEventData).(tmtypes.EventDataNewBlockHeader).Header + + n.Height = block.Height + n.logger.Info("new block", "height", block.Height, "numTxs", block.NumTxs) + + if n.blockCh != nil { + n.blockCh <- block + } + } +} + +// implements eventmeter.EventLatencyFunc +func latencyCallback(n *Node) em.LatencyCallbackFunc { + return func(latency float64) { + n.BlockLatency = latency / 1000000.0 // ns to ms + n.logger.Info("new block latency", "latency", n.BlockLatency) + + if n.blockLatencyCh != nil { + n.blockLatencyCh <- latency + } + } +} + +// implements eventmeter.DisconnectCallbackFunc +func disconnectCallback(n *Node) em.DisconnectCallbackFunc { + return func() { + n.Online = false + n.logger.Info("status", "down") + + if n.disconnectCh != nil { + n.disconnectCh <- true + } + } +} + +func (n *Node) RestartEventMeterBackoff() error { + attempt := 0 + + for { + d := time.Duration(math.Exp2(float64(attempt))) + time.Sleep(d * time.Second) + + if err := n.em.Start(); err != nil { + n.logger.Info("restart failed", "err", err) + } else { + // TODO: authenticate pubkey + return nil + } + + attempt++ + + if attempt > maxRestarts { + return errors.New("Reached max restarts") + } + } +} + +func (n *Node) NumValidators() (height int64, num int, err error) { + height, vals, err := n.validators() + if err != nil { + return 0, 0, err + } + return height, len(vals), nil +} + +func (n *Node) validators() (height int64, validators []*tmtypes.Validator, err error) { + vals := new(ctypes.ResultValidators) + if _, err = n.rpcClient.Call("validators", nil, vals); err != nil { + return 0, make([]*tmtypes.Validator, 0), err + } + return vals.BlockHeight, vals.Validators, nil +} + +func (n *Node) checkIsValidatorLoop() { + for { + select { + case <-n.quit: + return + case <-time.After(n.checkIsValidatorInterval): + n.checkIsValidator() + } + } +} + +func (n *Node) checkIsValidator() { + _, validators, err := n.validators() + if err == nil { + for _, v := range validators { + key, err1 := n.getPubKey() + // TODO: use bytes.Equal + if err1 == nil && v.PubKey == key { + n.IsValidator = true + } + } + } else { + n.logger.Info("check is validator failed", "err", err) + } +} + +func (n *Node) getPubKey() (crypto.PubKey, error) { + if n.pubKey != nil { + return n.pubKey, nil + } + + status := new(ctypes.ResultStatus) + _, err := n.rpcClient.Call("status", nil, status) + if err != nil { + return nil, err + } + n.pubKey = status.ValidatorInfo.PubKey + return n.pubKey, nil +} + +type eventMeter interface { + Start() error + Stop() + RegisterLatencyCallback(em.LatencyCallbackFunc) + RegisterDisconnectCallback(em.DisconnectCallbackFunc) + Subscribe(string, em.EventCallbackFunc) error + Unsubscribe(string) error + SetLogger(l log.Logger) +} + +// UnmarshalEvent unmarshals a json event +func UnmarshalEvent(b json.RawMessage) (string, events.EventData, error) { + event := new(ctypes.ResultEvent) + if err := cdc.UnmarshalJSON(b, event); err != nil { + return "", nil, err + } + return event.Query, event.Data, nil +} diff --git a/tools/tm-monitor/monitor/node_test.go b/tools/tm-monitor/monitor/node_test.go new file mode 100644 index 000000000..10c2a13f1 --- /dev/null +++ b/tools/tm-monitor/monitor/node_test.go @@ -0,0 +1,93 @@ +package monitor_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + amino "github.com/tendermint/go-amino" + "github.com/tendermint/tendermint/crypto/ed25519" + ctypes "github.com/tendermint/tendermint/rpc/core/types" + em "github.com/tendermint/tendermint/tools/tm-monitor/eventmeter" + mock "github.com/tendermint/tendermint/tools/tm-monitor/mock" + monitor "github.com/tendermint/tendermint/tools/tm-monitor/monitor" + tmtypes "github.com/tendermint/tendermint/types" +) + +const ( + blockHeight = int64(1) +) + +func TestNodeStartStop(t *testing.T) { + n, _ := startValidatorNode(t) + defer n.Stop() + + assert.Equal(t, true, n.Online) + assert.Equal(t, true, n.IsValidator) +} + +func TestNodeNewBlockReceived(t *testing.T) { + blockCh := make(chan tmtypes.Header, 100) + n, emMock := startValidatorNode(t) + defer n.Stop() + n.SendBlocksTo(blockCh) + + blockHeader := tmtypes.Header{Height: 5} + emMock.Call("eventCallback", &em.EventMetric{}, tmtypes.EventDataNewBlockHeader{blockHeader}) + + assert.Equal(t, int64(5), n.Height) + assert.Equal(t, blockHeader, <-blockCh) +} + +func TestNodeNewBlockLatencyReceived(t *testing.T) { + blockLatencyCh := make(chan float64, 100) + n, emMock := startValidatorNode(t) + defer n.Stop() + n.SendBlockLatenciesTo(blockLatencyCh) + + emMock.Call("latencyCallback", 1000000.0) + + assert.Equal(t, 1.0, n.BlockLatency) + assert.Equal(t, 1000000.0, <-blockLatencyCh) +} + +func TestNodeConnectionLost(t *testing.T) { + disconnectCh := make(chan bool, 100) + n, emMock := startValidatorNode(t) + defer n.Stop() + n.NotifyAboutDisconnects(disconnectCh) + + emMock.Call("disconnectCallback") + + assert.Equal(t, true, <-disconnectCh) + assert.Equal(t, false, n.Online) +} + +func TestNumValidators(t *testing.T) { + n, _ := startValidatorNode(t) + defer n.Stop() + + height, num, err := n.NumValidators() + assert.Nil(t, err) + assert.Equal(t, blockHeight, height) + assert.Equal(t, 1, num) +} + +func startValidatorNode(t *testing.T) (n *monitor.Node, emMock *mock.EventMeter) { + emMock = &mock.EventMeter{} + + stubs := make(map[string]interface{}) + pubKey := ed25519.GenPrivKey().PubKey() + stubs["validators"] = ctypes.ResultValidators{BlockHeight: blockHeight, Validators: []*tmtypes.Validator{tmtypes.NewValidator(pubKey, 0)}} + stubs["status"] = ctypes.ResultStatus{ValidatorInfo: ctypes.ValidatorInfo{PubKey: pubKey}} + cdc := amino.NewCodec() + rpcClientMock := &mock.RpcClient{Stubs: stubs} + rpcClientMock.SetCodec(cdc) + + n = monitor.NewNodeWithEventMeterAndRpcClient("tcp://127.0.0.1:26657", emMock, rpcClientMock) + + err := n.Start() + require.Nil(t, err) + return +} diff --git a/tools/tm-monitor/monitor/wire.go b/tools/tm-monitor/monitor/wire.go new file mode 100644 index 000000000..696b02778 --- /dev/null +++ b/tools/tm-monitor/monitor/wire.go @@ -0,0 +1,12 @@ +package monitor + +import ( + amino "github.com/tendermint/go-amino" + ctypes "github.com/tendermint/tendermint/rpc/core/types" +) + +var cdc = amino.NewCodec() + +func init() { + ctypes.RegisterAmino(cdc) +} diff --git a/tools/tm-monitor/rpc.go b/tools/tm-monitor/rpc.go new file mode 100644 index 000000000..ab62e0462 --- /dev/null +++ b/tools/tm-monitor/rpc.go @@ -0,0 +1,124 @@ +package main + +import ( + "errors" + "net/http" + + "github.com/tendermint/tendermint/libs/log" + rpc "github.com/tendermint/tendermint/rpc/lib/server" + monitor "github.com/tendermint/tendermint/tools/tm-monitor/monitor" +) + +func startRPC(listenAddr string, m *monitor.Monitor, logger log.Logger) { + routes := routes(m) + + mux := http.NewServeMux() + wm := rpc.NewWebsocketManager(routes, nil) + mux.HandleFunc("/websocket", wm.WebsocketHandler) + rpc.RegisterRPCFuncs(mux, routes, cdc, logger) + if _, err := rpc.StartHTTPServer(listenAddr, mux, logger, rpc.Config{}); err != nil { + panic(err) + } +} + +func routes(m *monitor.Monitor) map[string]*rpc.RPCFunc { + return map[string]*rpc.RPCFunc{ + "status": rpc.NewRPCFunc(RPCStatus(m), ""), + "status/network": rpc.NewRPCFunc(RPCNetworkStatus(m), ""), + "status/node": rpc.NewRPCFunc(RPCNodeStatus(m), "name"), + "monitor": rpc.NewRPCFunc(RPCMonitor(m), "endpoint"), + "unmonitor": rpc.NewRPCFunc(RPCUnmonitor(m), "endpoint"), + + // "start_meter": rpc.NewRPCFunc(network.StartMeter, "chainID,valID,event"), + // "stop_meter": rpc.NewRPCFunc(network.StopMeter, "chainID,valID,event"), + // "meter": rpc.NewRPCFunc(GetMeterResult(network), "chainID,valID,event"), + } +} + +// RPCStatus returns common statistics for the network and statistics per node. +func RPCStatus(m *monitor.Monitor) interface{} { + return func() (networkAndNodes, error) { + return networkAndNodes{m.Network, m.Nodes}, nil + } +} + +// RPCNetworkStatus returns common statistics for the network. +func RPCNetworkStatus(m *monitor.Monitor) interface{} { + return func() (*monitor.Network, error) { + return m.Network, nil + } +} + +// RPCNodeStatus returns statistics for the given node. +func RPCNodeStatus(m *monitor.Monitor) interface{} { + return func(name string) (*monitor.Node, error) { + if i, n := m.NodeByName(name); i != -1 { + return n, nil + } + return nil, errors.New("Cannot find node with that name") + } +} + +// RPCMonitor allows to dynamically add a endpoint to under the monitor. Safe +// to call multiple times. +func RPCMonitor(m *monitor.Monitor) interface{} { + return func(endpoint string) (*monitor.Node, error) { + i, n := m.NodeByName(endpoint) + if i == -1 { + n = monitor.NewNode(endpoint) + if err := m.Monitor(n); err != nil { + return nil, err + } + } + return n, nil + } +} + +// RPCUnmonitor removes the given endpoint from under the monitor. +func RPCUnmonitor(m *monitor.Monitor) interface{} { + return func(endpoint string) (bool, error) { + if i, n := m.NodeByName(endpoint); i != -1 { + m.Unmonitor(n) + return true, nil + } + return false, errors.New("Cannot find node with that name") + } +} + +// func (tn *TendermintNetwork) StartMeter(chainID, valID, eventID string) error { +// tn.mtx.Lock() +// defer tn.mtx.Unlock() +// val, err := tn.getChainVal(chainID, valID) +// if err != nil { +// return err +// } +// return val.EventMeter().Subscribe(eventID, nil) +// } + +// func (tn *TendermintNetwork) StopMeter(chainID, valID, eventID string) error { +// tn.mtx.Lock() +// defer tn.mtx.Unlock() +// val, err := tn.getChainVal(chainID, valID) +// if err != nil { +// return err +// } +// return val.EventMeter().Unsubscribe(eventID) +// } + +// func (tn *TendermintNetwork) GetMeter(chainID, valID, eventID string) (*eventmeter.EventMetric, error) { +// tn.mtx.Lock() +// defer tn.mtx.Unlock() +// val, err := tn.getChainVal(chainID, valID) +// if err != nil { +// return nil, err +// } + +// return val.EventMeter().GetMetric(eventID) +// } + +//--> types + +type networkAndNodes struct { + Network *monitor.Network `json:"network"` + Nodes []*monitor.Node `json:"nodes"` +} diff --git a/tools/tm-monitor/ton.go b/tools/tm-monitor/ton.go new file mode 100644 index 000000000..cad17b39c --- /dev/null +++ b/tools/tm-monitor/ton.go @@ -0,0 +1,100 @@ +package main + +import ( + "fmt" + "io" + "os" + "text/tabwriter" + "time" + + monitor "github.com/tendermint/tendermint/tools/tm-monitor/monitor" +) + +const ( + // Default refresh rate - 200ms + defaultRefreshRate = time.Millisecond * 200 +) + +// Ton - table of nodes. +// +// It produces the unordered list of nodes and updates it periodically. +// +// Default output is stdout, but it could be changed. Note if you want for +// refresh to work properly, output must support [ANSI escape +// codes](http://en.wikipedia.org/wiki/ANSI_escape_code). +// +// Ton was inspired by [Linux top +// program](https://en.wikipedia.org/wiki/Top_(software)) as the name suggests. +type Ton struct { + monitor *monitor.Monitor + + RefreshRate time.Duration + Output io.Writer + quit chan struct{} +} + +func NewTon(m *monitor.Monitor) *Ton { + return &Ton{ + RefreshRate: defaultRefreshRate, + Output: os.Stdout, + quit: make(chan struct{}), + monitor: m, + } +} + +func (o *Ton) Start() { + clearScreen(o.Output) + o.Print() + go o.refresher() +} + +func (o *Ton) Print() { + moveCursor(o.Output, 1, 1) + o.printHeader() + fmt.Println() + o.printTable() +} + +func (o *Ton) Stop() { + close(o.quit) +} + +func (o *Ton) printHeader() { + n := o.monitor.Network + fmt.Fprintf(o.Output, "%v up %.2f%%\n", n.StartTime(), n.Uptime()) + fmt.Println() + fmt.Fprintf(o.Output, "Height: %d\n", n.Height) + fmt.Fprintf(o.Output, "Avg block time: %.3f ms\n", n.AvgBlockTime) + fmt.Fprintf(o.Output, "Avg tx throughput: %.0f per sec\n", n.AvgTxThroughput) + fmt.Fprintf(o.Output, "Avg block latency: %.3f ms\n", n.AvgBlockLatency) + fmt.Fprintf(o.Output, "Active nodes: %d/%d (health: %s) Validators: %d\n", n.NumNodesMonitoredOnline, n.NumNodesMonitored, n.GetHealthString(), n.NumValidators) +} + +func (o *Ton) printTable() { + w := tabwriter.NewWriter(o.Output, 0, 0, 5, ' ', 0) + fmt.Fprintln(w, "NAME\tHEIGHT\tBLOCK LATENCY\tONLINE\tVALIDATOR\t") + for _, n := range o.monitor.Nodes { + fmt.Fprintln(w, fmt.Sprintf("%s\t%d\t%.3f ms\t%v\t%v\t", n.Name, n.Height, n.BlockLatency, n.Online, n.IsValidator)) + } + w.Flush() +} + +// Internal loop for refreshing +func (o *Ton) refresher() { + for { + select { + case <-o.quit: + return + case <-time.After(o.RefreshRate): + o.Print() + } + } +} + +func clearScreen(w io.Writer) { + fmt.Fprint(w, "\033[2J") +} + +func moveCursor(w io.Writer, x int, y int) { + fmt.Fprintf(w, "\033[%d;%dH", x, y) +} diff --git a/tools/tm-monitor/wire.go b/tools/tm-monitor/wire.go new file mode 100644 index 000000000..071c363b0 --- /dev/null +++ b/tools/tm-monitor/wire.go @@ -0,0 +1,12 @@ +package main + +import ( + amino "github.com/tendermint/go-amino" + ctypes "github.com/tendermint/tendermint/rpc/core/types" +) + +var cdc = amino.NewCodec() + +func init() { + ctypes.RegisterAmino(cdc) +} diff --git a/types/block.go b/types/block.go index 48412a0e8..0b64c7b8f 100644 --- a/types/block.go +++ b/types/block.go @@ -17,8 +17,8 @@ import ( // TODO: add Version byte type Block struct { mtx sync.Mutex - *Header `json:"header"` - *Data `json:"data"` + Header `json:"header"` + Data `json:"data"` Evidence EvidenceData `json:"evidence"` LastCommit *Commit `json:"last_commit"` } @@ -27,15 +27,15 @@ type Block struct { // It populates the same set of fields validated by ValidateBasic func MakeBlock(height int64, txs []Tx, commit *Commit) *Block { block := &Block{ - Header: &Header{ + Header: Header{ Height: height, Time: time.Now(), NumTxs: int64(len(txs)), }, - LastCommit: commit, - Data: &Data{ + Data: Data{ Txs: txs, }, + LastCommit: commit, } block.fillHeader() return block @@ -43,6 +43,9 @@ func MakeBlock(height int64, txs []Tx, commit *Commit) *Block { // AddEvidence appends the given evidence to the block func (b *Block) AddEvidence(evidence []Evidence) { + if b == nil { + return + } b.Evidence.Evidence = append(b.Evidence.Evidence, evidence...) } @@ -98,7 +101,7 @@ func (b *Block) Hash() cmn.HexBytes { b.mtx.Lock() defer b.mtx.Unlock() - if b == nil || b.Header == nil || b.Data == nil || b.LastCommit == nil { + if b == nil || b.LastCommit == nil { return nil } b.fillHeader() @@ -107,6 +110,7 @@ func (b *Block) Hash() cmn.HexBytes { // MakePartSet returns a PartSet containing parts of a serialized block. // This is the form in which the block is gossipped to peers. +// CONTRACT: partSize is greater than zero. func (b *Block) MakePartSet(partSize int) *PartSet { if b == nil { return nil @@ -209,7 +213,7 @@ type Header struct { // Hash returns the hash of the header. // Returns nil if ValidatorHash is missing, // since a Header is not valid unless there is -// a ValidaotrsHash (corresponding to the validator set). +// a ValidatorsHash (corresponding to the validator set). func (h *Header) Hash() cmn.HexBytes { if h == nil || len(h.ValidatorsHash) == 0 { return nil @@ -397,6 +401,9 @@ func (commit *Commit) ValidateBasic() error { // Hash returns the hash of the commit func (commit *Commit) Hash() cmn.HexBytes { + if commit == nil { + return nil + } if commit.hash == nil { bs := make([]merkle.Hasher, len(commit.Precommits)) for i, precommit := range commit.Precommits { diff --git a/types/block_meta.go b/types/block_meta.go index 6dd502e4f..d8926af0b 100644 --- a/types/block_meta.go +++ b/types/block_meta.go @@ -3,7 +3,7 @@ package types // BlockMeta contains meta information about a block - namely, it's ID and Header. type BlockMeta struct { BlockID BlockID `json:"block_id"` // the block hash and partsethash - Header *Header `json:"header"` // The block's Header + Header Header `json:"header"` // The block's Header } // NewBlockMeta returns a new BlockMeta from the block and its blockParts. diff --git a/types/block_test.go b/types/block_test.go index 0948e7b21..1d27a7746 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -10,7 +10,25 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" ) -func TestValidateBlock(t *testing.T) { +func TestBlockAddEvidence(t *testing.T) { + txs := []Tx{Tx("foo"), Tx("bar")} + lastID := makeBlockIDRandom() + h := int64(3) + + voteSet, valSet, vals := randVoteSet(h-1, 1, VoteTypePrecommit, 10, 1) + commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals) + require.NoError(t, err) + + block := MakeBlock(h, txs, commit) + require.NotNil(t, block) + + ev := NewMockGoodEvidence(h, 0, valSet.Validators[0].Address) + block.AddEvidence([]Evidence{ev}) +} + +func TestBlockValidateBasic(t *testing.T) { + require.Error(t, (*Block)(nil).ValidateBasic()) + txs := []Tx{Tx("foo"), Tx("bar")} lastID := makeBlockIDRandom() h := int64(3) @@ -57,6 +75,59 @@ func TestValidateBlock(t *testing.T) { block.DataHash = cmn.RandBytes(len(block.DataHash)) err = block.ValidateBasic() require.Error(t, err) + + // tamper with evidence + block = MakeBlock(h, txs, commit) + block.EvidenceHash = []byte("something else") + err = block.ValidateBasic() + require.Error(t, err) +} + +func TestBlockHash(t *testing.T) { + assert.Nil(t, (*Block)(nil).Hash()) + assert.Nil(t, MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil).Hash()) +} + +func TestBlockMakePartSet(t *testing.T) { + assert.Nil(t, (*Block)(nil).MakePartSet(2)) + + partSet := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil).MakePartSet(1024) + assert.NotNil(t, partSet) + assert.Equal(t, 1, partSet.Total()) +} + +func TestBlockHashesTo(t *testing.T) { + assert.False(t, (*Block)(nil).HashesTo(nil)) + + lastID := makeBlockIDRandom() + h := int64(3) + voteSet, valSet, vals := randVoteSet(h-1, 1, VoteTypePrecommit, 10, 1) + commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals) + require.NoError(t, err) + + block := MakeBlock(h, []Tx{Tx("Hello World")}, commit) + block.ValidatorsHash = valSet.Hash() + assert.False(t, block.HashesTo([]byte{})) + assert.False(t, block.HashesTo([]byte("something else"))) + assert.True(t, block.HashesTo(block.Hash())) +} + +func TestBlockSize(t *testing.T) { + size := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil).Size() + if size <= 0 { + t.Fatal("Size of the block is zero or negative") + } +} + +func TestBlockString(t *testing.T) { + assert.Equal(t, "nil-Block", (*Block)(nil).String()) + assert.Equal(t, "nil-Block", (*Block)(nil).StringIndented("")) + assert.Equal(t, "nil-Block", (*Block)(nil).StringShort()) + + block := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil) + assert.NotEqual(t, "nil-Block", block.String()) + assert.NotEqual(t, "nil-Block", block.StringIndented("")) + assert.NotEqual(t, "nil-Block", block.StringShort()) } func makeBlockIDRandom() BlockID { @@ -86,3 +157,61 @@ func TestNilDataHashDoesntCrash(t *testing.T) { assert.Equal(t, []byte((*Data)(nil).Hash()), nilBytes) assert.Equal(t, []byte(new(Data).Hash()), nilBytes) } + +func TestCommit(t *testing.T) { + lastID := makeBlockIDRandom() + h := int64(3) + voteSet, _, vals := randVoteSet(h-1, 1, VoteTypePrecommit, 10, 1) + commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals) + require.NoError(t, err) + + assert.NotNil(t, commit.FirstPrecommit()) + assert.Equal(t, h-1, commit.Height()) + assert.Equal(t, 1, commit.Round()) + assert.Equal(t, VoteTypePrecommit, commit.Type()) + if commit.Size() <= 0 { + t.Fatalf("commit %v has a zero or negative size: %d", commit, commit.Size()) + } + + require.NotNil(t, commit.BitArray()) + assert.Equal(t, cmn.NewBitArray(10).Size(), commit.BitArray().Size()) + + assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0)) + assert.True(t, commit.IsCommit()) +} + +func TestCommitValidateBasic(t *testing.T) { + commit := randCommit() + assert.NoError(t, commit.ValidateBasic()) + + // nil precommit is OK + commit = randCommit() + commit.Precommits[0] = nil + assert.NoError(t, commit.ValidateBasic()) + + // tamper with types + commit = randCommit() + commit.Precommits[0].Type = VoteTypePrevote + assert.Error(t, commit.ValidateBasic()) + + // tamper with height + commit = randCommit() + commit.Precommits[0].Height = int64(100) + assert.Error(t, commit.ValidateBasic()) + + // tamper with round + commit = randCommit() + commit.Precommits[0].Round = 100 + assert.Error(t, commit.ValidateBasic()) +} + +func randCommit() *Commit { + lastID := makeBlockIDRandom() + h := int64(3) + voteSet, _, vals := randVoteSet(h-1, 1, VoteTypePrecommit, 10, 1) + commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals) + if err != nil { + panic(err) + } + return commit +} diff --git a/types/event_buffer.go b/types/event_buffer.go deleted file mode 100644 index 18b41014e..000000000 --- a/types/event_buffer.go +++ /dev/null @@ -1,50 +0,0 @@ -package types - -// Interface assertions -var _ TxEventPublisher = (*TxEventBuffer)(nil) - -// TxEventBuffer is a buffer of events, which uses a slice to temporarily store -// events. -type TxEventBuffer struct { - next TxEventPublisher - capacity int - events []EventDataTx -} - -// NewTxEventBuffer accepts a TxEventPublisher and returns a new buffer with the given -// capacity. -func NewTxEventBuffer(next TxEventPublisher, capacity int) *TxEventBuffer { - return &TxEventBuffer{ - next: next, - capacity: capacity, - events: make([]EventDataTx, 0, capacity), - } -} - -// Len returns the number of events cached. -func (b TxEventBuffer) Len() int { - return len(b.events) -} - -// PublishEventTx buffers an event to be fired upon finality. -func (b *TxEventBuffer) PublishEventTx(e EventDataTx) error { - b.events = append(b.events, e) - return nil -} - -// Flush publishes events by running next.PublishWithTags on all cached events. -// Blocks. Clears cached events. -func (b *TxEventBuffer) Flush() error { - for _, e := range b.events { - err := b.next.PublishEventTx(e) - if err != nil { - return err - } - } - - // Clear out the elements and set the length to 0 - // but maintain the underlying slice's capacity. - // See Issue https://github.com/tendermint/tendermint/issues/1189 - b.events = b.events[:0] - return nil -} diff --git a/types/event_buffer_test.go b/types/event_buffer_test.go deleted file mode 100644 index 74ae9da29..000000000 --- a/types/event_buffer_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -type eventBusMock struct{} - -func (eventBusMock) PublishEventTx(e EventDataTx) error { - return nil -} - -func TestEventBuffer(t *testing.T) { - b := NewTxEventBuffer(eventBusMock{}, 1) - b.PublishEventTx(EventDataTx{}) - assert.Equal(t, 1, b.Len()) - b.Flush() - assert.Equal(t, 0, b.Len()) -} diff --git a/types/event_bus.go b/types/event_bus.go index 54fc60c7b..b4965feee 100644 --- a/types/event_bus.go +++ b/types/event_bus.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - tmpubsub "github.com/tendermint/tendermint/libs/pubsub" cmn "github.com/tendermint/tendermint/libs/common" "github.com/tendermint/tendermint/libs/log" + tmpubsub "github.com/tendermint/tendermint/libs/pubsub" ) const defaultCapacity = 0 @@ -49,7 +49,7 @@ func (b *EventBus) OnStart() error { } func (b *EventBus) OnStop() { - b.pubsub.OnStop() + b.pubsub.Stop() } func (b *EventBus) Subscribe(ctx context.Context, subscriber string, query tmpubsub.Query, out chan<- interface{}) error { diff --git a/types/event_bus_test.go b/types/event_bus_test.go index 81903004d..768b5b325 100644 --- a/types/event_bus_test.go +++ b/types/event_bus_test.go @@ -3,7 +3,6 @@ package types import ( "context" "fmt" - "math/rand" "testing" "time" @@ -11,9 +10,9 @@ import ( "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + cmn "github.com/tendermint/tendermint/libs/common" tmpubsub "github.com/tendermint/tendermint/libs/pubsub" tmquery "github.com/tendermint/tendermint/libs/pubsub/query" - cmn "github.com/tendermint/tendermint/libs/common" ) func TestEventBusPublishEventTx(t *testing.T) { @@ -59,6 +58,64 @@ func TestEventBusPublishEventTx(t *testing.T) { } } +func TestEventBusPublish(t *testing.T) { + eventBus := NewEventBus() + err := eventBus.Start() + require.NoError(t, err) + defer eventBus.Stop() + + eventsCh := make(chan interface{}) + err = eventBus.Subscribe(context.Background(), "test", tmquery.Empty{}, eventsCh) + require.NoError(t, err) + + const numEventsExpected = 14 + done := make(chan struct{}) + go func() { + numEvents := 0 + for range eventsCh { + numEvents++ + if numEvents >= numEventsExpected { + close(done) + } + } + }() + + err = eventBus.Publish(EventNewBlockHeader, EventDataNewBlockHeader{}) + require.NoError(t, err) + err = eventBus.PublishEventNewBlock(EventDataNewBlock{}) + require.NoError(t, err) + err = eventBus.PublishEventNewBlockHeader(EventDataNewBlockHeader{}) + require.NoError(t, err) + err = eventBus.PublishEventVote(EventDataVote{}) + require.NoError(t, err) + err = eventBus.PublishEventProposalHeartbeat(EventDataProposalHeartbeat{}) + require.NoError(t, err) + err = eventBus.PublishEventNewRoundStep(EventDataRoundState{}) + require.NoError(t, err) + err = eventBus.PublishEventTimeoutPropose(EventDataRoundState{}) + require.NoError(t, err) + err = eventBus.PublishEventTimeoutWait(EventDataRoundState{}) + require.NoError(t, err) + err = eventBus.PublishEventNewRound(EventDataRoundState{}) + require.NoError(t, err) + err = eventBus.PublishEventCompleteProposal(EventDataRoundState{}) + require.NoError(t, err) + err = eventBus.PublishEventPolka(EventDataRoundState{}) + require.NoError(t, err) + err = eventBus.PublishEventUnlock(EventDataRoundState{}) + require.NoError(t, err) + err = eventBus.PublishEventRelock(EventDataRoundState{}) + require.NoError(t, err) + err = eventBus.PublishEventLock(EventDataRoundState{}) + require.NoError(t, err) + + select { + case <-done: + case <-time.After(1 * time.Second): + t.Fatalf("expected to receive %d events after 1 sec.", numEventsExpected) + } +} + func BenchmarkEventBus(b *testing.B) { benchmarks := []struct { name string @@ -92,7 +149,7 @@ func BenchmarkEventBus(b *testing.B) { func benchmarkEventBus(numClients int, randQueries bool, randEvents bool, b *testing.B) { // for random* functions - rand.Seed(time.Now().Unix()) + cmn.Seed(time.Now().Unix()) eventBus := NewEventBusWithBufferCapacity(0) // set buffer capacity to 0 so we are not testing cache eventBus.Start() @@ -126,11 +183,7 @@ func benchmarkEventBus(numClients int, randQueries bool, randEvents bool, b *tes } } -var events = []string{EventBond, - EventUnbond, - EventRebond, - EventDupeout, - EventFork, +var events = []string{ EventNewBlock, EventNewBlockHeader, EventNewRound, @@ -145,14 +198,10 @@ var events = []string{EventBond, EventVote} func randEvent() string { - return events[rand.Intn(len(events))] + return events[cmn.RandIntn(len(events))] } -var queries = []tmpubsub.Query{EventQueryBond, - EventQueryUnbond, - EventQueryRebond, - EventQueryDupeout, - EventQueryFork, +var queries = []tmpubsub.Query{ EventQueryNewBlock, EventQueryNewBlockHeader, EventQueryNewRound, @@ -167,5 +216,5 @@ var queries = []tmpubsub.Query{EventQueryBond, EventQueryVote} func randQuery() tmpubsub.Query { - return queries[rand.Intn(len(queries))] + return queries[cmn.RandIntn(len(queries))] } diff --git a/types/events.go b/types/events.go index 2b87297cd..c26fecb71 100644 --- a/types/events.go +++ b/types/events.go @@ -10,22 +10,17 @@ import ( // Reserved event types const ( - EventBond = "Bond" EventCompleteProposal = "CompleteProposal" - EventDupeout = "Dupeout" - EventFork = "Fork" EventLock = "Lock" EventNewBlock = "NewBlock" EventNewBlockHeader = "NewBlockHeader" EventNewRound = "NewRound" EventNewRoundStep = "NewRoundStep" EventPolka = "Polka" - EventRebond = "Rebond" EventRelock = "Relock" EventTimeoutPropose = "TimeoutPropose" EventTimeoutWait = "TimeoutWait" EventTx = "Tx" - EventUnbond = "Unbond" EventUnlock = "Unlock" EventVote = "Vote" EventProposalHeartbeat = "ProposalHeartbeat" @@ -69,7 +64,7 @@ type EventDataNewBlock struct { // light weight event for benchmarking type EventDataNewBlockHeader struct { - Header *Header `json:"header"` + Header Header `json:"header"` } // All txs fire EventDataTx @@ -113,11 +108,6 @@ const ( ) var ( - EventQueryBond = QueryForEvent(EventBond) - EventQueryUnbond = QueryForEvent(EventUnbond) - EventQueryRebond = QueryForEvent(EventRebond) - EventQueryDupeout = QueryForEvent(EventDupeout) - EventQueryFork = QueryForEvent(EventFork) EventQueryNewBlock = QueryForEvent(EventNewBlock) EventQueryNewBlockHeader = QueryForEvent(EventNewBlockHeader) EventQueryNewRound = QueryForEvent(EventNewRound) diff --git a/types/events_test.go b/types/events_test.go new file mode 100644 index 000000000..a4b71d922 --- /dev/null +++ b/types/events_test.go @@ -0,0 +1,23 @@ +package types + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestQueryTxFor(t *testing.T) { + tx := Tx("foo") + assert.Equal(t, + fmt.Sprintf("tm.event='Tx' AND tx.hash='%X'", tx.Hash()), + EventQueryTxFor(tx).String(), + ) +} + +func TestQueryForEvent(t *testing.T) { + assert.Equal(t, + "tm.event='NewBlock'", + QueryForEvent(EventNewBlock).String(), + ) +} diff --git a/types/evidence.go b/types/evidence.go index 266375ec3..6313f43a5 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -4,7 +4,7 @@ import ( "bytes" "fmt" - "github.com/tendermint/go-amino" + amino "github.com/tendermint/go-amino" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/merkle" diff --git a/types/evidence_test.go b/types/evidence_test.go index 5bbb2a37d..54eba01cd 100644 --- a/types/evidence_test.go +++ b/types/evidence_test.go @@ -36,7 +36,7 @@ func TestEvidence(t *testing.T) { blockID3 := makeBlockID("blockhash", 10000, "partshash") blockID4 := makeBlockID("blockhash", 10000, "partshash2") - chainID := "mychain" + const chainID = "mychain" vote1 := makeVote(val, chainID, 0, 10, 2, 1, blockID) badVote := makeVote(val, chainID, 0, 10, 2, 1, blockID) @@ -72,3 +72,30 @@ func TestEvidence(t *testing.T) { } } } + +func TestDuplicatedVoteEvidence(t *testing.T) { + ev := randomDuplicatedVoteEvidence() + + assert.True(t, ev.Equal(ev)) + assert.False(t, ev.Equal(&DuplicateVoteEvidence{})) +} + +func TestEvidenceList(t *testing.T) { + ev := randomDuplicatedVoteEvidence() + evl := EvidenceList([]Evidence{ev}) + + assert.NotNil(t, evl.Hash()) + assert.True(t, evl.Has(ev)) + assert.False(t, evl.Has(&DuplicateVoteEvidence{})) +} + +func randomDuplicatedVoteEvidence() *DuplicateVoteEvidence { + val := NewMockPV() + blockID := makeBlockID("blockhash", 1000, "partshash") + blockID2 := makeBlockID("blockhash2", 1000, "partshash") + const chainID = "mychain" + return &DuplicateVoteEvidence{ + VoteA: makeVote(val, chainID, 0, 10, 2, 1, blockID), + VoteB: makeVote(val, chainID, 0, 10, 2, 1, blockID2), + } +} diff --git a/types/genesis.go b/types/genesis.go index 0367c6b2f..220ee0e0e 100644 --- a/types/genesis.go +++ b/types/genesis.go @@ -26,17 +26,7 @@ type GenesisDoc struct { ConsensusParams *ConsensusParams `json:"consensus_params,omitempty"` Validators []GenesisValidator `json:"validators"` AppHash cmn.HexBytes `json:"app_hash"` - AppStateJSON json.RawMessage `json:"app_state,omitempty"` - AppOptions json.RawMessage `json:"app_options,omitempty"` // DEPRECATED -} - -// AppState returns raw application state. -// TODO: replace with AppState field during next breaking release (0.18) -func (genDoc *GenesisDoc) AppState() json.RawMessage { - if len(genDoc.AppOptions) > 0 { - return genDoc.AppOptions - } - return genDoc.AppStateJSON + AppState json.RawMessage `json:"app_state,omitempty"` } // SaveAs is a utility method for saving GenensisDoc as a JSON file. diff --git a/types/genesis_test.go b/types/genesis_test.go index 24398a9a5..925bba790 100644 --- a/types/genesis_test.go +++ b/types/genesis_test.go @@ -1,10 +1,14 @@ package types import ( + "io/ioutil" + "os" "testing" + "time" "github.com/stretchr/testify/assert" - "github.com/tendermint/tendermint/crypto" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto/ed25519" ) func TestGenesisBad(t *testing.T) { @@ -36,7 +40,7 @@ func TestGenesisGood(t *testing.T) { // create a base gendoc from struct baseGenDoc := &GenesisDoc{ ChainID: "abc", - Validators: []GenesisValidator{{crypto.GenPrivKeyEd25519().PubKey(), 10, "myval"}}, + Validators: []GenesisValidator{{ed25519.GenPrivKey().PubKey(), 10, "myval"}}, } genDocBytes, err = cdc.MarshalJSON(baseGenDoc) assert.NoError(t, err, "error marshalling genDoc") @@ -59,3 +63,44 @@ func TestGenesisGood(t *testing.T) { genDoc, err = GenesisDocFromJSON(genDocBytes) assert.Error(t, err, "expected error for genDoc json with block size of 0") } + +func TestGenesisSaveAs(t *testing.T) { + tmpfile, err := ioutil.TempFile("", "genesis") + require.NoError(t, err) + defer os.Remove(tmpfile.Name()) + + genDoc := randomGenesisDoc() + + // save + genDoc.SaveAs(tmpfile.Name()) + stat, err := tmpfile.Stat() + require.NoError(t, err) + if err != nil && stat.Size() <= 0 { + t.Fatalf("SaveAs failed to write any bytes to %v", tmpfile.Name()) + } + + err = tmpfile.Close() + require.NoError(t, err) + + // load + genDoc2, err := GenesisDocFromFile(tmpfile.Name()) + require.NoError(t, err) + + // fails to unknown reason + // assert.EqualValues(t, genDoc2, genDoc) + assert.Equal(t, genDoc2.Validators, genDoc.Validators) +} + +func TestGenesisValidatorHash(t *testing.T) { + genDoc := randomGenesisDoc() + assert.NotEmpty(t, genDoc.ValidatorHash()) +} + +func randomGenesisDoc() *GenesisDoc { + return &GenesisDoc{ + GenesisTime: time.Now().UTC(), + ChainID: "abc", + Validators: []GenesisValidator{{ed25519.GenPrivKey().PubKey(), 10, "myval"}}, + ConsensusParams: DefaultConsensusParams(), + } +} diff --git a/types/heartbeat_test.go b/types/heartbeat_test.go index 174c3ba97..f55c0bf3f 100644 --- a/types/heartbeat_test.go +++ b/types/heartbeat_test.go @@ -4,8 +4,7 @@ import ( "testing" "github.com/stretchr/testify/require" - - "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" ) func TestHeartbeatCopy(t *testing.T) { @@ -27,7 +26,7 @@ func TestHeartbeatString(t *testing.T) { hb := &Heartbeat{ValidatorIndex: 1, Height: 11, Round: 2} require.Equal(t, hb.String(), "Heartbeat{1:000000000000 11/02 (0) }") - var key crypto.PrivKeyEd25519 + var key ed25519.PrivKeyEd25519 sig, err := key.Sign([]byte("Tendermint")) require.NoError(t, err) hb.Signature = sig diff --git a/types/params_test.go b/types/params_test.go index f645585eb..e8e13dba0 100644 --- a/types/params_test.go +++ b/types/params_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + abci "github.com/tendermint/tendermint/abci/types" ) func newConsensusParams(blockSize, partSize int) ConsensusParams { @@ -86,3 +87,59 @@ func TestConsensusParamsHash(t *testing.T) { assert.NotEqual(t, hashes[i], hashes[i+1]) } } + +func TestConsensusParamsUpdate(t *testing.T) { + testCases := []struct { + params ConsensusParams + updates *abci.ConsensusParams + updatedParams ConsensusParams + }{ + // empty updates + { + makeParams(1, 2, 3, 4, 5, 6), + &abci.ConsensusParams{}, + makeParams(1, 2, 3, 4, 5, 6), + }, + // negative BlockPartSizeBytes + { + makeParams(1, 2, 3, 4, 5, 6), + &abci.ConsensusParams{ + BlockSize: &abci.BlockSize{ + MaxBytes: -100, + MaxTxs: -200, + MaxGas: -300, + }, + TxSize: &abci.TxSize{ + MaxBytes: -400, + MaxGas: -500, + }, + BlockGossip: &abci.BlockGossip{ + BlockPartSizeBytes: -600, + }, + }, + makeParams(1, 2, 3, 4, 5, 6), + }, + // fine updates + { + makeParams(1, 2, 3, 4, 5, 6), + &abci.ConsensusParams{ + BlockSize: &abci.BlockSize{ + MaxBytes: 100, + MaxTxs: 200, + MaxGas: 300, + }, + TxSize: &abci.TxSize{ + MaxBytes: 400, + MaxGas: 500, + }, + BlockGossip: &abci.BlockGossip{ + BlockPartSizeBytes: 600, + }, + }, + makeParams(100, 200, 300, 400, 500, 600), + }, + } + for _, tc := range testCases { + assert.Equal(t, tc.updatedParams, tc.params.Update(tc.updates)) + } +} diff --git a/types/part_set_test.go b/types/part_set_test.go index 01437f05e..3576e747e 100644 --- a/types/part_set_test.go +++ b/types/part_set_test.go @@ -1,10 +1,12 @@ package types import ( - "bytes" "io/ioutil" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + cmn "github.com/tendermint/tendermint/libs/common" ) @@ -13,24 +15,21 @@ const ( ) func TestBasicPartSet(t *testing.T) { - // Construct random data of size partSize * 100 data := cmn.RandBytes(testPartSize * 100) - partSet := NewPartSetFromData(data, testPartSize) - if len(partSet.Hash()) == 0 { - t.Error("Expected to get hash") - } - if partSet.Total() != 100 { - t.Errorf("Expected to get 100 parts, but got %v", partSet.Total()) - } - if !partSet.IsComplete() { - t.Errorf("PartSet should be complete") - } + + assert.NotEmpty(t, partSet.Hash()) + assert.Equal(t, 100, partSet.Total()) + assert.Equal(t, 100, partSet.BitArray().Size()) + assert.True(t, partSet.HashesTo(partSet.Hash())) + assert.True(t, partSet.IsComplete()) + assert.Equal(t, 100, partSet.Count()) // Test adding parts to a new partSet. partSet2 := NewPartSetFromHeader(partSet.Header()) + assert.True(t, partSet2.HasHeader(partSet.Header())) for i := 0; i < partSet.Total(); i++ { part := partSet.GetPart(i) //t.Logf("\n%v", part) @@ -39,31 +38,28 @@ func TestBasicPartSet(t *testing.T) { t.Errorf("Failed to add part %v, error: %v", i, err) } } - - if !bytes.Equal(partSet.Hash(), partSet2.Hash()) { - t.Error("Expected to get same hash") - } - if partSet2.Total() != 100 { - t.Errorf("Expected to get 100 parts, but got %v", partSet2.Total()) - } - if !partSet2.IsComplete() { - t.Errorf("Reconstructed PartSet should be complete") - } + // adding part with invalid index + added, err := partSet2.AddPart(&Part{Index: 10000}) + assert.False(t, added) + assert.Error(t, err) + // adding existing part + added, err = partSet2.AddPart(partSet2.GetPart(0)) + assert.False(t, added) + assert.Nil(t, err) + + assert.Equal(t, partSet.Hash(), partSet2.Hash()) + assert.Equal(t, 100, partSet2.Total()) + assert.True(t, partSet2.IsComplete()) // Reconstruct data, assert that they are equal. data2Reader := partSet2.GetReader() data2, err := ioutil.ReadAll(data2Reader) - if err != nil { - t.Errorf("Error reading data2Reader: %v", err) - } - if !bytes.Equal(data, data2) { - t.Errorf("Got wrong data.") - } + require.NoError(t, err) + assert.Equal(t, data, data2) } func TestWrongProof(t *testing.T) { - // Construct random data of size partSize * 100 data := cmn.RandBytes(testPartSize * 100) partSet := NewPartSetFromData(data, testPartSize) @@ -86,5 +82,4 @@ func TestWrongProof(t *testing.T) { if added || err == nil { t.Errorf("Expected to fail adding a part with bad bytes.") } - } diff --git a/types/priv_validator.go b/types/priv_validator.go index 85db65a41..1642be41b 100644 --- a/types/priv_validator.go +++ b/types/priv_validator.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" ) // PrivValidator defines the functionality of a local Tendermint validator @@ -47,7 +48,7 @@ type MockPV struct { } func NewMockPV() *MockPV { - return &MockPV{crypto.GenPrivKeyEd25519()} + return &MockPV{ed25519.GenPrivKey()} } // Implements PrivValidator. diff --git a/types/proto3/block.pb.go b/types/proto3/block.pb.go new file mode 100644 index 000000000..805828f82 --- /dev/null +++ b/types/proto3/block.pb.go @@ -0,0 +1,261 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: block.proto + +/* +Package proto3 is a generated protocol buffer package. + +It is generated from these files: + block.proto + +It has these top-level messages: + PartSetHeader + BlockID + Header + Timestamp +*/ +package proto3 + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type PartSetHeader struct { + Total int32 `protobuf:"zigzag32,1,opt,name=Total" json:"Total,omitempty"` + Hash []byte `protobuf:"bytes,2,opt,name=Hash,proto3" json:"Hash,omitempty"` +} + +func (m *PartSetHeader) Reset() { *m = PartSetHeader{} } +func (m *PartSetHeader) String() string { return proto.CompactTextString(m) } +func (*PartSetHeader) ProtoMessage() {} +func (*PartSetHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *PartSetHeader) GetTotal() int32 { + if m != nil { + return m.Total + } + return 0 +} + +func (m *PartSetHeader) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +type BlockID struct { + Hash []byte `protobuf:"bytes,1,opt,name=Hash,proto3" json:"Hash,omitempty"` + PartsHeader *PartSetHeader `protobuf:"bytes,2,opt,name=PartsHeader" json:"PartsHeader,omitempty"` +} + +func (m *BlockID) Reset() { *m = BlockID{} } +func (m *BlockID) String() string { return proto.CompactTextString(m) } +func (*BlockID) ProtoMessage() {} +func (*BlockID) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *BlockID) GetHash() []byte { + if m != nil { + return m.Hash + } + return nil +} + +func (m *BlockID) GetPartsHeader() *PartSetHeader { + if m != nil { + return m.PartsHeader + } + return nil +} + +type Header struct { + // basic block info + ChainID string `protobuf:"bytes,1,opt,name=ChainID" json:"ChainID,omitempty"` + Height int64 `protobuf:"zigzag64,2,opt,name=Height" json:"Height,omitempty"` + Time *Timestamp `protobuf:"bytes,3,opt,name=Time" json:"Time,omitempty"` + NumTxs int64 `protobuf:"zigzag64,4,opt,name=NumTxs" json:"NumTxs,omitempty"` + // prev block info + LastBlockID *BlockID `protobuf:"bytes,5,opt,name=LastBlockID" json:"LastBlockID,omitempty"` + TotalTxs int64 `protobuf:"zigzag64,6,opt,name=TotalTxs" json:"TotalTxs,omitempty"` + // hashes of block data + LastCommitHash []byte `protobuf:"bytes,7,opt,name=LastCommitHash,proto3" json:"LastCommitHash,omitempty"` + DataHash []byte `protobuf:"bytes,8,opt,name=DataHash,proto3" json:"DataHash,omitempty"` + // hashes from the app output from the prev block + ValidatorsHash []byte `protobuf:"bytes,9,opt,name=ValidatorsHash,proto3" json:"ValidatorsHash,omitempty"` + ConsensusHash []byte `protobuf:"bytes,10,opt,name=ConsensusHash,proto3" json:"ConsensusHash,omitempty"` + AppHash []byte `protobuf:"bytes,11,opt,name=AppHash,proto3" json:"AppHash,omitempty"` + LastResultsHash []byte `protobuf:"bytes,12,opt,name=LastResultsHash,proto3" json:"LastResultsHash,omitempty"` + // consensus info + EvidenceHash []byte `protobuf:"bytes,13,opt,name=EvidenceHash,proto3" json:"EvidenceHash,omitempty"` +} + +func (m *Header) Reset() { *m = Header{} } +func (m *Header) String() string { return proto.CompactTextString(m) } +func (*Header) ProtoMessage() {} +func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *Header) GetChainID() string { + if m != nil { + return m.ChainID + } + return "" +} + +func (m *Header) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *Header) GetTime() *Timestamp { + if m != nil { + return m.Time + } + return nil +} + +func (m *Header) GetNumTxs() int64 { + if m != nil { + return m.NumTxs + } + return 0 +} + +func (m *Header) GetLastBlockID() *BlockID { + if m != nil { + return m.LastBlockID + } + return nil +} + +func (m *Header) GetTotalTxs() int64 { + if m != nil { + return m.TotalTxs + } + return 0 +} + +func (m *Header) GetLastCommitHash() []byte { + if m != nil { + return m.LastCommitHash + } + return nil +} + +func (m *Header) GetDataHash() []byte { + if m != nil { + return m.DataHash + } + return nil +} + +func (m *Header) GetValidatorsHash() []byte { + if m != nil { + return m.ValidatorsHash + } + return nil +} + +func (m *Header) GetConsensusHash() []byte { + if m != nil { + return m.ConsensusHash + } + return nil +} + +func (m *Header) GetAppHash() []byte { + if m != nil { + return m.AppHash + } + return nil +} + +func (m *Header) GetLastResultsHash() []byte { + if m != nil { + return m.LastResultsHash + } + return nil +} + +func (m *Header) GetEvidenceHash() []byte { + if m != nil { + return m.EvidenceHash + } + return nil +} + +// Timestamp wraps how amino encodes time. Note that this is different from the protobuf well-known type +// protobuf/timestamp.proto in the sense that there seconds and nanos are varint encoded. See: +// https://github.com/google/protobuf/blob/d2980062c859649523d5fd51d6b55ab310e47482/src/google/protobuf/timestamp.proto#L123-L135 +// Also nanos do not get skipped if they are zero in amino. +type Timestamp struct { + Seconds int64 `protobuf:"fixed64,1,opt,name=seconds" json:"seconds,omitempty"` + Nanos int32 `protobuf:"fixed32,2,opt,name=nanos" json:"nanos,omitempty"` +} + +func (m *Timestamp) Reset() { *m = Timestamp{} } +func (m *Timestamp) String() string { return proto.CompactTextString(m) } +func (*Timestamp) ProtoMessage() {} +func (*Timestamp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +func (m *Timestamp) GetSeconds() int64 { + if m != nil { + return m.Seconds + } + return 0 +} + +func (m *Timestamp) GetNanos() int32 { + if m != nil { + return m.Nanos + } + return 0 +} + +func init() { + proto.RegisterType((*PartSetHeader)(nil), "proto3.PartSetHeader") + proto.RegisterType((*BlockID)(nil), "proto3.BlockID") + proto.RegisterType((*Header)(nil), "proto3.Header") + proto.RegisterType((*Timestamp)(nil), "proto3.Timestamp") +} + +func init() { proto.RegisterFile("block.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 372 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x92, 0x4f, 0x6b, 0xe3, 0x30, + 0x10, 0xc5, 0xf1, 0xe6, 0xff, 0x38, 0xd9, 0x6c, 0x86, 0xdd, 0xc5, 0xf4, 0x14, 0x4c, 0x5b, 0x72, + 0x0a, 0xb4, 0x39, 0x94, 0xd2, 0x53, 0x9b, 0x14, 0x12, 0x28, 0xa5, 0xa8, 0x21, 0x77, 0x25, 0x16, + 0x8d, 0xa9, 0x2d, 0x19, 0x4b, 0x29, 0xfd, 0x7c, 0xfd, 0x64, 0x45, 0x23, 0xdb, 0x8d, 0x73, 0x4a, + 0xde, 0x9b, 0x37, 0xbf, 0x91, 0x47, 0x02, 0x7f, 0x9b, 0xa8, 0xdd, 0xfb, 0x34, 0xcb, 0x95, 0x51, + 0xd8, 0xa6, 0x9f, 0x59, 0x78, 0x0b, 0x83, 0x17, 0x9e, 0x9b, 0x57, 0x61, 0x96, 0x82, 0x47, 0x22, + 0xc7, 0xbf, 0xd0, 0x5a, 0x2b, 0xc3, 0x93, 0xc0, 0x1b, 0x7b, 0x93, 0x11, 0x73, 0x02, 0x11, 0x9a, + 0x4b, 0xae, 0xf7, 0xc1, 0xaf, 0xb1, 0x37, 0xe9, 0x33, 0xfa, 0x1f, 0x6e, 0xa0, 0xf3, 0x60, 0x89, + 0xab, 0x45, 0x55, 0xf6, 0x7e, 0xca, 0x78, 0x03, 0xbe, 0x25, 0x6b, 0xc7, 0xa5, 0x4e, 0xff, 0xfa, + 0x9f, 0x1b, 0x3f, 0x9b, 0xd6, 0x86, 0xb2, 0xe3, 0x64, 0xf8, 0xd5, 0x80, 0x76, 0x71, 0x98, 0x00, + 0x3a, 0xf3, 0x3d, 0x8f, 0xe5, 0x6a, 0x41, 0xe8, 0x1e, 0x2b, 0x25, 0xfe, 0xb7, 0x99, 0xf8, 0x6d, + 0x6f, 0x08, 0x8c, 0xac, 0x50, 0x78, 0x01, 0xcd, 0x75, 0x9c, 0x8a, 0xa0, 0x41, 0xe3, 0x46, 0xe5, + 0x38, 0xeb, 0x69, 0xc3, 0xd3, 0x8c, 0x51, 0xd9, 0xb6, 0x3f, 0x1f, 0xd2, 0xf5, 0xa7, 0x0e, 0x9a, + 0xae, 0xdd, 0x29, 0xbc, 0x02, 0xff, 0x89, 0x6b, 0x53, 0x7c, 0x57, 0xd0, 0x22, 0xca, 0xb0, 0xa4, + 0x14, 0x36, 0x3b, 0xce, 0xe0, 0x19, 0x74, 0x69, 0x47, 0x16, 0xd6, 0x26, 0x58, 0xa5, 0xf1, 0x12, + 0x7e, 0xdb, 0xe8, 0x5c, 0xa5, 0x69, 0x6c, 0x68, 0x43, 0x1d, 0xda, 0xd0, 0x89, 0x6b, 0x19, 0x0b, + 0x6e, 0x38, 0x25, 0xba, 0x94, 0xa8, 0xb4, 0x65, 0x6c, 0x78, 0x12, 0x47, 0xdc, 0xa8, 0x5c, 0x53, + 0xa2, 0xe7, 0x18, 0x75, 0x17, 0xcf, 0x61, 0x30, 0x57, 0x52, 0x0b, 0xa9, 0x0f, 0x2e, 0x06, 0x14, + 0xab, 0x9b, 0x76, 0xa3, 0xf7, 0x59, 0x46, 0x75, 0x9f, 0xea, 0xa5, 0xc4, 0x09, 0x0c, 0xed, 0xa9, + 0x98, 0xd0, 0x87, 0xc4, 0x38, 0x42, 0x9f, 0x12, 0xa7, 0x36, 0x86, 0xd0, 0x7f, 0xfc, 0x88, 0x23, + 0x21, 0x77, 0x82, 0x62, 0x03, 0x8a, 0xd5, 0xbc, 0xf0, 0x0e, 0x7a, 0xd5, 0xce, 0xed, 0x50, 0x2d, + 0x76, 0x4a, 0x46, 0x9a, 0xae, 0xf1, 0x0f, 0x2b, 0xa5, 0x7d, 0x6d, 0x92, 0x4b, 0xa5, 0xe9, 0x16, + 0x87, 0xcc, 0x89, 0x6d, 0xf1, 0x38, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x6b, 0x74, 0x2f, 0xbd, + 0xb2, 0x02, 0x00, 0x00, +} diff --git a/types/proto3/block.proto b/types/proto3/block.proto new file mode 100644 index 000000000..bc3cf8749 --- /dev/null +++ b/types/proto3/block.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; + +package proto3; + + +message PartSetHeader { + sint32 Total = 1; + bytes Hash = 2; +} + +message BlockID { + bytes Hash = 1; + PartSetHeader PartsHeader = 2; +} + +message Header { + // basic block info + string ChainID = 1; + sint64 Height = 2; + Timestamp Time = 3; + sint64 NumTxs = 4; + + // prev block info + BlockID LastBlockID = 5; + sint64 TotalTxs = 6; + + // hashes of block data + bytes LastCommitHash = 7; // commit from validators from the last block + bytes DataHash = 8; // transactions + + // hashes from the app output from the prev block + bytes ValidatorsHash = 9; // validators for the current block + bytes ConsensusHash = 10; // consensus params for current block + bytes AppHash = 11; // state after txs from the previous block + bytes LastResultsHash = 12; // root hash of all results from the txs from the previous block + + // consensus info + bytes EvidenceHash = 13; // evidence included in the block +} + +// Timestamp wraps how amino encodes time. Note that this is different from the protobuf well-known type +// protobuf/timestamp.proto in the sense that there seconds and nanos are varint encoded. See: +// https://github.com/google/protobuf/blob/d2980062c859649523d5fd51d6b55ab310e47482/src/google/protobuf/timestamp.proto#L123-L135 +// Also nanos do not get skipped if they are zero in amino. +message Timestamp { + sfixed64 seconds = 1; + sfixed32 nanos = 2; +} diff --git a/types/proto3_test.go b/types/proto3_test.go new file mode 100644 index 000000000..19a624a65 --- /dev/null +++ b/types/proto3_test.go @@ -0,0 +1,115 @@ +package types + +import ( + "testing" + "time" + + "github.com/golang/protobuf/proto" + "github.com/stretchr/testify/assert" + + "github.com/tendermint/tendermint/types/proto3" +) + +func TestProto3Compatibility(t *testing.T) { + tm, err := time.Parse("Mon Jan 2 15:04:05 -0700 MST 2006", "Mon Jan 2 15:04:05 -0700 MST 2006") + assert.NoError(t, err) + // add some nanos, otherwise protobuf will skip over this while amino (still) won't! + tm = tm.Add(50000 * time.Nanosecond) + seconds := tm.Unix() + nanos := int32(tm.Nanosecond()) + t.Log("seconds", seconds) + t.Log("nanos", nanos) + + pbHeader := proto3.Header{ + ChainID: "cosmos", + Height: 150, + Time: &proto3.Timestamp{Seconds: seconds, Nanos: nanos}, + NumTxs: 7, + LastBlockID: &proto3.BlockID{ + Hash: []byte("some serious hashing"), + PartsHeader: &proto3.PartSetHeader{ + Total: 8, + Hash: []byte("some more serious hashing"), + }, + }, + TotalTxs: 100, + LastCommitHash: []byte("commit hash"), + DataHash: []byte("data hash"), + ValidatorsHash: []byte("validators hash"), + } + aminoHeader := Header{ + ChainID: "cosmos", + Height: 150, + Time: tm, + NumTxs: 7, + LastBlockID: BlockID{ + Hash: []byte("some serious hashing"), + PartsHeader: PartSetHeader{ + Total: 8, + Hash: []byte("some more serious hashing"), + }, + }, + TotalTxs: 100, + LastCommitHash: []byte("commit hash"), + DataHash: []byte("data hash"), + ValidatorsHash: []byte("validators hash"), + } + ab, err := cdc.MarshalBinaryBare(aminoHeader) + assert.NoError(t, err, "unexpected error") + + pb, err := proto.Marshal(&pbHeader) + assert.NoError(t, err, "unexpected error") + // This works: + assert.Equal(t, ab, pb, "encoding doesn't match") + + emptyLastBlockPb := proto3.Header{ + ChainID: "cosmos", + Height: 150, + Time: &proto3.Timestamp{Seconds: seconds, Nanos: nanos}, + NumTxs: 7, + // This is not fully skipped in amino (yet) although it is empty: + LastBlockID: &proto3.BlockID{ + PartsHeader: &proto3.PartSetHeader{ + }, + }, + TotalTxs: 100, + LastCommitHash: []byte("commit hash"), + DataHash: []byte("data hash"), + ValidatorsHash: []byte("validators hash"), + } + emptyLastBlockAm := Header{ + ChainID: "cosmos", + Height: 150, + Time: tm, + NumTxs: 7, + TotalTxs: 100, + LastCommitHash: []byte("commit hash"), + DataHash: []byte("data hash"), + ValidatorsHash: []byte("validators hash"), + } + + ab, err = cdc.MarshalBinaryBare(emptyLastBlockAm) + assert.NoError(t, err, "unexpected error") + + pb, err = proto.Marshal(&emptyLastBlockPb) + assert.NoError(t, err, "unexpected error") + // This works: + assert.Equal(t, ab, pb, "encoding doesn't match") + + pb, err = proto.Marshal(&proto3.Header{}) + assert.NoError(t, err, "unexpected error") + t.Log(pb) + + // While in protobuf Header{} encodes to an empty byte slice it does not in amino: + ab, err = cdc.MarshalBinaryBare(Header{}) + assert.NoError(t, err, "unexpected error") + t.Log(ab) + + pb, err = proto.Marshal(&proto3.Timestamp{}) + assert.NoError(t, err, "unexpected error") + t.Log(pb) + + ab, err = cdc.MarshalBinaryBare(time.Time{}) + assert.NoError(t, err, "unexpected error") + t.Log(ab) +} diff --git a/types/protobuf.go b/types/protobuf.go index ad7362e03..0e1e446db 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -7,7 +7,9 @@ import ( "time" abci "github.com/tendermint/tendermint/abci/types" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" ) //------------------------------------------------------- @@ -61,12 +63,12 @@ func (tm2pb) Validator(val *Validator) abci.Validator { // TODO: add cases when new pubkey types are added to crypto func (tm2pb) PubKey(pubKey crypto.PubKey) abci.PubKey { switch pk := pubKey.(type) { - case crypto.PubKeyEd25519: + case ed25519.PubKeyEd25519: return abci.PubKey{ Type: ABCIPubKeyTypeEd25519, Data: pk[:], } - case crypto.PubKeySecp256k1: + case secp256k1.PubKeySecp256k1: return abci.PubKey{ Type: ABCIPubKeyTypeSecp256k1, Data: pk[:], @@ -78,7 +80,7 @@ func (tm2pb) PubKey(pubKey crypto.PubKey) abci.PubKey { // XXX: panics on nil or unknown pubkey type func (tm2pb) Validators(vals *ValidatorSet) []abci.Validator { - validators := make([]abci.Validator, len(vals.Validators)) + validators := make([]abci.Validator, vals.Size()) for i, val := range vals.Validators { validators[i] = TM2PB.Validator(val) } @@ -161,14 +163,14 @@ func (pb2tm) PubKey(pubKey abci.PubKey) (crypto.PubKey, error) { if len(pubKey.Data) != sizeEd { return nil, fmt.Errorf("Invalid size for PubKeyEd25519. Got %d, expected %d", len(pubKey.Data), sizeEd) } - var pk crypto.PubKeyEd25519 + var pk ed25519.PubKeyEd25519 copy(pk[:], pubKey.Data) return pk, nil case ABCIPubKeyTypeSecp256k1: if len(pubKey.Data) != sizeSecp { return nil, fmt.Errorf("Invalid size for PubKeyEd25519. Got %d, expected %d", len(pubKey.Data), sizeSecp) } - var pk crypto.PubKeySecp256k1 + var pk secp256k1.PubKeySecp256k1 copy(pk[:], pubKey.Data) return pk, nil default: diff --git a/types/protobuf_test.go b/types/protobuf_test.go index cd986fd81..6ee79b906 100644 --- a/types/protobuf_test.go +++ b/types/protobuf_test.go @@ -2,15 +2,18 @@ package types import ( "testing" + "time" "github.com/stretchr/testify/assert" abci "github.com/tendermint/tendermint/abci/types" - crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/secp256k1" ) func TestABCIPubKey(t *testing.T) { - pkEd := crypto.GenPrivKeyEd25519().PubKey() - pkSecp := crypto.GenPrivKeySecp256k1().PubKey() + pkEd := ed25519.GenPrivKey().PubKey() + pkSecp := secp256k1.GenPrivKey().PubKey() testABCIPubKey(t, pkEd, ABCIPubKeyTypeEd25519) testABCIPubKey(t, pkSecp, ABCIPubKeyTypeSecp256k1) } @@ -23,7 +26,7 @@ func testABCIPubKey(t *testing.T, pk crypto.PubKey, typeStr string) { } func TestABCIValidators(t *testing.T) { - pkEd := crypto.GenPrivKeyEd25519().PubKey() + pkEd := ed25519.GenPrivKey().PubKey() // correct validator tmValExpected := &Validator{ @@ -43,6 +46,9 @@ func TestABCIValidators(t *testing.T) { assert.Nil(t, err) assert.Equal(t, tmValExpected, tmVals[0]) + abciVals := TM2PB.Validators(NewValidatorSet(tmVals)) + assert.Equal(t, []abci.Validator{abciVal}, abciVals) + // val with address tmVal.Address = pkEd.Address() @@ -67,3 +73,50 @@ func TestABCIConsensusParams(t *testing.T) { assert.Equal(t, *cp, cp2) } + +func TestABCIHeader(t *testing.T) { + header := &Header{ + Height: int64(3), + Time: time.Now(), + NumTxs: int64(10), + } + abciHeader := TM2PB.Header(header) + + assert.Equal(t, int64(3), abciHeader.Height) +} + +func TestABCIEvidence(t *testing.T) { + val := NewMockPV() + blockID := makeBlockID("blockhash", 1000, "partshash") + blockID2 := makeBlockID("blockhash2", 1000, "partshash") + const chainID = "mychain" + ev := &DuplicateVoteEvidence{ + PubKey: val.GetPubKey(), + VoteA: makeVote(val, chainID, 0, 10, 2, 1, blockID), + VoteB: makeVote(val, chainID, 0, 10, 2, 1, blockID2), + } + abciEv := TM2PB.Evidence( + ev, + NewValidatorSet([]*Validator{NewValidator(val.GetPubKey(), 10)}), + time.Now(), + ) + + assert.Equal(t, "duplicate/vote", abciEv.Type) +} + +type pubKeyEddie struct{} + +func (pubKeyEddie) Address() Address { return []byte{} } +func (pubKeyEddie) Bytes() []byte { return []byte{} } +func (pubKeyEddie) VerifyBytes(msg []byte, sig crypto.Signature) bool { return false } +func (pubKeyEddie) Equals(crypto.PubKey) bool { return false } + +func TestABCIValidatorFromPubKeyAndPower(t *testing.T) { + pubkey := ed25519.GenPrivKey().PubKey() + + abciVal := TM2PB.ValidatorFromPubKeyAndPower(pubkey, 10) + assert.Equal(t, int64(10), abciVal.Power) + + assert.Panics(t, func() { TM2PB.ValidatorFromPubKeyAndPower(nil, 10) }) + assert.Panics(t, func() { TM2PB.ValidatorFromPubKeyAndPower(pubKeyEddie{}, 10) }) +} diff --git a/types/results.go b/types/results.go index 7f8e6093a..17d5891c3 100644 --- a/types/results.go +++ b/types/results.go @@ -24,15 +24,16 @@ func (a ABCIResult) Hash() []byte { // ABCIResults wraps the deliver tx results to return a proof type ABCIResults []ABCIResult -// NewResults creates ABCIResults from ResponseDeliverTx -func NewResults(del []*abci.ResponseDeliverTx) ABCIResults { - res := make(ABCIResults, len(del)) - for i, d := range del { +// NewResults creates ABCIResults from the list of ResponseDeliverTx. +func NewResults(responses []*abci.ResponseDeliverTx) ABCIResults { + res := make(ABCIResults, len(responses)) + for i, d := range responses { res[i] = NewResultFromResponse(d) } return res } +// NewResultFromResponse creates ABCIResult from ResponseDeliverTx. func NewResultFromResponse(response *abci.ResponseDeliverTx) ABCIResult { return ABCIResult{ Code: response.Code, diff --git a/types/results_test.go b/types/results_test.go index 009e2693d..8cbe319ff 100644 --- a/types/results_test.go +++ b/types/results_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" ) func TestABCIResults(t *testing.T) { @@ -41,3 +42,14 @@ func TestABCIResults(t *testing.T) { assert.True(t, valid, "%d", i) } } + +func TestABCIBytes(t *testing.T) { + results := NewResults([]*abci.ResponseDeliverTx{ + {Code: 0, Data: []byte{}}, + {Code: 0, Data: []byte("one")}, + {Code: 14, Data: nil}, + {Code: 14, Data: []byte("foo")}, + {Code: 14, Data: []byte("bar")}, + }) + assert.NotNil(t, results.Bytes()) +} diff --git a/types/tx_test.go b/types/tx_test.go index 67df5c5f3..df7a74496 100644 --- a/types/tx_test.go +++ b/types/tx_test.go @@ -24,21 +24,32 @@ func randInt(low, high int) int { } func TestTxIndex(t *testing.T) { - assert := assert.New(t) for i := 0; i < 20; i++ { txs := makeTxs(15, 60) for j := 0; j < len(txs); j++ { tx := txs[j] idx := txs.Index(tx) - assert.Equal(j, idx) + assert.Equal(t, j, idx) } - assert.Equal(-1, txs.Index(nil)) - assert.Equal(-1, txs.Index(Tx("foodnwkf"))) + assert.Equal(t, -1, txs.Index(nil)) + assert.Equal(t, -1, txs.Index(Tx("foodnwkf"))) + } +} + +func TestTxIndexByHash(t *testing.T) { + for i := 0; i < 20; i++ { + txs := makeTxs(15, 60) + for j := 0; j < len(txs); j++ { + tx := txs[j] + idx := txs.IndexByHash(tx.Hash()) + assert.Equal(t, j, idx) + } + assert.Equal(t, -1, txs.IndexByHash(nil)) + assert.Equal(t, -1, txs.IndexByHash(Tx("foodnwkf").Hash())) } } func TestValidTxProof(t *testing.T) { - assert := assert.New(t) cases := []struct { txs Txs }{ @@ -58,21 +69,21 @@ func TestValidTxProof(t *testing.T) { leaf := txs[i] leafHash := leaf.Hash() proof := txs.Proof(i) - assert.Equal(i, proof.Index, "%d: %d", h, i) - assert.Equal(len(txs), proof.Total, "%d: %d", h, i) - assert.EqualValues(root, proof.RootHash, "%d: %d", h, i) - assert.EqualValues(leaf, proof.Data, "%d: %d", h, i) - assert.EqualValues(leafHash, proof.LeafHash(), "%d: %d", h, i) - assert.Nil(proof.Validate(root), "%d: %d", h, i) - assert.NotNil(proof.Validate([]byte("foobar")), "%d: %d", h, i) + assert.Equal(t, i, proof.Index, "%d: %d", h, i) + assert.Equal(t, len(txs), proof.Total, "%d: %d", h, i) + assert.EqualValues(t, root, proof.RootHash, "%d: %d", h, i) + assert.EqualValues(t, leaf, proof.Data, "%d: %d", h, i) + assert.EqualValues(t, leafHash, proof.LeafHash(), "%d: %d", h, i) + assert.Nil(t, proof.Validate(root), "%d: %d", h, i) + assert.NotNil(t, proof.Validate([]byte("foobar")), "%d: %d", h, i) // read-write must also work var p2 TxProof bin, err := cdc.MarshalBinary(proof) - assert.Nil(err) + assert.Nil(t, err) err = cdc.UnmarshalBinary(bin, &p2) - if assert.Nil(err, "%d: %d: %+v", h, i, err) { - assert.Nil(p2.Validate(root), "%d: %d", h, i) + if assert.Nil(t, err, "%d: %d: %+v", h, i, err) { + assert.Nil(t, p2.Validate(root), "%d: %d", h, i) } } } @@ -86,8 +97,6 @@ func TestTxProofUnchangable(t *testing.T) { } func testTxProofUnchangable(t *testing.T) { - assert := assert.New(t) - // make some proof txs := makeTxs(randInt(2, 100), randInt(16, 128)) root := txs.Hash() @@ -95,9 +104,9 @@ func testTxProofUnchangable(t *testing.T) { proof := txs.Proof(i) // make sure it is valid to start with - assert.Nil(proof.Validate(root)) + assert.Nil(t, proof.Validate(root)) bin, err := cdc.MarshalBinary(proof) - assert.Nil(err) + assert.Nil(t, err) // try mutating the data and make sure nothing breaks for j := 0; j < 500; j++ { diff --git a/types/validator_set.go b/types/validator_set.go index 248fbda5c..6d580acef 100644 --- a/types/validator_set.go +++ b/types/validator_set.go @@ -41,7 +41,7 @@ func NewValidatorSet(valz []*Validator) *ValidatorSet { vals := &ValidatorSet{ Validators: validators, } - if valz != nil { + if len(valz) > 0 { vals.IncrementAccum(1) } @@ -55,7 +55,8 @@ func (vals *ValidatorSet) CopyIncrementAccum(times int) *ValidatorSet { return copy } -// Increment Accum and update the proposer. +// IncrementAccum increments accum of each validator and updates the +// proposer. Panics if validator set is empty. func (vals *ValidatorSet) IncrementAccum(times int) { // Add VotingPower * times to each validator and order into heap. diff --git a/types/validator_set_test.go b/types/validator_set_test.go index 61f4dada9..1756f7890 100644 --- a/types/validator_set_test.go +++ b/types/validator_set_test.go @@ -11,9 +11,64 @@ import ( "github.com/stretchr/testify/assert" crypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" cmn "github.com/tendermint/tendermint/libs/common" ) +func TestValidatorSetBasic(t *testing.T) { + for _, vset := range []*ValidatorSet{NewValidatorSet([]*Validator{}), NewValidatorSet(nil)} { + assert.Panics(t, func() { vset.IncrementAccum(1) }) + + assert.EqualValues(t, vset, vset.Copy()) + assert.False(t, vset.HasAddress([]byte("some val"))) + idx, val := vset.GetByAddress([]byte("some val")) + assert.Equal(t, -1, idx) + assert.Nil(t, val) + addr, val := vset.GetByIndex(-100) + assert.Nil(t, addr) + assert.Nil(t, val) + addr, val = vset.GetByIndex(0) + assert.Nil(t, addr) + assert.Nil(t, val) + addr, val = vset.GetByIndex(100) + assert.Nil(t, addr) + assert.Nil(t, val) + assert.Zero(t, vset.Size()) + assert.Equal(t, int64(0), vset.TotalVotingPower()) + assert.Nil(t, vset.GetProposer()) + assert.Nil(t, vset.Hash()) + + // add + val = randValidator_() + assert.True(t, vset.Add(val)) + assert.True(t, vset.HasAddress(val.Address)) + idx, val2 := vset.GetByAddress(val.Address) + assert.Equal(t, 0, idx) + assert.Equal(t, val, val2) + addr, val2 = vset.GetByIndex(0) + assert.Equal(t, []byte(val.Address), addr) + assert.Equal(t, val, val2) + assert.Equal(t, 1, vset.Size()) + assert.Equal(t, val.VotingPower, vset.TotalVotingPower()) + assert.Equal(t, val, vset.GetProposer()) + assert.NotNil(t, vset.Hash()) + assert.NotPanics(t, func() { vset.IncrementAccum(1) }) + + // update + assert.False(t, vset.Update(randValidator_())) + val.VotingPower = 100 + assert.True(t, vset.Update(val)) + + // remove + val2, removed := vset.Remove(randValidator_().Address) + assert.Nil(t, val2) + assert.False(t, removed) + val2, removed = vset.Remove(val.Address) + assert.Equal(t, val.Address, val2.Address) + assert.True(t, removed) + } +} + func TestCopy(t *testing.T) { vset := randValidatorSet(10) vsetHash := vset.Hash() @@ -33,7 +88,7 @@ func BenchmarkValidatorSetCopy(b *testing.B) { b.StopTimer() vset := NewValidatorSet([]*Validator{}) for i := 0; i < 1000; i++ { - privKey := crypto.GenPrivKeyEd25519() + privKey := ed25519.GenPrivKey() pubKey := privKey.PubKey() val := NewValidator(pubKey, 0) if !vset.Add(val) { @@ -197,7 +252,7 @@ func newValidator(address []byte, power int64) *Validator { func randPubKey() crypto.PubKey { var pubKey [32]byte copy(pubKey[:], cmn.RandBytes(32)) - return crypto.PubKeyEd25519(pubKey) + return ed25519.PubKeyEd25519(pubKey) } func randValidator_() *Validator { @@ -314,7 +369,7 @@ func TestSafeSubClip(t *testing.T) { //------------------------------------------------------------------- func TestValidatorSetVerifyCommit(t *testing.T) { - privKey := crypto.GenPrivKeyEd25519() + privKey := ed25519.GenPrivKey() pubKey := privKey.PubKey() v1 := NewValidator(pubKey, 1000) vset := NewValidatorSet([]*Validator{v1}) diff --git a/types/vote_test.go b/types/vote_test.go index cbb22aaae..836baa615 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -4,7 +4,9 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto/ed25519" ) func examplePrevote() *Vote { @@ -50,29 +52,9 @@ func TestVoteSignable(t *testing.T) { } } -func TestVoteString(t *testing.T) { - tc := []struct { - name string - in string - out string - }{ - {"Precommit", examplePrecommit().String(), `Vote{56789:616464720000 12345/02/2(Precommit) 686173680000 @ 2017-12-25T03:00:01.234Z}`}, - {"Prevote", examplePrevote().String(), `Vote{56789:616464720000 12345/02/1(Prevote) 686173680000 @ 2017-12-25T03:00:01.234Z}`}, - } - - for _, tt := range tc { - tt := tt - t.Run(tt.name, func(st *testing.T) { - if tt.in != tt.out { - t.Errorf("Got unexpected string for Proposal. Expected:\n%v\nGot:\n%v", tt.in, tt.out) - } - }) - } -} - func TestVoteVerifySignature(t *testing.T) { privVal := NewMockPV() - pubKey := privVal.GetPubKey() + pubkey := privVal.GetPubKey() vote := examplePrecommit() signBytes := vote.SignBytes("test_chain_id") @@ -82,7 +64,7 @@ func TestVoteVerifySignature(t *testing.T) { require.NoError(t, err) // verify the same vote - valid := pubKey.VerifyBytes(vote.SignBytes("test_chain_id"), vote.Signature) + valid := pubkey.VerifyBytes(vote.SignBytes("test_chain_id"), vote.Signature) require.True(t, valid) // serialize, deserialize and verify again.... @@ -95,7 +77,7 @@ func TestVoteVerifySignature(t *testing.T) { // verify the transmitted vote newSignBytes := precommit.SignBytes("test_chain_id") require.Equal(t, string(signBytes), string(newSignBytes)) - valid = pubKey.VerifyBytes(newSignBytes, precommit.Signature) + valid = pubkey.VerifyBytes(newSignBytes, precommit.Signature) require.True(t, valid) } @@ -119,3 +101,21 @@ func TestIsVoteTypeValid(t *testing.T) { }) } } + +func TestVoteVerify(t *testing.T) { + privVal := NewMockPV() + pubkey := privVal.GetPubKey() + + vote := examplePrevote() + vote.ValidatorAddress = pubkey.Address() + + err := vote.Verify("test_chain_id", ed25519.GenPrivKey().PubKey()) + if assert.Error(t, err) { + assert.Equal(t, ErrVoteInvalidValidatorAddress, err) + } + + err = vote.Verify("test_chain_id", pubkey) + if assert.Error(t, err) { + assert.Equal(t, ErrVoteInvalidSignature, err) + } +} diff --git a/types/wire.go b/types/wire.go index 6342d7eba..9221de968 100644 --- a/types/wire.go +++ b/types/wire.go @@ -2,11 +2,11 @@ package types import ( "github.com/tendermint/go-amino" - "github.com/tendermint/tendermint/crypto" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" ) var cdc = amino.NewCodec() func init() { - crypto.RegisterAmino(cdc) + cryptoAmino.RegisterAmino(cdc) } diff --git a/version/version.go b/version/version.go index aac5dd587..706264372 100644 --- a/version/version.go +++ b/version/version.go @@ -3,14 +3,14 @@ package version // Version components const ( Maj = "0" - Min = "23" - Fix = "0" + Min = "22" + Fix = "5" ) var ( // Version is the current version of Tendermint // Must be a string because scripts like dist.sh read this file. - Version = "0.23.0-dev" + Version = "0.22.5" // GitCommit is the current HEAD set using ldflags. GitCommit string