mirror of
https://github.com/fluencelabs/tendermint
synced 2025-07-15 12:31:42 +00:00
Compare commits
17 Commits
aditya/rev
...
tessr/nil-
Author | SHA1 | Date | |
---|---|---|---|
54ba7769c2 | |||
482cb62cf5 | |||
fe2dddd3fe | |||
34aac2aee6 | |||
9c4cf401b5 | |||
acb874eaf6 | |||
1802b60833 | |||
72785a2e86 | |||
5346d8b9a2 | |||
f46e43eb38 | |||
e3a97b0981 | |||
c475f25786 | |||
7b2d018f84 | |||
eec6d33e14 | |||
ead3eefe5b | |||
5670a7cf7b | |||
7b101ab912 |
@ -216,11 +216,11 @@ jobs:
|
||||
name: Trigger website build
|
||||
command: |
|
||||
curl --silent \
|
||||
--show-error \
|
||||
-X POST \
|
||||
--header "Content-Type: application/json" \
|
||||
-d "{\"branch\": \"$CIRCLE_BRANCH\"}" \
|
||||
"https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$WEBSITE_REPO_NAME/build?circle-token=$TENDERBOT_API_TOKEN" > response.json
|
||||
--show-error \
|
||||
-X POST \
|
||||
--header "Content-Type: application/json" \
|
||||
-d "{\"branch\": \"$CIRCLE_BRANCH\"}" \
|
||||
"https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$WEBSITE_REPO_NAME/build?circle-token=$TENDERBOT_API_TOKEN" > response.json
|
||||
|
||||
RESULT=`jq -r '.status' response.json`
|
||||
MESSAGE=`jq -r '.message' response.json`
|
||||
@ -359,6 +359,35 @@ jobs:
|
||||
- store_artifacts:
|
||||
path: /go/src/github.com/tendermint/tendermint/tendermint-*.tar.gz
|
||||
|
||||
# Test RPC implementation against the swagger documented specs
|
||||
contract_tests:
|
||||
working_directory: /home/circleci/.go_workspace/src/github.com/tendermint/tendermint
|
||||
machine:
|
||||
image: circleci/classic:latest
|
||||
environment:
|
||||
GOBIN: /home/circleci/.go_workspace/bin
|
||||
GOPATH: /home/circleci/.go_workspace/
|
||||
GOOS: linux
|
||||
GOARCH: amd64
|
||||
parallelism: 1
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Test RPC endpoints against swagger documentation
|
||||
command: |
|
||||
set -x
|
||||
export PATH=~/.local/bin:$PATH
|
||||
|
||||
# install node and dredd
|
||||
./scripts/get_nodejs.sh
|
||||
|
||||
# build the binaries with a proper version of Go
|
||||
docker run --rm -v "$PWD":/go/src/github.com/tendermint/tendermint -w /go/src/github.com/tendermint/tendermint golang make build-linux build-contract-tests-hooks
|
||||
|
||||
# This docker image works with go 1.7, we can install here the hook handler that contract-tests is going to use
|
||||
go get github.com/snikch/goodman/cmd/goodman
|
||||
make contract-tests
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
test-suite:
|
||||
@ -397,6 +426,10 @@ workflows:
|
||||
only:
|
||||
- master
|
||||
- /v[0-9]+\.[0-9]+/
|
||||
- contract_tests:
|
||||
requires:
|
||||
- setup_dependencies
|
||||
|
||||
release:
|
||||
jobs:
|
||||
- prepare_build
|
||||
|
35
CHANGELOG.md
35
CHANGELOG.md
@ -1,5 +1,32 @@
|
||||
# Changelog
|
||||
|
||||
## v0.32.3
|
||||
|
||||
*August 28, 2019*
|
||||
|
||||
@climber73 wrote the [Writing a Tendermint Core application in Java
|
||||
(gRPC)](https://github.com/tendermint/tendermint/blob/master/docs/guides/java.md)
|
||||
guide.
|
||||
|
||||
Special thanks to external contributors on this release:
|
||||
@gchaincl, @bluele, @climber73
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### IMPROVEMENTS:
|
||||
|
||||
- [consensus] [\#3839](https://github.com/tendermint/tendermint/issues/3839) Reduce "Error attempting to add vote" message severity (Error -> Info)
|
||||
- [mempool] [\#3877](https://github.com/tendermint/tendermint/pull/3877) Make `max_tx_bytes` configurable instead of `max_msg_bytes` (@bluele)
|
||||
- [privval] [\#3370](https://github.com/tendermint/tendermint/issues/3370) Refactor and simplify validator/kms connection handling. Please refer to [this comment](https://github.com/tendermint/tendermint/pull/3370#issue-257360971) for details
|
||||
- [rpc] [\#3880](https://github.com/tendermint/tendermint/issues/3880) Document endpoints with `swagger`, introduce contract tests of implementation against documentation
|
||||
|
||||
### BUG FIXES:
|
||||
|
||||
- [config] [\#3868](https://github.com/tendermint/tendermint/issues/3868) Move misplaced `max_msg_bytes` into mempool section (@bluele)
|
||||
- [rpc] [\#3910](https://github.com/tendermint/tendermint/pull/3910) Fix DATA RACE in HTTP client (@gchaincl)
|
||||
- [store] [\#3893](https://github.com/tendermint/tendermint/issues/3893) Fix "Unregistered interface types.Evidence" panic
|
||||
|
||||
## v0.32.2
|
||||
|
||||
*July 31, 2019*
|
||||
@ -17,20 +44,20 @@ program](https://hackerone.com/tendermint).
|
||||
|
||||
### FEATURES:
|
||||
|
||||
- [blockchain] [\#3561](https://github.com/tendermint/tendermint/issues/3561) Add early version of the new blockchain reactor, which is supposed to be more modular and testable compared to the old version. To try it, you'll have to change `version` in the config file, [here](https://github.com/tendermint/tendermint/blob/master/config/toml.go#L303) NOTE: It's not ready for a production yet. For further information, see [ADR-40](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-040-blockchain-reactor-refactor.md) & [ADR-43](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-043-blockchain-riri-org.md)
|
||||
- [mempool] [\#3826](https://github.com/tendermint/tendermint/issues/3826) Make `max_msg_bytes` configurable(@bluele)
|
||||
- [node] [\#3846](https://github.com/tendermint/tendermint/pull/3846) Allow replacing existing p2p.Reactor(s) using [`CustomReactors`
|
||||
option](https://godoc.org/github.com/tendermint/tendermint/node#CustomReactors).
|
||||
Warning: beware of accidental name clashes. Here is the list of existing
|
||||
reactors: MEMPOOL, BLOCKCHAIN, CONSENSUS, EVIDENCE, PEX.
|
||||
- [p2p] [\#3834](https://github.com/tendermint/tendermint/issues/3834) Do not write 'Couldn't connect to any seeds' error log if there are no seeds in config file
|
||||
- [rpc] [\#3818](https://github.com/tendermint/tendermint/issues/3818) Make `max_body_bytes` and `max_header_bytes` configurable(@bluele)
|
||||
- [mempool] [\#3826](https://github.com/tendermint/tendermint/issues/3826) Make `max_msg_bytes` configurable(@bluele)
|
||||
- [blockchain] [\#3561](https://github.com/tendermint/tendermint/issues/3561) Add early version of the new blockchain reactor, which is supposed to be more modular and testable compared to the old version. To try it, you'll have to change `version` in the config file, [here](https://github.com/tendermint/tendermint/blob/master/config/toml.go#L303) NOTE: It's not ready for a production yet. For further information, see [ADR-40](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-040-blockchain-reactor-refactor.md) & [ADR-43](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-043-blockchain-riri-org.md)
|
||||
- [rpc] [\#2252](https://github.com/tendermint/tendermint/issues/2252) Add `/broadcast_evidence` endpoint to submit double signing and other types of evidence
|
||||
|
||||
### IMPROVEMENTS:
|
||||
|
||||
- [abci] [\#3809](https://github.com/tendermint/tendermint/issues/3809) Recover from application panics in `server/socket_server.go` to allow socket cleanup (@ruseinov)
|
||||
- [rpc] [\#2252](https://github.com/tendermint/tendermint/issues/2252) Add `/broadcast_evidence` endpoint to submit double signing and other types of evidence
|
||||
- [p2p] [\#3664](https://github.com/tendermint/tendermint/issues/3664) p2p/conn: reuse buffer when write/read from secret connection(@guagualvcha)
|
||||
- [p2p] [\#3834](https://github.com/tendermint/tendermint/issues/3834) Do not write 'Couldn't connect to any seeds' error log if there are no seeds in config file
|
||||
- [rpc] [\#3076](https://github.com/tendermint/tendermint/issues/3076) Improve transaction search performance
|
||||
|
||||
### BUG FIXES:
|
||||
|
@ -1,4 +1,4 @@
|
||||
## v0.32.3
|
||||
## v0.32.4
|
||||
|
||||
\*\*
|
||||
|
||||
@ -19,11 +19,4 @@ program](https://hackerone.com/tendermint).
|
||||
|
||||
### IMPROVEMENTS:
|
||||
|
||||
- [privval] \#3370 Refactors and simplifies validator/kms connection handling. Please refer to thttps://github.com/tendermint/tendermint/pull/3370#issue-257360971
|
||||
- [consensus] \#3839 Reduce "Error attempting to add vote" message severity (Error -> Info)
|
||||
- [mempool] \#3877 Make `max_tx_bytes` configurable instead of `max_msg_bytes`
|
||||
|
||||
### BUG FIXES:
|
||||
|
||||
- [config] \#3868 move misplaced `max_msg_bytes` into mempool section
|
||||
- [store] \#3893 register block amino, not just crypto
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Thank you for considering making contributions to Tendermint and related repositories! Start by taking a look at the [coding repo](https://github.com/tendermint/coding) for overall information on repository workflow and standards.
|
||||
|
||||
Please follow standard github best practices: fork the repo, branch from the tip of `master`, make some commits, and submit a pull request to `master`.
|
||||
Please follow standard github best practices: fork the repo, branch from the tip of `master`, make some commits, and submit a pull request to `master`.
|
||||
See the [open issues](https://github.com/tendermint/tendermint/issues) for things we need help with!
|
||||
|
||||
Before making a pull request, please open an issue describing the
|
||||
@ -21,16 +21,16 @@ Please make sure to use `gofmt` before every commit - the easiest way to do this
|
||||
|
||||
Please note that Go requires code to live under absolute paths, which complicates forking.
|
||||
While my fork lives at `https://github.com/ebuchman/tendermint`,
|
||||
the code should never exist at `$GOPATH/src/github.com/ebuchman/tendermint`.
|
||||
the code should never exist at `$GOPATH/src/github.com/ebuchman/tendermint`.
|
||||
Instead, we use `git remote` to add the fork as a new remote for the original repo,
|
||||
`$GOPATH/src/github.com/tendermint/tendermint `, and do all the work there.
|
||||
`$GOPATH/src/github.com/tendermint/tendermint`, and do all the work there.
|
||||
|
||||
For instance, to create a fork and work on a branch of it, I would:
|
||||
|
||||
* Create the fork on github, using the fork button.
|
||||
* Go to the original repo checked out locally (i.e. `$GOPATH/src/github.com/tendermint/tendermint`)
|
||||
* `git remote rename origin upstream`
|
||||
* `git remote add origin git@github.com:ebuchman/basecoin.git`
|
||||
- Create the fork on github, using the fork button.
|
||||
- Go to the original repo checked out locally (i.e. `$GOPATH/src/github.com/tendermint/tendermint`)
|
||||
- `git remote rename origin upstream`
|
||||
- `git remote add origin git@github.com:ebuchman/basecoin.git`
|
||||
|
||||
Now `origin` refers to my fork and `upstream` refers to the tendermint version.
|
||||
So I can `git push -u origin master` to update my fork, and make pull requests to tendermint from there.
|
||||
@ -38,8 +38,8 @@ Of course, replace `ebuchman` with your git handle.
|
||||
|
||||
To pull in updates from the origin repo, run
|
||||
|
||||
* `git fetch upstream`
|
||||
* `git rebase upstream/master` (or whatever branch you want)
|
||||
- `git fetch upstream`
|
||||
- `git rebase upstream/master` (or whatever branch you want)
|
||||
|
||||
## Dependencies
|
||||
|
||||
@ -113,7 +113,7 @@ removed from the header in rpc responses as well.
|
||||
|
||||
## Branching Model and Release
|
||||
|
||||
The main development branch is master.
|
||||
The main development branch is master.
|
||||
|
||||
Every release is maintained in a release branch named `vX.Y.Z`.
|
||||
|
||||
@ -140,36 +140,35 @@ easy to reference the pull request where a change was introduced.
|
||||
|
||||
#### Major Release
|
||||
|
||||
1. start on `master`
|
||||
1. start on `master`
|
||||
2. run integration tests (see `test_integrations` in Makefile)
|
||||
3. prepare release in a pull request against `master` (to be squash merged):
|
||||
- copy `CHANGELOG_PENDING.md` to top of `CHANGELOG.md`
|
||||
- run `python ./scripts/linkify_changelog.py CHANGELOG.md` to add links for
|
||||
all issues
|
||||
- run `bash ./scripts/authors.sh` to get a list of authors since the latest
|
||||
release, and add the github aliases of external contributors to the top of
|
||||
the changelog. To lookup an alias from an email, try `bash
|
||||
./scripts/authors.sh <email>`
|
||||
- reset the `CHANGELOG_PENDING.md`
|
||||
- bump versions
|
||||
- copy `CHANGELOG_PENDING.md` to top of `CHANGELOG.md`
|
||||
- run `python ./scripts/linkify_changelog.py CHANGELOG.md` to add links for
|
||||
all issues
|
||||
- run `bash ./scripts/authors.sh` to get a list of authors since the latest
|
||||
release, and add the github aliases of external contributors to the top of
|
||||
the changelog. To lookup an alias from an email, try `bash ./scripts/authors.sh <email>`
|
||||
- reset the `CHANGELOG_PENDING.md`
|
||||
- bump versions
|
||||
4. push your changes with prepared release details to `vX.X` (this will trigger the release `vX.X.0`)
|
||||
5. merge back to master (don't squash merge!)
|
||||
|
||||
#### Minor Release
|
||||
|
||||
If there were no breaking changes and you need to create a release nonetheless,
|
||||
the procedure is almost exactly like with a new release above.
|
||||
If there were no breaking changes and you need to create a release nonetheless,
|
||||
the procedure is almost exactly like with a new release above.
|
||||
|
||||
The only difference is that in the end you create a pull request against the existing `X.X` branch.
|
||||
The branch name should match the release number you want to create.
|
||||
Merging this PR will trigger the next release.
|
||||
For example, if the PR is against an existing 0.34 branch which already contains a v0.34.0 release/tag,
|
||||
Merging this PR will trigger the next release.
|
||||
For example, if the PR is against an existing 0.34 branch which already contains a v0.34.0 release/tag,
|
||||
the patch version will be incremented and the created release will be v0.34.1.
|
||||
|
||||
#### Backport Release
|
||||
|
||||
1. start from the existing release branch you want to backport changes to (e.g. v0.30)
|
||||
Branch to a release/vX.X.X branch locally (e.g. release/v0.30.7)
|
||||
Branch to a release/vX.X.X branch locally (e.g. release/v0.30.7)
|
||||
2. cherry pick the commit(s) that contain the changes you want to backport (usually these commits are from squash-merged PRs which were already reviewed)
|
||||
3. steps 2 and 3 from [Major Release](#major-release)
|
||||
4. push changes to release/vX.X.X branch
|
||||
@ -183,3 +182,16 @@ If they have `.go` files in the root directory, they will be automatically
|
||||
tested by circle using `go test -v -race ./...`. If not, they will need a
|
||||
`circle.yml`. Ideally, every repo has a `Makefile` that defines `make test` and
|
||||
includes its continuous integration status using a badge in the `README.md`.
|
||||
|
||||
### RPC Testing
|
||||
|
||||
If you contribute to the RPC endpoints it's important to document your changes in the [Swagger file](./docs/spec/rpc/swagger.yaml)
|
||||
To test your changes you should install `nodejs` and run:
|
||||
|
||||
```bash
|
||||
npm i -g dredd
|
||||
make build-linux build-contract-tests-hooks
|
||||
make contract-tests
|
||||
```
|
||||
|
||||
This command will popup a network and check every endpoint against what has been documented
|
||||
|
20
Makefile
20
Makefile
@ -28,7 +28,7 @@ build_c:
|
||||
CGO_ENABLED=1 go build $(BUILD_FLAGS) -tags "$(BUILD_TAGS) cleveldb" -o $(OUTPUT) ./cmd/tendermint/
|
||||
|
||||
build_race:
|
||||
CGO_ENABLED=0 go build -race $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o $(OUTPUT) ./cmd/tendermint
|
||||
CGO_ENABLED=1 go build -race $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o $(OUTPUT) ./cmd/tendermint
|
||||
|
||||
install:
|
||||
CGO_ENABLED=0 go install $(BUILD_FLAGS) -tags $(BUILD_TAGS) ./cmd/tendermint
|
||||
@ -308,7 +308,23 @@ sentry-stop:
|
||||
build-slate:
|
||||
bash scripts/slate.sh
|
||||
|
||||
# Build hooks for dredd, to skip or add information on some steps
|
||||
build-contract-tests-hooks:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/contract_tests.exe ./cmd/contract_tests
|
||||
else
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/contract_tests ./cmd/contract_tests
|
||||
endif
|
||||
|
||||
# Run a nodejs tool to test endpoints against a localnet
|
||||
# The command takes care of starting and stopping the network
|
||||
# prerequisits: build-contract-tests-hooks build-linux
|
||||
# the two build commands were not added to let this command run from generic containers or machines.
|
||||
# The binaries should be built beforehand
|
||||
contract-tests:
|
||||
dredd
|
||||
|
||||
# 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 build_abci dist install install_abci check_tools get_tools update_tools 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 rpc-docs build-linux localnet-start localnet-stop build-docker build-docker-localnode sentry-start sentry-config sentry-stop build-slate protoc_grpc protoc_all build_c install_c test_with_deadlock cleanup_after_test_with_deadlock lint
|
||||
.PHONY: check build build_race build_abci dist install install_abci check_tools get_tools update_tools 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 rpc-docs build-linux localnet-start localnet-stop build-docker build-docker-localnode sentry-start sentry-config sentry-stop build-slate protoc_grpc protoc_all build_c install_c test_with_deadlock cleanup_after_test_with_deadlock lint build-contract-tests-hooks contract-tests
|
||||
|
@ -74,9 +74,8 @@ and the [contributing guidelines](CONTRIBUTING.md) when submitting code.
|
||||
Join the larger community on the [forum](https://forum.cosmos.network/) and the [chat](https://riot.im/app/#/room/#tendermint:matrix.org).
|
||||
|
||||
To learn more about the structure of the software, watch the [Developer
|
||||
Sessions](https://www.youtube.com/playlist?list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv)
|
||||
and read some [Architectural
|
||||
Decision Records](https://github.com/tendermint/tendermint/tree/master/docs/architecture).
|
||||
Sessions](/docs/DEV_SESSIONS.md) and read some [Architectural Decision
|
||||
Records](https://github.com/tendermint/tendermint/tree/master/docs/architecture).
|
||||
|
||||
Learn more by reading the code and comparing it to the
|
||||
[specification](https://github.com/tendermint/tendermint/tree/develop/docs/spec).
|
||||
|
23
ROADMAP.md
23
ROADMAP.md
@ -1,23 +0,0 @@
|
||||
# Roadmap
|
||||
|
||||
BREAKING CHANGES:
|
||||
- Better support for injecting randomness
|
||||
- Upgrade consensus for more real-time use of evidence
|
||||
|
||||
FEATURES:
|
||||
- Use the chain as its own CA for nodes and validators
|
||||
- Tooling to run multiple blockchains/apps, possibly in a single process
|
||||
- State syncing (without transaction replay)
|
||||
- Add authentication and rate-limitting to the RPC
|
||||
|
||||
IMPROVEMENTS:
|
||||
- Improve subtleties around mempool caching and logic
|
||||
- Consensus optimizations:
|
||||
- cache block parts for faster agreement after round changes
|
||||
- propagate block parts rarest first
|
||||
- Better testing of the consensus state machine (ie. use a DSL)
|
||||
- Auto compiled serialization/deserialization code instead of go-wire reflection
|
||||
|
||||
BUG FIXES:
|
||||
- Graceful handling/recovery for apps that have non-determinism or fail to halt
|
||||
- Graceful handling/recovery for violations of safety, or liveness
|
@ -40,7 +40,7 @@ func main() {
|
||||
}
|
||||
if writeImportTime && !wroteImport {
|
||||
wroteImport = true
|
||||
fmt.Fprintf(outFile, "import \"github.com/tendermint/go-wire/data\"\n")
|
||||
fmt.Fprintf(outFile, "import \"github.com/tendermint/go-amino/data\"\n")
|
||||
|
||||
}
|
||||
if gotPackageLine {
|
||||
|
34
cmd/contract_tests/main.go
Normal file
34
cmd/contract_tests/main.go
Normal file
@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/snikch/goodman/hooks"
|
||||
"github.com/snikch/goodman/transaction"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// This must be compiled beforehand and given to dredd as parameter, in the meantime the server should be running
|
||||
h := hooks.NewHooks()
|
||||
server := hooks.NewServer(hooks.NewHooksRunner(h))
|
||||
h.BeforeAll(func(t []*transaction.Transaction) {
|
||||
fmt.Println(t[0].Name)
|
||||
})
|
||||
h.BeforeEach(func(t *transaction.Transaction) {
|
||||
if strings.HasPrefix(t.Name, "Tx") ||
|
||||
// We need a proper example of evidence to broadcast
|
||||
strings.HasPrefix(t.Name, "Info > /broadcast_evidence") ||
|
||||
// We need a proper example of path and data
|
||||
strings.HasPrefix(t.Name, "ABCI > /abci_query") ||
|
||||
// We need to find a way to make a transaction before starting the tests,
|
||||
// that hash should replace the dummy one in hte swagger file
|
||||
strings.HasPrefix(t.Name, "Info > /tx") {
|
||||
t.Skip = true
|
||||
fmt.Printf("%s Has been skipped\n", t.Name)
|
||||
}
|
||||
})
|
||||
server.Serve()
|
||||
defer server.Listener.Close()
|
||||
fmt.Print("FINE")
|
||||
}
|
@ -2,6 +2,7 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
@ -385,7 +386,7 @@ func DefaultRPCConfig() *RPCConfig {
|
||||
return &RPCConfig{
|
||||
ListenAddress: "tcp://127.0.0.1:26657",
|
||||
CORSAllowedOrigins: []string{},
|
||||
CORSAllowedMethods: []string{"HEAD", "GET", "POST"},
|
||||
CORSAllowedMethods: []string{http.MethodHead, http.MethodGet, http.MethodPost},
|
||||
CORSAllowedHeaders: []string{"Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time"},
|
||||
GRPCListenAddress: "",
|
||||
GRPCMaxOpenConnections: 900,
|
||||
|
@ -1672,7 +1672,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool,
|
||||
}
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Unexpected vote type %X", vote.Type)) // go-wire should prevent this.
|
||||
panic(fmt.Sprintf("Unexpected vote type %X", vote.Type)) // go-amino should prevent this.
|
||||
}
|
||||
|
||||
return
|
||||
|
33
docs/DEV_SESSIONS.md
Normal file
33
docs/DEV_SESSIONS.md
Normal file
@ -0,0 +1,33 @@
|
||||
# Developer Sessions
|
||||
|
||||
The Tendermint Core developer call is comprised of both [Interchain
|
||||
Foundation](http://interchain.io/) and [All in Bits](https://tendermint.com/)
|
||||
team members discussing the development of [Tendermint
|
||||
BFT](https://github.com/tendermint/tendermint) and related research. The goal
|
||||
of the Tendermint Core developer calls is to provide transparency into the
|
||||
decision making process, technical information, update cycles etc.
|
||||
|
||||
## List
|
||||
|
||||
| Date | Topic | Link(s) |
|
||||
| --------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
||||
| August 2019 | Part Three: Tendermint Lite Client | [YouTube](https://www.youtube.com/watch?v=whyL6UrKe7I&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=5) |
|
||||
| August 2019 | Fork Accountability | [YouTube](https://www.youtube.com/watch?v=Jph-4PGtdPo&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=4) |
|
||||
| July 2019 | Part Two: Tendermint Lite Client | [YouTube](https://www.youtube.com/watch?v=gTjG7jNNdKQ&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=6) |
|
||||
| July 2019 | Part One: Tendermint Lite Client | [YouTube](https://www.youtube.com/watch?v=C6fH_sgPJzA&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=7) |
|
||||
| June 2019 | Testnet Deployments | [YouTube](https://www.youtube.com/watch?v=gYA6no7tRlM&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=10) |
|
||||
| June 2019 | Blockchain Reactor Refactor | [YouTube](https://www.youtube.com/watch?v=JLBGH8yxABk&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=11) |
|
||||
| June 2019 | Tendermint Rust Libraries | [YouTube](https://www.youtube.com/watch?v=-WXKdyoGHwA&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=9) |
|
||||
| May 2019 | Merkle Tree Deep Dive | [YouTube](https://www.youtube.com/watch?v=L3bt2Uw8ICg&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=8) |
|
||||
| May 2019 | Remote Signer Refactor | [YouTube](https://www.youtube.com/watch?v=eUyXXEEuBzQ&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=12) |
|
||||
| May 2019 | Introduction to Ansible | [YouTube](https://www.youtube.com/watch?v=72clQLjzPg4&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=14&t=0s) | | |
|
||||
| April 2019 | Tendermint State Sync Design Discussion | [YouTube](https://www.youtube.com/watch?v=4k23j2QHwrM&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=11) |
|
||||
| April 2019 | ADR-036 - Blockchain Reactor Refactor | [YouTube](https://www.youtube.com/watch?v=TW2xC1LwEkE&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=10) |
|
||||
| April 2019 | Verifying Distributed Algorithms | [YouTube](https://www.youtube.com/watch?v=tMd4lgPVBxE&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=9) |
|
||||
| April 2019 | Byzantine Model Checker Presentation | [YouTube](https://www.youtube.com/watch?v=rdXl4VCQyow&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=8) |
|
||||
| January 2019 | Proposer Selection in Idris | [YouTube](https://www.youtube.com/watch?v=hWZdc9c1aH8&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=7) |
|
||||
| January 2019 | Current Mempool Design | [YouTube](https://www.youtube.com/watch?v=--iGIYYiLu4&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=6) |
|
||||
| December 2018 | ABCI Proxy App | [YouTube](https://www.youtube.com/watch?v=s6sQ2HOVHdo&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=5) |
|
||||
| October 2018 | DB Performance | [YouTube](https://www.youtube.com/watch?v=jVSNHi4l0fQ&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=4) |
|
||||
| October 2018 | Alternative Mempool Algorithms | [YouTube](https://www.youtube.com/watch?v=XxH5ZtM4vMM&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv&index=2) |
|
||||
| October 2018 | Tendermint Termination | [YouTube](https://www.youtube.com/watch?v=YBZjecfjeIk&list=PLdQIb0qr3pnBbG5ZG-0gr3zM86_s8Rpqv) |
|
141
docs/architecture/adr-044-lite-client-with-weak-subjectivity.md
Normal file
141
docs/architecture/adr-044-lite-client-with-weak-subjectivity.md
Normal file
@ -0,0 +1,141 @@
|
||||
# ADR 044: Lite Client with Weak Subjectivity
|
||||
|
||||
## Changelog
|
||||
* 13-07-2019: Initial draft
|
||||
* 14-08-2019: Address cwgoes comments
|
||||
|
||||
## Context
|
||||
|
||||
The concept of light clients was introduced in the Bitcoin white paper. It
|
||||
describes a watcher of distributed consensus process that only validates the
|
||||
consensus algorithm and not the state machine transactions within.
|
||||
|
||||
Tendermint light clients allow bandwidth & compute-constrained devices, such as smartphones, low-power embedded chips, or other blockchains to
|
||||
efficiently verify the consensus of a Tendermint blockchain. This forms the
|
||||
basis of safe and efficient state synchronization for new network nodes and
|
||||
inter-blockchain communication (where a light client of one Tendermint instance
|
||||
runs in another chain's state machine).
|
||||
|
||||
In a network that is expected to reliably punish validators for misbehavior
|
||||
by slashing bonded stake and where the validator set changes
|
||||
infrequently, clients can take advantage of this assumption to safely
|
||||
synchronize a lite client without downloading the intervening headers.
|
||||
|
||||
Light clients (and full nodes) operating in the Proof Of Stake context need a
|
||||
trusted block height from a trusted source that is no older than 1 unbonding
|
||||
window plus a configurable evidence submission synchrony bound. This is called “weak subjectivity”.
|
||||
|
||||
Weak subjectivity is required in Proof of Stake blockchains because it is
|
||||
costless for an attacker to buy up voting keys that are no longer bonded and
|
||||
fork the network at some point in its prior history. See Vitalik’s post at
|
||||
[Proof of Stake: How I Learned to Love Weak
|
||||
Subjectivity](https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/).
|
||||
|
||||
Currently, Tendermint provides a lite client implementation in the
|
||||
[lite](https://github.com/tendermint/tendermint/tree/master/lite) package. This
|
||||
lite client implements a bisection algorithm that tries to use a binary search
|
||||
to find the minimum number of block headers where the validator set voting
|
||||
power changes are less than < 1/3rd. This interface does not support weak
|
||||
subjectivity at this time. The Cosmos SDK also does not support counterfactual
|
||||
slashing, nor does the lite client have any capacity to report evidence making
|
||||
these systems *theoretically unsafe*.
|
||||
|
||||
NOTE: Tendermint provides a somewhat different (stronger) light client model
|
||||
than Bitcoin under eclipse, since the eclipsing node(s) can only fool the light
|
||||
client if they have two-thirds of the private keys from the last root-of-trust.
|
||||
|
||||
## Decision
|
||||
|
||||
### The Weak Subjectivity Interface
|
||||
|
||||
Add the weak subjectivity interface for when a new light client connects to the
|
||||
network or when a light client that has been offline for longer than the
|
||||
unbonding period connects to the network. Specifically, the node needs to
|
||||
initialize the following structure before syncing from user input:
|
||||
|
||||
```
|
||||
type TrustOptions struct {
|
||||
// Required: only trust commits up to this old.
|
||||
// Should be equal to the unbonding period minus some delta for evidence reporting.
|
||||
TrustPeriod time.Duration `json:"trust-period"`
|
||||
|
||||
// Option 1: TrustHeight and TrustHash can both be provided
|
||||
// to force the trusting of a particular height and hash.
|
||||
// If the latest trusted height/hash is more recent, then this option is
|
||||
// ignored.
|
||||
TrustHeight int64 `json:"trust-height"`
|
||||
TrustHash []byte `json:"trust-hash"`
|
||||
|
||||
// Option 2: Callback can be set to implement a confirmation
|
||||
// step if the trust store is uninitialized, or expired.
|
||||
Callback func(height int64, hash []byte) error
|
||||
}
|
||||
```
|
||||
|
||||
The expectation is the user will get this information from a trusted source
|
||||
like a validator, a friend, or a secure website. A more user friendly
|
||||
solution with trust tradeoffs is that we establish an https based protocol with
|
||||
a default end point that populates this information. Also an on-chain registry
|
||||
of roots-of-trust (e.g. on the Cosmos Hub) seems likely in the future.
|
||||
|
||||
### Linear Verification
|
||||
|
||||
The linear verification algorithm requires downloading all headers
|
||||
between the `TrustHeight` and the `LatestHeight`. The lite client downloads the
|
||||
full header for the provided `TrustHeight` and then proceeds to download `N+1`
|
||||
headers and applies the [Tendermint validation
|
||||
rules](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/blockchain.md#validation)
|
||||
to each block.
|
||||
|
||||
### Bisecting Verification
|
||||
|
||||
Bisecting Verification is a more bandwidth and compute intensive mechanism that
|
||||
in the most optimistic case requires a light client to only download two block
|
||||
headers to come into synchronization.
|
||||
|
||||
The bisection algorithm proceeds in the following fashion. The client downloads
|
||||
and verifies the full block header for `TrustHeight` and then fetches
|
||||
`LatestHeight` blocker header. The client then verifies the `LatestHeight`
|
||||
header. Finally the client attempts to verify the `LatestHeight` header with
|
||||
voting powers taken from `NextValidatorSet` in the `TrustHeight` header. This
|
||||
verification will succeed if the validators from `TrustHeight` still have > 2/3
|
||||
+1 of voting power in the `LatestHeight`. If this succeeds, the client is fully
|
||||
synchronized. If this fails, then following Bisection Algorithm should be
|
||||
executed.
|
||||
|
||||
The Client tries to download the block at the mid-point block between
|
||||
`LatestHeight` and `TrustHeight` and attempts that same algorithm as above
|
||||
using `MidPointHeight` instead of `LatestHeight` and a different threshold -
|
||||
1/3 +1 of voting power for *non-adjacent headers*. In the case the of failure,
|
||||
recursively perform the `MidPoint` verification until success then start over
|
||||
with an updated `NextValidatorSet` and `TrustHeight`.
|
||||
|
||||
If the client encounters a forged header, it should submit the header along
|
||||
with some other intermediate headers as the evidence of misbehavior to other
|
||||
full nodes. After that, it can retry the bisection using another full node. An
|
||||
optimal client will cache trusted headers from the previous run to minimize
|
||||
network usage.
|
||||
|
||||
---
|
||||
|
||||
Check out the formal specification
|
||||
[here](https://github.com/tendermint/tendermint/blob/master/docs/spec/consensus/light-client.md).
|
||||
|
||||
## Status
|
||||
|
||||
Accepted.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
* light client which is safe to use (it can go offline, but not for too long)
|
||||
|
||||
### Negative
|
||||
|
||||
* complexity of bisection
|
||||
|
||||
### Neutral
|
||||
|
||||
* social consensus can be prone to errors (for cases where a new light client
|
||||
joins a network or it has been offline for too long)
|
@ -66,7 +66,7 @@ After `Commit`, CheckTx is run again on all transactions that remain in the
|
||||
node's local mempool after filtering those included in the block. To prevent the
|
||||
mempool from rechecking all transactions every time a block is committed, set
|
||||
the configuration option `mempool.recheck=false`. As of Tendermint v0.32.1,
|
||||
an additional `Type` parameter is made available to the CheckTx function that
|
||||
an additional `Type` parameter is made available to the CheckTx function that
|
||||
indicates whether an incoming transaction is new (`CheckTxType_New`), or a
|
||||
recheck (`CheckTxType_Recheck`).
|
||||
|
||||
@ -211,7 +211,7 @@ message PubKey {
|
||||
|
||||
The `pub_key` currently supports only one type:
|
||||
|
||||
- `type = "ed25519" and`data = <raw 32-byte public key>`
|
||||
- `type = "ed25519"` and `data = <raw 32-byte public key>`
|
||||
|
||||
The `power` is the new voting power for the validator, with the
|
||||
following rules:
|
||||
|
@ -1,113 +1,329 @@
|
||||
# Light Client
|
||||
# Lite client
|
||||
|
||||
A light client is a process that connects to the Tendermint Full Node(s) and then tries to verify the Merkle proofs
|
||||
about the blockchain application. In this document we describe mechanisms that ensures that the Tendermint light client
|
||||
has the same level of security as Full Node processes (without being itself a Full Node).
|
||||
A lite client is a process that connects to Tendermint full nodes and then tries to verify application data using the Merkle proofs.
|
||||
|
||||
To be able to validate a Merkle proof, a light client needs to validate the blockchain header that contains the root app hash.
|
||||
Validating a blockchain header in Tendermint consists in verifying that the header is committed (signed) by >2/3 of the
|
||||
voting power of the corresponding validator set. As the validator set is a dynamic set (it is changing), one of the
|
||||
core functionality of the light client is updating the current validator set, that is then used to verify the
|
||||
blockchain header, and further the corresponding Merkle proofs.
|
||||
## Context of this document
|
||||
|
||||
For the purpose of this light client specification, we assume that the Tendermint Full Node exposes the following functions over
|
||||
Tendermint RPC:
|
||||
In order to make sure that full nodes have the incentive to follow the protocol, we have to address the following three Issues
|
||||
|
||||
```golang
|
||||
Header(height int64) (SignedHeader, error) // returns signed header for the given height
|
||||
Validators(height int64) (ResultValidators, error) // returns validator set for the given height
|
||||
LastHeader(valSetNumber int64) (SignedHeader, error) // returns last header signed by the validator set with the given validator set number
|
||||
1) The lite client needs a method to verify headers it obtains from full nodes according to trust assumptions -- this document.
|
||||
|
||||
type SignedHeader struct {
|
||||
Header Header
|
||||
Commit Commit
|
||||
ValSetNumber int64
|
||||
}
|
||||
2) The lite client must be able to connect to one correct full node to detect and report on failures in the trust assumptions (i.e., conflicting headers) -- a future document.
|
||||
|
||||
type ResultValidators struct {
|
||||
BlockHeight int64
|
||||
Validators []Validator
|
||||
// time the current validator set is initialised, i.e, time of the last validator change before header BlockHeight
|
||||
ValSetTime int64
|
||||
}
|
||||
3) In the event the trust assumption fails (i.e., a lite client is fooled by a conflicting header), the Tendermint fork accountability protocol must account for the evidence -- see #3840
|
||||
|
||||
## Problem statement
|
||||
|
||||
|
||||
We assume that the lite client knows a (base) header *inithead* it trusts (by social consensus or because the lite client has decided to trust the header before). The goal is to check whether another header *newhead* can be trusted based on the data in *inithead*.
|
||||
|
||||
The correctness of the protocol is based on the assumption that *inithead* was generated by an instance of Tendermint consensus. The term "trusting" above indicates that the correctness on the protocol depends on this assumption. It is in the responsibility of the user that runs the lite client to make sure that the risk of trusting a corrupted/forged *inithead* is negligible.
|
||||
|
||||
|
||||
## Definitions
|
||||
|
||||
### Data structures
|
||||
|
||||
In the following, only the details of the data structures needed for this specification are given.
|
||||
|
||||
* header fields
|
||||
- *height*
|
||||
- *bfttime*: the chain time when the header (block) was generated
|
||||
- *V*: validator set containing validators for this block.
|
||||
- *NextV*: validator set for next block.
|
||||
- *commit*: evidence that block with height *height* - 1 was committed by a set of validators (canonical commit). We will use ```signers(commit)``` to refer to the set of validators that committed the block.
|
||||
|
||||
* signed header fields: contains a header and a *commit* for the current header; a "seen commit". In the Tendermint consensus the "canonical commit" is stored in header *height* + 1.
|
||||
|
||||
* For each header *h* it has locally stored, the lite client stores whether
|
||||
it trusts *h*. We write *trust(h) = true*, if this is the case.
|
||||
|
||||
* Validator fields. We will write a validator as a tuple *(v,p)* such that
|
||||
+ *v* is the identifier (we assume identifiers are unique in each validator set)
|
||||
+ *p* is its voting power
|
||||
|
||||
|
||||
### Functions
|
||||
|
||||
For the purpose of this lite client specification, we assume that the Tendermint Full Node exposes the following function over Tendermint RPC:
|
||||
```go
|
||||
func Commit(height int64) (SignedHeader, error)
|
||||
// returns signed header: header (with the fields from
|
||||
// above) with Commit that include signatures of
|
||||
// validators that signed the header
|
||||
|
||||
|
||||
type SignedHeader struct {
|
||||
Header Header
|
||||
Commit Commit
|
||||
}
|
||||
```
|
||||
|
||||
We assume that Tendermint keeps track of the validator set changes and that each time a validator set is changed it is
|
||||
being assigned the next sequence number. We can call this number the validator set sequence number. Tendermint also remembers
|
||||
the Time from the header when the next validator set is initialised (starts to be in power), and we refer to this time
|
||||
as validator set init time.
|
||||
Furthermore, we assume that each validator set change is signed (committed) by the current validator set. More precisely,
|
||||
given a block `H` that contains transactions that are modifying the current validator set, the Merkle root hash of the next
|
||||
validator set (modified based on transactions from block H) will be in block `H+1` (and signed by the current validator
|
||||
set), and then starting from the block `H+2`, it will be signed by the next validator set.
|
||||
### Definitions
|
||||
|
||||
Note that the real Tendermint RPC API is slightly different (for example, response messages contain more data and function
|
||||
names are slightly different); we shortened (and modified) it for the purpose of this document to make the spec more
|
||||
clear and simple. Furthermore, note that in case of the third function, the returned header has `ValSetNumber` equals to
|
||||
`valSetNumber+1`.
|
||||
* *tp*: trusting period
|
||||
* for realtime *t*, the predicate *correct(v,t)* is true if the validator *v*
|
||||
follows the protocol until time *t* (we will see about recovery later).
|
||||
|
||||
Locally, light client manages the following state:
|
||||
|
||||
```golang
|
||||
valSet []Validator // current validator set (last known and verified validator set)
|
||||
valSetNumber int64 // sequence number of the current validator set
|
||||
valSetHash []byte // hash of the current validator set
|
||||
valSetTime int64 // time when the current validator set is initialised
|
||||
|
||||
|
||||
### Tendermint Failure Model
|
||||
|
||||
If a block *h* is generated at time *bfttime* (and this time is stored in the block), then a set of validators that hold more than 2/3 of the voting power in h.Header.NextV is correct until time h.Header.bfttime + tp.
|
||||
|
||||
Formally,
|
||||
\[
|
||||
\sum_{(v,p) \in h.Header.NextV \wedge correct(v,h.Header.bfttime + tp)} p >
|
||||
2/3 \sum_{(v,p) \in h.Header.NextV} p
|
||||
\]
|
||||
|
||||
*Assumption*: "correct" is defined w.r.t. realtime (some Newtonian global notion of time, i.e., wall time), while *bfttime* corresponds to the reading of the local clock of a validator (how this time is computed may change when the Tendermint consensus is modified). In this note, we assume that all clocks are synchronized to realtime. We can make this more precise eventually (incorporating clock drift, accuracy, precision, etc.). Right now, we consider this assumption sufficient, as clock synchronization (under NTP) is in the order of milliseconds and *tp* is in the order of weeks.
|
||||
|
||||
*Remark*: This failure model might change to a hybrid version that takes heights into account in the future.
|
||||
|
||||
The specification in this document considers an implementation of the lite client under this assumption. Issues like *counter-factual signing* and *fork accountability* and *evidence submission* are mechanisms that justify this assumption by incentivizing validators to follow the protocol.
|
||||
If they don't, and we have more that 1/3 faults, safety may be violated. Our approach then is to *detect* these cases (after the fact), and take suitable repair actions (automatic and social). This is discussed in an upcoming document on "Fork accountability". (These safety violations include the lite client wrongly trusting a header, a fork in the blockchain, etc.)
|
||||
|
||||
|
||||
## Lite Client Trusting Spec
|
||||
|
||||
The lite client communicates with a full node and learns new headers. The goal is to locally decide whether to trust a header. Our implementation needs to ensure the following two properties:
|
||||
|
||||
- Lite Client Completeness: If header *h* was correctly generated by an instance of Tendermint consensus (and its age is less than the trusting period), then the lite client should eventually set *trust(h)* to true.
|
||||
|
||||
- Lite Client Accuracy: If header *h* was *not generated* by an instance of Tendermint consensus, then the lite client should never set *trust(h)* to true.
|
||||
|
||||
*Remark*: If in the course of the computation, the lite client obtains certainty that some headers were forged by adversaries (that is were not generated by an instance of Tendermint consensus), it may submit (a subset of) the headers it has seen as evidence of misbehavior.
|
||||
|
||||
*Remark*: In Completeness we use "eventually", while in practice *trust(h)* should be set to true before *h.Header.bfttime + tp*. If not, the block cannot be trusted because it is too old.
|
||||
|
||||
*Remark*: If a header *h* is marked with *trust(h)*, but it is too old (its bfttime is more than *tp* ago), then the lite client should set *trust(h)* to false again.
|
||||
|
||||
*Assumption*: Initially, the lite client has a header *inithead* that it trusts correctly, that is, *inithead* was correctly generated by the Tendermint consensus.
|
||||
|
||||
To reason about the correctness, we may prove the following invariant.
|
||||
|
||||
*Verification Condition: Lite Client Invariant.*
|
||||
For each lite client *l* and each header *h*:
|
||||
if *l* has set *trust(h) = true*,
|
||||
then validators that are correct until time *h.Header.bfttime + tp* have more than two thirds of the voting power in *h.Header.NextV*.
|
||||
|
||||
Formally,
|
||||
\[
|
||||
\sum_{(v,p) \in h.Header.NextV \wedge correct(v,h.Header.bfttime + tp)} p >
|
||||
2/3 \sum_{(v,p) \in h.Header.NextV} p
|
||||
\]
|
||||
|
||||
*Remark.* To prove the invariant, we will have to prove that the lite client only trusts headers that were correctly generated by Tendermint consensus, then the formula above follows from the Tendermint failure model.
|
||||
|
||||
|
||||
## High Level Solution
|
||||
|
||||
Upon initialization, the lite client is given a header *inithead* it trusts (by
|
||||
social consensus). It is assumed that *inithead* satisfies the lite client invariant. (If *inithead* has been correctly generated by Tendermint consensus, the invariant follows from the Tendermint Failure Model.)
|
||||
|
||||
When a lite clients sees a signed new header *snh*, it has to decide whether to trust the new
|
||||
header. Trust can be obtained by (possibly) the combination of three methods.
|
||||
|
||||
1. **Uninterrupted sequence of proof.** If a block is appended to the chain, where the last block
|
||||
is trusted (and properly committed by the old validator set in the next block),
|
||||
and the new block contains a new validator set, the new block is trusted if the lite client knows all headers in the prefix.
|
||||
Intuitively, a trusted validator set is assumed to only chose a new validator set that will obey the Tendermint Failure Model.
|
||||
|
||||
2. **Trusting period.** Based on a trusted block *h*, and the lite client
|
||||
invariant, which ensures the fault assumption during the trusting period, we can check whether at least one validator, that has been continuously correct from *h.Header.bfttime* until now, has signed *snh*.
|
||||
If this is the case, similarly to above, the chosen validator set in *snh* does not violate the Tendermint Failure Model.
|
||||
|
||||
3. **Bisection.** If a check according to the trusting period fails, the lite client can try to obtain a header *hp* whose height lies between *h* and *snh* in order to check whether *h* can be used to get trust for *hp*, and *hp* can be used to get trust for *snh*. If this is the case we can trust *snh*; if not, we may continue recursively.
|
||||
|
||||
## How to use it
|
||||
|
||||
We consider the following use case:
|
||||
the lite client wants to verify a header for some given height *k*. Thus:
|
||||
- it requests the signed header for height *k* from a full node
|
||||
- it tries to verify this header with the methods described here.
|
||||
|
||||
This can be used in several settings:
|
||||
- someone tells the lite client that application data that is relevant for it can be read in the block of height *k*.
|
||||
- the lite clients wants the latest state. It asks a full nude for the current height, and uses the response for *k*.
|
||||
|
||||
|
||||
## Details
|
||||
|
||||
*Assumptions*
|
||||
|
||||
1. *tp < unbonding period*.
|
||||
2. *snh.Header.bfttime < now*
|
||||
3. *snh.Header.bfttime < h.Header.bfttime+tp*
|
||||
4. *trust(h)=true*
|
||||
|
||||
|
||||
**Observation 1.** If *h.Header.bfttime + tp > now*, we trust the old
|
||||
validator set *h.Header.NextV*.
|
||||
|
||||
When we say we trust *h.Header.NextV* we do *not* trust that each individual validator in *h.Header.NextV* is correct, but we only trust the fact that at most 1/3 of them are faulty (more precisely, the faulty ones have at most 1/3 of the total voting power).
|
||||
|
||||
|
||||
|
||||
### Functions
|
||||
|
||||
The function *Bisection* checks whether to trust header *h2* based on the trusted header *h1*. It does so by calling
|
||||
the function *CheckSupport* in the process of
|
||||
bisection/recursion. *CheckSupport* implements the trusted period method and, for two adjacent headers (in term of heights), it checks uninterrupted sequence of proof.
|
||||
|
||||
*Assumption*: In the following, we assume that *h2.Header.height > h1.Header.height*. We will quickly discuss the other case in the next section.
|
||||
|
||||
We consider the following set-up:
|
||||
- the lite client communicates with one full node
|
||||
- the lite client locally stores all the signed headers it obtained (trusted or not). In the pseudo code below we write *Store(header)* for this.
|
||||
- If *Bisection* returns *false*, then the lite client has seen a forged header.
|
||||
* However, it does not know which header(s) is/are the problematic one(s).
|
||||
* In this case, the lite client can submit (some of) the headers it has seen as evidence. As the lite client communicates with one full node only when executing Bisection, there are two cases
|
||||
- the full node is faulty
|
||||
- the full node is correct and there was a fork in Tendermint consensus. Header *h1* is from a different branch than the one taken by the full node. This case is not focus of this document, but will be treated in the document on fork accountability.
|
||||
|
||||
- the lite client must retry to retrieve correct headers from another full node
|
||||
* it picks a new full node
|
||||
* it restarts *Bisection*
|
||||
* there might be optimizations; a lite client may not need to call *Commit(k)*, for a height *k* for which it already has a signed header it trusts.
|
||||
* how to make sure that a lite client can communicate with a correct full node will be the focus of a separate document (recall Issue 3 from "Context of this document").
|
||||
|
||||
**Auxiliary Functions.** We will use the function ```votingpower_in(V1,V2)``` to compute the voting power the validators in set V1 have according to their voting power in set V2;
|
||||
we will write ```totalVotingPower(V)``` for ```votingpower_in(V,V)```, which returns the total voting power in V.
|
||||
We further use the function ```signers(Commit)``` that returns the set of validators that signed the Commit.
|
||||
|
||||
**CheckSupport.** The following function checks whether we can trust the header h2 based on header h1 following the trusting period method.
|
||||
|
||||
```go
|
||||
func CheckSupport(h1,h2,trustlevel) bool {
|
||||
if h1.Header.bfttime + tp < now { // Observation 1
|
||||
return false // old header was once trusted but it is expired
|
||||
}
|
||||
vp_all := totalVotingPower(h1.Header.NextV)
|
||||
// total sum of voting power of validators in h2
|
||||
|
||||
if h2.Header.height == h1.Header.height + 1 {
|
||||
// specific check for adjacent headers; everything must be
|
||||
// properly signed.
|
||||
// also check that h2.Header.V == h1.Header.NextV
|
||||
// Plus the following check that 2/3 of the voting power
|
||||
// in h1 signed h2
|
||||
return (votingpower_in(signers(h2.Commit),h1.Header.NextV) >
|
||||
2/3 * vp_all)
|
||||
// signing validators are more than two third in h1.
|
||||
}
|
||||
|
||||
return (votingpower_in(signers(h2.Commit),h1.Header.NextV) >
|
||||
max(1/3,trustlevel) * vp_all)
|
||||
// get validators in h1 that signed h2
|
||||
// sum of voting powers in h1 of
|
||||
// validators that signed h2
|
||||
// is more than a third in h1
|
||||
}
|
||||
```
|
||||
|
||||
The light client is initialised with the trusted validator set, for example based on the known validator set hash,
|
||||
validator set sequence number and the validator set init time.
|
||||
The core of the light client logic is captured by the VerifyAndUpdate function that is used to 1) verify if the given header is valid,
|
||||
and 2) update the validator set (when the given header is valid and it is more recent than the seen headers).
|
||||
*Remark*: Basic header verification must be done for *h2*. Similar checks are done in:
|
||||
https://github.com/tendermint/tendermint/blob/master/types/validator_set.go#L591-L633
|
||||
|
||||
```golang
|
||||
VerifyAndUpdate(signedHeader SignedHeader):
|
||||
assertThat signedHeader.valSetNumber >= valSetNumber
|
||||
if isValid(signedHeader) and signedHeader.Header.Time <= valSetTime + UNBONDING_PERIOD then
|
||||
setValidatorSet(signedHeader)
|
||||
*Remark*: There are some sanity checks which are not in the code:
|
||||
*h2.Header.height > h1.Header.height* and *h2.Header.bfttime > h1.Header.bfttime* and *h2.Header.bfttime < now*.
|
||||
|
||||
*Remark*: ```return (votingpower_in(signers(h2.Commit),h1.Header.NextV) > max(1/3,trustlevel) * vp_all)``` may return false even if *h2* was properly generated by Tendermint consensus in the case of big changes in the validator sets. However, the check ```return (votingpower_in(signers(h2.Commit),h1.Header.NextV) >
|
||||
2/3 * vp_all)``` must return true if *h1* and *h2* were generated by Tendermint consensus.
|
||||
|
||||
*Remark*: The 1/3 check differs from a previously proposed method that was based on intersecting validator sets and checking that the new validator set contains "enough" correct validators. We found that the old check is not suited for realistic changes in the validator sets. The new method is not only based on cardinalities, but also exploits that we can trust what is signed by a correct validator (i.e., signed by more than 1/3 of the voting power).
|
||||
|
||||
*Correctness arguments*
|
||||
|
||||
Towards Lite Client Accuracy:
|
||||
- Assume by contradiction that *h2* was not generated correctly and the lite client sets trust to true because *CheckSupport* returns true.
|
||||
- h1 is trusted and sufficiently new
|
||||
- by Tendermint Fault Model, less than 1/3 of voting power held by faulty validators => at least one correct validator *v* has signed *h2*.
|
||||
- as *v* is correct up to now, it followed the Tendermint consensus protocol at least up to signing *h2* => *h2* was correctly generated, we arrive at the required contradiction.
|
||||
|
||||
|
||||
Towards Lite Client Completeness:
|
||||
- The check is successful if sufficiently many validators of *h1* are still validators in *h2* and signed *h2*.
|
||||
- If *h2.Header.height = h1.Header.height + 1*, and both headers were generated correctly, the test passes
|
||||
|
||||
*Verification Condition:* We may need a Tendermint invariant stating that if *h2.Header.height = h1.Header.height + 1* then *signers(h2.Commit) \subseteq h1.Header.NextV*.
|
||||
|
||||
*Remark*: The variable *trustlevel* can be used if the user believes that relying on one correct validator is not sufficient. However, in case of (frequent) changes in the validator set, the higher the *trustlevel* is chosen, the more unlikely it becomes that CheckSupport returns true for non-adjacent headers.
|
||||
|
||||
**Bisection.** The following function uses CheckSupport in a recursion to find intermediate headers that allow to establish a sequence of trust.
|
||||
|
||||
|
||||
|
||||
|
||||
```go
|
||||
func Bisection(h1,h2,trustlevel) bool{
|
||||
if CheckSupport(h1,h2,trustlevel) {
|
||||
return true
|
||||
else
|
||||
updateValidatorSet(signedHeader.ValSetNumber)
|
||||
return VerifyAndUpdate(signedHeader)
|
||||
|
||||
isValid(signedHeader SignedHeader):
|
||||
valSetOfTheHeader = Validators(signedHeader.Header.Height)
|
||||
assertThat Hash(valSetOfTheHeader) == signedHeader.Header.ValSetHash
|
||||
assertThat signedHeader is passing basic validation
|
||||
if votingPower(signedHeader.Commit) > 2/3 * votingPower(valSetOfTheHeader) then return true
|
||||
else
|
||||
}
|
||||
if h2.Header.height == h1.Header.height + 1 {
|
||||
// we have adjacent headers that are not matching (failed
|
||||
// the CheckSupport)
|
||||
// we could submit evidence here
|
||||
return false
|
||||
}
|
||||
pivot := (h1.Header.height + h2.Header.height) / 2
|
||||
hp := Commit(pivot)
|
||||
// ask a full node for header of height pivot
|
||||
Store(hp)
|
||||
// store header hp locally
|
||||
if Bisection(h1,hp,trustlevel) {
|
||||
// only check right branch if hp is trusted
|
||||
// (otherwise a lot of unnecessary computation may be done)
|
||||
return Bisection(hp,h2,trustlevel)
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
setValidatorSet(signedHeader SignedHeader):
|
||||
nextValSet = Validators(signedHeader.Header.Height)
|
||||
assertThat Hash(nextValSet) == signedHeader.Header.ValidatorsHash
|
||||
valSet = nextValSet.Validators
|
||||
valSetHash = signedHeader.Header.ValidatorsHash
|
||||
valSetNumber = signedHeader.ValSetNumber
|
||||
valSetTime = nextValSet.ValSetTime
|
||||
|
||||
votingPower(commit Commit):
|
||||
votingPower = 0
|
||||
for each precommit in commit.Precommits do:
|
||||
if precommit.ValidatorAddress is in valSet and signature of the precommit verifies then
|
||||
votingPower += valSet[precommit.ValidatorAddress].VotingPower
|
||||
return votingPower
|
||||
|
||||
votingPower(validatorSet []Validator):
|
||||
for each validator in validatorSet do:
|
||||
votingPower += validator.VotingPower
|
||||
return votingPower
|
||||
|
||||
updateValidatorSet(valSetNumberOfTheHeader):
|
||||
while valSetNumber != valSetNumberOfTheHeader do
|
||||
signedHeader = LastHeader(valSetNumber)
|
||||
if isValid(signedHeader) then
|
||||
setValidatorSet(signedHeader)
|
||||
else return error
|
||||
return
|
||||
*Correctness arguments (sketch)*
|
||||
|
||||
Lite Client Accuracy:
|
||||
- Assume by contradiction that *h2* was not generated correctly and the lite client sets trust to true because Bisection returns true.
|
||||
- Bisection returns true only if all calls to CheckSupport in the recursion return true.
|
||||
- Thus we have a sequence of headers that all satisfied the CheckSupport
|
||||
- again a contradiction
|
||||
|
||||
Lite Client Completeness:
|
||||
|
||||
This is only ensured if upon *Commit(pivot)* the lite client is always provided with a correctly generated header.
|
||||
|
||||
*Stalling*
|
||||
|
||||
With Bisection, a faulty full node could stall a lite client by creating a long sequence of headers that are queried one-by-one by the lite client and look OK, before the lite client eventually detects a problem. There are several ways to address this:
|
||||
* Each call to ```Commit``` could be issued to a different full node
|
||||
* Instead of querying header by header, the lite client tells a full node which header it trusts, and the height of the header it needs. The full node responds with the header along with a proof consisting of intermediate headers that the light client can use to verify. Roughly, Bisection would then be executed at the full node.
|
||||
* We may set a timeout how long bisection may take.
|
||||
|
||||
|
||||
### The case *h2.Header.height < h1.Header.height*
|
||||
|
||||
In the use case where someone tells the lite client that application data that is relevant for it can be read in the block of height *k* and the lite client trusts a more recent header, we can use the hashes to verify headers "down the chain." That is, we iterate down the heights and check the hashes in each step.
|
||||
|
||||
*Remark.* For the case were the lite client trusts two headers *i* and *j* with *i < k < j*, we should discuss/experiment whether the forward or the backward method is more effective.
|
||||
|
||||
```go
|
||||
func Backwards(h1,h2) bool {
|
||||
assert (h2.Header.height < h1.Header.height)
|
||||
old := h1
|
||||
for i := h1.Header.height - 1; i > h2.Header.height; i-- {
|
||||
new := Commit(i)
|
||||
Store(new)
|
||||
if (hash(new) != old.Header.hash) {
|
||||
return false
|
||||
}
|
||||
old := new
|
||||
}
|
||||
return (hash(h2) == old.Header.hash)
|
||||
}
|
||||
```
|
||||
|
||||
Note that in the logic above we assume that the light client will always go upward with respect to header verifications,
|
||||
i.e., that it will always be used to verify more recent headers. In case a light client needs to be used to verify older
|
||||
headers (go backward) the same mechanisms and similar logic can be used. In case a call to the FullNode or subsequent
|
||||
checks fail, a light client need to implement some recovery strategy, for example connecting to other FullNode.
|
||||
|
@ -61,7 +61,7 @@ func (m MConnection) TrySend(chID byte, msg interface{}) bool {}
|
||||
|
||||
`Send(chID, msg)` is a blocking call that waits until `msg` is successfully queued
|
||||
for the channel with the given id byte `chID`. The message `msg` is serialized
|
||||
using the `tendermint/wire` submodule's `WriteBinary()` reflection routine.
|
||||
using the `tendermint/go-amino` submodule's `WriteBinary()` reflection routine.
|
||||
|
||||
`TrySend(chID, msg)` is a nonblocking call that queues the message msg in the channel
|
||||
with the given id byte chID if the queue is not full; otherwise it returns false immediately.
|
||||
|
@ -13,13 +13,13 @@ type TxMessage struct {
|
||||
}
|
||||
```
|
||||
|
||||
TxMessage is go-wire encoded and prepended with `0x1` as a
|
||||
"type byte". This is followed by a go-wire encoded byte-slice.
|
||||
TxMessage is go-amino encoded and prepended with `0x1` as a
|
||||
"type byte". This is followed by a go-amino encoded byte-slice.
|
||||
Prefix of 40=0x28 byte tx is: `0x010128...` followed by
|
||||
the actual 40-byte tx. Prefix of 350=0x015e byte tx is:
|
||||
`0x0102015e...` followed by the actual 350 byte tx.
|
||||
|
||||
(Please see the [go-wire repo](https://github.com/tendermint/go-wire#an-interface-example) for more information)
|
||||
(Please see the [go-amino repo](https://github.com/tendermint/go-amino#an-interface-example) for more information)
|
||||
|
||||
## RPC Messages
|
||||
|
||||
|
25
docs/spec/rpc/index.html
Normal file
25
docs/spec/rpc/index.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!-- HTML for static distribution bundle build -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Tendermint RPC</title>
|
||||
<link rel="stylesheet" type="text/css" href="//unpkg.com/swagger-ui-dist@3/swagger-ui.css" >
|
||||
<link rel="icon" type="image/png" href="//unpkg.com/swagger-ui-dist@3/favicon-16x16.png"/>
|
||||
<script src="//unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
window.ui = SwaggerUIBundle({
|
||||
url: "./swagger.yaml",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
layout: "BaseLayout"
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
2677
docs/spec/rpc/swagger.yaml
Normal file
2677
docs/spec/rpc/swagger.yaml
Normal file
File diff suppressed because it is too large
Load Diff
33
dredd.yml
Normal file
33
dredd.yml
Normal file
@ -0,0 +1,33 @@
|
||||
color: true
|
||||
dry-run: null
|
||||
hookfiles: build/contract_tests
|
||||
language: go
|
||||
require: null
|
||||
server: make localnet-start
|
||||
server-wait: 30
|
||||
init: false
|
||||
custom: {}
|
||||
names: false
|
||||
only: []
|
||||
reporter: []
|
||||
output: []
|
||||
header: []
|
||||
sorted: false
|
||||
user: null
|
||||
inline-errors: false
|
||||
details: false
|
||||
method: [GET]
|
||||
loglevel: warning
|
||||
path: []
|
||||
hooks-worker-timeout: 5000
|
||||
hooks-worker-connect-timeout: 1500
|
||||
hooks-worker-connect-retry: 500
|
||||
hooks-worker-after-connect-wait: 100
|
||||
hooks-worker-term-timeout: 5000
|
||||
hooks-worker-term-retry: 500
|
||||
hooks-worker-handler-host: 127.0.0.1
|
||||
hooks-worker-handler-port: 61321
|
||||
config: ./dredd.yml
|
||||
# This path accepts no variables
|
||||
blueprint: ./docs/spec/rpc/swagger.yaml
|
||||
endpoint: 'http://127.0.0.1:26657/'
|
8
go.mod
8
go.mod
@ -11,17 +11,15 @@ require (
|
||||
github.com/go-kit/kit v0.6.0
|
||||
github.com/go-logfmt/logfmt v0.3.0
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/gogo/protobuf v1.2.1
|
||||
github.com/gogo/protobuf v1.3.0
|
||||
github.com/golang/protobuf v1.3.2
|
||||
github.com/google/gofuzz v1.0.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70 // indirect
|
||||
github.com/gorilla/websocket v1.2.0
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.0.1
|
||||
github.com/magiconair/properties v1.8.0
|
||||
github.com/magiconair/properties v1.8.1
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.1.2 // indirect
|
||||
github.com/pelletier/go-toml v1.2.0 // indirect
|
||||
@ -32,6 +30,7 @@ require (
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165
|
||||
github.com/rs/cors v1.6.0
|
||||
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa
|
||||
github.com/spf13/afero v1.1.2 // indirect
|
||||
github.com/spf13/cast v1.3.0 // indirect
|
||||
github.com/spf13/cobra v0.0.1
|
||||
@ -41,7 +40,6 @@ require (
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/tendermint/go-amino v0.14.1
|
||||
github.com/tendermint/tm-db v0.1.1
|
||||
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c // indirect
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
|
||||
google.golang.org/grpc v1.22.0
|
||||
|
17
go.sum
17
go.sum
@ -35,6 +35,8 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE=
|
||||
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
@ -46,16 +48,12 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70 h1:XTnP8fJpa4Kvpw2qARB4KS9izqxPS0Sd92cDlY3uk+w=
|
||||
github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
|
||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
@ -63,6 +61,7 @@ github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U
|
||||
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
|
||||
@ -71,6 +70,8 @@ github.com/libp2p/go-buffer-pool v0.0.1 h1:9Rrn/H46cXjaA2HQ5Y8lyhOS1NhTkZ4yuEs2r
|
||||
github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ=
|
||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
@ -98,6 +99,8 @@ github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 h1:nkcn14uNmFE
|
||||
github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa h1:YJfZp12Z3AFhSBeXOlv4BO55RMwPn2NoQeDsrdWnBtY=
|
||||
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4=
|
||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
@ -119,14 +122,10 @@ github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 h1:1oFLiOyVl+W7
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
|
||||
github.com/tendermint/go-amino v0.14.1 h1:o2WudxNfdLNBwMyl2dqOJxiro5rfrEaU0Ugs6offJMk=
|
||||
github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=
|
||||
github.com/tendermint/tm-db v0.0.0-20190731085305-94017c88bf1d h1:yCHL2COLGLNfb4sA9AlzIHpapb8UATvAQyJulS6Eg6Q=
|
||||
github.com/tendermint/tm-db v0.0.0-20190731085305-94017c88bf1d/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw=
|
||||
github.com/tendermint/tm-db v0.1.1 h1:G3Xezy3sOk9+ekhjZ/kjArYIs1SmwV+1OUgNkj7RgV0=
|
||||
github.com/tendermint/tm-db v0.1.1/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw=
|
||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c h1:Rx/HTKi09myZ25t1SOlDHmHOy/mKxNAcu0hP1oPX9qM=
|
||||
golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@ -146,6 +145,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
@ -163,4 +163,3 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
@ -453,6 +453,8 @@ func (w *WSEvents) UnsubscribeAll(ctx context.Context, subscriber string) error
|
||||
func (w *WSEvents) redoSubscriptionsAfter(d time.Duration) {
|
||||
time.Sleep(d)
|
||||
|
||||
w.mtx.RLock()
|
||||
defer w.mtx.RUnlock()
|
||||
for q := range w.subscriptions {
|
||||
err := w.ws.Subscribe(context.Background(), q)
|
||||
if err != nil {
|
||||
|
@ -346,7 +346,7 @@ func UnconfirmedTxs(ctx *rpctypes.Context, limit int) (*ctypes.ResultUnconfirmed
|
||||
// client := client.NewHTTP("tcp://0.0.0.0:26657", "/websocket")
|
||||
// err := client.Start()
|
||||
// if err != nil {
|
||||
// // handle error
|
||||
// // handle error
|
||||
// }
|
||||
// defer client.Stop()
|
||||
// result, err := client.UnconfirmedTxs()
|
||||
@ -361,8 +361,8 @@ func UnconfirmedTxs(ctx *rpctypes.Context, limit int) (*ctypes.ResultUnconfirmed
|
||||
// "result" : {
|
||||
// "n_txs" : "0",
|
||||
// "total_bytes" : "0",
|
||||
// "txs" : null,
|
||||
// "total" : "0"
|
||||
// "txs" : null,
|
||||
// }
|
||||
// }
|
||||
// ```
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
// TODO: better system than "unsafe" prefix
|
||||
// NOTE: Amino is registered in rpc/core/types/wire.go.
|
||||
// NOTE: Amino is registered in rpc/core/types/codec.go.
|
||||
var Routes = map[string]*rpc.RPCFunc{
|
||||
// subscribe/unsubscribe are reserved for websocket events.
|
||||
"subscribe": rpc.NewWSRPCFunc(Subscribe, "query"),
|
||||
|
14
scripts/get_nodejs.sh
Executable file
14
scripts/get_nodejs.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
VERSION=v12.9.0
|
||||
NODE_FULL=node-${VERSION}-linux-x64
|
||||
|
||||
mkdir -p ~/.local/bin
|
||||
mkdir -p ~/.local/node
|
||||
wget http://nodejs.org/dist/${VERSION}/${NODE_FULL}.tar.gz -O ~/.local/node/${NODE_FULL}.tar.gz
|
||||
tar -xzf ~/.local/node/${NODE_FULL}.tar.gz -C ~/.local/node/
|
||||
ln -s ~/.local/node/${NODE_FULL}/bin/node ~/.local/bin/node
|
||||
ln -s ~/.local/node/${NODE_FULL}/bin/npm ~/.local/bin/npm
|
||||
export PATH=~/.local/bin:$PATH
|
||||
npm i -g dredd
|
||||
ln -s ~/.local/node/${NODE_FULL}/bin/dredd ~/.local/bin/dredd
|
@ -49,18 +49,25 @@ installFromGithub() {
|
||||
}
|
||||
|
||||
######################## DEVELOPER TOOLS #####################################
|
||||
installFromGithub gogo/protobuf 61dbc136cf5d2f08d68a011382652244990a53a9 protoc-gen-gogo
|
||||
## protobuf v1.3.0
|
||||
installFromGithub gogo/protobuf 0ca988a254f991240804bf9821f3450d87ccbb1b protoc-gen-gogo
|
||||
|
||||
installFromGithub square/certstrap e27060a3643e814151e65b9807b6b06d169580a7
|
||||
installFromGithub square/certstrap 338204a88c4349b1c135eac1e8c14c693ad007da
|
||||
|
||||
# used to build tm-monitor & tm-bench binaries
|
||||
installFromGithub mitchellh/gox 51ed453898ca5579fea9ad1f08dff6b121d9f2e8
|
||||
## gox v1.0.1
|
||||
installFromGithub mitchellh/gox d8caaff5a9dc98f4cfa1fcce6e7265a04689f641
|
||||
|
||||
## golangci-lint v1.13.2
|
||||
installFromGithub golangci/golangci-lint 7b2421d55194c9dc385eff7720a037aa9244ca3c cmd/golangci-lint
|
||||
## Trying to install golangci with Go 1.13 gives:
|
||||
## go: github.com/go-critic/go-critic@v0.0.0-20181204210945-1df300866540: invalid pseudo-version: does not match version-control timestamp (2019-05-26T07:48:19Z)
|
||||
## golangci-lint v1.17.1
|
||||
# installFromGithub golangci/golangci-lint 4ba2155996359eabd8800d1fbf3e3a9777c80490 cmd/golangci-lint
|
||||
|
||||
## Trying to install golangci with Go 1.13 gives:
|
||||
## go: cannot find main module, but found .git/config in /go/src/github.com/petermattis/goid
|
||||
## make test_with_deadlock
|
||||
## XXX: https://github.com/tendermint/tendermint/issues/3242
|
||||
installFromGithub petermattis/goid b0b1615b78e5ee59739545bb38426383b2cda4c9
|
||||
installFromGithub sasha-s/go-deadlock d68e2bc52ae3291765881b9056f2c1527f245f1e
|
||||
go get golang.org/x/tools/cmd/goimports
|
||||
# installFromGithub petermattis/goid b0b1615b78e5ee59739545bb38426383b2cda4c9
|
||||
# installFromGithub sasha-s/go-deadlock d68e2bc52ae3291765881b9056f2c1527f245f1e
|
||||
# go get golang.org/x/tools/cmd/goimports
|
||||
# installFromGithub snikch/goodman 10e37e294daa3c9a90abded60ff9924bafab3888 cmd/goodman
|
||||
|
@ -8,7 +8,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
GITIAN_CACHE_DIRNAME='.gitian-builder-cache'
|
||||
GO_DEBIAN_RELEASE='1.12.5-1'
|
||||
GO_DEBIAN_RELEASE='1.12.8-1'
|
||||
GO_TARBALL="golang-debian-${GO_DEBIAN_RELEASE}.tar.gz"
|
||||
GO_TARBALL_URL="https://salsa.debian.org/go-team/compiler/golang/-/archive/debian/${GO_DEBIAN_RELEASE}/${GO_TARBALL}"
|
||||
|
||||
|
@ -23,11 +23,11 @@ remotes:
|
||||
- "url": "https://github.com/tendermint/tendermint.git"
|
||||
"dir": "tendermint"
|
||||
files:
|
||||
- "golang-debian-1.12.5-1.tar.gz"
|
||||
- "golang-debian-1.12.8-1.tar.gz"
|
||||
script: |
|
||||
set -e -o pipefail
|
||||
|
||||
GO_SRC_RELEASE=golang-debian-1.12.5-1
|
||||
GO_SRC_RELEASE=golang-debian-1.12.8-1
|
||||
GO_SRC_TARBALL="${GO_SRC_RELEASE}.tar.gz"
|
||||
# Compile go and configure the environment
|
||||
export TAR_OPTIONS="--mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME""
|
||||
|
@ -23,11 +23,11 @@ remotes:
|
||||
- "url": "https://github.com/tendermint/tendermint.git"
|
||||
"dir": "tendermint"
|
||||
files:
|
||||
- "golang-debian-1.12.5-1.tar.gz"
|
||||
- "golang-debian-1.12.8-1.tar.gz"
|
||||
script: |
|
||||
set -e -o pipefail
|
||||
|
||||
GO_SRC_RELEASE=golang-debian-1.12.5-1
|
||||
GO_SRC_RELEASE=golang-debian-1.12.8-1
|
||||
GO_SRC_TARBALL="${GO_SRC_RELEASE}.tar.gz"
|
||||
# Compile go and configure the environment
|
||||
export TAR_OPTIONS="--mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME""
|
||||
|
@ -23,11 +23,11 @@ remotes:
|
||||
- "url": "https://github.com/tendermint/tendermint.git"
|
||||
"dir": "tendermint"
|
||||
files:
|
||||
- "golang-debian-1.12.5-1.tar.gz"
|
||||
- "golang-debian-1.12.8-1.tar.gz"
|
||||
script: |
|
||||
set -e -o pipefail
|
||||
|
||||
GO_SRC_RELEASE=golang-debian-1.12.5-1
|
||||
GO_SRC_RELEASE=golang-debian-1.12.8-1
|
||||
GO_SRC_TARBALL="${GO_SRC_RELEASE}.tar.gz"
|
||||
# Compile go and configure the environment
|
||||
export TAR_OPTIONS="--mtime="$REFERENCE_DATE\\\ $REFERENCE_TIME""
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
|
||||
@ -367,6 +368,104 @@ func TestCommitToVoteSet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommitToVoteSetWithBadVotes(t *testing.T) {
|
||||
lastID := makeBlockIDRandom()
|
||||
height := int64(3)
|
||||
round := 1
|
||||
numValidators := 10
|
||||
|
||||
voteSet, valSet, vals := randVoteSet(height-1, 1, PrecommitType, numValidators, 1)
|
||||
|
||||
// > 2/3 sign for this block
|
||||
numBlockValidators := numValidators*2/3 + 1
|
||||
for i := 0; i < numBlockValidators; i++ {
|
||||
addr := vals[i].GetPubKey().Address()
|
||||
vote := &Vote{
|
||||
ValidatorAddress: addr,
|
||||
ValidatorIndex: i,
|
||||
Height: height - 1,
|
||||
Round: round,
|
||||
Type: PrecommitType,
|
||||
BlockID: lastID,
|
||||
Timestamp: tmtime.Now(),
|
||||
}
|
||||
|
||||
_, err := signAddVote(vals[i], vote, voteSet)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
// 1/3 vote for a different block
|
||||
for i := numBlockValidators; i < numValidators; i++ {
|
||||
addr := vals[i].GetPubKey().Address()
|
||||
vote := &Vote{
|
||||
ValidatorAddress: addr,
|
||||
ValidatorIndex: i,
|
||||
Height: height - 1,
|
||||
Round: round,
|
||||
Type: PrecommitType,
|
||||
BlockID: makeBlockIDRandom(),
|
||||
Timestamp: tmtime.Now(),
|
||||
}
|
||||
|
||||
_, err := signAddVote(vals[i], vote, voteSet)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
commit := voteSet.MakeCommit()
|
||||
|
||||
chainID := voteSet.ChainID()
|
||||
voteSet2 := CommitToVoteSet(chainID, commit, valSet)
|
||||
assert.NotNil(t, voteSet2)
|
||||
}
|
||||
|
||||
func TestCommitToVoteSetWithNil(t *testing.T) {
|
||||
lastID := makeBlockIDRandom()
|
||||
height := int64(3)
|
||||
round := 1
|
||||
numValidators := 10
|
||||
|
||||
voteSet, valSet, vals := randVoteSet(height-1, 1, PrecommitType, numValidators, 1)
|
||||
|
||||
// > 2/3 sign for this block
|
||||
numBlockValidators := numValidators*2/3 + 1
|
||||
for i := 0; i < numBlockValidators; i++ {
|
||||
addr := vals[i].GetPubKey().Address()
|
||||
vote := &Vote{
|
||||
ValidatorAddress: addr,
|
||||
ValidatorIndex: i,
|
||||
Height: height - 1,
|
||||
Round: round,
|
||||
Type: PrecommitType,
|
||||
BlockID: lastID,
|
||||
Timestamp: tmtime.Now(),
|
||||
}
|
||||
|
||||
_, err := signAddVote(vals[i], vote, voteSet)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
// 1/3 vote for a nil block
|
||||
for i := numBlockValidators; i < numValidators; i++ {
|
||||
addr := vals[i].GetPubKey().Address()
|
||||
vote := &Vote{
|
||||
ValidatorAddress: addr,
|
||||
ValidatorIndex: i,
|
||||
Height: height - 1,
|
||||
Round: round,
|
||||
Type: PrecommitType,
|
||||
BlockID: BlockID{}, // "nil"
|
||||
Timestamp: tmtime.Now(),
|
||||
}
|
||||
|
||||
_, err := signAddVote(vals[i], vote, voteSet)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
commit := voteSet.MakeCommit()
|
||||
|
||||
chainID := voteSet.ChainID()
|
||||
voteSet2 := CommitToVoteSet(chainID, commit, valSet)
|
||||
assert.NotNil(t, voteSet2)
|
||||
}
|
||||
|
||||
func TestSignedHeaderValidateBasic(t *testing.T) {
|
||||
commit := randCommit()
|
||||
chainID := "𠜎"
|
||||
|
@ -41,7 +41,7 @@ func NewResultFromResponse(response *abci.ResponseDeliverTx) ABCIResult {
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes serializes the ABCIResponse using wire
|
||||
// Bytes serializes the ABCIResponse using amino
|
||||
func (a ABCIResults) Bytes() []byte {
|
||||
bz, err := cdc.MarshalBinaryLengthPrefixed(a)
|
||||
if err != nil {
|
||||
|
@ -20,7 +20,7 @@ const (
|
||||
// Must be a string because scripts like dist.sh read this file.
|
||||
// XXX: Don't change the name of this variable or you will break
|
||||
// automation :)
|
||||
TMCoreSemVer = "0.32.2"
|
||||
TMCoreSemVer = "0.32.3"
|
||||
|
||||
// ABCISemVer is the semantic version of the ABCI library
|
||||
ABCISemVer = "0.16.1"
|
||||
|
Reference in New Issue
Block a user