@ -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,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 <https://github.com/tendermint/abci/blob/master/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. | |||
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! |
@ -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,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 |
@ -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 |
@ -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) | |||
} |
@ -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) | |||
} |
@ -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 | |||
} |
@ -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)) | |||
} |
@ -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 | |||
} |