Compare commits

...

48 Commits

Author SHA1 Message Date
Anton Kaliaev
7b67ee408b fix test 2019-10-29 11:00:56 -07:00
Anton Kaliaev
7ffd3fff43 fix tests 2019-10-29 11:00:56 -07:00
Anton Kaliaev
c013501f45 align max wal msg and max consensus msg sizes 2019-10-29 11:00:56 -07:00
Anton Kaliaev
7ec2dff6fd fixes after Ethan's review 2019-10-29 11:00:56 -07:00
Anton Kaliaev
b5cad43b26 update changelog and bump version to 0.32.7 2019-10-29 11:00:56 -07:00
Anton Kaliaev
714948505b cs: only assert important stuff 2019-10-29 11:00:56 -07:00
Anton Kaliaev
564d6a203a cs: test new limits 2019-10-29 11:00:56 -07:00
Anton Kaliaev
c38dbdb640 cs: limit max bit array size and block parts count 2019-10-29 11:00:56 -07:00
Anton Kaliaev
c207fa6eff types: validate Part#Proof
add ValidateBasic to crypto/merkle/SimpleProof
2019-10-29 11:00:56 -07:00
Anton Kaliaev
470a23f9b4 cs: panic only when WAL#WriteSync fails
- modify WAL#Write and WAL#WriteSync to return an error
2019-10-29 11:00:56 -07:00
Anton Kaliaev
c4ba93a1e6 set the date to today 2019-10-10 09:01:51 -07:00
Anton Kaliaev
88946fd6d8 update changelog and bump version to v0.32.6 2019-10-10 09:01:51 -07:00
Anton Kaliaev
ab62fd977f p2p: only allow ed25519 pubkeys when connecting
also, recover from any possible failures in acceptPeers

Refs #4030
2019-10-10 09:01:51 -07:00
Anton Kaliaev
0f111b3c5c update changelog 2019-10-01 23:11:51 -07:00
Zaki Manian
b08f655024 Update CHANGELOG.md
Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>
2019-10-01 23:11:51 -07:00
Zaki Manian
d6ea1ed96f Changelog update 2019-10-01 23:11:51 -07:00
Zaki Manian
d06286916d update version.go 2019-10-01 23:11:51 -07:00
Zaki Manian
0354ea87f7 Fix for panic in signature verification if a peer sends a nil public key. 2019-10-01 23:11:51 -07:00
Ethan Buchman
ff2308b5f4 Merge pull request #4002 from tendermint/release/v0.32.4
Release/v0.32.4
2019-09-20 11:17:52 -04:00
Ethan Buchman
0ad70fb69a Merge pull request #3926 from tendermint/anton/v0.32.3
v0.32.3
2019-08-28 09:02:58 -04:00
Anton Kaliaev
86a581f28f Merge branch 'master' into v0.32 2019-08-28 12:43:24 +04:00
Marko
76f3db06b8 Merge PR #3860: Update log v0.32.2
* changelog updates

