Compare commits

..

35 Commits

Author SHA1 Message Date
Callum Waters
2dd5a8303e lint 2022-08-08 16:46:40 +02:00
Callum Waters
bdda0ad33b chore: bump go to 1.18 (#9147) 2022-08-08 16:03:12 +02:00
Callum Waters
4be2e2266e add another test and port internal test factory 2022-08-06 21:09:45 +02:00
Callum Waters
35bb8e3f8b add tests 2022-08-06 19:40:06 +02:00
Callum Waters
8188ad3f90 Merge branch 'feature/abci++ppp' into cal/process_proposal 2022-08-06 19:39:53 +02:00
Callum Waters
b54253cada add process proposal test 2022-08-04 14:47:07 +02:00
Sergio Mena
b2409b3345 Follow-up fixes to main PrepareProposal implementation (#9162)
* -----start------

* [cherrypicked] state: panic on ResponsePrepareProposal validation error (#8145)

* state: panic on ResponsePrepareProposal validation error

* lint++

Co-authored-by: Sam Kleinman <garen@tychoish.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

* [cherrypicked] abci++: remove CheckTx call from PrepareProposal flow (#8176)

* [cherrypicked] abci++: correct max-size check to only operate on added and unmodified (#8242)

* [cherrypicked] Remove `ModifiedTxStatus` from the spec and the code (#8210)

* Outstanding abci-gen changes to 'pb.go' files

* Removed modified_tx_status from spec and protobufs

* Fix sed for OSX

* Regenerated abci protobufs with 'abci-proto-gen'

* Code changes. UTs e2e tests passing

* Recovered UT: TestPrepareProposalModifiedTxStatusFalse

* Adapted UT

* Fixed UT

* Revert "Fix sed for OSX"

This reverts commit e576708c61.

* Update internal/state/execution_test.go

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>

* Update abci/example/kvstore/kvstore.go

Co-authored-by: M. J. Fromberger <fromberger@interchain.io>

* Update internal/state/execution_test.go

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>

* Update spec/abci++/abci++_tmint_expected_behavior_002_draft.md

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>

* Addressed some comments

* Added one test that tests error at the ABCI client + Fixed some mock calls

* Addressed remaining comments

* Update abci/example/kvstore/kvstore.go

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>

* Update abci/example/kvstore/kvstore.go

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>

* Update abci/example/kvstore/kvstore.go

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>

* Update spec/abci++/abci++_tmint_expected_behavior_002_draft.md

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>

* Addressed William's latest comments

* Adressed Michael's comment

* Fixed UT

* Some md fixes

* More md fixes

* gofmt

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>
Co-authored-by: M. J. Fromberger <fromberger@interchain.io>

* make proto-gen

* Fixed testcase on PrepareProposal error

* mockery

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>
Co-authored-by: Sam Kleinman <garen@tychoish.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: M. J. Fromberger <fromberger@interchain.io>
2022-08-03 19:39:17 +02:00
Sergio Mena
d268e56383 Sync PrepareProposal with Spec. Main part (#9158)
* ----start----

* [PARTIAL cherry-pick] ABCI Vote Extension 2 (#6885)

* Cherry-picked #6567: state/types: refactor makeBlock, makeBlocks and makeTxs (#6567)

* [Cherrypicked] types: remove panic from block methods (#7501)

* [cherrypicked] abci++: synchronize PrepareProposal with the newest version of the spec (#8094)

This change implements the logic for the PrepareProposal ABCI++ method call. The main logic for creating and issuing the PrepareProposal request lives in execution.go and is tested in a set of new tests in execution_test.go. This change also updates the mempool mock to use a mockery generated version and removes much of the plumbing for the no longer used ABCIResponses.

* make proto-gen

* Backported EvidenceList's method ToABCI from #7961

* make build

* Fix mockery for Mempool

* mockery

* Backported abci Application mocks from #7961

* mockery2

* Fixed new PrepareProposal test cases in state/execution_test.go

* Fixed returned errors in consensus/state.go

* lint

* Addressed @cmwaters' comment

Co-authored-by: mconcat <monoidconcat@gmail.com>
Co-authored-by: JayT106 <JayT106@users.noreply.github.com>
Co-authored-by: Sam Kleinman <garen@tychoish.com>
Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>
2022-08-03 17:24:24 +02:00
Sergio Mena
2164883501 Old PrepareProposal and vote extension integration on feature/abci++ppp (#9117)
* abci: PrepareProposal-VoteExtension integration [2nd try] (#7821)

* PrepareProposal-VoteExtension integration (#6915)

* make proto-gen

* Fix protobuf crash in e2e nightly tests

* Update types/vote.go

Co-authored-by: M. J. Fromberger <fromberger@interchain.io>

* Addressed @creachadair's comments

Co-authored-by: mconcat <monoidconcat@gmail.com>
Co-authored-by: M. J. Fromberger <fromberger@interchain.io>

* Proto changes

* make proto-gen

* Fixed UTs

* bump

* lint

* lint2

* lint3

* lint4

* lint5

* lint6

* no_lint

Co-authored-by: mconcat <monoidconcat@gmail.com>
Co-authored-by: M. J. Fromberger <fromberger@interchain.io>
2022-08-03 13:29:15 +02:00
Sergio Mena
61619ab072 Update feature/abci++ppp branch with latest infra changes in main (#9157)
* Update CODEOWNERS to use teams (#9129)

* Update CODEOWNERS to use teams

Update the `CODEOWNERS` file to use the
@tendermint/tendermint-engineering and @tendermint/tendermint-research
teams as opposed to adding people one by one. This makes repository
administration somewhat easier to manage, especially when
onboarding/offboarding people.

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Add Ethan as superuser

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Prepare `main` to become new default branch (#9095)

* Update Makefile with changes from #7372

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Sync main GitHub config with master and update

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Remove unnecesary dot folders

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Sync dotfiles

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Remove unused Jepsen tests for now

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* tools: remove k8s (#6625)

Remove mintnet as discussed on team call.

closes #1941

* Restore nightly fuzz testing of P2P addrbook and pex

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Fix YAML lints

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Fix YAML formatting nits

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* More YAML nits

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* github: fix linter configuration errors and occluded errors (#6400)

* Minor fixes to OpenAPI spec to sync with structs on main

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Remove .github/auto-comment.yml - does not appear to be used

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Add issue config with link to discussions

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Adjust issue/PR templates to suit current process

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Remove unused RC branch config from release workflow

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Fix wildcard matching in build jobs config

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Document markdownlint config

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Restore manual E2E test group config

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Document linter workflow with local execution instructions

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Document and fix minor nit in Super-Linter markdownlint config

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Update .github/ISSUE_TEMPLATE/bug-report.md

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>

* Update pull request template to add language around discussions/issues

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* .golangci.yml: Deleted commented-out lines

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* ci: Drop "-2" from e2e-nightly-fail workflow

Signed-off-by: Thane Thomson <connect@thanethomson.com>

* Address triviality concern in PR template

Signed-off-by: Thane Thomson <connect@thanethomson.com>

Co-authored-by: Marko <marbar3778@yahoo.com>
Co-authored-by: Sam Kleinman <garen@tychoish.com>
Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>

Co-authored-by: Thane Thomson <connect@thanethomson.com>
Co-authored-by: Marko <marbar3778@yahoo.com>
Co-authored-by: Sam Kleinman <garen@tychoish.com>
Co-authored-by: William Banfield <4561443+williambanfield@users.noreply.github.com>
2022-08-03 11:06:54 +02:00
Callum Waters
227db0267b follow #7961 and complete process proposal to spec 2022-07-28 15:17:13 +02:00
Sergio Mena
d9d6a2f513 Proto-bufs for #7961 2022-07-28 10:38:28 +02:00
Sergio Mena
b2109ed922 mockery 2022-07-27 20:07:37 +02:00
Sergio Mena
b9cb5e3782 Added missing ProcessProposal in kvstore 2022-07-27 20:07:36 +02:00
Sergio Mena
14e85b220c make format 2022-07-27 20:07:19 +02:00
Sergio Mena
96ac25d5d3 Fixed base app 2022-07-27 20:07:03 +02:00
Sergio Mena
fe5c4a2b8e Addressed Callum's comments 2022-07-27 20:07:03 +02:00
Sergio Mena
e9d17d0e36 Addressed William's comment on ProcessProposal error 2022-07-27 20:07:03 +02:00
Sergio Mena
d6d61a3047 Re-renamed TwoThirdPrevote... to Valid... 2022-07-27 20:07:03 +02:00
Sergio Mena
fbf26c9a59 Adapt TestProcessProposal 2022-07-27 20:07:03 +02:00
Sergio Mena
bd8bbe86d4 Added missing ProcessProposal to socket_server.go 2022-07-27 20:07:02 +02:00
Sergio Mena
359f6af103 Fixed some UTs 2022-07-27 20:07:02 +02:00
Sergio Mena
b8ae6501e4 Fixed ProcessProposalSync 2022-07-27 20:07:02 +02:00
Sergio Mena
0a0812cce9 Fix ProcessProposalAsync 2022-07-27 20:07:02 +02:00
Sergio Mena
873b90867a make proto-gen 2022-07-27 20:07:02 +02:00
mconcat
5cc5110e9e Rebased and git-squashed the commits in PR #7091
add processproposal proto/boilerplate/logic

mockery

gofmt

fix test

gofmt

move UNKNOWN response behaviour to reject
2022-07-27 20:07:02 +02:00
JayT106
51f3118bd6 Cherry-picked #6567: state/types: refactor makeBlock, makeBlocks and makeTxs (#6567) 2022-07-27 20:07:02 +02:00
Sergio Mena
58effdd8b3 Old PrepareProposal on feature/abci++ppp (#9106)
* [Rebased to v0.34.x] abci: PrepareProposal (#6544)

* fixed cherry-pick

* proto changes

* make proto-gen

* UT fixes

* generate Client directive

* mockery

* App fixes

* Disable 'modified tx' hack

* mockery

* Make format

* Fix lint

Co-authored-by: Marko <marbar3778@yahoo.com>
2022-07-27 15:09:02 +02:00
Marko
46badfabd9 cli: add command to manually reindex tx and block events (backport: #6676) (#9034) 2022-07-22 16:37:08 +02:00
dependabot[bot]
eb465a3f4f build(deps): Bump github.com/golangci/golangci-lint (#9071)
Bumps [github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint) from 1.47.1 to 1.47.2.
- [Release notes](https://github.com/golangci/golangci-lint/releases)
- [Changelog](https://github.com/golangci/golangci-lint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/golangci/golangci-lint/compare/v1.47.1...v1.47.2)

---
updated-dependencies:
- dependency-name: github.com/golangci/golangci-lint
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-22 10:16:06 -04:00
dependabot[bot]
d6be59788b build(deps): Bump github.com/BurntSushi/toml from 1.1.0 to 1.2.0 (#9062)
Bumps [github.com/BurntSushi/toml](https://github.com/BurntSushi/toml) from 1.1.0 to 1.2.0.
- [Release notes](https://github.com/BurntSushi/toml/releases)
- [Commits](https://github.com/BurntSushi/toml/compare/v1.1.0...v1.2.0)

---
updated-dependencies:
- dependency-name: github.com/BurntSushi/toml
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-21 09:25:40 -04:00
dependabot[bot]
f9f3bed808 build(deps): Bump github.com/golangci/golangci-lint (#9043) 2022-07-20 12:26:25 +02:00
M. J. Fromberger
64dfeb775c mempool: rework lock discipline to mitigate callback deadlocks (backport #9030) (#9033)
(manual cherry-pick of commit 22ed610083)
2022-07-19 13:48:47 -07:00
dependabot[bot]
6688db7be1 build(deps): Bump github.com/golangci/golangci-lint (#9036)
Bumps [github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint) from 1.46.2 to 1.47.0.
- [Release notes](https://github.com/golangci/golangci-lint/releases)
- [Changelog](https://github.com/golangci/golangci-lint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/golangci/golangci-lint/compare/v1.46.2...v1.47.0)

---
updated-dependencies:
- dependency-name: github.com/golangci/golangci-lint
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-19 06:57:04 -07:00
M. J. Fromberger
d32df22c8b Prepare changelog for Release v0.34.20 (#9032) 2022-07-18 10:04:38 -07:00
327 changed files with 8250 additions and 3717 deletions

View File

@@ -1,168 +0,0 @@
version: 2.1
executors:
golang:
docker:
- image: tendermintdev/docker-tendermint-build
working_directory: /go/src/github.com/tendermint/tendermint
environment:
GOBIN: /tmp/bin
release:
machine: true
docs:
docker:
- image: tendermintdev/docker-website-deployment
environment:
AWS_REGION: us-east-1
commands:
run_test:
parameters:
script_path:
type: string
steps:
- attach_workspace:
at: /tmp/bin
- restore_cache:
name: "Restore source code cache"
keys:
- go-src-v1-{{ .Revision }}
- checkout
- restore_cache:
name: "Restore go modules cache"
keys:
- go-mod-v1-{{ checksum "go.sum" }}
- run:
name: "Running test"
command: |
bash << parameters.script_path >>
jobs:
setup_dependencies:
executor: golang
steps:
- checkout
- restore_cache:
name: "Restore go modules cache"
keys:
- go-mod-v1-{{ checksum "go.sum" }}
- run:
command: |
mkdir -p /tmp/bin
- run:
name: Cache go modules
command: make go-mod-cache
- run:
name: tools
command: make tools
- run:
name: "Build binaries"
command: make install install_abci
- save_cache:
name: "Save go modules cache"
key: go-mod-v1-{{ checksum "go.sum" }}
paths:
- "/go/pkg/mod"
- save_cache:
name: "Save source code cache"
key: go-src-v1-{{ .Revision }}
paths:
- ".git"
- persist_to_workspace:
root: "/tmp/bin"
paths:
- "."
deploy_docs:
executor: docs
steps:
- checkout
- run:
name: "Pull versions"
command: git fetch origin v0.32 v0.33
- run:
name: "Build docs"
command: make build-docs
- run:
name: "Sync to S3"
command: make sync-docs
prepare_build:
executor: golang
steps:
- restore_cache:
name: "Restore source code cache"
keys:
- go-src-v1-{{ .Revision }}
- checkout
- run:
name: Get next release number
command: |
export LAST_TAG="`git describe --tags --abbrev=0 --match "${CIRCLE_BRANCH}.*"`"
echo "Last tag: ${LAST_TAG}"
if [ -z "${LAST_TAG}" ]; then
export LAST_TAG="${CIRCLE_BRANCH}"
echo "Last tag not found. Possibly fresh branch or feature branch. Setting ${LAST_TAG} as tag."
fi
export NEXT_TAG="`python -u scripts/release_management/bump-semver.py --version "${LAST_TAG}"`"
echo "Next tag: ${NEXT_TAG}"
echo "export CIRCLE_TAG=\"${NEXT_TAG}\"" > release-version.source
- run:
name: Build dependencies
command: make tools
- persist_to_workspace:
root: .
paths:
- "release-version.source"
- save_cache:
key: v2-release-deps-{{ checksum "go.sum" }}
paths:
- "/go/pkg/mod"
# # 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
docs:
jobs:
- deploy_docs:
context: tendermint-docs
filters:
branches:
only:
- master
tags:
only:
- /^v.*/
- deploy_docs:
context: tendermint-docs-staging
filters:
branches:
only:
- docs-staging
# - contract_tests:
# requires:
# - setup_dependencies

4
.github/CODEOWNERS vendored
View File

@@ -7,4 +7,6 @@
# global owners are only requested if there isn't a more specific
# codeowner specified below. For this reason, the global codeowners
# are often repeated in package-level definitions.
* @ebuchman @cmwaters @tychoish @williambanfield @creachadair
* @ebuchman @tendermint/tendermint-engineering
/spec @ebuchman @tendermint/tendermint-research @tendermint/tendermint-engineering

View File

@@ -1,13 +1,18 @@
---
name: Bug Report
name: Bug report
about: Create a report to help us squash bugs!
---
<!--
Please fill in as much of the template below as you can.
Be ready for followup questions, and please respond in a timely
manner. We might ask you to provide additional logs and data (tendermint & app).
If you have general questions, please create a new discussion:
https://github.com/tendermint/tendermint/discussions
Be ready for followup questions, and please respond in a timely manner. We might
ask you to provide additional logs and data (tendermint & app).
-->
**Tendermint version** (use `tendermint version` or `git rev-parse --verify HEAD` if installed from source):

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: Ask a question
url: https://github.com/tendermint/tendermint/discussions
about: Please ask and answer questions here

View File

@@ -1,5 +1,5 @@
---
name: Feature Request
name: Feature request
about: Create a proposal to request a feature
---
@@ -25,12 +25,3 @@ Are there any disadvantages of including this feature? -->
## Proposal
<!-- Detailed description of requirements of implementation -->
____
#### For Admin Use
- [ ] Not duplicate issue
- [ ] Appropriate labels applied
- [ ] Appropriate contributors tagged
- [ ] Contributor assigned/self-assigned

28
.github/ISSUE_TEMPLATE/proposal.md vendored Normal file
View File

@@ -0,0 +1,28 @@
---
name: Protocol change proposal
about: Create a proposal to request a change to the protocol
---
<!-- < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < ☺
v ✰ Thanks for opening an issue! ✰
v Before smashing the submit button please review the template.
v Word of caution: Under-specified proposals may be rejected summarily
☺ > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -->
# Protocol Change Proposal
## Summary
<!-- Short, concise description of the proposed change -->
## Problem Definition
<!-- Why do we need this change?
What problems may be addressed by introducing this change?
What benefits does Tendermint stand to gain by including this change?
Are there any disadvantages of including this change? -->
## Proposal
<!-- Detailed description of requirements of implementation -->

View File

@@ -1,7 +1,32 @@
## Description
<!--
_Please add a description of the changes that this PR introduces and the files that
are the most critical to review._
Please add a reference to the issue that this PR addresses and indicate which
files are most critical to review. If it fully addresses a particular issue,
please include "Closes #XXX" (where "XXX" is the issue number).
Closes: #XXX
If this PR is non-trivial/large/complex, please ensure that you have either
created an issue that the team's had a chance to respond to, or had some
discussion with the team prior to submitting substantial pull requests. The team
can be reached via GitHub Discussions or the Cosmos Network Discord server in
the #tendermint-core channel. GitHub Discussions is preferred over Discord as it
allows us to keep track of conversations topically.
https://github.com/tendermint/tendermint/discussions
If the work in this PR is not aligned with the team's current priorities, please
be advised that it may take some time before it is merged - especially if it has
not yet been discussed with the team.
See the project board for the team's current priorities:
https://github.com/orgs/tendermint/projects/15/views/5
-->
---
#### PR checklist
- [ ] Tests written/updated, or no tests needed
- [ ] `CHANGELOG_PENDING.md` updated, or no changelog entry needed
- [ ] Updated relevant documentation (`docs/`) and code comments, or no
documentation updates needed

View File

@@ -1,16 +0,0 @@
pullRequestOpened: |
:wave: Thanks for creating a PR!
Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.
- [ ] Wrote tests
- [ ] Updated CHANGELOG_PENDING.md
- [ ] Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
- [ ] Updated relevant documentation (`docs/`) and code comments
- [ ] Re-reviewed `Files changed` in the Github PR explorer
- [ ] Applied Appropriate Labels
Thank you for your contribution to Tendermint! :rocket:

25
.github/codecov.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
coverage:
precision: 2
round: down
range: "70...100"
status:
project:
default:
threshold: 20%
patch: off
changes: off
github_checks:
annotations: false
comment: false
ignore:
- "docs"
- "DOCKER"
- "scripts"
- "**/*.pb.go"
- "libs/pubsub/query/query.peg.go"
- "*.md"
- "*.rst"
- "*.yml"

51
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
target-branch: "main"
open-pull-requests-limit: 10
labels:
- T:dependencies
- S:automerge
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
target-branch: "v0.34.x"
open-pull-requests-limit: 10
labels:
- T:dependencies
- S:automerge
- package-ecosystem: npm
directory: "/docs"
schedule:
interval: weekly
open-pull-requests-limit: 10
###################################
##
## Update All Go Dependencies
- package-ecosystem: gomod
directory: "/"
schedule:
interval: weekly
target-branch: "main"
open-pull-requests-limit: 10
labels:
- T:dependencies
- S:automerge
- package-ecosystem: gomod
directory: "/"
schedule:
interval: weekly
target-branch: "v0.34.x"
open-pull-requests-limit: 10
labels:
- T:dependencies
- S:automerge

6
.github/issue_template.md vendored Normal file
View File

@@ -0,0 +1,6 @@
<!--
If you want to ask a general question, please create a new discussion instead of
an issue: https://github.com/tendermint/tendermint/discussions
-->

15
.github/linters/markdownlint.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
# markdownlint configuration for Super-Linter
# - https://github.com/DavidAnson/markdownlint
# - https://github.com/github/super-linter
# Default state for all rules
default: true
# See https://github.com/DavidAnson/markdownlint#rules--aliases for rules
MD007: {"indent": 4}
MD013: false
MD024: {siblings_only: true}
MD025: false
MD033: {no-inline-html: false}
no-hard-tabs: false
whitespace: false

9
.github/linters/yaml-lint.yml vendored Normal file
View File

@@ -0,0 +1,9 @@
---
# Default rules for YAML linting from super-linter.
# See: See https://yamllint.readthedocs.io/en/stable/rules.html
extends: default
rules:
document-end: disable
document-start: disable
line-length: disable
truthy: disable

14
.github/mergify.yml vendored
View File

@@ -1,13 +1,13 @@
queue_rules:
- name: default
conditions:
- base=v0.34.x
- base=main
- label=S:automerge
pull_request_rules:
- name: Automerge to v0.34.x
- name: Automerge to main
conditions:
- base=v0.34.x
- base=main
- label=S:automerge
actions:
queue:
@@ -17,3 +17,11 @@ pull_request_rules:
{{ title }} (#{{ number }})
{{ body }}
- name: backport patches to v0.34.x branch
conditions:
- base=main
- label=S:backport-to-v0.34.x
actions:
backport:
branches:
- v0.34.x

82
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,82 @@
name: Build
# Tests runs different tests (test_abci_apps, test_abci_cli, test_apps)
# This workflow runs on every push to main or release branch and every pull requests
# All jobs will pass without running if no *{.go, .mod, .sum} files have been modified
on:
pull_request:
push:
branches:
- main
- release/**
jobs:
build:
name: Build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
goarch: ["arm", "amd64"]
goos: ["linux"]
timeout-minutes: 5
steps:
- uses: actions/setup-go@v3
with:
go-version: "1.18"
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/*.go
"!test/"
go.mod
go.sum
Makefile
- name: install
run: GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} make build
if: "env.GIT_DIFF != ''"
test_abci_cli:
runs-on: ubuntu-latest
needs: build
timeout-minutes: 5
steps:
- uses: actions/setup-go@v3
with:
go-version: "1.18"
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/*.go
go.mod
go.sum
- name: install
run: make install_abci
if: "env.GIT_DIFF != ''"
- run: abci/tests/test_cli/test.sh
shell: bash
if: "env.GIT_DIFF != ''"
test_apps:
runs-on: ubuntu-latest
needs: build
timeout-minutes: 5
steps:
- uses: actions/setup-go@v3
with:
go-version: "1.18"
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/*.go
go.mod
go.sum
- name: install
run: make install install_abci
if: "env.GIT_DIFF != ''"
- name: test_apps
run: test/app/test.sh
shell: bash
if: "env.GIT_DIFF != ''"

View File

@@ -18,7 +18,7 @@ jobs:
steps:
- uses: actions/setup-go@v3
with:
go-version: '1.17'
go-version: '1.18'
- uses: actions/checkout@v3
@@ -44,7 +44,7 @@ jobs:
steps:
- uses: actions/setup-go@v3
with:
go-version: '1.17'
go-version: '1.18'
- uses: actions/checkout@v3
with:

View File

@@ -1,123 +0,0 @@
name: Test Coverage
on:
pull_request:
push:
branches:
- master
- release/**
jobs:
split-test-files:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Create a file with all the pkgs
run: go list ./... > pkgs.txt
- name: Split pkgs into 4 files
run: split -d -n l/4 pkgs.txt pkgs.txt.part.
# cache multiple
- uses: actions/upload-artifact@v3
with:
name: "${{ github.sha }}-00"
path: ./pkgs.txt.part.00
- uses: actions/upload-artifact@v3
with:
name: "${{ github.sha }}-01"
path: ./pkgs.txt.part.01
- uses: actions/upload-artifact@v3
with:
name: "${{ github.sha }}-02"
path: ./pkgs.txt.part.02
- uses: actions/upload-artifact@v3
with:
name: "${{ github.sha }}-03"
path: ./pkgs.txt.part.03
build-linux:
name: Build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
goarch: ["arm", "amd64"]
timeout-minutes: 5
steps:
- uses: actions/setup-go@v3
with:
go-version: "^1.15.4"
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- name: install
run: GOOS=linux GOARCH=${{ matrix.goarch }} make build
if: "env.GIT_DIFF != ''"
tests:
runs-on: ubuntu-latest
needs: split-test-files
strategy:
fail-fast: false
matrix:
part: ["00", "01", "02", "03"]
steps:
- uses: actions/setup-go@v3
with:
go-version: "^1.15.4"
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- uses: actions/download-artifact@v3
with:
name: "${{ github.sha }}-${{ matrix.part }}"
if: env.GIT_DIFF
- name: test & coverage report creation
run: |
cat pkgs.txt.part.${{ matrix.part }} | xargs go test -mod=readonly -timeout 8m -race -coverprofile=${{ matrix.part }}profile.out -covermode=atomic
if: env.GIT_DIFF
- uses: actions/upload-artifact@v3
with:
name: "${{ github.sha }}-${{ matrix.part }}-coverage"
path: ./${{ matrix.part }}profile.out
upload-coverage-report:
runs-on: ubuntu-latest
needs: tests
steps:
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- uses: actions/download-artifact@v3
with:
name: "${{ github.sha }}-00-coverage"
if: env.GIT_DIFF
- uses: actions/download-artifact@v3
with:
name: "${{ github.sha }}-01-coverage"
if: env.GIT_DIFF
- uses: actions/download-artifact@v3
with:
name: "${{ github.sha }}-02-coverage"
if: env.GIT_DIFF
- uses: actions/download-artifact@v3
with:
name: "${{ github.sha }}-03-coverage"
if: env.GIT_DIFF
- run: |
cat ./*profile.out | grep -v "mode: atomic" >> coverage.txt
if: env.GIT_DIFF
- uses: codecov/codecov-action@v3
with:
file: ./coverage.txt
if: env.GIT_DIFF

View File

@@ -1,14 +1,13 @@
name: Build & Push
# Build & Push rebuilds the tendermint docker image on every push to master and creation of tags
# and pushes the image to https://hub.docker.com/r/interchainio/simapp/tags
name: Docker
# Build & Push rebuilds the Tendermint docker image on every push to main and creation of tags
# and pushes the image to https://hub.docker.com/r/tendermint/tendermint
on:
pull_request:
push:
branches:
- master
- main
tags:
- "v[0-9]+.[0-9]+.[0-9]+" # Push events to matching v*, i.e. v1.0, v20.15.10
- "v[0-9]+.[0-9]+.[0-9]+-rc*" # Push events to matching v*, i.e. v1.0-rc1, v20.15.10-rc5
- "v[0-9]+.[0-9]+.[0-9]+" # Push events to matching v*, i.e. v1.0, v20.15.10
- "v[0-9]+.[0-9]+.[0-9]+-rc*" # Push events to matching v*, i.e. v1.0-rc1, v20.15.10-rc5
jobs:
build:
@@ -39,18 +38,18 @@ jobs:
with:
platforms: all
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Set up Docker Build
uses: docker/setup-buildx-action@v2.0.0
- name: Login to DockerHub
if: ${{ github.event_name != 'pull_request' }}
uses: docker/login-action@v2
uses: docker/login-action@v2.0.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Publish to Docker Hub
uses: docker/build-push-action@v3
uses: docker/build-push-action@v3.1.0
with:
context: .
file: ./DOCKER/Dockerfile

62
.github/workflows/docs-deployment.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
# Build and deploy the docs.tendermint.com website content.
# The static content is published to GitHub Pages.
#
# For documentation build info, see docs/DOCS_README.md.
name: Build static documentation site
on:
workflow_dispatch: # allow manual updates
push:
branches:
- main
paths:
- docs/**
- spec/**
jobs:
# This is split into two jobs so that the build, which runs npm, does not
# have write access to anything. The deploy requires write access to publish
# to the branch used by GitHub Pages, however, so we can't just make the
# whole workflow read-only.
build:
name: VuePress build
runs-on: ubuntu-latest
container:
image: alpine:latest
permissions:
contents: read
steps:
- name: Install generator dependencies
run: |
apk add --no-cache make bash git npm
- uses: actions/checkout@v3
with:
# We need to fetch full history so the backport branches for previous
# versions will be available for the build.
fetch-depth: 0
- name: Build documentation
run: |
git config --global --add safe.directory "$PWD"
make build-docs
- uses: actions/upload-artifact@v3
with:
name: build-output
path: ~/output/
deploy:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
needs: build
permissions:
contents: write
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: build-output
path: ~/output
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: 'docs-tendermint-com'
folder: ~/output
single-commit: true

21
.github/workflows/docs-toc.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
# TODO(thane): Re-enable once we've pulled in the ADRs and RFCs from master.
# Verify that important design docs have ToC entries.
#name: Check documentation ToC
#on:
# pull_request:
# push:
# branches:
# - main
#
#jobs:
# check:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v3
# - uses: technote-space/get-diff-action@v6
# with:
# PATTERNS: |
# docs/architecture/**
# docs/rfc/**
# - run: ./docs/presubmit.sh
# if: env.GIT_DIFF

View File

@@ -1,4 +1,5 @@
# Manually run randomly generated E2E testnets (as nightly).
# Runs randomly generated E2E testnets nightly on main
# manually run e2e tests
name: e2e-manual
on:
workflow_dispatch:
@@ -16,7 +17,7 @@ jobs:
steps:
- uses: actions/setup-go@v3
with:
go-version: '1.17'
go-version: '1.18'
- uses: actions/checkout@v3
@@ -28,7 +29,7 @@ jobs:
- name: Generate testnets
working-directory: test/e2e
# When changing -g, also change the matrix groups above
run: ./build/generator -g 4 -d networks/nightly/
run: ./build/generator -g 5 -d networks/nightly/
- name: Run ${{ matrix.p2p }} p2p testnets
working-directory: test/e2e

View File

@@ -1,12 +1,10 @@
# Runs randomly generated E2E testnets nightly
# on the 0.34.x release branch
# Runs randomly generated E2E testnets nightly on the 0.34.x branch.
# !! If you change something in this file, you probably want
# to update the e2e-nightly-master workflow as well!
# !! This file should be kept in sync with the e2e-nightly-main.yml file,
# modulo changes to the version labels.
name: e2e-nightly-34x
on:
workflow_dispatch: # allow running workflow manually, in theory
schedule:
- cron: '0 2 * * *'
@@ -17,13 +15,13 @@ jobs:
strategy:
fail-fast: false
matrix:
group: ['00', '01', '02', '03']
group: ['00', '01', '02', '03', "04"]
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/setup-go@v3
with:
go-version: '^1.15.4'
go-version: '1.18'
- uses: actions/checkout@v3
with:
@@ -37,7 +35,7 @@ jobs:
- name: Generate testnets
working-directory: test/e2e
# When changing -g, also change the matrix groups above
run: ./build/generator -g 4 -d networks/nightly
run: ./build/generator -g 2 -d networks/nightly
- name: Run testnets in group ${{ matrix.group }}
working-directory: test/e2e
@@ -49,7 +47,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Notify Slack on failure
uses: rtCamp/action-slack-notify@f565a63638bd3615e76249bffab00fcb9dab90f7
uses: rtCamp/action-slack-notify@12e36fc18b0689399306c2e0b3e0f2978b7f1ee7
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_CHANNEL: tendermint-internal
@@ -58,19 +56,3 @@ jobs:
SLACK_COLOR: danger
SLACK_MESSAGE: Nightly E2E tests failed on v0.34.x
SLACK_FOOTER: ''
e2e-nightly-success: # may turn this off once they seem to pass consistently
needs: e2e-nightly-test
if: ${{ success() }}
runs-on: ubuntu-latest
steps:
- name: Notify Slack on success
uses: rtCamp/action-slack-notify@f565a63638bd3615e76249bffab00fcb9dab90f7
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_CHANNEL: tendermint-internal
SLACK_USERNAME: Nightly E2E Tests
SLACK_ICON_EMOJI: ':white_check_mark:'
SLACK_COLOR: good
SLACK_MESSAGE: Nightly E2E tests passed on v0.34.x
SLACK_FOOTER: ''

View File

@@ -1,73 +1,73 @@
# Runs randomly generated E2E testnets nightly on master
# Runs randomly generated E2E testnets nightly on main
# !! If you change something in this file, you probably want
# to update the e2e-nightly-34x workflow as well!
# !! Relevant changes to this file should be propagated to the e2e-nightly-<V>x
# files for the supported backport branches, when appropriate, modulo version
# markers.
name: e2e-nightly-master
name: e2e-nightly-main
on:
workflow_dispatch: # allow running workflow manually
schedule:
- cron: '0 2 * * *'
jobs:
e2e-nightly-test-2:
e2e-nightly-test:
# Run parallel jobs for the listed testnet groups (must match the
# ./build/generator -g flag)
strategy:
fail-fast: false
matrix:
group: ['00', '01', '02', '03']
group: ['00', '01', '02', '03', "04"]
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/setup-go@v3
with:
go-version: '1.15'
go-version: '1.18'
- uses: actions/checkout@v3
- name: Build
working-directory: test/e2e
# Run make jobs in parallel, since we can't run steps in parallel.
run: make -j2 docker generator runner
run: make -j2 docker generator runner tests
- name: Generate testnets
working-directory: test/e2e
# When changing -g, also change the matrix groups above
run: ./build/generator -g 4 -d networks/nightly
run: ./build/generator -g 5 -d networks/nightly/
- name: Run testnets in group ${{ matrix.group }}
- name: Run ${{ matrix.p2p }} p2p testnets
working-directory: test/e2e
run: ./run-multiple.sh networks/nightly/*-group${{ matrix.group }}-*.toml
e2e-nightly-fail-2:
needs: e2e-nightly-test-2
e2e-nightly-fail:
needs: e2e-nightly-test
if: ${{ failure() }}
runs-on: ubuntu-latest
steps:
- name: Notify Slack on failure
uses: rtCamp/action-slack-notify@f565a63638bd3615e76249bffab00fcb9dab90f7
uses: rtCamp/action-slack-notify@12e36fc18b0689399306c2e0b3e0f2978b7f1ee7
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_CHANNEL: tendermint-internal
SLACK_USERNAME: Nightly E2E Tests
SLACK_ICON_EMOJI: ':skull:'
SLACK_COLOR: danger
SLACK_MESSAGE: Nightly E2E tests failed on master
SLACK_MESSAGE: Nightly E2E tests failed on main
SLACK_FOOTER: ''
e2e-nightly-success: # may turn this off once they seem to pass consistently
needs: e2e-nightly-test-2
e2e-nightly-success: # may turn this off once they seem to pass consistently
needs: e2e-nightly-test
if: ${{ success() }}
runs-on: ubuntu-latest
steps:
- name: Notify Slack on success
uses: rtCamp/action-slack-notify@f565a63638bd3615e76249bffab00fcb9dab90f7
uses: rtCamp/action-slack-notify@12e36fc18b0689399306c2e0b3e0f2978b7f1ee7
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_CHANNEL: tendermint-internal
SLACK_USERNAME: Nightly E2E Tests
SLACK_ICON_EMOJI: ':white_check_mark:'
SLACK_COLOR: good
SLACK_MESSAGE: Nightly E2E tests passed on master
SLACK_MESSAGE: Nightly E2E tests passed on main
SLACK_FOOTER: ''

View File

@@ -1,11 +1,12 @@
name: e2e
# Runs the CI end-to-end test network on all pushes to master or release branches
# Runs the CI end-to-end test network on all pushes to main or release branches
# and every pull request, but only if any Go files have been changed.
on:
workflow_dispatch: # allow running workflow manually
pull_request:
push:
branches:
- master
- main
- release/**
jobs:
@@ -15,7 +16,7 @@ jobs:
steps:
- uses: actions/setup-go@v3
with:
go-version: '^1.15.4'
go-version: '1.18'
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
@@ -27,15 +28,10 @@ jobs:
- name: Build
working-directory: test/e2e
# Run two make jobs in parallel, since we can't run steps in parallel.
run: make -j2 docker runner
run: make -j2 docker runner tests
if: "env.GIT_DIFF != ''"
- name: Run CI testnet
working-directory: test/e2e
run: ./build/runner -f networks/ci.toml
run: ./run-multiple.sh networks/ci.toml
if: "env.GIT_DIFF != ''"
- name: Emit logs on failure
if: ${{ failure() }}
working-directory: test/e2e
run: ./build/runner -f networks/ci.toml logs

View File

@@ -1,9 +1,13 @@
# Runs fuzzing nightly.
name: fuzz-nightly
name: Fuzz Tests
on:
workflow_dispatch: # allow running workflow manually
workflow_dispatch: # allow running workflow manually
schedule:
- cron: '0 3 * * *'
pull_request:
branches: [main]
paths:
- "test/fuzz/**/*.go"
jobs:
fuzz-nightly-test:
@@ -11,13 +15,13 @@ jobs:
steps:
- uses: actions/setup-go@v3
with:
go-version: '1.15'
go-version: '1.18'
- uses: actions/checkout@v3
- name: Install go-fuzz
working-directory: test/fuzz
run: go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build
run: go install github.com/dvyukov/go-fuzz/go-fuzz@latest github.com/dvyukov/go-fuzz/go-fuzz-build@latest
- name: Fuzz mempool
working-directory: test/fuzz
@@ -49,14 +53,14 @@ jobs:
with:
name: crashers
path: test/fuzz/**/crashers
retention-days: 1
retention-days: 3
- name: Archive suppressions
uses: actions/upload-artifact@v3
with:
name: suppressions
path: test/fuzz/**/suppressions
retention-days: 1
retention-days: 3
- name: Set crashers count
working-directory: test/fuzz
@@ -72,7 +76,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Notify Slack if any crashers
uses: rtCamp/action-slack-notify@f565a63638bd3615e76249bffab00fcb9dab90f7
uses: rtCamp/action-slack-notify@12e36fc18b0689399306c2e0b3e0f2978b7f1ee7
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_CHANNEL: tendermint-internal

16
.github/workflows/janitor.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: Janitor
# Janitor cleans up previous runs of various workflows
# To add more workflows to cancel visit https://api.github.com/repos/tendermint/tendermint/actions/workflows and find the actions name
on:
pull_request:
jobs:
cancel:
name: "Cancel Previous Runs"
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- uses: styfle/cancel-workflow-action@0.10.0
with:
workflow_id: 1041851,1401230,2837803
access_token: ${{ github.token }}

View File

@@ -1,12 +0,0 @@
name: Check Markdown links
on:
schedule:
- cron: '* */24 * * *'
jobs:
markdown-link-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: creachadair/github-action-markdown-link-check@master
with:
folder-path: "docs"

View File

@@ -1,12 +1,18 @@
name: Lint
# Lint runs golangci-lint over the entire Tendermint repository
# This workflow is run on every pull request and push to master
# The `golangci` job will pass without running if no *.{go, mod, sum} files have been modified.
name: Golang Linter
# Lint runs golangci-lint over the entire Tendermint repository.
#
# This workflow is run on every pull request and push to main.
#
# The `golangci` job will pass without running if no *.{go, mod, sum}
# files have been modified.
#
# To run this locally, simply run `make lint` from the root of the repo.
on:
pull_request:
push:
branches:
- master
- main
jobs:
golangci:
name: golangci-lint
@@ -16,7 +22,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: '^1.16'
go-version: '1.18'
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
@@ -25,8 +31,10 @@ jobs:
go.sum
- uses: golangci/golangci-lint-action@v3
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.45
# Required: the version of golangci-lint is required and
# must be specified without patch version: we always use the
# latest patch version.
version: v1.47.3
args: --timeout 10m
github-token: ${{ secrets.github_token }}
if: env.GIT_DIFF

View File

@@ -1,14 +1,14 @@
name: Lint
name: Markdown Linter
on:
push:
branches:
- master
- main
paths:
- "**.md"
- "**.yml"
- "**.yaml"
pull_request:
branches: [master]
branches: [main]
paths:
- "**.md"
- "**.yml"
@@ -21,12 +21,12 @@ jobs:
- name: Checkout Code
uses: actions/checkout@v3
- name: Lint Code Base
uses: docker://github/super-linter:v3
uses: docker://github/super-linter:v4
env:
LINTER_RULES_PATH: .
VALIDATE_ALL_CODEBASE: true
DEFAULT_BRANCH: master
DEFAULT_BRANCH: main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VALIDATE_MD: true
VALIDATE_OPENAPI: true
VALIDATE_YAML: true
YAML_CONFIG_FILE: yaml-lint.yml

23
.github/workflows/markdown-links.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Check Markdown links
on:
push:
branches:
- main
pull_request:
branches: [main]
jobs:
markdown-link-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/**.md
- uses: creachadair/github-action-markdown-link-check@master
with:
check-modified-files-only: 'yes'
config-file: '.md-link-check.json'
if: env.GIT_DIFF

View File

@@ -5,7 +5,7 @@ on:
- 'proto/**'
push:
branches:
- v0.34.x
- main
paths:
- 'proto/**'

View File

@@ -1,22 +0,0 @@
name: Protobuf
# Protobuf runs buf (https://buf.build/) lint and check-breakage
# This workflow is only run when a .proto file has been modified
on:
pull_request:
paths:
- "**.proto"
jobs:
proto-lint:
runs-on: ubuntu-latest
timeout-minutes: 4
steps:
- uses: actions/checkout@v3
- name: lint
run: make proto-lint
proto-breakage:
runs-on: ubuntu-latest
timeout-minutes: 4
steps:
- uses: actions/checkout@v3
- name: check-breakage
run: make proto-check-breaking-ci

View File

@@ -3,7 +3,7 @@ name: "Release"
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+" # Push events to matching v*, i.e. v1.0, v20.15.10
- "v[0-9]+.[0-9]+.[0-9]+" # Push events to matching v*, i.e. v1.0, v20.15.10
jobs:
goreleaser:
@@ -16,12 +16,20 @@ jobs:
- uses: actions/setup-go@v3
with:
go-version: '^1.15.4'
go-version: '1.18'
- run: echo https://github.com/tendermint/tendermint/blob/${GITHUB_REF#refs/tags/}/CHANGELOG.md#${GITHUB_REF#refs/tags/} > ../release_notes.md
- name: Run GoReleaser
- name: Build
uses: goreleaser/goreleaser-action@v3
if: ${{ github.event_name == 'pull_request' }}
with:
version: latest
args: build --skip-validate # skip validate skips initial sanity checks in order to be able to fully run
- run: echo https://github.com/tendermint/tendermint/blob/${GITHUB_REF#refs/tags/}/CHANGELOG.md#${GITHUB_REF#refs/tags/} > ../release_notes.md
- name: Release
uses: goreleaser/goreleaser-action@v3
if: startsWith(github.ref, 'refs/tags/')
with:
version: latest
args: release --rm-dist --release-notes=../release_notes.md

View File

@@ -13,6 +13,8 @@ jobs:
stale-pr-message: "This pull request has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions."
days-before-stale: 10
days-before-close: 4
days-before-stale: -1
days-before-close: -1
days-before-pr-stale: 10
days-before-pr-close: 4
exempt-pr-labels: "S:wip"

View File

@@ -1,146 +1,34 @@
name: Tests
# Tests runs different tests (test_abci_apps, test_abci_cli, test_apps)
# This workflow runs on every push to master or release branch and every pull requests
# All jobs will pass without running if no *{.go, .mod, .sum} files have been modified
name: Test
on:
pull_request:
push:
paths:
- "**.go"
branches:
- master
- main
- release/**
jobs:
cleanup-runs:
tests:
runs-on: ubuntu-latest
steps:
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/master'"
build:
name: Build
runs-on: ubuntu-latest
timeout-minutes: 5
strategy:
fail-fast: false
matrix:
part: ["00", "01", "02", "03", "04", "05"]
steps:
- uses: actions/setup-go@v3
with:
go-version: "^1.15.4"
go-version: "1.18"
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/**.go
"!test/"
go.mod
go.sum
- name: install
run: make install install_abci
if: "env.GIT_DIFF != ''"
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
if: env.GIT_DIFF
# Cache binaries for use by other jobs
- uses: actions/cache@v3
with:
path: ~/go/bin
key: ${{ runner.os }}-${{ github.sha }}-tm-binary
if: env.GIT_DIFF
test_abci_apps:
runs-on: ubuntu-latest
needs: build
timeout-minutes: 5
steps:
- uses: actions/setup-go@v3
with:
go-version: "^1.15.4"
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
if: env.GIT_DIFF
- uses: actions/cache@v3
with:
path: ~/go/bin
key: ${{ runner.os }}-${{ github.sha }}-tm-binary
if: env.GIT_DIFF
- name: test_abci_apps
run: abci/tests/test_app/test.sh
shell: bash
if: env.GIT_DIFF
test_abci_cli:
runs-on: ubuntu-latest
needs: build
timeout-minutes: 5
steps:
- uses: actions/setup-go@v3
with:
go-version: "^1.15.4"
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
if: env.GIT_DIFF
- uses: actions/cache@v3
with:
path: ~/go/bin
key: ${{ runner.os }}-${{ github.sha }}-tm-binary
if: env.GIT_DIFF
- run: abci/tests/test_cli/test.sh
shell: bash
if: env.GIT_DIFF
test_apps:
runs-on: ubuntu-latest
needs: build
timeout-minutes: 5
steps:
- uses: actions/setup-go@v3
with:
go-version: "^1.15.4"
- uses: actions/checkout@v3
- uses: technote-space/get-diff-action@v6
with:
PATTERNS: |
**/**.go
go.mod
go.sum
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
if: env.GIT_DIFF
- uses: actions/cache@v3
with:
path: ~/go/bin
key: ${{ runner.os }}-${{ github.sha }}-tm-binary
if: env.GIT_DIFF
- name: test_apps
run: test/app/test.sh
shell: bash
Makefile
- name: Run Go Tests
run: |
make test-group-${{ matrix.part }} NUM_SPLIT=6
if: env.GIT_DIFF

68
.gitignore vendored
View File

@@ -1,58 +1,56 @@
*.swp
*.swo
.bak
*.bak
*.iml
*.swo
*.swp
*/.glide
*/vendor
.DS_Store
build/*
rpc/test/.tendermint
.tendermint
remote_dump
.bak
.idea/
.revision
vendor
.tendermint
.tendermint-lite
.terraform
.vagrant
test/e2e/build
test/maverick/maverick
test/e2e/networks/*/
test/p2p/data/
test/logs
.vendor-new/
.vscode/
abci/abci-cli
addrbook.json
artifacts/*
build/*
coverage.txt
docs/.vuepress/dist
docs/_build
docs/dist
docs/.vuepress/dist
*.log
abci-cli
docs/node_modules/
docs/spec
docs/.vuepress/public/rpc
index.html.md
scripts/wal2json/wal2json
scripts/cutWALUntil/cutWALUntil
.idea/
*.iml
.vscode/
libs/pubsub/query/fuzz_test/output
profile\.out
remote_dump
rpc/test/.tendermint
scripts/cutWALUntil/cutWALUntil
scripts/wal2json/wal2json
shunit2
.tendermint-lite
addrbook.json
*/vendor
.vendor-new/
*/.glide
.terraform
terraform.tfstate
terraform.tfstate.backup
terraform.tfstate.d
profile\.out
test/app/grpc_client
test/e2e/build
test/e2e/networks/*/
test/logs
test/maverick/maverick
test/p2p/data/
vendor
test/fuzz/**/corpus
test/fuzz/**/crashers
test/fuzz/**/suppressions
test/fuzz/**/*.zip
proto/spec/**/*.pb.go
*.aux
*.bbl
*.blg
*.log
*.pdf
*.gz
*.dvi

View File

@@ -8,14 +8,7 @@ linters:
- dupl
- errcheck
- exportloopref
# - funlen
# - gochecknoglobals
# - gochecknoinits
# - gocognit
- goconst
# - gocritic
# - gocyclo
# - godox
- gofmt
- goimports
- revive
@@ -23,48 +16,31 @@ linters:
- gosimple
- govet
- ineffassign
# - interfacer
- lll
# - maligned
# - misspell
- misspell
- nakedret
- nolintlint
- prealloc
- staticcheck
- structcheck
# - structcheck // to be fixed by golangci-lint
- stylecheck
# - typecheck
- typecheck
- unconvert
# - unparam
- unused
- varcheck
# - whitespace
# - wsl
issues:
exclude-rules:
- path: _test\.go
linters:
- gosec
- linters:
- lll
source: "https://"
max-same-issues: 50
linters-settings:
dogsled:
max-blank-identifiers: 3
maligned:
suggest-new: true
# govet:
# check-shadowing: true
revive:
golint:
min-confidence: 0
maligned:
suggest-new: true
misspell:
locale: US
ignore-words:
- behaviour

View File

@@ -5,7 +5,7 @@ env:
- GO111MODULE=on
builds:
- id: "Tendermint"
- id: "tendermint"
main: ./cmd/tendermint/main.go
ldflags:
- -s -w -X github.com/tendermint/tendermint/version.TMCoreSemVer={{ .Version }}
@@ -26,3 +26,11 @@ checksum:
release:
name_template: "{{.Version}} (WARNING: BETA SOFTWARE)"
archives:
- files:
- LICENSE
- README.md
- UPGRADING.md
- SECURITY.md
- CHANGELOG.md

View File

@@ -1,5 +1,12 @@
default: true,
MD007: { "indent": 4 }
# markdownlint configuration
# https://github.com/DavidAnson/markdownlint
# Default state for all rules
default: true
# See https://github.com/DavidAnson/markdownlint#rules--aliases for rules
MD001: false
MD007: {indent: 4}
MD013: false
MD024: { siblings_only: true }
MD025: false

6
.md-link-check.json Normal file
View File

@@ -0,0 +1,6 @@
{
"retryOn429": true,
"retryCount": 5,
"fallbackRetryDelay": "30s",
"aliveStatusCodes": [200, 206, 503]
}

View File

@@ -1,10 +0,0 @@
pull_request_rules:
- name: Automerge to master
conditions:
- base=master
- label=S:automerge
actions:
merge:
method: squash
strict: true
commit_message: title+body

View File

@@ -1,8 +0,0 @@
{
"protoc": {
"options": [
"--proto_path=${workspaceRoot}/proto",
"--proto_path=${workspaceRoot}/third_party/proto"
]
}
}

View File

@@ -2,21 +2,20 @@
Friendly reminder, we have a [bug bounty program](https://hackerone.com/cosmos).
## v0.34.20-rc1
## v0.34.20
Special thanks to external contributors on this release: @joeabbey @yihuang
This release introduces a prioritized mempool. Further notes can be found in UPGRADING.md.
NOTE: There's a known issue when combining the prioritized mempool with the ABCI socket client, that the team are curently working to resolve. Read more about the issue [here](https://github.com/tendermint/tendermint/pull/9030).
### BUG FIXES
- [blocksync] [\#8496](https://github.com/tendermint/tendermint/pull/8496) validate block against state before persisting it to disk (@cmwaters)
- [indexer] [#8625](https://github.com/tendermint/tendermint/pull/8625) Fix overriding tx index of duplicated txs. (@yihuang)
- [mempool] [\#8962](https://github.com/tendermint/tendermint/issues/8962) Backport priority mempool fixes from v0.35.x to v0.34.x (@creachadair).
## v0.34.20-rc0
This RC introduces the prioritized mempool.
NOTE: There's a known memory leak with the prioritized mempool that the team are currently working on resolving. We will cut v0.34.20 when this has been resolved. This release candidate is to provide the SDK with the new APIs. Read more about the issue [here](https://github.com/tendermint/tendermint/issues/8775)
### FEATURES
- [cli] [\#8674] Add command to force compact goleveldb databases (@cmwaters)
@@ -26,10 +25,6 @@ NOTE: There's a known memory leak with the prioritized mempool that the team are
- [logging] [\#8845](https://github.com/tendermint/tendermint/issues/8845) Add "Lazy" Stringers to defer Sprintf and Hash until logs print. (@joeabbey)
### BUG FIXES
- [blocksync] [\#8496](https://github.com/tendermint/tendermint/pull/8496) validate block against state before persisting it to disk (@cmwaters)
## v0.34.19
### BUG FIXES

View File

@@ -1,6 +1,6 @@
# Unreleased Changes
## v0.34.20
## v0.34.21
Special thanks to external contributors on this release:
@@ -20,6 +20,8 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
### FEATURES
- [#9083] backport cli command to reindex missed events (@cmwaters)
### IMPROVEMENTS
### BUG FIXES

View File

@@ -1,5 +1,6 @@
PACKAGES=$(shell go list ./...)
OUTPUT?=build/tendermint
BUILDDIR?=$(CURDIR)/build
OUTPUT?=$(BUILDDIR)/tendermint
BUILD_TAGS?=tendermint
@@ -286,3 +287,25 @@ endif
contract-tests:
dredd
.PHONY: contract-tests
# Implements test splitting and running. This is pulled directly from
# the github action workflows for better local reproducibility.
GO_TEST_FILES != find $(CURDIR) -name "*_test.go"
# default to four splits by default
NUM_SPLIT ?= 4
$(BUILDDIR):
mkdir -p $@
# The format statement filters out all packages that don't have tests.
# Note we need to check for both in-package tests (.TestGoFiles) and
# out-of-package tests (.XTestGoFiles).
$(BUILDDIR)/packages.txt:$(GO_TEST_FILES) $(BUILDDIR)
go list -f "{{ if (or .TestGoFiles .XTestGoFiles) }}{{ .ImportPath }}{{ end }}" ./... | sort > $@
split-test-packages:$(BUILDDIR)/packages.txt
split -d -n l/$(NUM_SPLIT) $< $<.
test-group-%:split-test-packages
cat $(BUILDDIR)/packages.txt.$* | xargs go test -mod=readonly -timeout=5m -race -coverprofile=$(BUILDDIR)/$*.profile.out

View File

@@ -51,7 +51,7 @@ to notify you of vulnerabilities and fixes in Tendermint Core. You can subscribe
| Requirement | Notes |
| ----------- | ---------------- |
| Go version | Go1.15 or higher |
| Go version | Go1.18 or higher |
## Documentation

View File

@@ -2,13 +2,28 @@
This guide provides instructions for upgrading to specific versions of Tendermint Core.
## v0.34.20
### Feature: Priority Mempool
This release backports an implementation of the Priority Mempool from the v0.35
branch. This implementation of the mempool permits the application to set a
priority on each transaction during CheckTx, and during block selection the
highest-priority transactions are chosen (subject to the constraints on size
and gas cost).
Operators can enable the priority mempool by setting `mempool.version` to
`"v1"` in the `config.toml`. For more technical details about the priority
mempool, see [ADR 067: Mempool
Refactor](https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-067-mempool-refactor.md).
## v0.34.0
**Upgrading to Tendermint 0.34 requires a blockchain restart.**
This release is not compatible with previous blockchains due to changes to
the encoding format (see "Protocol Buffers," below) and the block header (see "Blockchain Protocol").
Note also that Tendermint 0.34 also requires Go 1.15 or higher.
Note also that Tendermint 0.34 also requires Go 1.15 or higher.
### ABCI Changes
@@ -112,7 +127,7 @@ Tendermint 0.34 includes new and updated consensus parameters.
#### Evidence Parameters
* `MaxBytes`, which caps the total amount of evidence. The default is 1048576 (1 MB).
* `MaxBytes`, which caps the total amount of evidence. The default is 1048576 (1 MB).
### Crypto
@@ -188,7 +203,7 @@ blockchains, we recommend that you check the chain ID.
### Version
Version is now set through Go linker flags `ld_flags`. Applications that are using tendermint as a library should set this at compile time.
Version is now set through Go linker flags `ld_flags`. Applications that are using tendermint as a library should set this at compile time.
Example:
@@ -196,7 +211,7 @@ Example:
go install -mod=readonly -ldflags "-X github.com/tendermint/tendermint/version.TMCoreSemVer=$(go list -m github.com/tendermint/tendermint | sed 's/ /\@/g') -s -w " -trimpath ./cmd
```
Additionally, the exported constant `version.Version` is now `version.TMCoreSemVer`.
Additionally, the exported constant `version.Version` is now `version.TMCoreSemVer`.
## v0.33.4

View File

@@ -14,6 +14,8 @@ const (
echoRetryIntervalSeconds = 1
)
//go:generate mockery --case underscore --name Client
// Client defines an interface for an ABCI client.
// All `Async` methods return a `ReqRes` object.
// All `Sync` methods return the appropriate protobuf ResponseXxx struct and an error.
@@ -34,12 +36,14 @@ type Client interface {
QueryAsync(types.RequestQuery) *ReqRes
CommitAsync() *ReqRes
InitChainAsync(types.RequestInitChain) *ReqRes
PrepareProposalAsync(types.RequestPrepareProposal) *ReqRes
BeginBlockAsync(types.RequestBeginBlock) *ReqRes
EndBlockAsync(types.RequestEndBlock) *ReqRes
ListSnapshotsAsync(types.RequestListSnapshots) *ReqRes
OfferSnapshotAsync(types.RequestOfferSnapshot) *ReqRes
LoadSnapshotChunkAsync(types.RequestLoadSnapshotChunk) *ReqRes
ApplySnapshotChunkAsync(types.RequestApplySnapshotChunk) *ReqRes
ProcessProposalAsync(types.RequestProcessProposal) *ReqRes
FlushSync() error
EchoSync(msg string) (*types.ResponseEcho, error)
@@ -50,12 +54,14 @@ type Client interface {
QuerySync(types.RequestQuery) (*types.ResponseQuery, error)
CommitSync() (*types.ResponseCommit, error)
InitChainSync(types.RequestInitChain) (*types.ResponseInitChain, error)
PrepareProposalSync(types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error)
BeginBlockSync(types.RequestBeginBlock) (*types.ResponseBeginBlock, error)
EndBlockSync(types.RequestEndBlock) (*types.ResponseEndBlock, error)
ListSnapshotsSync(types.RequestListSnapshots) (*types.ResponseListSnapshots, error)
OfferSnapshotSync(types.RequestOfferSnapshot) (*types.ResponseOfferSnapshot, error)
LoadSnapshotChunkSync(types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error)
ApplySnapshotChunkSync(types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error)
ProcessProposalSync(types.RequestProcessProposal) (*types.ResponseProcessProposal, error)
}
//----------------------------------------

View File

@@ -300,6 +300,25 @@ func (cli *grpcClient) ApplySnapshotChunkAsync(params types.RequestApplySnapshot
return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_ApplySnapshotChunk{ApplySnapshotChunk: res}})
}
func (cli *grpcClient) PrepareProposalAsync(params types.RequestPrepareProposal) *ReqRes {
req := types.ToRequestPrepareProposal(params)
res, err := cli.client.PrepareProposal(context.Background(), req.GetPrepareProposal(), grpc.WaitForReady(true))
if err != nil {
cli.StopForError(err)
}
return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_PrepareProposal{PrepareProposal: res}})
}
func (cli *grpcClient) ProcessProposalAsync(params types.RequestProcessProposal) *ReqRes {
req := types.ToRequestProcessProposal(params)
res, err := cli.client.ProcessProposal(context.Background(), req.GetProcessProposal(), grpc.WaitForReady(true))
if err != nil {
cli.StopForError(err)
}
return cli.finishAsyncCall(req, &types.Response{Value: &types.Response_ProcessProposal{ProcessProposal: res}})
}
// finishAsyncCall creates a ReqRes for an async call, and immediately populates it
// with the response. We don't complete it until it's been ordered via the channel.
func (cli *grpcClient) finishAsyncCall(req *types.Request, res *types.Response) *ReqRes {
@@ -417,3 +436,14 @@ func (cli *grpcClient) ApplySnapshotChunkSync(
reqres := cli.ApplySnapshotChunkAsync(params)
return cli.finishSyncCall(reqres).GetApplySnapshotChunk(), cli.Error()
}
func (cli *grpcClient) PrepareProposalSync(
params types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) {
reqres := cli.PrepareProposalAsync(params)
return cli.finishSyncCall(reqres).GetPrepareProposal(), cli.Error()
}
func (cli *grpcClient) ProcessProposalSync(params types.RequestProcessProposal) (*types.ResponseProcessProposal, error) {
reqres := cli.ProcessProposalAsync(params)
return cli.finishSyncCall(reqres).GetProcessProposal(), cli.Error()
}

View File

@@ -207,6 +207,28 @@ func (app *localClient) ApplySnapshotChunkAsync(req types.RequestApplySnapshotCh
)
}
func (app *localClient) PrepareProposalAsync(req types.RequestPrepareProposal) *ReqRes {
app.mtx.Lock()
defer app.mtx.Unlock()
res := app.Application.PrepareProposal(req)
return app.callback(
types.ToRequestPrepareProposal(req),
types.ToResponsePrepareProposal(res),
)
}
func (app *localClient) ProcessProposalAsync(req types.RequestProcessProposal) *ReqRes {
app.mtx.Lock()
defer app.mtx.Unlock()
res := app.Application.ProcessProposal(req)
return app.callback(
types.ToRequestProcessProposal(req),
types.ToResponseProcessProposal(res),
)
}
//-------------------------------------------------------
func (app *localClient) FlushSync() error {
@@ -323,6 +345,22 @@ func (app *localClient) ApplySnapshotChunkSync(
return &res, nil
}
func (app *localClient) PrepareProposalSync(req types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) {
app.mtx.Lock()
defer app.mtx.Unlock()
res := app.Application.PrepareProposal(req)
return &res, nil
}
func (app *localClient) ProcessProposalSync(req types.RequestProcessProposal) (*types.ResponseProcessProposal, error) {
app.mtx.Lock()
defer app.mtx.Unlock()
res := app.Application.ProcessProposal(req)
return &res, nil
}
//-------------------------------------------------------
func (app *localClient) callback(req *types.Request, res *types.Response) *ReqRes {

View File

@@ -1,4 +1,4 @@
// Code generated by mockery v1.1.1. DO NOT EDIT.
// Code generated by mockery v2.14.0. DO NOT EDIT.
package mocks
@@ -575,6 +575,84 @@ func (_m *Client) OnStop() {
_m.Called()
}
// PrepareProposalAsync provides a mock function with given fields: _a0
func (_m *Client) PrepareProposalAsync(_a0 types.RequestPrepareProposal) *abcicli.ReqRes {
ret := _m.Called(_a0)
var r0 *abcicli.ReqRes
if rf, ok := ret.Get(0).(func(types.RequestPrepareProposal) *abcicli.ReqRes); ok {
r0 = rf(_a0)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*abcicli.ReqRes)
}
}
return r0
}
// PrepareProposalSync provides a mock function with given fields: _a0
func (_m *Client) PrepareProposalSync(_a0 types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) {
ret := _m.Called(_a0)
var r0 *types.ResponsePrepareProposal
if rf, ok := ret.Get(0).(func(types.RequestPrepareProposal) *types.ResponsePrepareProposal); ok {
r0 = rf(_a0)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponsePrepareProposal)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(types.RequestPrepareProposal) error); ok {
r1 = rf(_a0)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// ProcessProposalAsync provides a mock function with given fields: _a0
func (_m *Client) ProcessProposalAsync(_a0 types.RequestProcessProposal) *abcicli.ReqRes {
ret := _m.Called(_a0)
var r0 *abcicli.ReqRes
if rf, ok := ret.Get(0).(func(types.RequestProcessProposal) *abcicli.ReqRes); ok {
r0 = rf(_a0)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*abcicli.ReqRes)
}
}
return r0
}
// ProcessProposalSync provides a mock function with given fields: _a0
func (_m *Client) ProcessProposalSync(_a0 types.RequestProcessProposal) (*types.ResponseProcessProposal, error) {
ret := _m.Called(_a0)
var r0 *types.ResponseProcessProposal
if rf, ok := ret.Get(0).(func(types.RequestProcessProposal) *types.ResponseProcessProposal); ok {
r0 = rf(_a0)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*types.ResponseProcessProposal)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(types.RequestProcessProposal) error); ok {
r1 = rf(_a0)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// QueryAsync provides a mock function with given fields: _a0
func (_m *Client) QueryAsync(_a0 types.RequestQuery) *abcicli.ReqRes {
ret := _m.Called(_a0)
@@ -734,3 +812,18 @@ func (_m *Client) String() string {
return r0
}
type mockConstructorTestingTNewClient interface {
mock.TestingT
Cleanup(func())
}
// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewClient(t mockConstructorTestingTNewClient) *Client {
mock := &Client{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

View File

@@ -279,6 +279,14 @@ func (cli *socketClient) ApplySnapshotChunkAsync(req types.RequestApplySnapshotC
return cli.queueRequest(types.ToRequestApplySnapshotChunk(req))
}
func (cli *socketClient) PrepareProposalAsync(req types.RequestPrepareProposal) *ReqRes {
return cli.queueRequest(types.ToRequestPrepareProposal(req))
}
func (cli *socketClient) ProcessProposalAsync(req types.RequestProcessProposal) *ReqRes {
return cli.queueRequest(types.ToRequestProcessProposal(req))
}
//----------------------------------------
func (cli *socketClient) FlushSync() error {
@@ -417,6 +425,24 @@ func (cli *socketClient) ApplySnapshotChunkSync(
return reqres.Response.GetApplySnapshotChunk(), cli.Error()
}
func (cli *socketClient) PrepareProposalSync(req types.RequestPrepareProposal) (*types.ResponsePrepareProposal, error) {
reqres := cli.queueRequest(types.ToRequestPrepareProposal(req))
if err := cli.FlushSync(); err != nil {
return nil, err
}
return reqres.Response.GetPrepareProposal(), cli.Error()
}
func (cli *socketClient) ProcessProposalSync(req types.RequestProcessProposal) (*types.ResponseProcessProposal, error) {
reqres := cli.queueRequest(types.ToRequestProcessProposal(req))
if err := cli.FlushSync(); err != nil {
return nil, err
}
return reqres.Response.GetProcessProposal(), cli.Error()
}
//----------------------------------------
func (cli *socketClient) queueRequest(req *types.Request) *ReqRes {
@@ -492,6 +518,10 @@ func resMatchesReq(req *types.Request, res *types.Response) (ok bool) {
_, ok = res.Value.(*types.Response_ListSnapshots)
case *types.Request_OfferSnapshot:
_, ok = res.Value.(*types.Response_OfferSnapshot)
case *types.Request_PrepareProposal:
_, ok = res.Value.(*types.Response_PrepareProposal)
case *types.Request_ProcessProposal:
_, ok = res.Value.(*types.Response_ProcessProposal)
}
return ok
}

View File

@@ -170,3 +170,13 @@ func (app *Application) Query(reqQuery types.RequestQuery) (resQuery types.Respo
return resQuery
}
func (app *Application) ProcessProposal(
req types.RequestProcessProposal) types.ResponseProcessProposal {
for _, tx := range req.Txs {
if len(tx) == 0 {
return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_REJECT}
}
}
return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_ACCEPT}
}

View File

@@ -76,6 +76,10 @@ func (app *PersistentKVStoreApplication) DeliverTx(req types.RequestDeliverTx) t
return app.execValidatorTx(req.Tx)
}
if isPrepareTx(req.Tx) {
return app.execPrepareTx(req.Tx)
}
// otherwise, update the key-value store
return app.app.DeliverTx(req)
}
@@ -170,6 +174,21 @@ func (app *PersistentKVStoreApplication) ApplySnapshotChunk(
return types.ResponseApplySnapshotChunk{Result: types.ResponseApplySnapshotChunk_ABORT}
}
func (app *PersistentKVStoreApplication) PrepareProposal(
req types.RequestPrepareProposal) types.ResponsePrepareProposal {
return types.ResponsePrepareProposal{TxRecords: app.substPrepareTx(req.Txs, req.MaxTxBytes)}
}
func (app *PersistentKVStoreApplication) ProcessProposal(
req types.RequestProcessProposal) types.ResponseProcessProposal {
for _, tx := range req.Txs {
if len(tx) == 0 {
return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_REJECT}
}
}
return types.ResponseProcessProposal{Status: types.ResponseProcessProposal_ACCEPT}
}
//---------------------------------------------
// update validators
@@ -284,3 +303,50 @@ func (app *PersistentKVStoreApplication) updateValidator(v types.ValidatorUpdate
return types.ResponseDeliverTx{Code: code.CodeTypeOK}
}
// -----------------------------
const PreparePrefix = "prepare"
func isPrepareTx(tx []byte) bool {
return bytes.HasPrefix(tx, []byte(PreparePrefix))
}
// execPrepareTx is noop. tx data is considered as placeholder
// and is substitute at the PrepareProposal.
func (app *PersistentKVStoreApplication) execPrepareTx(tx []byte) types.ResponseDeliverTx {
// noop
return types.ResponseDeliverTx{}
}
// substPrepareTx substitutes all the transactions prefixed with 'prepare' in the
// proposal for transactions with the prefix stripped.
// It marks all of the original transactions as 'REMOVED' so that
// Tendermint will remove them from its mempool.
func (app *PersistentKVStoreApplication) substPrepareTx(blockData [][]byte, maxTxBytes int64) []*types.TxRecord {
trs := make([]*types.TxRecord, 0, len(blockData))
var removed []*types.TxRecord
var totalBytes int64
for _, tx := range blockData {
txMod := tx
action := types.TxRecord_UNMODIFIED
if isPrepareTx(tx) {
removed = append(removed, &types.TxRecord{
Tx: tx,
Action: types.TxRecord_REMOVED,
})
txMod = bytes.TrimPrefix(tx, []byte(PreparePrefix))
action = types.TxRecord_ADDED
}
totalBytes += int64(len(txMod))
if totalBytes > maxTxBytes {
break
}
trs = append(trs, &types.TxRecord{
Tx: txMod,
Action: action,
})
}
return append(trs, removed...)
}

View File

@@ -230,6 +230,12 @@ func (s *SocketServer) handleRequest(req *types.Request, responses chan<- *types
case *types.Request_OfferSnapshot:
res := s.app.OfferSnapshot(*r.OfferSnapshot)
responses <- types.ToResponseOfferSnapshot(res)
case *types.Request_PrepareProposal:
res := s.app.PrepareProposal(*r.PrepareProposal)
responses <- types.ToResponsePrepareProposal(res)
case *types.Request_ProcessProposal:
res := s.app.ProcessProposal(*r.ProcessProposal)
responses <- types.ToResponseProcessProposal(res)
case *types.Request_LoadSnapshotChunk:
res := s.app.LoadSnapshotChunk(*r.LoadSnapshotChunk)
responses <- types.ToResponseLoadSnapshotChunk(res)

View File

@@ -4,6 +4,8 @@ import (
context "golang.org/x/net/context"
)
//go:generate ../../scripts/mockery_generate.sh Application
// Application is an interface that enables any finite, deterministic state machine
// to be driven by a blockchain-based replication engine via the ABCI.
// All methods take a RequestXxx argument and return a ResponseXxx argument,
@@ -18,7 +20,9 @@ type Application interface {
CheckTx(RequestCheckTx) ResponseCheckTx // Validate a tx for the mempool
// Consensus Connection
InitChain(RequestInitChain) ResponseInitChain // Initialize blockchain w validators/other info from TendermintCore
InitChain(RequestInitChain) ResponseInitChain // Initialize blockchain w validators/other info from TendermintCore
PrepareProposal(RequestPrepareProposal) ResponsePrepareProposal
ProcessProposal(RequestProcessProposal) ResponseProcessProposal
BeginBlock(RequestBeginBlock) ResponseBeginBlock // Signals the beginning of a block
DeliverTx(RequestDeliverTx) ResponseDeliverTx // Deliver a tx for full processing
EndBlock(RequestEndBlock) ResponseEndBlock // Signals the end of a block, returns changes to the validator set
@@ -95,6 +99,27 @@ func (BaseApplication) ApplySnapshotChunk(req RequestApplySnapshotChunk) Respons
return ResponseApplySnapshotChunk{}
}
func (BaseApplication) PrepareProposal(req RequestPrepareProposal) ResponsePrepareProposal {
trs := make([]*TxRecord, 0, len(req.Txs))
var totalBytes int64
for _, tx := range req.Txs {
totalBytes += int64(len(tx))
if totalBytes > req.MaxTxBytes {
break
}
trs = append(trs, &TxRecord{
Action: TxRecord_UNMODIFIED,
Tx: tx,
})
}
return ResponsePrepareProposal{TxRecords: trs}
}
func (BaseApplication) ProcessProposal(req RequestProcessProposal) ResponseProcessProposal {
return ResponseProcessProposal{
Status: ResponseProcessProposal_ACCEPT}
}
//-------------------------------------------------------
// GRPCApplication is a GRPC wrapper for Application
@@ -182,3 +207,15 @@ func (app *GRPCApplication) ApplySnapshotChunk(
res := app.app.ApplySnapshotChunk(*req)
return &res, nil
}
func (app *GRPCApplication) PrepareProposal(
ctx context.Context, req *RequestPrepareProposal) (*ResponsePrepareProposal, error) {
res := app.app.PrepareProposal(*req)
return &res, nil
}
func (app *GRPCApplication) ProcessProposal(
ctx context.Context, req *RequestProcessProposal) (*ResponseProcessProposal, error) {
res := app.app.ProcessProposal(*req)
return &res, nil
}

View File

@@ -159,6 +159,18 @@ func ToRequestApplySnapshotChunk(req RequestApplySnapshotChunk) *Request {
}
}
func ToRequestPrepareProposal(req RequestPrepareProposal) *Request {
return &Request{
Value: &Request_PrepareProposal{&req},
}
}
func ToRequestProcessProposal(req RequestProcessProposal) *Request {
return &Request{
Value: &Request_ProcessProposal{&req},
}
}
//----------------------------------------
func ToResponseException(errStr string) *Response {
@@ -256,3 +268,15 @@ func ToResponseApplySnapshotChunk(res ResponseApplySnapshotChunk) *Response {
Value: &Response_ApplySnapshotChunk{&res},
}
}
func ToResponsePrepareProposal(res ResponsePrepareProposal) *Response {
return &Response{
Value: &Response_PrepareProposal{&res},
}
}
func ToResponseProcessProposal(res ResponseProcessProposal) *Response {
return &Response{
Value: &Response_ProcessProposal{&res},
}
}

View File

@@ -0,0 +1,238 @@
// Code generated by mockery. DO NOT EDIT.
package mocks
import (
mock "github.com/stretchr/testify/mock"
types "github.com/tendermint/tendermint/abci/types"
)
// Application is an autogenerated mock type for the Application type
type Application struct {
mock.Mock
}
// ApplySnapshotChunk provides a mock function with given fields: _a0
func (_m *Application) ApplySnapshotChunk(_a0 types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk {
ret := _m.Called(_a0)
var r0 types.ResponseApplySnapshotChunk
if rf, ok := ret.Get(0).(func(types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseApplySnapshotChunk)
}
return r0
}
// BeginBlock provides a mock function with given fields: _a0
func (_m *Application) BeginBlock(_a0 types.RequestBeginBlock) types.ResponseBeginBlock {
ret := _m.Called(_a0)
var r0 types.ResponseBeginBlock
if rf, ok := ret.Get(0).(func(types.RequestBeginBlock) types.ResponseBeginBlock); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseBeginBlock)
}
return r0
}
// CheckTx provides a mock function with given fields: _a0
func (_m *Application) CheckTx(_a0 types.RequestCheckTx) types.ResponseCheckTx {
ret := _m.Called(_a0)
var r0 types.ResponseCheckTx
if rf, ok := ret.Get(0).(func(types.RequestCheckTx) types.ResponseCheckTx); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseCheckTx)
}
return r0
}
// Commit provides a mock function with given fields:
func (_m *Application) Commit() types.ResponseCommit {
ret := _m.Called()
var r0 types.ResponseCommit
if rf, ok := ret.Get(0).(func() types.ResponseCommit); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(types.ResponseCommit)
}
return r0
}
// DeliverTx provides a mock function with given fields: _a0
func (_m *Application) DeliverTx(_a0 types.RequestDeliverTx) types.ResponseDeliverTx {
ret := _m.Called(_a0)
var r0 types.ResponseDeliverTx
if rf, ok := ret.Get(0).(func(types.RequestDeliverTx) types.ResponseDeliverTx); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseDeliverTx)
}
return r0
}
// EndBlock provides a mock function with given fields: _a0
func (_m *Application) EndBlock(_a0 types.RequestEndBlock) types.ResponseEndBlock {
ret := _m.Called(_a0)
var r0 types.ResponseEndBlock
if rf, ok := ret.Get(0).(func(types.RequestEndBlock) types.ResponseEndBlock); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseEndBlock)
}
return r0
}
// Info provides a mock function with given fields: _a0
func (_m *Application) Info(_a0 types.RequestInfo) types.ResponseInfo {
ret := _m.Called(_a0)
var r0 types.ResponseInfo
if rf, ok := ret.Get(0).(func(types.RequestInfo) types.ResponseInfo); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseInfo)
}
return r0
}
// InitChain provides a mock function with given fields: _a0
func (_m *Application) InitChain(_a0 types.RequestInitChain) types.ResponseInitChain {
ret := _m.Called(_a0)
var r0 types.ResponseInitChain
if rf, ok := ret.Get(0).(func(types.RequestInitChain) types.ResponseInitChain); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseInitChain)
}
return r0
}
// ListSnapshots provides a mock function with given fields: _a0
func (_m *Application) ListSnapshots(_a0 types.RequestListSnapshots) types.ResponseListSnapshots {
ret := _m.Called(_a0)
var r0 types.ResponseListSnapshots
if rf, ok := ret.Get(0).(func(types.RequestListSnapshots) types.ResponseListSnapshots); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseListSnapshots)
}
return r0
}
// LoadSnapshotChunk provides a mock function with given fields: _a0
func (_m *Application) LoadSnapshotChunk(_a0 types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk {
ret := _m.Called(_a0)
var r0 types.ResponseLoadSnapshotChunk
if rf, ok := ret.Get(0).(func(types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseLoadSnapshotChunk)
}
return r0
}
// OfferSnapshot provides a mock function with given fields: _a0
func (_m *Application) OfferSnapshot(_a0 types.RequestOfferSnapshot) types.ResponseOfferSnapshot {
ret := _m.Called(_a0)
var r0 types.ResponseOfferSnapshot
if rf, ok := ret.Get(0).(func(types.RequestOfferSnapshot) types.ResponseOfferSnapshot); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseOfferSnapshot)
}
return r0
}
// PrepareProposal provides a mock function with given fields: _a0
func (_m *Application) PrepareProposal(_a0 types.RequestPrepareProposal) types.ResponsePrepareProposal {
ret := _m.Called(_a0)
var r0 types.ResponsePrepareProposal
if rf, ok := ret.Get(0).(func(types.RequestPrepareProposal) types.ResponsePrepareProposal); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponsePrepareProposal)
}
return r0
}
// ProcessProposal provides a mock function with given fields: _a0
func (_m *Application) ProcessProposal(_a0 types.RequestProcessProposal) types.ResponseProcessProposal {
ret := _m.Called(_a0)
var r0 types.ResponseProcessProposal
if rf, ok := ret.Get(0).(func(types.RequestProcessProposal) types.ResponseProcessProposal); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseProcessProposal)
}
return r0
}
// Query provides a mock function with given fields: _a0
func (_m *Application) Query(_a0 types.RequestQuery) types.ResponseQuery {
ret := _m.Called(_a0)
var r0 types.ResponseQuery
if rf, ok := ret.Get(0).(func(types.RequestQuery) types.ResponseQuery); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseQuery)
}
return r0
}
// SetOption provides a mock function with given fields: _a0
func (_m *Application) SetOption(_a0 types.RequestSetOption) types.ResponseSetOption {
ret := _m.Called(_a0)
var r0 types.ResponseSetOption
if rf, ok := ret.Get(0).(func(types.RequestSetOption) types.ResponseSetOption); ok {
r0 = rf(_a0)
} else {
r0 = ret.Get(0).(types.ResponseSetOption)
}
return r0
}
type mockConstructorTestingTNewApplication interface {
mock.TestingT
Cleanup(func())
}
// NewApplication creates a new instance of Application. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func NewApplication(t mockConstructorTestingTNewApplication) *Application {
mock := &Application{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}

187
abci/types/mocks/base.go Normal file
View File

@@ -0,0 +1,187 @@
package mocks
import (
types "github.com/tendermint/tendermint/abci/types"
)
// BaseMock provides a wrapper around the generated Application mock and a BaseApplication.
// BaseMock first tries to use the mock's implementation of the method.
// If no functionality was provided for the mock by the user, BaseMock dispatches
// to the BaseApplication and uses its functionality.
// BaseMock allows users to provide mocked functionality for only the methods that matter
// for their test while avoiding a panic if the code calls Application methods that are
// not relevant to the test.
type BaseMock struct {
base *types.BaseApplication
*Application
}
func NewBaseMock() BaseMock {
return BaseMock{
base: types.NewBaseApplication(),
Application: new(Application),
}
}
// Info/Query Connection
// Return application info
func (m BaseMock) Info(input types.RequestInfo) types.ResponseInfo {
var ret types.ResponseInfo
defer func() {
if r := recover(); r != nil {
ret = m.base.Info(input)
}
}()
ret = m.Application.Info(input)
return ret
}
func (m BaseMock) Query(input types.RequestQuery) types.ResponseQuery {
var ret types.ResponseQuery
defer func() {
if r := recover(); r != nil {
ret = m.base.Query(input)
}
}()
ret = m.Application.Query(input)
return ret
}
// Mempool Connection
// Validate a tx for the mempool
func (m BaseMock) CheckTx(input types.RequestCheckTx) types.ResponseCheckTx {
var ret types.ResponseCheckTx
defer func() {
if r := recover(); r != nil {
ret = m.base.CheckTx(input)
}
}()
ret = m.Application.CheckTx(input)
return ret
}
// Consensus Connection
// Initialize blockchain w validators/other info from TendermintCore
func (m BaseMock) InitChain(input types.RequestInitChain) types.ResponseInitChain {
var ret types.ResponseInitChain
defer func() {
if r := recover(); r != nil {
ret = m.base.InitChain(input)
}
}()
ret = m.Application.InitChain(input)
return ret
}
func (m BaseMock) PrepareProposal(input types.RequestPrepareProposal) types.ResponsePrepareProposal {
var ret types.ResponsePrepareProposal
defer func() {
if r := recover(); r != nil {
ret = m.base.PrepareProposal(input)
}
}()
ret = m.Application.PrepareProposal(input)
return ret
}
func (m BaseMock) ProcessProposal(input types.RequestProcessProposal) types.ResponseProcessProposal {
var ret types.ResponseProcessProposal
defer func() {
if r := recover(); r != nil {
ret = m.base.ProcessProposal(input)
}
}()
ret = m.Application.ProcessProposal(input)
return ret
}
// Commit the state and return the application Merkle root hash
func (m BaseMock) Commit() types.ResponseCommit {
var ret types.ResponseCommit
defer func() {
if r := recover(); r != nil {
ret = m.base.Commit()
}
}()
ret = m.Application.Commit()
return ret
}
// State Sync Connection
// List available snapshots
func (m BaseMock) ListSnapshots(input types.RequestListSnapshots) types.ResponseListSnapshots {
var ret types.ResponseListSnapshots
defer func() {
if r := recover(); r != nil {
ret = m.base.ListSnapshots(input)
}
}()
ret = m.Application.ListSnapshots(input)
return ret
}
func (m BaseMock) OfferSnapshot(input types.RequestOfferSnapshot) types.ResponseOfferSnapshot {
var ret types.ResponseOfferSnapshot
defer func() {
if r := recover(); r != nil {
ret = m.base.OfferSnapshot(input)
}
}()
ret = m.Application.OfferSnapshot(input)
return ret
}
func (m BaseMock) LoadSnapshotChunk(input types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk {
var ret types.ResponseLoadSnapshotChunk
defer func() {
if r := recover(); r != nil {
ret = m.base.LoadSnapshotChunk(input)
}
}()
ret = m.Application.LoadSnapshotChunk(input)
return ret
}
func (m BaseMock) ApplySnapshotChunk(input types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk {
var ret types.ResponseApplySnapshotChunk
defer func() {
if r := recover(); r != nil {
ret = m.base.ApplySnapshotChunk(input)
}
}()
ret = m.Application.ApplySnapshotChunk(input)
return ret
}
func (m BaseMock) BeginBlock(input types.RequestBeginBlock) types.ResponseBeginBlock {
var ret types.ResponseBeginBlock
defer func() {
if r := recover(); r != nil {
ret = m.base.BeginBlock(input)
}
}()
ret = m.Application.BeginBlock(input)
return ret
}
func (m BaseMock) DeliverTx(input types.RequestDeliverTx) types.ResponseDeliverTx {
var ret types.ResponseDeliverTx
defer func() {
if r := recover(); r != nil {
ret = m.base.DeliverTx(input)
}
}()
ret = m.Application.DeliverTx(input)
return ret
}
func (m BaseMock) EndBlock(input types.RequestEndBlock) types.ResponseEndBlock {
var ret types.ResponseEndBlock
defer func() {
if r := recover(); r != nil {
ret = m.base.EndBlock(input)
}
}()
ret = m.Application.EndBlock(input)
return ret
}

View File

@@ -41,6 +41,11 @@ func (r ResponseQuery) IsErr() bool {
return r.Code != CodeTypeOK
}
// IsOK returns true if Code is OK
func (r ResponseProcessProposal) IsOK() bool {
return r.Status == ResponseProcessProposal_ACCEPT
}
//---------------------------------------------------------------------------
// override JSON marshaling so we emit defaults (ie. disable omitempty)

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,12 @@
version: 1.0.{build}
configuration: Release
platform:
- x64
- x86
- x64
- x86
clone_folder: c:\go\path\src\github.com\tendermint\tendermint
before_build:
- cmd: set GOPATH=%GOROOT%\path
- cmd: set PATH=%GOPATH%\bin;%PATH%
- cmd: set GOPATH=%GOROOT%\path
- cmd: set PATH=%GOPATH%\bin;%PATH%
build_script:
- cmd: make test
- cmd: make test
test: off

View File

@@ -1,10 +1,10 @@
/*
Package Behaviour provides a mechanism for reactors to report behaviour of peers.
Package Behavior provides a mechanism for reactors to report behavior of peers.
Instead of a reactor calling the switch directly it will call the behaviour module which will
Instead of a reactor calling the switch directly it will call the behavior module which will
handle the stoping and marking peer as good on behalf of the reactor.
There are four different behaviours a reactor can report.
There are four different behaviors a reactor can report.
1. bad message
@@ -39,4 +39,4 @@ type blockPart struct {
This message will request the peer be marked as good
*/
package behaviour
package behaviour //nolint:misspell

View File

@@ -1,12 +1,12 @@
package behaviour
package behaviour //nolint:misspell
import (
"github.com/tendermint/tendermint/p2p"
)
// PeerBehaviour is a struct describing a behaviour a peer performed.
// PeerBehaviour is a struct describing a behavior a peer performed.
// `peerID` identifies the peer and reason characterizes the specific
// behaviour performed by the peer.
// behavior performed by the peer.
type PeerBehaviour struct {
peerID p2p.ID
reason interface{}

View File

@@ -1,4 +1,4 @@
package behaviour
package behaviour //nolint:misspell
import (
"errors"
@@ -7,13 +7,13 @@ import (
"github.com/tendermint/tendermint/p2p"
)
// Reporter provides an interface for reactors to report the behaviour
// Reporter provides an interface for reactors to report the behavior
// of peers synchronously to other components.
type Reporter interface {
Report(behaviour PeerBehaviour) error
Report(behavior PeerBehaviour) error
}
// SwitchReporter reports peer behaviour to an internal Switch.
// SwitchReporter reports peer behavior to an internal Switch.
type SwitchReporter struct {
sw *p2p.Switch
}
@@ -25,14 +25,14 @@ func NewSwitchReporter(sw *p2p.Switch) *SwitchReporter {
}
}
// Report reports the behaviour of a peer to the Switch.
func (spbr *SwitchReporter) Report(behaviour PeerBehaviour) error {
peer := spbr.sw.Peers().Get(behaviour.peerID)
// Report reports the behavior of a peer to the Switch.
func (spbr *SwitchReporter) Report(behavior PeerBehaviour) error {
peer := spbr.sw.Peers().Get(behavior.peerID)
if peer == nil {
return errors.New("peer not found")
}
switch reason := behaviour.reason.(type) {
switch reason := behavior.reason.(type) {
case consensusVote, blockPart:
spbr.sw.MarkPeerAsGood(peer)
case badMessage:
@@ -48,14 +48,14 @@ func (spbr *SwitchReporter) Report(behaviour PeerBehaviour) error {
// MockReporter is a concrete implementation of the Reporter
// interface used in reactor tests to ensure reactors report the correct
// behaviour in manufactured scenarios.
// behavior in manufactured scenarios.
type MockReporter struct {
mtx tmsync.RWMutex
pb map[p2p.ID][]PeerBehaviour
}
// NewMockReporter returns a Reporter which records all reported
// behaviours in memory.
// behaviors in memory.
func NewMockReporter() *MockReporter {
return &MockReporter{
pb: map[p2p.ID][]PeerBehaviour{},
@@ -63,15 +63,15 @@ func NewMockReporter() *MockReporter {
}
// Report stores the PeerBehaviour produced by the peer identified by peerID.
func (mpbr *MockReporter) Report(behaviour PeerBehaviour) error {
func (mpbr *MockReporter) Report(behavior PeerBehaviour) error {
mpbr.mtx.Lock()
defer mpbr.mtx.Unlock()
mpbr.pb[behaviour.peerID] = append(mpbr.pb[behaviour.peerID], behaviour)
mpbr.pb[behavior.peerID] = append(mpbr.pb[behavior.peerID], behavior)
return nil
}
// GetBehaviours returns all behaviours reported on the peer identified by peerID.
// GetBehaviours returns all behaviors reported on the peer identified by peerID.
func (mpbr *MockReporter) GetBehaviours(peerID p2p.ID) []PeerBehaviour {
mpbr.mtx.RLock()
defer mpbr.mtx.RUnlock()

View File

@@ -1,41 +1,41 @@
package behaviour_test
package behaviour_test //nolint:misspell
import (
"sync"
"testing"
bh "github.com/tendermint/tendermint/behaviour"
bh "github.com/tendermint/tendermint/behaviour" //nolint:misspell
"github.com/tendermint/tendermint/p2p"
)
// TestMockReporter tests the MockReporter's ability to store reported
// peer behaviour in memory indexed by the peerID.
// peer behavior in memory indexed by the peerID.
func TestMockReporter(t *testing.T) {
var peerID p2p.ID = "MockPeer"
pr := bh.NewMockReporter()
behaviours := pr.GetBehaviours(peerID)
if len(behaviours) != 0 {
t.Error("Expected to have no behaviours reported")
behaviors := pr.GetBehaviours(peerID)
if len(behaviors) != 0 {
t.Error("Expected to have no behaviors reported")
}
badMessage := bh.BadMessage(peerID, "bad message")
if err := pr.Report(badMessage); err != nil {
t.Error(err)
}
behaviours = pr.GetBehaviours(peerID)
if len(behaviours) != 1 {
t.Error("Expected the peer have one reported behaviour")
behaviors = pr.GetBehaviours(peerID)
if len(behaviors) != 1 {
t.Error("Expected the peer have one reported behavior")
}
if behaviours[0] != badMessage {
if behaviors[0] != badMessage {
t.Error("Expected Bad Message to have been reported")
}
}
type scriptItem struct {
peerID p2p.ID
behaviour bh.PeerBehaviour
peerID p2p.ID
behavior bh.PeerBehaviour
}
// equalBehaviours returns true if a and b contain the same PeerBehaviours with
@@ -44,26 +44,26 @@ func equalBehaviours(a []bh.PeerBehaviour, b []bh.PeerBehaviour) bool {
aHistogram := map[bh.PeerBehaviour]int{}
bHistogram := map[bh.PeerBehaviour]int{}
for _, behaviour := range a {
aHistogram[behaviour]++
for _, behavior := range a {
aHistogram[behavior]++
}
for _, behaviour := range b {
bHistogram[behaviour]++
for _, behavior := range b {
bHistogram[behavior]++
}
if len(aHistogram) != len(bHistogram) {
return false
}
for _, behaviour := range a {
if aHistogram[behaviour] != bHistogram[behaviour] {
for _, behavior := range a {
if aHistogram[behavior] != bHistogram[behavior] {
return false
}
}
for _, behaviour := range b {
if bHistogram[behaviour] != aHistogram[behaviour] {
for _, behavior := range b {
if bHistogram[behavior] != aHistogram[behavior] {
return false
}
}
@@ -72,8 +72,8 @@ func equalBehaviours(a []bh.PeerBehaviour, b []bh.PeerBehaviour) bool {
}
// TestEqualPeerBehaviours tests that equalBehaviours can tell that two slices
// of peer behaviours can be compared for the behaviours they contain and the
// freequencies that those behaviours occur.
// of peer behaviors can be compared for the behaviors they contain and the
// freequencies that those behaviors occur.
func TestEqualPeerBehaviours(t *testing.T) {
var (
peerID p2p.ID = "MockPeer"
@@ -85,7 +85,7 @@ func TestEqualPeerBehaviours(t *testing.T) {
}{
// Empty sets
{[]bh.PeerBehaviour{}, []bh.PeerBehaviour{}},
// Single behaviours
// Single behaviors
{[]bh.PeerBehaviour{consensusVote}, []bh.PeerBehaviour{consensusVote}},
// Equal Frequencies
{[]bh.PeerBehaviour{consensusVote, consensusVote},
@@ -100,9 +100,9 @@ func TestEqualPeerBehaviours(t *testing.T) {
}{
// Comparing empty sets to non empty sets
{[]bh.PeerBehaviour{}, []bh.PeerBehaviour{consensusVote}},
// Different behaviours
// Different behaviors
{[]bh.PeerBehaviour{consensusVote}, []bh.PeerBehaviour{blockPart}},
// Same behaviour with different frequencies
// Same behavior with different frequencies
{[]bh.PeerBehaviour{consensusVote},
[]bh.PeerBehaviour{consensusVote, consensusVote}},
}
@@ -128,8 +128,8 @@ func TestEqualPeerBehaviours(t *testing.T) {
func TestMockPeerBehaviourReporterConcurrency(t *testing.T) {
var (
behaviourScript = []struct {
peerID p2p.ID
behaviours []bh.PeerBehaviour
peerID p2p.ID
behaviors []bh.PeerBehaviour
}{
{"1", []bh.PeerBehaviour{bh.ConsensusVote("1", "")}},
{"2", []bh.PeerBehaviour{bh.ConsensusVote("2", ""), bh.ConsensusVote("2", ""), bh.ConsensusVote("2", "")}},
@@ -166,7 +166,7 @@ func TestMockPeerBehaviourReporterConcurrency(t *testing.T) {
for {
select {
case pb := <-scriptItems:
if err := pr.Report(pb.behaviour); err != nil {
if err := pr.Report(pb.behavior); err != nil {
t.Error(err)
}
case <-done:
@@ -181,7 +181,7 @@ func TestMockPeerBehaviourReporterConcurrency(t *testing.T) {
go func() {
defer sendingWg.Done()
for _, item := range behaviourScript {
for _, reason := range item.behaviours {
for _, reason := range item.behaviors {
scriptItems <- scriptItem{item.peerID, reason}
}
}
@@ -197,9 +197,9 @@ func TestMockPeerBehaviourReporterConcurrency(t *testing.T) {
for _, items := range behaviourScript {
reported := pr.GetBehaviours(items.peerID)
if !equalBehaviours(reported, items.behaviours) {
if !equalBehaviours(reported, items.behaviors) {
t.Errorf("expected peer %s to have behaved \nExpected: %#v \nGot %#v \n",
items.peerID, items.behaviours, reported)
items.peerID, items.behaviors, reported)
}
}
}

View File

@@ -360,14 +360,20 @@ FOR_LOOP:
didProcessCh <- struct{}{}
}
firstParts := first.MakePartSet(types.BlockPartSizeBytes)
firstParts, err := first.MakePartSet(types.BlockPartSizeBytes)
if err != nil {
bcR.Logger.Error("failed to make ",
"height", first.Height,
"err", err.Error())
break FOR_LOOP
}
firstPartSetHeader := firstParts.Header()
firstID := types.BlockID{Hash: first.Hash(), PartSetHeader: firstPartSetHeader}
// Finally, verify the first block using the second's commit
// NOTE: we can probably make this more efficient, but note that calling
// first.Hash() doesn't verify the tx contents, so MakePartSet() is
// currently necessary.
err := state.Validators.VerifyCommitLight(
err = state.Validators.VerifyCommitLight(
chainID, firstID, first.Height, second.LastCommit)
if err == nil {

View File

@@ -8,6 +8,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
dbm "github.com/tendermint/tm-db"
@@ -15,10 +16,11 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/mempool/mock"
mpmocks "github.com/tendermint/tendermint/mempool/mocks"
"github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/proxy"
sm "github.com/tendermint/tendermint/state"
sf "github.com/tendermint/tendermint/state/test/factory"
"github.com/tendermint/tendermint/store"
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
@@ -52,6 +54,7 @@ type BlockchainReactorPair struct {
}
func newBlockchainReactor(
t *testing.T,
logger log.Logger,
genDoc *types.GenesisDoc,
privVals []types.PrivValidator,
@@ -78,6 +81,18 @@ func newBlockchainReactor(
panic(fmt.Errorf("error constructing state from genesis file: %w", err))
}
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
// Make the BlockchainReactor itself.
// NOTE we have to create and commit the blocks first because
// pool.height is determined from the store.
@@ -85,7 +100,7 @@ func newBlockchainReactor(
db := dbm.NewMemDB()
stateStore = sm.NewStore(db)
blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(),
mock.Mempool{}, sm.EmptyEvidencePool{})
mp, sm.EmptyEvidencePool{})
if err = stateStore.Save(state); err != nil {
panic(err)
}
@@ -112,9 +127,10 @@ func newBlockchainReactor(
lastBlockMeta.BlockID, []types.CommitSig{vote.CommitSig()})
}
thisBlock := makeBlock(blockHeight, state, lastCommit)
thisBlock := sf.MakeBlock(state, blockHeight, lastCommit)
thisParts := thisBlock.MakePartSet(types.BlockPartSizeBytes)
thisParts, err := thisBlock.MakePartSet(types.BlockPartSizeBytes)
require.NoError(t, err)
blockID := types.BlockID{Hash: thisBlock.Hash(), PartSetHeader: thisParts.Header()}
state, _, err = blockExec.ApplyBlock(state, blockID, thisBlock)
@@ -140,8 +156,8 @@ func TestNoBlockResponse(t *testing.T) {
reactorPairs := make([]BlockchainReactorPair, 2)
reactorPairs[0] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, maxBlockHeight)
reactorPairs[1] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, 0)
reactorPairs[0] = newBlockchainReactor(t, log.TestingLogger(), genDoc, privVals, maxBlockHeight)
reactorPairs[1] = newBlockchainReactor(t, log.TestingLogger(), genDoc, privVals, 0)
p2p.MakeConnectedSwitches(config.P2P, 2, func(i int, s *p2p.Switch) *p2p.Switch {
s.AddReactor("BLOCKCHAIN", reactorPairs[i].reactor)
@@ -202,7 +218,7 @@ func TestBadBlockStopsPeer(t *testing.T) {
// Other chain needs a different validator set
otherGenDoc, otherPrivVals := randGenesisDoc(1, false, 30)
otherChain := newBlockchainReactor(log.TestingLogger(), otherGenDoc, otherPrivVals, maxBlockHeight)
otherChain := newBlockchainReactor(t, log.TestingLogger(), otherGenDoc, otherPrivVals, maxBlockHeight)
defer func() {
err := otherChain.reactor.Stop()
@@ -213,10 +229,10 @@ func TestBadBlockStopsPeer(t *testing.T) {
reactorPairs := make([]BlockchainReactorPair, 4)
reactorPairs[0] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, maxBlockHeight)
reactorPairs[1] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, 0)
reactorPairs[2] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, 0)
reactorPairs[3] = newBlockchainReactor(log.TestingLogger(), genDoc, privVals, 0)
reactorPairs[0] = newBlockchainReactor(t, log.TestingLogger(), genDoc, privVals, maxBlockHeight)
reactorPairs[1] = newBlockchainReactor(t, log.TestingLogger(), genDoc, privVals, 0)
reactorPairs[2] = newBlockchainReactor(t, log.TestingLogger(), genDoc, privVals, 0)
reactorPairs[3] = newBlockchainReactor(t, log.TestingLogger(), genDoc, privVals, 0)
switches := p2p.MakeConnectedSwitches(config.P2P, 4, func(i int, s *p2p.Switch) *p2p.Switch {
s.AddReactor("BLOCKCHAIN", reactorPairs[i].reactor)
@@ -254,7 +270,7 @@ func TestBadBlockStopsPeer(t *testing.T) {
// race, but can't be easily avoided.
reactorPairs[3].reactor.store = otherChain.reactor.store
lastReactorPair := newBlockchainReactor(log.TestingLogger(), genDoc, privVals, 0)
lastReactorPair := newBlockchainReactor(t, log.TestingLogger(), genDoc, privVals, 0)
reactorPairs = append(reactorPairs, lastReactorPair)
switches = append(switches, p2p.MakeConnectedSwitches(config.P2P, 1, func(i int, s *p2p.Switch) *p2p.Switch {
@@ -278,21 +294,6 @@ func TestBadBlockStopsPeer(t *testing.T) {
assert.True(t, lastReactorPair.reactor.Switch.Peers().Size() < len(reactorPairs)-1)
}
//----------------------------------------------
// utility funcs
func makeTxs(height int64) (txs []types.Tx) {
for i := 0; i < 10; i++ {
txs = append(txs, types.Tx([]byte{byte(height), byte(i)}))
}
return txs
}
func makeBlock(height int64, state sm.State, lastCommit *types.Commit) *types.Block {
block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, nil, state.Validators.GetProposer().Address)
return block
}
type testApp struct {
abci.BaseApplication
}

View File

@@ -5,7 +5,7 @@ import (
"reflect"
"time"
"github.com/tendermint/tendermint/behaviour"
"github.com/tendermint/tendermint/behaviour" //nolint:misspell
bc "github.com/tendermint/tendermint/blockchain"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/p2p"
@@ -100,7 +100,7 @@ func NewBlockchainReactor(state sm.State, blockExec *sm.BlockExecutor, store *st
fsm := NewFSM(startHeight, bcR)
bcR.fsm = fsm
bcR.BaseReactor = *p2p.NewBaseReactor("BlockchainReactor", bcR)
// bcR.swReporter = behaviour.NewSwitchReporter(bcR.BaseReactor.Switch)
// bcR.swReporter = behavior.NewSwitchReporter(bcR.BaseReactor.Switch)
return bcR
}
@@ -465,7 +465,13 @@ func (bcR *BlockchainReactor) processBlock() error {
chainID := bcR.initialState.ChainID
firstParts := first.MakePartSet(types.BlockPartSizeBytes)
firstParts, err := first.MakePartSet(types.BlockPartSizeBytes)
if err != nil {
bcR.Logger.Error("failed to make ",
"height", first.Height,
"err", err.Error())
return err
}
firstPartSetHeader := firstParts.Header()
firstID := types.BlockID{Hash: first.Hash(), PartSetHeader: firstPartSetHeader}
// Finally, verify the first block using the second's commit

View File

@@ -9,6 +9,7 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
dbm "github.com/tendermint/tm-db"
@@ -16,11 +17,12 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/mempool/mock"
mpmocks "github.com/tendermint/tendermint/mempool/mocks"
"github.com/tendermint/tendermint/p2p"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/tendermint/tendermint/proxy"
sm "github.com/tendermint/tendermint/state"
sf "github.com/tendermint/tendermint/state/test/factory"
"github.com/tendermint/tendermint/store"
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
@@ -110,6 +112,18 @@ func newBlockchainReactor(
panic(fmt.Errorf("error constructing state from genesis file: %w", err))
}
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
// Make the BlockchainReactor itself.
// NOTE we have to create and commit the blocks first because
// pool.height is determined from the store.
@@ -117,7 +131,7 @@ func newBlockchainReactor(
db := dbm.NewMemDB()
stateStore = sm.NewStore(db)
blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(),
mock.Mempool{}, sm.EmptyEvidencePool{})
mp, sm.EmptyEvidencePool{})
if err = stateStore.Save(state); err != nil {
panic(err)
}
@@ -133,9 +147,10 @@ func newBlockchainReactor(
lastCommit = types.NewCommit(vote.Height, vote.Round, lastBlockMeta.BlockID, []types.CommitSig{vote.CommitSig()})
}
thisBlock := makeBlock(blockHeight, state, lastCommit)
thisBlock := sf.MakeBlock(state, blockHeight, lastCommit)
thisParts := thisBlock.MakePartSet(types.BlockPartSizeBytes)
thisParts, err := thisBlock.MakePartSet(types.BlockPartSizeBytes)
require.NoError(t, err)
blockID := types.BlockID{Hash: thisBlock.Hash(), PartSetHeader: thisParts.Header()}
state, _, err = blockExec.ApplyBlock(state, blockID, thisBlock)
@@ -345,21 +360,6 @@ outerFor:
assert.True(t, lastReactorPair.bcR.Switch.Peers().Size() < len(reactorPairs)-1)
}
//----------------------------------------------
// utility funcs
func makeTxs(height int64) (txs []types.Tx) {
for i := 0; i < 10; i++ {
txs = append(txs, types.Tx([]byte{byte(height), byte(i)}))
}
return txs
}
func makeBlock(height int64, state sm.State, lastCommit *types.Commit) *types.Block {
block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, nil, state.Validators.GetProposer().Address)
return block
}
type testApp struct {
abci.BaseApplication
}

View File

@@ -158,11 +158,12 @@ func (state *pcState) handle(event Event) (Event, error) {
return noOp, nil
}
var (
first, second = firstItem.block, secondItem.block
firstParts = first.MakePartSet(types.BlockPartSizeBytes)
firstID = types.BlockID{Hash: first.Hash(), PartSetHeader: firstParts.Header()}
)
first, second := firstItem.block, secondItem.block
firstParts, err := first.MakePartSet(types.BlockPartSizeBytes)
if err != nil {
panic(fmt.Sprintf("failed to make part set, height %d: %v ", first.Height, err.Error()))
}
firstID := types.BlockID{Hash: first.Hash(), PartSetHeader: firstParts.Header()}
// verify if +second+ last commit "confirms" +first+ block
err = state.context.verifyCommit(tmState.ChainID, firstID, first.Height, second.LastCommit)

View File

@@ -82,7 +82,7 @@ func executeProcessorTests(t *testing.T, tests []testFields) {
}
}()
// First step must always initialise the currentState as state.
// First step must always initialize the currentState as state.
if step.currentState != nil {
state = makeState(step.currentState)
}

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"time"
"github.com/tendermint/tendermint/behaviour"
"github.com/tendermint/tendermint/behaviour" //nolint:misspell
bc "github.com/tendermint/tendermint/blockchain"
"github.com/tendermint/tendermint/libs/log"
tmsync "github.com/tendermint/tendermint/libs/sync"
@@ -139,7 +139,7 @@ func (r *BlockchainReactor) Start() error {
return nil
}
// startSync begins a fast sync, signalled by r.events being non-nil. If state is non-nil,
// startSync begins a fast sync, signaled by r.events being non-nil. If state is non-nil,
// the scheduler and processor is updated with this state on startup.
func (r *BlockchainReactor) startSync(state *state.State) error {
r.mtx.Lock()

View File

@@ -10,21 +10,23 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
dbm "github.com/tendermint/tm-db"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/behaviour"
"github.com/tendermint/tendermint/behaviour" //nolint:misspell
bc "github.com/tendermint/tendermint/blockchain"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/libs/service"
"github.com/tendermint/tendermint/mempool/mock"
mpmocks "github.com/tendermint/tendermint/mempool/mocks"
"github.com/tendermint/tendermint/p2p"
"github.com/tendermint/tendermint/p2p/conn"
bcproto "github.com/tendermint/tendermint/proto/tendermint/blockchain"
"github.com/tendermint/tendermint/proxy"
sm "github.com/tendermint/tendermint/state"
sf "github.com/tendermint/tendermint/state/test/factory"
"github.com/tendermint/tendermint/store"
"github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
@@ -142,8 +144,8 @@ type testReactorParams struct {
mockA bool
}
func newTestReactor(p testReactorParams) *BlockchainReactor {
store, state, _ := newReactorStore(p.genDoc, p.privVals, p.startHeight)
func newTestReactor(t *testing.T, p testReactorParams) *BlockchainReactor {
store, state, _ := newReactorStore(t, p.genDoc, p.privVals, p.startHeight)
reporter := behaviour.NewMockReporter()
var appl blockApplier
@@ -151,6 +153,18 @@ func newTestReactor(p testReactorParams) *BlockchainReactor {
if p.mockA {
appl = &mockBlockApplier{}
} else {
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
app := &testApp{}
cc := proxy.NewLocalClientCreator(app)
proxyApp := proxy.NewAppConns(cc)
@@ -160,7 +174,7 @@ func newTestReactor(p testReactorParams) *BlockchainReactor {
}
db := dbm.NewMemDB()
stateStore := sm.NewStore(db)
appl = sm.NewBlockExecutor(stateStore, p.logger, proxyApp.Consensus(), mock.Mempool{}, sm.EmptyEvidencePool{})
appl = sm.NewBlockExecutor(stateStore, p.logger, proxyApp.Consensus(), mp, sm.EmptyEvidencePool{})
if err = stateStore.Save(state); err != nil {
panic(err)
}
@@ -301,7 +315,7 @@ func newTestReactor(p testReactorParams) *BlockchainReactor {
// t.Run(tt.name, func(t *testing.T) {
// reactor := newTestReactor(params)
// reactor.Start()
// reactor.reporter = behaviour.NewMockReporter()
// reactor.reporter = behavior.NewMockReporter()
// mockSwitch := &mockSwitchIo{switchedToConsensus: false}
// reactor.io = mockSwitch
// // time for go routines to start
@@ -391,7 +405,7 @@ func TestReactorHelperMode(t *testing.T) {
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
reactor := newTestReactor(params)
reactor := newTestReactor(t, params)
mockSwitch := &mockSwitchIo{switchedToConsensus: false}
reactor.io = mockSwitch
err := reactor.Start()
@@ -434,7 +448,7 @@ func TestReactorSetSwitchNil(t *testing.T) {
defer os.RemoveAll(config.RootDir)
genDoc, privVals := randGenesisDoc(config.ChainID(), 1, false, 30)
reactor := newTestReactor(testReactorParams{
reactor := newTestReactor(t, testReactorParams{
logger: log.TestingLogger(),
genDoc: genDoc,
privVals: privVals,
@@ -445,21 +459,6 @@ func TestReactorSetSwitchNil(t *testing.T) {
assert.Nil(t, reactor.io)
}
//----------------------------------------------
// utility funcs
func makeTxs(height int64) (txs []types.Tx) {
for i := 0; i < 10; i++ {
txs = append(txs, types.Tx([]byte{byte(height), byte(i)}))
}
return txs
}
func makeBlock(height int64, state sm.State, lastCommit *types.Commit) *types.Block {
block, _ := state.MakeBlock(height, makeTxs(height), lastCommit, nil, state.Validators.GetProposer().Address)
return block
}
type testApp struct {
abci.BaseApplication
}
@@ -488,6 +487,7 @@ func randGenesisDoc(chainID string, numValidators int, randPower bool, minPower
// Why are we importing the entire blockExecutor dependency graph here
// when we have the facilities to
func newReactorStore(
t *testing.T,
genDoc *types.GenesisDoc,
privVals []types.PrivValidator,
maxBlockHeight int64) (*store.BlockStore, sm.State, *sm.BlockExecutor) {
@@ -510,10 +510,22 @@ func newReactorStore(
panic(fmt.Errorf("error constructing state from genesis file: %w", err))
}
mp := &mpmocks.Mempool{}
mp.On("Lock").Return()
mp.On("Unlock").Return()
mp.On("FlushAppConn", mock.Anything).Return(nil)
mp.On("Update",
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything,
mock.Anything).Return(nil)
db := dbm.NewMemDB()
stateStore = sm.NewStore(db)
blockExec := sm.NewBlockExecutor(stateStore, log.TestingLogger(), proxyApp.Consensus(),
mock.Mempool{}, sm.EmptyEvidencePool{})
mp, sm.EmptyEvidencePool{})
if err = stateStore.Save(state); err != nil {
panic(err)
}
@@ -539,9 +551,11 @@ func newReactorStore(
lastBlockMeta.BlockID, []types.CommitSig{vote.CommitSig()})
}
thisBlock := makeBlock(blockHeight, state, lastCommit)
thisBlock := sf.MakeBlock(state, blockHeight, lastCommit)
thisParts, err := thisBlock.MakePartSet(types.BlockPartSizeBytes)
require.NoError(t, err)
thisParts := thisBlock.MakePartSet(types.BlockPartSizeBytes)
blockID := types.BlockID{Hash: thisBlock.Hash(), PartSetHeader: thisParts.Header()}
state, _, err = blockExec.ApplyBlock(state, blockID, thisBlock)

View File

@@ -2225,7 +2225,7 @@ func TestScHandle(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
var sc *scheduler
for i, step := range tt.steps {
// First step must always initialise the currentState as state.
// First step must always initialize the currentState as state.
if step.currentSc != nil {
sc = newTestScheduler(*step.currentSc)
}

View File

@@ -14,7 +14,7 @@ import (
tmtime "github.com/tendermint/tendermint/types/time"
)
// InitFilesCmd initialises a fresh Tendermint Core instance.
// InitFilesCmd initializes a fresh Tendermint Core instance.
var InitFilesCmd = &cobra.Command{
Use: "init",
Short: "Initialize Tendermint",

View File

@@ -101,7 +101,7 @@ func init() {
}
func runProxy(cmd *cobra.Command, args []string) error {
// Initialise logger.
// Initialize logger.
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
var option log.Option
if verbose {

View File

@@ -0,0 +1,229 @@
package commands
import (
"errors"
"fmt"
"strings"
"github.com/spf13/cobra"
dbm "github.com/tendermint/tm-db"
abcitypes "github.com/tendermint/tendermint/abci/types"
tmcfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/progressbar"
"github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/state/indexer"
blockidxkv "github.com/tendermint/tendermint/state/indexer/block/kv"
"github.com/tendermint/tendermint/state/indexer/sink/psql"
"github.com/tendermint/tendermint/state/txindex"
"github.com/tendermint/tendermint/state/txindex/kv"
"github.com/tendermint/tendermint/types"
)
const (
reindexFailed = "event re-index failed: "
)
var (
ErrHeightNotAvailable = errors.New("height is not available")
ErrInvalidRequest = errors.New("invalid request")
)
// ReIndexEventCmd constructs a command to re-index events in a block height interval.
var ReIndexEventCmd = &cobra.Command{
Use: "reindex-event",
Short: "reindex events to the event store backends",
Long: `
reindex-event is an offline tooling to re-index block and tx events to the eventsinks,
you can run this command when the event store backend dropped/disconnected or you want to
replace the backend. The default start-height is 0, meaning the tooling will start
reindex from the base block height(inclusive); and the default end-height is 0, meaning
the tooling will reindex until the latest block height(inclusive). User can omit
either or both arguments.
`,
Example: `
tendermint reindex-event
tendermint reindex-event --start-height 2
tendermint reindex-event --end-height 10
tendermint reindex-event --start-height 2 --end-height 10
`,
Run: func(cmd *cobra.Command, args []string) {
bs, ss, err := loadStateAndBlockStore(config)
if err != nil {
fmt.Println(reindexFailed, err)
return
}
if err := checkValidHeight(bs); err != nil {
fmt.Println(reindexFailed, err)
return
}
bi, ti, err := loadEventSinks(config)
if err != nil {
fmt.Println(reindexFailed, err)
return
}
riArgs := eventReIndexArgs{
startHeight: startHeight,
endHeight: endHeight,
blockIndexer: bi,
txIndexer: ti,
blockStore: bs,
stateStore: ss,
}
if err := eventReIndex(cmd, riArgs); err != nil {
panic(fmt.Errorf("%s: %w", reindexFailed, err))
}
fmt.Println("event re-index finished")
},
}
var (
startHeight int64
endHeight int64
)
func init() {
ReIndexEventCmd.Flags().Int64Var(&startHeight, "start-height", 0, "the block height would like to start for re-index")
ReIndexEventCmd.Flags().Int64Var(&endHeight, "end-height", 0, "the block height would like to finish for re-index")
}
func loadEventSinks(cfg *tmcfg.Config) (indexer.BlockIndexer, txindex.TxIndexer, error) {
switch strings.ToLower(cfg.TxIndex.Indexer) {
case "null":
return nil, nil, errors.New("found null event sink, please check the tx-index section in the config.toml")
case "psql":
conn := cfg.TxIndex.PsqlConn
if conn == "" {
return nil, nil, errors.New("the psql connection settings cannot be empty")
}
es, err := psql.NewEventSink(conn, cfg.ChainID())
if err != nil {
return nil, nil, err
}
return es.BlockIndexer(), es.TxIndexer(), nil
case "kv":
store, err := dbm.NewDB("tx_index", dbm.BackendType(cfg.DBBackend), cfg.DBDir())
if err != nil {
return nil, nil, err
}
txIndexer := kv.NewTxIndex(store)
blockIndexer := blockidxkv.New(dbm.NewPrefixDB(store, []byte("block_events")))
return blockIndexer, txIndexer, nil
default:
return nil, nil, fmt.Errorf("unsupported event sink type: %s", cfg.TxIndex.Indexer)
}
}
type eventReIndexArgs struct {
startHeight int64
endHeight int64
blockIndexer indexer.BlockIndexer
txIndexer txindex.TxIndexer
blockStore state.BlockStore
stateStore state.Store
}
func eventReIndex(cmd *cobra.Command, args eventReIndexArgs) error {
var bar progressbar.Bar
bar.NewOption(args.startHeight-1, args.endHeight)
fmt.Println("start re-indexing events:")
defer bar.Finish()
for i := args.startHeight; i <= args.endHeight; i++ {
select {
case <-cmd.Context().Done():
return fmt.Errorf("event re-index terminated at height %d: %w", i, cmd.Context().Err())
default:
b := args.blockStore.LoadBlock(i)
if b == nil {
return fmt.Errorf("not able to load block at height %d from the blockstore", i)
}
r, err := args.stateStore.LoadABCIResponses(i)
if err != nil {
return fmt.Errorf("not able to load ABCI Response at height %d from the statestore", i)
}
e := types.EventDataNewBlockHeader{
Header: b.Header,
NumTxs: int64(len(b.Txs)),
ResultBeginBlock: *r.BeginBlock,
ResultEndBlock: *r.EndBlock,
}
var batch *txindex.Batch
if e.NumTxs > 0 {
batch = txindex.NewBatch(e.NumTxs)
for i := range b.Data.Txs {
tr := abcitypes.TxResult{
Height: b.Height,
Index: uint32(i),
Tx: b.Data.Txs[i],
Result: *(r.DeliverTxs[i]),
}
if err = batch.Add(&tr); err != nil {
return fmt.Errorf("adding tx to batch: %w", err)
}
}
if err := args.txIndexer.AddBatch(batch); err != nil {
return fmt.Errorf("tx event re-index at height %d failed: %w", i, err)
}
}
if err := args.blockIndexer.Index(e); err != nil {
return fmt.Errorf("block event re-index at height %d failed: %w", i, err)
}
}
bar.Play(i)
}
return nil
}
func checkValidHeight(bs state.BlockStore) error {
base := bs.Base()
if startHeight == 0 {
startHeight = base
fmt.Printf("set the start block height to the base height of the blockstore %d \n", base)
}
if startHeight < base {
return fmt.Errorf("%s (requested start height: %d, base height: %d)",
ErrHeightNotAvailable, startHeight, base)
}
height := bs.Height()
if startHeight > height {
return fmt.Errorf(
"%s (requested start height: %d, store height: %d)", ErrHeightNotAvailable, startHeight, height)
}
if endHeight == 0 || endHeight > height {
endHeight = height
fmt.Printf("set the end block height to the latest height of the blockstore %d \n", height)
}
if endHeight < base {
return fmt.Errorf(
"%s (requested end height: %d, base height: %d)", ErrHeightNotAvailable, endHeight, base)
}
if endHeight < startHeight {
return fmt.Errorf(
"%s (requested the end height: %d is less than the start height: %d)",
ErrInvalidRequest, startHeight, endHeight)
}
return nil
}

View File

@@ -0,0 +1,193 @@
package commands
import (
"context"
"errors"
"testing"
"github.com/spf13/cobra"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
dbm "github.com/tendermint/tm-db"
abcitypes "github.com/tendermint/tendermint/abci/types"
tmcfg "github.com/tendermint/tendermint/config"
prototmstate "github.com/tendermint/tendermint/proto/tendermint/state"
blockmocks "github.com/tendermint/tendermint/state/indexer/mocks"
"github.com/tendermint/tendermint/state/mocks"
txmocks "github.com/tendermint/tendermint/state/txindex/mocks"
"github.com/tendermint/tendermint/types"
)
const (
height int64 = 10
base int64 = 2
)
func setupReIndexEventCmd() *cobra.Command {
reIndexEventCmd := &cobra.Command{
Use: ReIndexEventCmd.Use,
Run: func(cmd *cobra.Command, args []string) {},
}
_ = reIndexEventCmd.ExecuteContext(context.Background())
return reIndexEventCmd
}
func TestReIndexEventCheckHeight(t *testing.T) {
mockBlockStore := &mocks.BlockStore{}
mockBlockStore.
On("Base").Return(base).
On("Height").Return(height)
testCases := []struct {
startHeight int64
endHeight int64
validHeight bool
}{
{0, 0, true},
{0, base, true},
{0, base - 1, false},
{0, height, true},
{0, height + 1, true},
{0, 0, true},
{base - 1, 0, false},
{base, 0, true},
{base, base, true},
{base, base - 1, false},
{base, height, true},
{base, height + 1, true},
{height, 0, true},
{height, base, false},
{height, height - 1, false},
{height, height, true},
{height, height + 1, true},
{height + 1, 0, false},
}
for _, tc := range testCases {
startHeight = tc.startHeight
endHeight = tc.endHeight
err := checkValidHeight(mockBlockStore)
if tc.validHeight {
require.NoError(t, err)
} else {
require.Error(t, err)
}
}
}
func TestLoadEventSink(t *testing.T) {
testCases := []struct {
sinks string
connURL string
loadErr bool
}{
{"", "", true},
{"NULL", "", true},
{"KV", "", false},
{"PSQL", "", true}, // true because empty connect url
// skip to test PSQL connect with correct url
{"UnsupportedSinkType", "wrongUrl", true},
}
for idx, tc := range testCases {
cfg := tmcfg.TestConfig()
cfg.TxIndex.Indexer = tc.sinks
cfg.TxIndex.PsqlConn = tc.connURL
_, _, err := loadEventSinks(cfg)
if tc.loadErr {
require.Error(t, err, idx)
} else {
require.NoError(t, err, idx)
}
}
}
func TestLoadBlockStore(t *testing.T) {
cfg := tmcfg.TestConfig()
cfg.DBPath = t.TempDir()
_, _, err := loadStateAndBlockStore(cfg)
require.Error(t, err)
_, err = dbm.NewDB("blockstore", dbm.GoLevelDBBackend, cfg.DBDir())
require.NoError(t, err)
// Get StateStore
_, err = dbm.NewDB("state", dbm.GoLevelDBBackend, cfg.DBDir())
require.NoError(t, err)
bs, ss, err := loadStateAndBlockStore(cfg)
require.NoError(t, err)
require.NotNil(t, bs)
require.NotNil(t, ss)
}
func TestReIndexEvent(t *testing.T) {
mockBlockStore := &mocks.BlockStore{}
mockStateStore := &mocks.Store{}
mockBlockIndexer := &blockmocks.BlockIndexer{}
mockTxIndexer := &txmocks.TxIndexer{}
mockBlockStore.
On("Base").Return(base).
On("Height").Return(height).
On("LoadBlock", base).Return(nil).Once().
On("LoadBlock", base).Return(&types.Block{Data: types.Data{Txs: types.Txs{make(types.Tx, 1)}}}).
On("LoadBlock", height).Return(&types.Block{Data: types.Data{Txs: types.Txs{make(types.Tx, 1)}}})
dtx := abcitypes.ResponseDeliverTx{}
abciResp := &prototmstate.ABCIResponses{
DeliverTxs: []*abcitypes.ResponseDeliverTx{&dtx},
EndBlock: &abcitypes.ResponseEndBlock{},
BeginBlock: &abcitypes.ResponseBeginBlock{},
}
mockBlockIndexer.
On("Index", mock.AnythingOfType("types.EventDataNewBlockHeader")).Return(errors.New("")).Once().
On("Index", mock.AnythingOfType("types.EventDataNewBlockHeader")).Return(nil)
mockTxIndexer.
On("AddBatch", mock.AnythingOfType("*txindex.Batch")).Return(errors.New("")).Once().
On("AddBatch", mock.AnythingOfType("*txindex.Batch")).Return(nil)
mockStateStore.
On("LoadABCIResponses", base).Return(nil, errors.New("")).Once().
On("LoadABCIResponses", base).Return(abciResp, nil).
On("LoadABCIResponses", height).Return(abciResp, nil)
testCases := []struct {
startHeight int64
endHeight int64
reIndexErr bool
}{
{base, height, true}, // LoadBlock error
{base, height, true}, // LoadABCIResponses error
{base, height, true}, // index block event error
{base, height, true}, // index tx event error
{base, base, false},
{height, height, false},
}
for _, tc := range testCases {
args := eventReIndexArgs{
startHeight: tc.startHeight,
endHeight: tc.endHeight,
blockIndexer: mockBlockIndexer,
txIndexer: mockTxIndexer,
blockStore: mockBlockStore,
stateStore: mockStateStore,
}
err := eventReIndex(setupReIndexEventCmd(), args)
if tc.reIndexErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
}
}

View File

@@ -2,12 +2,14 @@ package commands
import (
"fmt"
"path/filepath"
"github.com/spf13/cobra"
dbm "github.com/tendermint/tm-db"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/os"
"github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/store"
)
@@ -55,6 +57,10 @@ func RollbackState(config *cfg.Config) (int64, []byte, error) {
func loadStateAndBlockStore(config *cfg.Config) (*store.BlockStore, state.Store, error) {
dbType := dbm.BackendType(config.DBBackend)
if !os.FileExists(filepath.Join(config.DBDir(), "blockstore.db")) {
return nil, nil, fmt.Errorf("no blockstore found in %v", config.DBDir())
}
// Get BlockStore
blockStoreDB, err := dbm.NewDB("blockstore", dbType, config.DBDir())
if err != nil {
@@ -62,6 +68,10 @@ func loadStateAndBlockStore(config *cfg.Config) (*store.BlockStore, state.Store,
}
blockStore := store.NewBlockStore(blockStoreDB)
if !os.FileExists(filepath.Join(config.DBDir(), "state.db")) {
return nil, nil, fmt.Errorf("no statestore found in %v", config.DBDir())
}
// Get StateStore
stateDB, err := dbm.NewDB("state", dbType, config.DBDir())
if err != nil {

View File

@@ -370,7 +370,7 @@ type RPCConfig struct {
//
// Enabling this parameter will cause the WebSocket connection to be closed
// instead if it cannot read fast enough, allowing for greater
// predictability in subscription behaviour.
// predictability in subscription behavior.
CloseOnSlowClient bool `mapstructure:"experimental_close_on_slow_client"`
// How long to wait for a tx to be committed during /broadcast_tx_commit

View File

@@ -230,7 +230,7 @@ experimental_websocket_write_buffer_size = {{ .RPC.WebSocketWriteBufferSize }}
#
# Enabling this experimental parameter will cause the WebSocket connection to
# be closed instead if it cannot read fast enough, allowing for greater
# predictability in subscription behaviour.
# predictability in subscription behavior.
experimental_close_on_slow_client = {{ .RPC.CloseOnSlowClient }}
# How long to wait for a tx to be committed during /broadcast_tx_commit.

Some files were not shown because too many files have changed in this diff Show More