diff --git a/consensus/state.go b/consensus/state.go index da8710056..110c2529c 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1332,9 +1332,9 @@ 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). - me := EndHeightMessage{height} - if err := cs.wal.WriteSync(me); 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", me, err)) + 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 diff --git a/consensus/wal.go b/consensus/wal.go index 373f01a16..9cdb3c3f0 100644 --- a/consensus/wal.go +++ b/consensus/wal.go @@ -20,7 +20,7 @@ import ( const ( // must be greater than types.BlockPartSizeBytes + a few bytes - maxMsgSizeBytes = 1024 * 1024 // 1MB + maxMsgSizeBytes = types.BlockPartSizeBytes * 2 // how often the WAL should be sync'd during period sync'ing walDefaultFlushInterval = 2 * time.Second diff --git a/crypto/merkle/simple_proof.go b/crypto/merkle/simple_proof.go index 8bd2570f4..93b6f9fea 100644 --- a/crypto/merkle/simple_proof.go +++ b/crypto/merkle/simple_proof.go @@ -9,8 +9,7 @@ import ( ) const ( - // given maxMsgSizeBytes in consensus wal is 1MB - maxAunts = 30000 + maxAunts = 100 ) // SimpleProof represents a simple Merkle proof. @@ -115,7 +114,8 @@ func (sp *SimpleProof) StringIndented(indent string) string { } // ValidateBasic performs basic validation. -// NOTE: it expects LeafHash and Aunts of tmhash.Size size. +// 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") diff --git a/docs/spec/blockchain/encoding.md b/docs/spec/blockchain/encoding.md index 170e91605..a171020b0 100644 --- a/docs/spec/blockchain/encoding.md +++ b/docs/spec/blockchain/encoding.md @@ -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) diff --git a/docs/spec/reactors/consensus/consensus-reactor.md b/docs/spec/reactors/consensus/consensus-reactor.md index 47c6949a7..0f74c5f88 100644 --- a/docs/spec/reactors/consensus/consensus-reactor.md +++ b/docs/spec/reactors/consensus/consensus-reactor.md @@ -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. diff --git a/scripts/wal2json/main.go b/scripts/wal2json/main.go index ee90ecaa4..96aadd146 100644 --- a/scripts/wal2json/main.go +++ b/scripts/wal2json/main.go @@ -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 { diff --git a/types/params.go b/types/params.go index 834178f73..61c1d2da6 100644 --- a/types/params.go +++ b/types/params.go @@ -16,7 +16,7 @@ const ( BlockPartSizeBytes = 65536 // 64kB // MaxBlockPartsCount is the maximum count of block parts. - MaxBlockPartsCount = MaxBlockSizeBytes / BlockPartSizeBytes + MaxBlockPartsCount = (MaxBlockSizeBytes / BlockPartSizeBytes) + 1 ) // ConsensusParams contains consensus critical parameters that determine the