Release/v0.22.2pull/1971/head v0.22.2
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -1,99 +0,0 @@ | |||||
GOTOOLS = \ | |||||
github.com/golang/dep/cmd/dep \ | |||||
# gopkg.in/alecthomas/gometalinter.v2 \ | |||||
GOTOOLS_CHECK = dep #gometalinter.v2 | |||||
all: check get_vendor_deps build test install | |||||
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")))" | |||||
get_tools: | |||||
@echo "--> Installing tools" | |||||
go get -u -v $(GOTOOLS) | |||||
#@gometalinter.v2 --install | |||||
update_tools: | |||||
@echo "--> Updating tools" | |||||
@go get -u $(GOTOOLS) | |||||
get_vendor_deps: | |||||
@rm -rf vendor/ | |||||
@echo "--> Running dep ensure" | |||||
@dep ensure | |||||
######################################## | |||||
### Testing | |||||
test: | |||||
CGO_ENABLED=0 go test -p 1 $(shell go list ./... | grep -v vendor) | |||||
######################################## | |||||
### 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 ./... | |||||
# 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 |
@ -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 " | |||||
} | |||||
] | |||||
} |
@ -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 |
@ -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 | |||||
``` |
@ -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 | |||||
``` |
@ -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 |
@ -1,14 +0,0 @@ | |||||
#! /bin/bash | |||||
set +u | |||||
if [[ "$DEP" == "" ]]; then | |||||
DEP=$GOPATH/src/github.com/tendermint/tendermint/Gopkg.lock | |||||
fi | |||||
set -u | |||||
set -euo pipefail | |||||
LIB=$1 | |||||
grep -A100 "$LIB" "$DEP" | grep revision | head -n1 | grep -o '"[^"]\+"' | cut -d '"' -f 2 |
@ -1,12 +0,0 @@ | |||||
#! /bin/bash | |||||
# get the abci commit used by tendermint | |||||
COMMIT=$(bash scripts/dep_utils/parse.sh abci) | |||||
echo "Checking out vendored commit for abci: $COMMIT" | |||||
go get -d github.com/tendermint/abci | |||||
cd "$GOPATH/src/github.com/tendermint/abci" || exit | |||||
git checkout "$COMMIT" | |||||
make get_tools | |||||
make get_vendor_deps | |||||
make install |