* pr comments
2019-08-01 10:28:32 -07:00
Marko Baricevic
15878dc80c release for v0.32.2 2019-08-01 10:28:32 -07:00
Alexander Bezobchuk
aacc71dc29 txindexer: Refactor Tx Search Aggregation (#3851)
- Replace the previous intersect call, which was called at each query condition, with a map intersection.
- Replace fmt.Sprintf with string()

closes: #3076

Benchmarks

```
Old
goos: darwin
goarch: amd64
pkg: github.com/tendermint/tendermint/state/txindex/kv
BenchmarkTxSearch-4   	     200	 103641206 ns/op	 7998416 B/op	   71171 allocs/op
PASS
ok  	github.com/tendermint/tendermint/state/txindex/kv	26.019s

New
goos: darwin
goarch: amd64
pkg: github.com/tendermint/tendermint/state/txindex/kv
BenchmarkTxSearch-4   	    1000	  38615024 ns/op	13515226 B/op	  166460 allocs/op
PASS
ok  	github.com/tendermint/tendermint/state/txindex/kv	53.618s
```

~62% performance improvement

Commits:

* Refactor tx search

* Add pending changelog entry

* Add tx search benchmarking

* remove intermediate hashes list

also reset timer in BenchmarkTxSearch
and fix other benchmark

* fix import

* Add test cases

* Fix searching

* Replace fmt.Sprintf with string

* Update state/txindex/kv/kv.go

Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>

* Rename params

* Cleanup

* Check error in benchmarks
2019-08-01 10:28:32 -07:00
Marko
d56fb6ed22 version tmdb (#3854) 2019-08-01 10:28:32 -07:00
Marko
8025d402e2 tm-cmn to tm-db (#3850)
* tm-cmn to tm-db

* go.mod changes

* go.mod changes

* more go.mod

* fix tm-db

* ci fix, pending change
2019-08-01 10:28:32 -07:00
Marko
513a32a6e3 gocritic (1/2) (#3836)
Add gocritic as a linter

    The linting is not complete, but should i complete in this PR or in a following.

    23 files have been touched so it may be better to do in a following PR


Commits:

* Add gocritic to linting

- Added gocritic to linting

Signed-off-by: Marko Baricevic <marbar3778@yahoo.com>

* gocritic

* pr comments

* remove switch in cmdBatch
2019-08-01 10:28:32 -07:00
Anton Kaliaev
5c9d6d839e node: allow replacing existing p2p.Reactor(s) (#3846)
* node: allow replacing existing p2p.Reactor(s)

using [`CustomReactors`
option](https://godoc.org/github.com/tendermint/tendermint/node#CustomReactors).
Warning: beware of accidental name clashes. Here is the list of existing
reactors: MEMPOOL, BLOCKCHAIN, CONSENSUS, EVIDENCE, PEX.

* check the absence of "CUSTOM" prefix

* merge 2 tests

* add doc.go to node package
2019-08-01 10:28:32 -07:00
Ivan Kushmantsev
53fdcfd7e9 docs: "Writing a Tendermint Core application in Kotlin (gRPC)" guide (#3838)
* add abci grpc kotlin guide

* Update docs/guides/kotlin.md

Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>

* Update docs/guides/kotlin.md

Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>

* Update docs/guides/kotlin.md

Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>

* Update kotlin.md
2019-08-01 10:28:32 -07:00
Anton Kaliaev
5f6617db7a docs: add a footer to guides (#3835) 2019-08-01 10:28:32 -07:00
folex
6d4f18aa8c p2p: Do not write 'Couldn't connect to any seeds' if there are no seeds (#3834)
* Do not write 'Couldn't connect to any seeds' if there are no seeds

* changelog

* remove privValUpgrade

* Fix typo in changelog

* Update CHANGELOG_PENDING.md

Co-Authored-By: Marko <marbar3778@yahoo.com>

I'm setting up all peers dynamically by calling dial_peers, so p2p.seeds in configs is empty, and I'm seeing error log a lot in logs.
2019-08-01 10:28:32 -07:00
Anton Kaliaev
55066ceaad p2p: Fix error logging for connection stop (#3824)
* p2p: fix false-positive error logging when stopping connections

This changeset fixes two types of false-positive errors occurring during
connection shutdown.

The first occurs when the process invokes FlushStop() or Stop() on a
connection. While the previous behavior did properly wait for the sendRoutine
to finish, it did not notify the recvRoutine that the connection was shutting
down. This would cause the recvRouting to receive and error when reading and
log this error. The changeset fixes this by notifying the recvRoutine that
the connection is shutting down.

The second occurs when the connection is terminated (gracefully) by the other side.
The recvRoutine would get an EOF error during the read, log it, and stop the connection
with an error. The changeset detects EOF and gracefully shuts down the connection.

* bring back the comment about flushing

* add changelog entry

* listen for quitRecvRoutine too

* we have to call stopForError

Otherwise peer won't be removed from the peer set and maybe readded
later.
2019-08-01 10:28:32 -07:00
Marko
58c3e590b4 types: move MakeVote / MakeBlock functions (#3819)
to the types package

Paritally Fixes #3584
2019-08-01 10:28:32 -07:00
Marko
ff9e08a32f add staticcheck linting (#3828)
cleanup to add linter

    grpc change:
        https://godoc.org/google.golang.org/grpc#WithContextDialer
        https://godoc.org/google.golang.org/grpc#WithDialer
        grpc/grpc-go#2627
    prometheous change:
        due to UninstrumentedHandler, being deprecated in the future
    empty branch = empty if or else statement
        didn't delete them entirely but commented
        couldn't find a reason to have them
    could not replicate the issue #3406
        but if want to keep it commented then we should comment out the if statement as well
2019-08-01 10:28:32 -07:00
Anton Kaliaev
0335add437 docs: add guides to docs (#3830) 2019-08-01 10:28:32 -07:00
Marko
5d0e7034e8 Renamed wire.go to codec.go (#3827)
* Renamed wire.go to codec.go

- Wire was the previous name of amino
- Codec describes the file better than `wire` & `amino`

Signed-off-by: Marko Baricevic <marbar3778@yahoo.com>

* ide error

* rename amino.go to codec.go
2019-08-01 10:28:32 -07:00
Anca Zamfir
abc30821f4 blockchain: Reorg reactor (#3561)
* go routines in blockchain reactor

* Added reference to the go routine diagram

* Initial commit

* cleanup

* Undo testing_logger change, committed by mistake

* Fix the test loggers

* pulled some fsm code into pool.go

* added pool tests

* changes to the design

added block requests under peer

moved the request trigger in the reactor poolRoutine, triggered now by a ticker

in general moved everything required for making block requests smarter in the poolRoutine

added a simple map of heights to keep track of what will need to be requested next

added a few more tests

* send errors to FSM in a different channel than blocks

send errors (RemovePeer) from switch on a different channel than the
one receiving blocks
renamed channels
added more pool tests

* more pool tests

* lint errors

* more tests

* more tests

* switch fast sync to new implementation

* fixed data race in tests

* cleanup

* finished fsm tests

* address golangci comments :)

* address golangci comments :)

* Added timeout on next block needed to advance

* updating docs and cleanup

* fix issue in test from previous cleanup

* cleanup

* Added termination scenarios, tests and more cleanup

* small fixes to adr, comments and cleanup

* Fix bug in sendRequest()

If we tried to send a request to a peer not present in the switch, a
missing continue statement caused the request to be blackholed in a peer
that was removed and never retried.

While this bug was manifesting, the reactor kept asking for other
blocks that would be stored and never consumed. Added the number of
unconsumed blocks in the math for requesting blocks ahead of current
processing height so eventually there will be no more blocks requested
until the already received ones are consumed.

* remove bpPeer's didTimeout field

* Use distinct err codes for peer timeout and FSM timeouts

* Don't allow peers to update with lower height

* review comments from Ethan and Zarko

* some cleanup, renaming, comments

* Move block execution in separate goroutine

* Remove pool's numPending

* review comments

* fix lint, remove old blockchain reactor and duplicates in fsm tests

* small reorg around peer after review comments

* add the reactor spec

* verify block only once

* review comments

* change to int for max number of pending requests

* cleanup and godoc

* Add configuration flag fast sync version

* golangci fixes

* fix config template

* move both reactor versions under blockchain

* cleanup, golint, renaming stuff

* updated documentation, fixed more golint warnings

* integrate with behavior package

* sync with master

* gofmt

* add changelog_pending entry

* move to improvments

* suggestion to changelog entry
2019-08-01 10:28:32 -07:00
Anton Kaliaev
e89991c445 rpc: return err if page is incorrect (less than 0 or greater than tot… (#3825)
* rpc: return err if page is incorrect (less than 0 or greater than total pages)

Fixes #3813

* fix rpc_test
2019-08-01 10:28:32 -07:00
Jun Kimura
df6df61ea9 mempool: make max_msg_bytes configurable (#3826)
* mempool: make max_msg_bytes configurable

* apply suggestions from code review

* update changelog pending

* apply suggestions from code review again
2019-08-01 10:28:32 -07:00
Anton Kaliaev
5ed39fd0b3 rpc: /broadcast_evidence (#3481)
* implement broadcast_duplicate_vote endpoint

* fix test_cover

* address comments

* address comments

* Update abci/example/kvstore/persistent_kvstore.go

Co-Authored-By: mossid <torecursedivine@gmail.com>

* Update rpc/client/main_test.go

Co-Authored-By: mossid <torecursedivine@gmail.com>

* address comments in progress

* reformat the code

* make linter happy

* make tests pass

* replace BroadcastDuplicateVote with BroadcastEvidence

* fix test

* fix endpoint name

* improve doc

* fix TestBroadcastEvidenceDuplicateVote

* Update rpc/core/evidence.go

Co-Authored-By: Thane Thomson <connect@thanethomson.com>

* add changelog entry

* fix TestBroadcastEvidenceDuplicateVote
2019-08-01 10:28:32 -07:00
zjubfd
17b69d4d56 p2p/conn: Add Bufferpool (#3664)
* use byte buffer pool to decreass allocs

* wrap to put buffer in defer

* wapper defer

* add dependency

* remove Gopkg,*

* add change log
2019-08-01 10:28:32 -07:00
Jun Kimura
5d7e22a53c rpc: make max_body_bytes and max_header_bytes configurable (#3818)
* rpc: make max_body_bytes and max_header_bytes configurable

* update changelog pending
2019-08-01 10:28:32 -07:00
Marko
073cd1125e docs: add A TOC to the Readme.md of ADR Section (#3820)
* ADR TOC in readme.md

* Added A TOC to the Readme.md of ADR Section

- Added table of contents to the Readme of the architecture section.
	- Easier to traverse and when you know what is there.
	- If the Adr's become viewable online it would help guide the user

Signed-off-by: Marko Baricevic <marbar3778@yahoo.com>

* add tm-cmn to subprojects

* normalize word
2019-08-01 10:28:32 -07:00
Marko
7041001fb6 libs: Remove db from tendermint in favor of tendermint/tm-cmn (#3811)
* Remove db from tendemrint in favor of tendermint/tm-cmn

- remove db from `libs`
- update dependancy, there have been no breaking changes in the updated deps
	- https://github.com/grpc/grpc-go/releases
	- https://github.com/golang/protobuf/releases

Signed-off-by: Marko Baricevic <marbar3778@yahoo.com>

* changelog add

* gofmt

* more gofmt
2019-08-01 10:28:32 -07:00
Anton Kaliaev
c264db339e docs: "Writing a built-in Tendermint Core application in Go" guide (#3608)
* docs: go built-in guide

* fix package imports, add badger db, simplify Query

* newTendermint function

* working example

* finish the first guide

* add one more note

* add the second Golang guide - external ABCI app

* fix typos
2019-08-01 10:28:32 -07:00
Marko
8da43508f8 abci/client: fix DATA RACE in gRPC client (#3798)
* Remove go func {}()

closes #357

- Remove go func(){}() that caused race condiditon

- To reproduce
	- add -race in make file to `install_abci`
	- Remove `CGO_ENABLED=0` & add -race to `install`

Signed-off-by: Marko Baricevic <marbar3778@yahoo.com>

* remove -race

* fix data race

also, reorder callbacks similarly to socket client
2019-08-01 10:28:32 -07:00
Roman Useinov
9867a65de7 abci/server: recover from app panics in socket server (#3809)
fixes #3800
2019-08-01 10:28:32 -07:00
Alex Dupre
9df117748e docs: fix consensus spec formatting (#3804) 2019-08-01 10:28:32 -07:00
23 changed files with 441 additions and 137 deletions

View File

@@ -1,5 +1,73 @@
# Changelog
## v0.32.7
*October 18, 2019*
This security release fixes a vulnerability found in the `consensus` package,
where an attacker could construct a `BlockPartMessage` message in such a way
that it will lead to consensus failure. A few similar issues have been
identified and fixed here.
**All clients are recommended to upgrade**
Special thanks to [elvishacker](https://hackerone.com/elvishacker) for finding
and reporting this.
Friendly reminder, we have a [bug bounty
program](https://hackerone.com/tendermint).
### BREAKING CHANGES:
- Go API
- [consensus] Modify `WAL#Write` and `WAL#WriteSync` to return an error if
they fail to write a message
### SECURITY:
- [consensus] Validate incoming messages more throughly
## v0.32.6
*October 8, 2019*
The previous patch was insufficient because the attacker could still find a way
to submit a `nil` pubkey by constructing a `PubKeyMultisigThreshold` pubkey
with `nil` subpubkeys for example.
This release provides multiple fixes, which include recovering from panics when
accepting new peers and only allowing `ed25519` pubkeys.
**All clients are recommended to upgrade**
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for pointing
this out.
Friendly reminder, we have a [bug bounty
program](https://hackerone.com/tendermint).
### SECURITY:
- [p2p] [\#4030](https://github.com/tendermint/tendermint/issues/4030) Only allow ed25519 pubkeys when connecting
## v0.32.5
*September 30, 2019*
This release fixes a major security vulnerability found in the `p2p` package.
All clients are recommended to upgrade. See [TODO](hxxp://githublink) for
details.
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for discovering
and reporting this issue.
Friendly reminder, we have a [bug bounty
program](https://hackerone.com/tendermint).
### SECURITY:
- [p2p] [TODO](hxxp://githublink) Fix for panic on nil public key send to a peer
## v0.32.4
*September 19, 2019*
@@ -22,9 +90,9 @@ program](https://hackerone.com/tendermint).
- [deps] [\#3951](https://github.com/tendermint/tendermint/pull/3951) bump github.com/stretchr/testify from 1.3.0 to 1.4.0
- [deps] [\#3945](https://github.com/tendermint/tendermint/pull/3945) bump github.com/gorilla/websocket from 1.2.0 to 1.4.1
- [deps] [\#3948](https://github.com/tendermint/tendermint/pull/3948) bump github.com/libp2p/go-buffer-pool from 0.0.1 to 0.0.2
- [deps] [\#3943](https://github.com/tendermint/tendermint/pull/3943) bump github.com/fortytw2/leaktest from 1.2.0 to 1.3.0
- [deps] [\#3939](https://github.com/tendermint/tendermint/pull/3939) bump github.com/rs/cors from 1.6.0 to 1.7.0
- [deps] [\#3937](https://github.com/tendermint/tendermint/pull/3937) bump github.com/magiconair/properties from 1.8.0 to 1.8.1
- [deps] [\#3943](https://github.com/tendermint/tendermint/pull/3943) bump github.com/fortytw2/leaktest from 1.2.0 to 1.3.0
- [deps] [\#3939](https://github.com/tendermint/tendermint/pull/3939) bump github.com/rs/cors from 1.6.0 to 1.7.0
- [deps] [\#3937](https://github.com/tendermint/tendermint/pull/3937) bump github.com/magiconair/properties from 1.8.0 to 1.8.1
- [deps] [\#3947](https://github.com/tendermint/tendermint/pull/3947) update gogo/protobuf version from v1.2.1 to v1.3.0
- [deps] [\#4001](https://github.com/tendermint/tendermint/pull/4001) bump github.com/tendermint/tm-db from 0.1.1 to 0.2.0

View File

@@ -1,4 +1,4 @@
## v0.32.5
## v0.32.8
\*\*

View File

@@ -1453,11 +1453,17 @@ func (m *NewValidBlockMessage) ValidateBasic() error {
if err := m.BlockPartsHeader.ValidateBasic(); err != nil {
return fmt.Errorf("Wrong BlockPartsHeader: %v", err)
}
if m.BlockParts.Size() == 0 {
return errors.New("Empty BlockParts")
}
if m.BlockParts.Size() != m.BlockPartsHeader.Total {
return fmt.Errorf("BlockParts bit array size %d not equal to BlockPartsHeader.Total %d",
m.BlockParts.Size(),
m.BlockPartsHeader.Total)
}
if m.BlockParts.Size() > types.MaxBlockPartsCount {
return errors.Errorf("BlockParts bit array is too big: %d, max: %d", m.BlockParts.Size(), types.MaxBlockPartsCount)
}
return nil
}
@@ -1504,6 +1510,9 @@ func (m *ProposalPOLMessage) ValidateBasic() error {
if m.ProposalPOL.Size() == 0 {
return errors.New("Empty ProposalPOL bit array")
}
if m.ProposalPOL.Size() > types.MaxVotesCount {
return errors.Errorf("ProposalPOL bit array is too big: %d, max: %d", m.ProposalPOL.Size(), types.MaxVotesCount)
}
return nil
}
@@ -1647,6 +1656,9 @@ func (m *VoteSetBitsMessage) ValidateBasic() error {
return fmt.Errorf("Wrong BlockID: %v", err)
}
// NOTE: Votes.Size() can be zero if the node does not have any
if m.Votes.Size() > types.MaxVotesCount {
return fmt.Errorf("Votes bit array is too big: %d, max: %d", m.Votes.Size(), types.MaxVotesCount)
}
return nil
}

View File

@@ -19,6 +19,7 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
cfg "github.com/tendermint/tendermint/config"
cstypes "github.com/tendermint/tendermint/consensus/types"
"github.com/tendermint/tendermint/crypto/tmhash"
cmn "github.com/tendermint/tendermint/libs/common"
"github.com/tendermint/tendermint/libs/log"
mempl "github.com/tendermint/tendermint/mempool"
@@ -671,67 +672,82 @@ func TestNewRoundStepMessageValidateBasic(t *testing.T) {
}
func TestNewValidBlockMessageValidateBasic(t *testing.T) {
testBitArray := cmn.NewBitArray(1)
testCases := []struct {
testName string
messageHeight int64
messageRound int
messageBlockParts *cmn.BitArray
expectErr bool
malleateFn func(*NewValidBlockMessage)
expErr string
}{
{"Valid Message", 0, 0, testBitArray, false},
{"Invalid Message", -1, 0, testBitArray, true},
{"Invalid Message", 0, -1, testBitArray, true},
{"Invalid Message", 0, 0, cmn.NewBitArray(0), true},
{func(msg *NewValidBlockMessage) {}, ""},
{func(msg *NewValidBlockMessage) { msg.Height = -1 }, "Negative Height"},
{func(msg *NewValidBlockMessage) { msg.Round = -1 }, "Negative Round"},
{
func(msg *NewValidBlockMessage) { msg.BlockPartsHeader.Total = 2 },
"BlockParts bit array size 1 not equal to BlockPartsHeader.Total 2",
},
{
func(msg *NewValidBlockMessage) { msg.BlockPartsHeader.Total = 0; msg.BlockParts = cmn.NewBitArray(0) },
"Empty BlockParts",
},
{
func(msg *NewValidBlockMessage) { msg.BlockParts = cmn.NewBitArray(types.MaxBlockPartsCount + 1) },
"BlockParts bit array size 1602 not equal to BlockPartsHeader.Total 1",
},
}
for _, tc := range testCases {
for i, tc := range testCases {
tc := tc
t.Run(tc.testName, func(t *testing.T) {
message := NewValidBlockMessage{
Height: tc.messageHeight,
Round: tc.messageRound,
BlockParts: tc.messageBlockParts,
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
msg := &NewValidBlockMessage{
Height: 1,
Round: 0,
BlockPartsHeader: types.PartSetHeader{
Total: 1,
},
BlockParts: cmn.NewBitArray(1),
}
message.BlockPartsHeader.Total = 1
assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
tc.malleateFn(msg)
err := msg.ValidateBasic()
if tc.expErr != "" && assert.Error(t, err) {
assert.Contains(t, err.Error(), tc.expErr)
}
})
}
}
func TestProposalPOLMessageValidateBasic(t *testing.T) {
testBitArray := cmn.NewBitArray(1)
testCases := []struct {
testName string
messageHeight int64
messageProposalPOLRound int
messageProposalPOL *cmn.BitArray
expectErr bool
malleateFn func(*ProposalPOLMessage)
expErr string
}{
{"Valid Message", 0, 0, testBitArray, false},
{"Invalid Message", -1, 0, testBitArray, true},
{"Invalid Message", 0, -1, testBitArray, true},
{"Invalid Message", 0, 0, cmn.NewBitArray(0), true},
{func(msg *ProposalPOLMessage) {}, ""},
{func(msg *ProposalPOLMessage) { msg.Height = -1 }, "Negative Height"},
{func(msg *ProposalPOLMessage) { msg.ProposalPOLRound = -1 }, "Negative ProposalPOLRound"},
{func(msg *ProposalPOLMessage) { msg.ProposalPOL = cmn.NewBitArray(0) }, "Empty ProposalPOL bit array"},
{func(msg *ProposalPOLMessage) { msg.ProposalPOL = cmn.NewBitArray(types.MaxVotesCount + 1) },
"ProposalPOL bit array is too big: 10001, max: 10000"},
}
for _, tc := range testCases {
for i, tc := range testCases {
tc := tc
t.Run(tc.testName, func(t *testing.T) {
message := ProposalPOLMessage{
Height: tc.messageHeight,
ProposalPOLRound: tc.messageProposalPOLRound,
ProposalPOL: tc.messageProposalPOL,
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
msg := &ProposalPOLMessage{
Height: 1,
ProposalPOLRound: 1,
ProposalPOL: cmn.NewBitArray(1),
}
assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
tc.malleateFn(msg)
err := msg.ValidateBasic()
if tc.expErr != "" && assert.Error(t, err) {
assert.Contains(t, err.Error(), tc.expErr)
}
})
}
}
func TestBlockPartMessageValidateBasic(t *testing.T) {
testPart := new(types.Part)
testPart.Proof.LeafHash = tmhash.Sum([]byte("leaf"))
testCases := []struct {
testName string
messageHeight int64
@@ -845,49 +861,43 @@ func TestVoteSetMaj23MessageValidateBasic(t *testing.T) {
}
func TestVoteSetBitsMessageValidateBasic(t *testing.T) {
const (
validSignedMsgType types.SignedMsgType = 0x01
invalidSignedMsgType types.SignedMsgType = 0x03
)
validBlockID := types.BlockID{}
invalidBlockID := types.BlockID{
Hash: cmn.HexBytes{},
PartsHeader: types.PartSetHeader{
Total: -1,
Hash: cmn.HexBytes{},
},
}
testBitArray := cmn.NewBitArray(1)
testCases := []struct {
testName string
messageHeight int64
messageRound int
messageType types.SignedMsgType
messageBlockID types.BlockID
messageVotes *cmn.BitArray
expectErr bool
testCases := []struct { // nolint: maligned
malleateFn func(*VoteSetBitsMessage)
expErr string
}{
{"Valid Message", 0, 0, validSignedMsgType, validBlockID, testBitArray, false},
{"Invalid Message", -1, 0, validSignedMsgType, validBlockID, testBitArray, true},
{"Invalid Message", 0, -1, validSignedMsgType, validBlockID, testBitArray, true},
{"Invalid Message", 0, 0, invalidSignedMsgType, validBlockID, testBitArray, true},
{"Invalid Message", 0, 0, validSignedMsgType, invalidBlockID, testBitArray, true},
{func(msg *VoteSetBitsMessage) {}, ""},
{func(msg *VoteSetBitsMessage) { msg.Height = -1 }, "Negative Height"},
{func(msg *VoteSetBitsMessage) { msg.Round = -1 }, "Negative Round"},
{func(msg *VoteSetBitsMessage) { msg.Type = 0x03 }, "Invalid Type"},
{func(msg *VoteSetBitsMessage) {
msg.BlockID = types.BlockID{
Hash: cmn.HexBytes{},
PartsHeader: types.PartSetHeader{
Total: -1,
Hash: cmn.HexBytes{},
},
}
}, "Wrong BlockID: Wrong PartsHeader: Negative Total"},
{func(msg *VoteSetBitsMessage) { msg.Votes = cmn.NewBitArray(types.MaxVotesCount + 1) },
"Votes bit array is too big: 10001, max: 10000"},
}
for _, tc := range testCases {
for i, tc := range testCases {
tc := tc
t.Run(tc.testName, func(t *testing.T) {
message := VoteSetBitsMessage{
Height: tc.messageHeight,
Round: tc.messageRound,
Type: tc.messageType,
// Votes: tc.messageVotes,
BlockID: tc.messageBlockID,
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
msg := &VoteSetBitsMessage{
Height: 1,
Round: 0,
Type: 0x01,
Votes: cmn.NewBitArray(1),
BlockID: types.BlockID{},
}
assert.Equal(t, tc.expectErr, message.ValidateBasic() != nil, "Validate Basic had an unexpected result")
tc.malleateFn(msg)
err := msg.ValidateBasic()
if tc.expErr != "" && assert.Error(t, err) {
assert.Contains(t, err.Error(), tc.expErr)
}
})
}
}

View File

@@ -228,15 +228,15 @@ func (e ReachedHeightToStopError) Error() string {
// Write simulate WAL's crashing by sending an error to the panicCh and then
// exiting the cs.receiveRoutine.
func (w *crashingWAL) Write(m WALMessage) {
func (w *crashingWAL) Write(m WALMessage) error {
if endMsg, ok := m.(EndHeightMessage); ok {
if endMsg.Height == w.heightToStop {
w.panicCh <- ReachedHeightToStopError{endMsg.Height}
runtime.Goexit()
} else {
w.next.Write(m)
return nil
}
return
return w.next.Write(m)
}
if w.msgIndex > w.lastPanickedForMsgIndex {
@@ -244,14 +244,15 @@ func (w *crashingWAL) Write(m WALMessage) {
_, file, line, _ := runtime.Caller(1)
w.panicCh <- WALWriteError{fmt.Sprintf("failed to write %T to WAL (fileline: %s:%d)", m, file, line)}
runtime.Goexit()
} else {
w.msgIndex++
w.next.Write(m)
return nil
}
w.msgIndex++
return w.next.Write(m)
}
func (w *crashingWAL) WriteSync(m WALMessage) {
w.Write(m)
func (w *crashingWAL) WriteSync(m WALMessage) error {
return w.Write(m)
}
func (w *crashingWAL) FlushAndSync() error { return w.next.FlushAndSync() }

View File

@@ -632,7 +632,10 @@ func (cs *ConsensusState) receiveRoutine(maxSteps int) {
// may generate internal events (votes, complete proposals, 2/3 majorities)
cs.handleMsg(mi)
case mi = <-cs.internalMsgQueue:
cs.wal.WriteSync(mi) // NOTE: fsync
err := cs.wal.WriteSync(mi) // NOTE: fsync
if err != nil {
panic(fmt.Sprintf("Failed to write %v msg to consensus wal due to %v. Check your FS and restart the node", mi, err))
}
if _, ok := mi.Msg.(*VoteMessage); ok {
// we actually want to simulate failing during
@@ -1329,7 +1332,10 @@ func (cs *ConsensusState) finalizeCommit(height int64) {
// Either way, the ConsensusState should not be resumed until we
// successfully call ApplyBlock (ie. later here, or in Handshake after
// restart).
cs.wal.WriteSync(EndHeightMessage{height}) // NOTE: fsync
endMsg := EndHeightMessage{height}
if err := cs.wal.WriteSync(endMsg); err != nil { // NOTE: fsync
panic(fmt.Sprintf("Failed to write %v msg to consensus wal due to %v. Check your FS and restart the node", endMsg, err))
}
fail.Fail() // XXX

View File

@@ -19,8 +19,8 @@ import (
)
const (
// must be greater than types.BlockPartSizeBytes + a few bytes
maxMsgSizeBytes = 1024 * 1024 // 1MB
// amino overhead + time.Time + max consensus msg size
maxMsgSizeBytes = maxMsgSize + 24
// how often the WAL should be sync'd during period sync'ing
walDefaultFlushInterval = 2 * time.Second
@@ -29,8 +29,9 @@ const (
//--------------------------------------------------------
// types and functions for savings consensus messages
// TimedWALMessage wraps WALMessage and adds Time for debugging purposes.
type TimedWALMessage struct {
Time time.Time `json:"time"` // for debugging purposes
Time time.Time `json:"time"`
Msg WALMessage `json:"msg"`
}
@@ -55,8 +56,8 @@ func RegisterWALMessages(cdc *amino.Codec) {
// WAL is an interface for any write-ahead logger.
type WAL interface {
Write(WALMessage)
WriteSync(WALMessage)
Write(WALMessage) error
WriteSync(WALMessage) error
FlushAndSync() error
SearchForEndHeight(height int64, options *WALSearchOptions) (rd io.ReadCloser, found bool, err error)
@@ -174,29 +175,39 @@ func (wal *baseWAL) Wait() {
// Write is called in newStep and for each receive on the
// peerMsgQueue and the timeoutTicker.
// NOTE: does not call fsync()
func (wal *baseWAL) Write(msg WALMessage) {
func (wal *baseWAL) Write(msg WALMessage) error {
if wal == nil {
return
return nil
}
// Write the wal message
if err := wal.enc.Encode(&TimedWALMessage{tmtime.Now(), msg}); err != nil {
panic(fmt.Sprintf("Error writing msg to consensus wal: %v \n\nMessage: %v", err, msg))
wal.Logger.Error("Error writing msg to consensus wal. WARNING: recover may not be possible for the current height",
"err", err, "msg", msg)
return err
}
return nil
}
// WriteSync is called when we receive a msg from ourselves
// so that we write to disk before sending signed messages.
// NOTE: calls fsync()
func (wal *baseWAL) WriteSync(msg WALMessage) {
func (wal *baseWAL) WriteSync(msg WALMessage) error {
if wal == nil {
return
return nil
}
wal.Write(msg)
if err := wal.FlushAndSync(); err != nil {
panic(fmt.Sprintf("Error flushing consensus wal buf to file. Error: %v \n", err))
if err := wal.Write(msg); err != nil {
return err
}
if err := wal.FlushAndSync(); err != nil {
wal.Logger.Error("WriteSync failed to flush consensus wal. WARNING: may result in creating alternative proposals / votes for the current height iff the node restarted",
"err", err)
return err
}
return nil
}
// WALSearchOptions are optional arguments to SearchForEndHeight.
@@ -285,7 +296,7 @@ func (enc *WALEncoder) Encode(v *TimedWALMessage) error {
crc := crc32.Checksum(data, crc32c)
length := uint32(len(data))
if length > maxMsgSizeBytes {
return fmt.Errorf("Msg is too big: %d bytes, max: %d bytes", length, maxMsgSizeBytes)
return fmt.Errorf("msg is too big: %d bytes, max: %d bytes", length, maxMsgSizeBytes)
}
totalLength := 8 + int(length)
@@ -295,7 +306,6 @@ func (enc *WALEncoder) Encode(v *TimedWALMessage) error {
copy(msg[8:], data)
_, err := enc.wr.Write(msg)
return err
}
@@ -383,9 +393,9 @@ type nilWAL struct{}
var _ WAL = nilWAL{}
func (nilWAL) Write(m WALMessage) {}
func (nilWAL) WriteSync(m WALMessage) {}
func (nilWAL) FlushAndSync() error { return nil }
func (nilWAL) Write(m WALMessage) error { return nil }
func (nilWAL) WriteSync(m WALMessage) error { return nil }
func (nilWAL) FlushAndSync() error { return nil }
func (nilWAL) SearchForEndHeight(height int64, options *WALSearchOptions) (rd io.ReadCloser, found bool, err error) {
return nil, false, nil
}

View File

@@ -168,10 +168,10 @@ func newByteBufferWAL(logger log.Logger, enc *WALEncoder, nBlocks int64, signalS
// Save writes message to the internal buffer except when heightToStop is
// reached, in which case it will signal the caller via signalWhenStopsTo and
// skip writing.
func (w *byteBufferWAL) Write(m WALMessage) {
func (w *byteBufferWAL) Write(m WALMessage) error {
if w.stopped {
w.logger.Debug("WAL already stopped. Not writing message", "msg", m)
return
return nil
}
if endMsg, ok := m.(EndHeightMessage); ok {
@@ -180,7 +180,7 @@ func (w *byteBufferWAL) Write(m WALMessage) {
w.logger.Debug("Stopping WAL at height", "height", endMsg.Height)
w.signalWhenStopsTo <- struct{}{}
w.stopped = true
return
return nil
}
}
@@ -189,10 +189,12 @@ func (w *byteBufferWAL) Write(m WALMessage) {
if err != nil {
panic(fmt.Sprintf("failed to encode the msg %v", m))
}
return nil
}
func (w *byteBufferWAL) WriteSync(m WALMessage) {
w.Write(m)
func (w *byteBufferWAL) WriteSync(m WALMessage) error {
return w.Write(m)
}
func (w *byteBufferWAL) FlushAndSync() error { return nil }

View File

@@ -11,14 +11,15 @@ import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/consensus/types"
"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/libs/autofile"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const (
@@ -103,7 +104,7 @@ func TestWALEncoderDecoder(t *testing.T) {
}
}
func TestWALWritePanicsIfMsgIsTooBig(t *testing.T) {
func TestWALWrite(t *testing.T) {
walDir, err := ioutil.TempDir("", "wal")
require.NoError(t, err)
defer os.RemoveAll(walDir)
@@ -120,7 +121,24 @@ func TestWALWritePanicsIfMsgIsTooBig(t *testing.T) {
wal.Wait()
}()
assert.Panics(t, func() { wal.Write(make([]byte, maxMsgSizeBytes+1)) })
// 1) Write returns an error if msg is too big
msg := &BlockPartMessage{
Height: 1,
Round: 1,
Part: &tmtypes.Part{
Index: 1,
Bytes: make([]byte, 1),
Proof: merkle.SimpleProof{
Total: 1,
Index: 1,
LeafHash: make([]byte, maxMsgSizeBytes-30),
},
},
}
err = wal.Write(msg)
if assert.Error(t, err) {
assert.Contains(t, err.Error(), "msg is too big")
}
}
func TestWALSearchForEndHeight(t *testing.T) {

View File

@@ -5,6 +5,11 @@ import (
"fmt"
"github.com/pkg/errors"
"github.com/tendermint/tendermint/crypto/tmhash"
)
const (
maxAunts = 100
)
// SimpleProof represents a simple Merkle proof.
@@ -108,6 +113,30 @@ func (sp *SimpleProof) StringIndented(indent string) string {
indent)
}
// ValidateBasic performs basic validation.
// NOTE: - it expects LeafHash and Aunts of tmhash.Size size
// - it expects no more than 100 aunts
func (sp *SimpleProof) ValidateBasic() error {
if sp.Total < 0 {
return errors.New("negative Total")
}
if sp.Index < 0 {
return errors.New("negative Index")
}
if len(sp.LeafHash) != tmhash.Size {
return errors.Errorf("expected LeafHash size to be %d, got %d", tmhash.Size, len(sp.LeafHash))
}
if len(sp.Aunts) > maxAunts {
return errors.Errorf("expected no more than %d aunts, got %d", maxAunts, len(sp.Aunts))
}
for i, auntHash := range sp.Aunts {
if len(auntHash) != tmhash.Size {
return errors.Errorf("expected Aunts#%d size to be %d, got %d", i, tmhash.Size, len(auntHash))
}
}
return nil
}
// Use the leafHash and innerHashes to get the root merkle hash.
// If the length of the innerHashes slice isn't exactly correct, the result is nil.
// Recursive impl.

View File

@@ -0,0 +1,38 @@
package merkle
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSimpleProofValidateBasic(t *testing.T) {
testCases := []struct {
testName string
malleateProof func(*SimpleProof)
errStr string
}{
{"Good", func(sp *SimpleProof) {}, ""},
{"Negative Total", func(sp *SimpleProof) { sp.Total = -1 }, "negative Total"},
{"Negative Index", func(sp *SimpleProof) { sp.Index = -1 }, "negative Index"},
{"Invalid LeafHash", func(sp *SimpleProof) { sp.LeafHash = make([]byte, 10) }, "expected LeafHash size to be 32, got 10"},
{"Too many Aunts", func(sp *SimpleProof) { sp.Aunts = make([][]byte, maxAunts+1) }, "expected no more than 100 aunts, got 101"},
{"Invalid Aunt", func(sp *SimpleProof) { sp.Aunts[0] = make([]byte, 10) }, "expected Aunts#0 size to be 32, got 10"},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.testName, func(t *testing.T) {
_, proofs := SimpleProofsFromByteSlices([][]byte{
[]byte("apple"),
[]byte("watermelon"),
[]byte("kiwi"),
})
tc.malleateProof(proofs[0])
err := proofs[0].ValidateBasic()
if tc.errStr != "" {
assert.Contains(t, err.Error(), tc.errStr)
}
})
}
}

View File

@@ -21,6 +21,11 @@ func NewPubKeyMultisigThreshold(k int, pubkeys []crypto.PubKey) crypto.PubKey {
if len(pubkeys) < k {
panic("threshold k of n multisignature: len(pubkeys) < k")
}
for _, pubkey := range pubkeys {
if pubkey == nil {
panic("nil pubkey")
}
}
return PubKeyMultisigThreshold{uint(k), pubkeys}
}

View File

@@ -288,6 +288,8 @@ func computeHashFromAunts(index, total int, leafHash []byte, innerHashes [][]byt
}
```
The number of aunts is limited to 100 (`maxAunts`) to protect the node against DOS attacks.
### IAVL+ Tree
Because Tendermint only uses a Simple Merkle Tree, application developers are expect to use their own Merkle tree in their applications. For example, the IAVL+ Tree - an immutable self-balancing binary tree for persisting application state is used by the [Cosmos SDK](https://github.com/cosmos/cosmos-sdk/blob/master/docs/clients/lite/specification.md)

View File

@@ -96,11 +96,13 @@ type PeerRoundState struct {
## Receive method of Consensus reactor
The entry point of the Consensus reactor is a receive method. When a message is received from a peer p,
normally the peer round state is updated correspondingly, and some messages
are passed for further processing, for example to ConsensusState service. We now specify the processing of messages
in the receive method of Consensus reactor for each message type. In the following message handler, `rs` and `prs` denote
`RoundState` and `PeerRoundState`, respectively.
The entry point of the Consensus reactor is a receive method. When a message is
received from a peer p, normally the peer round state is updated
correspondingly, and some messages are passed for further processing, for
example to ConsensusState service. We now specify the processing of messages in
the receive method of Consensus reactor for each message type. In the following
message handler, `rs` and `prs` denote `RoundState` and `PeerRoundState`,
respectively.
### NewRoundStepMessage handler
@@ -134,13 +136,16 @@ handleMessage(msg):
```
handleMessage(msg):
if prs.Height != msg.Height then return
if prs.Round != msg.Round && !msg.IsCommit then return
prs.ProposalBlockPartsHeader = msg.BlockPartsHeader
prs.ProposalBlockParts = msg.BlockParts
```
The number of block parts is limited to 1601 (`types.MaxBlockPartsCount`) to
protect the node against DOS attacks.
### HasVoteMessage handler
```
@@ -179,6 +184,9 @@ handleMessage(msg):
prs.ProposalPOL = msg.ProposalPOL
```
The number of votes is limited to 10000 (`types.MaxVotesCount`) to protect the
node against DOS attacks.
### BlockPartMessage handler
```
@@ -203,6 +211,9 @@ handleMessage(msg):
Update prs for the bit-array of votes peer claims to have for the msg.BlockID
```
The number of votes is limited to 10000 (`types.MaxVotesCount`) to protect the
node against DOS attacks.
## Gossip Data Routine
It is used to send the following messages to the peer: `BlockPartMessage`, `ProposalMessage` and
@@ -338,7 +349,7 @@ BlockID has seen +2/3 votes. This routine is based on the local RoundState (`rs`
## Broadcast routine
The Broadcast routine subscribes to an internal event bus to receive new round steps and votes messages, and broadcasts messages to peers upon receiving those
The Broadcast routine subscribes to an internal event bus to receive new round steps and votes messages, and broadcasts messages to peers upon receiving those
events.
It broadcasts `NewRoundStepMessage` or `CommitStepMessage` upon new round state event. Note that
broadcasting these messages does not depend on the PeerRoundState; it is sent on the StateChannel.

View File

@@ -7,21 +7,22 @@ import (
"crypto/sha256"
"crypto/subtle"
"encoding/binary"
"errors"
"io"
"math"
"net"
"sync"
"time"
pool "github.com/libp2p/go-buffer-pool"
"github.com/pkg/errors"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/curve25519"
"golang.org/x/crypto/hkdf"
"golang.org/x/crypto/nacl/box"
pool "github.com/libp2p/go-buffer-pool"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
cmn "github.com/tendermint/tendermint/libs/common"
"golang.org/x/crypto/hkdf"
)
// 4 + 1024 == 1028 total frame size
@@ -107,11 +108,11 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
sendAead, err := chacha20poly1305.New(sendSecret[:])
if err != nil {
return nil, errors.New("Invalid send SecretConnection Key")
return nil, errors.New("invalid send SecretConnection Key")
}
recvAead, err := chacha20poly1305.New(recvSecret[:])
if err != nil {
return nil, errors.New("Invalid receive SecretConnection Key")
return nil, errors.New("invalid receive SecretConnection Key")
}
// Construct SecretConnection.
sc := &SecretConnection{
@@ -133,8 +134,13 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
}
remPubKey, remSignature := authSigMsg.Key, authSigMsg.Sig
if _, ok := remPubKey.(ed25519.PubKeyEd25519); !ok {
return nil, errors.Errorf("expected ed25519 pubkey, got %T", remPubKey)
}
if !remPubKey.VerifyBytes(challenge[:], remSignature) {
return nil, errors.New("Challenge verification failed")
return nil, errors.New("challenge verification failed")
}
// We've authorized.
@@ -217,7 +223,7 @@ func (sc *SecretConnection) Read(data []byte) (n int, err error) {
defer pool.Put(frame)
_, err = sc.recvAead.Open(frame[:0], sc.recvNonce[:], sealedFrame, nil)
if err != nil {
return n, errors.New("Failed to decrypt SecretConnection")
return n, errors.New("failed to decrypt SecretConnection")
}
incrNonce(sc.recvNonce)
// end decryption

View File

@@ -17,7 +17,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/secp256k1"
cmn "github.com/tendermint/tendermint/libs/common"
)
@@ -366,6 +368,51 @@ func TestDeriveSecretsAndChallengeGolden(t *testing.T) {
}
}
type privKeyWithNilPubKey struct {
orig crypto.PrivKey
}
func (pk privKeyWithNilPubKey) Bytes() []byte { return pk.orig.Bytes() }
func (pk privKeyWithNilPubKey) Sign(msg []byte) ([]byte, error) { return pk.orig.Sign(msg) }
func (pk privKeyWithNilPubKey) PubKey() crypto.PubKey { return nil }
func (pk privKeyWithNilPubKey) Equals(pk2 crypto.PrivKey) bool { return pk.orig.Equals(pk2) }
func TestNilPubkey(t *testing.T) {
var fooConn, barConn = makeKVStoreConnPair()
var fooPrvKey = ed25519.GenPrivKey()
var barPrvKey = privKeyWithNilPubKey{ed25519.GenPrivKey()}
go func() {
_, err := MakeSecretConnection(barConn, barPrvKey)
assert.NoError(t, err)
}()
assert.NotPanics(t, func() {
_, err := MakeSecretConnection(fooConn, fooPrvKey)
if assert.Error(t, err) {
assert.Equal(t, "expected ed25519 pubkey, got <nil>", err.Error())
}
})
}
func TestNonEd25519Pubkey(t *testing.T) {
var fooConn, barConn = makeKVStoreConnPair()
var fooPrvKey = ed25519.GenPrivKey()
var barPrvKey = secp256k1.GenPrivKey()
go func() {
_, err := MakeSecretConnection(barConn, barPrvKey)
assert.NoError(t, err)
}()
assert.NotPanics(t, func() {
_, err := MakeSecretConnection(fooConn, fooPrvKey)
if assert.Error(t, err) {
assert.Equal(t, "expected ed25519 pubkey, got secp256k1.PubKeySecp256k1", err.Error())
}
})
}
// Creates the data for a test vector file.
// The file format is:
// Hex(diffie_hellman_secret), loc_is_least, Hex(recvSecret), Hex(sendSecret), Hex(challenge)

View File

@@ -6,6 +6,8 @@ import (
"net"
"time"
"github.com/pkg/errors"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/p2p/conn"
)
@@ -270,6 +272,23 @@ func (mt *MultiplexTransport) acceptPeers() {
//
// [0] https://en.wikipedia.org/wiki/Head-of-line_blocking
go func(c net.Conn) {
defer func() {
if r := recover(); r != nil {
err := ErrRejected{
conn: c,
err: errors.Errorf("recovered from panic: %v", r),
isAuthFailure: true,
}
select {
case mt.acceptc <- accept{err: err}:
case <-mt.closec:
// Give up if the transport was closed.
_ = c.Close()
return
}
}
}()
var (
nodeInfo NodeInfo
secretConn *conn.SecretConnection

View File

@@ -56,8 +56,8 @@ func main() {
_, err = os.Stdout.Write([]byte("\n"))
}
if err == nil {
if end, ok := msg.Msg.(cs.EndHeightMessage); ok {
_, err = os.Stdout.Write([]byte(fmt.Sprintf("ENDHEIGHT %d\n", end.Height))) // nolint: errcheck, gas
if endMsg, ok := msg.Msg.(cs.EndHeightMessage); ok {
_, err = os.Stdout.Write([]byte(fmt.Sprintf("ENDHEIGHT %d\n", endMsg.Height))) // nolint: errcheck, gas
}
}
if err != nil {

View File

@@ -14,6 +14,9 @@ const (
// BlockPartSizeBytes is the size of one block part.
BlockPartSizeBytes = 65536 // 64kB
// MaxBlockPartsCount is the maximum count of block parts.
MaxBlockPartsCount = (MaxBlockSizeBytes / BlockPartSizeBytes) + 1
)
// ConsensusParams contains consensus critical parameters that determine the

View File

@@ -26,10 +26,13 @@ type Part struct {
// ValidateBasic performs basic validation.
func (part *Part) ValidateBasic() error {
if part.Index < 0 {
return errors.New("Negative Index")
return errors.New("negative Index")
}
if len(part.Bytes) > BlockPartSizeBytes {
return fmt.Errorf("Too big (max: %d)", BlockPartSizeBytes)
return errors.Errorf("too big: %d bytes, max: %d", len(part.Bytes), BlockPartSizeBytes)
}
if err := part.Proof.ValidateBasic(); err != nil {
return errors.Wrap(err, "wrong Proof")
}
return nil
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/merkle"
cmn "github.com/tendermint/tendermint/libs/common"
)
@@ -115,6 +116,13 @@ func TestPartValidateBasic(t *testing.T) {
{"Good Part", func(pt *Part) {}, false},
{"Negative index", func(pt *Part) { pt.Index = -1 }, true},
{"Too big part", func(pt *Part) { pt.Bytes = make([]byte, BlockPartSizeBytes+1) }, true},
{"Too big proof", func(pt *Part) {
pt.Proof = merkle.SimpleProof{
Total: 1,
Index: 1,
LeafHash: make([]byte, 1024*1024),
}
}, true},
}
for _, tc := range testCases {

View File

@@ -11,6 +11,12 @@ import (
cmn "github.com/tendermint/tendermint/libs/common"
)
const (
// MaxVotesCount is the maximum votes count. Used in ValidateBasic funcs for
// protection against DOS attacks.
MaxVotesCount = 10000
)
// UNSTABLE
// XXX: duplicate of p2p.ID to avoid dependence between packages.
// Perhaps we can have a minimal types package containing this (and other things?)

View File

@@ -20,7 +20,7 @@ const (
// Must be a string because scripts like dist.sh read this file.
// XXX: Don't change the name of this variable or you will break
// automation :)
TMCoreSemVer = "0.32.4"
TMCoreSemVer = "0.32.7"
// ABCISemVer is the semantic version of the ABCI library
ABCISemVer = "0.16.1"