213 lines
7.3 KiB
Markdown
Raw Normal View History

2018-01-03 10:46:43 +01:00
# Tendermint Consensus Reactor
2018-01-03 10:46:43 +01:00
Tendermint Consensus is a distributed protocol executed by validator processes to agree on
the next block to be added to the Tendermint blockchain. The protocol proceeds in rounds, where
each round is a try to reach agreement on the next block. A round starts by having a dedicated
process (called proposer) suggesting to other processes what should be the next block with
the `ProposalMessage`.
2018-01-03 11:29:19 +01:00
The processes respond by voting for a block with `VoteMessage` (there are two kinds of vote
messages, prevote and precommit votes). Note that a proposal message is just a suggestion what the
next block should be; a validator might vote with a `VoteMessage` for a different block. If in some
round, enough number of processes vote for the same block, then this block is committed and later
added to the blockchain. `ProposalMessage` and `VoteMessage` are signed by the private key of the
validator. The internals of the protocol and how it ensures safety and liveness properties are
explained in a forthcoming document.
2018-01-03 11:29:19 +01:00
For efficiency reasons, validators in Tendermint consensus protocol do not agree directly on the
block as the block size is big, i.e., they don't embed the block inside `Proposal` and
`VoteMessage`. Instead, they reach agreement on the `BlockID` (see `BlockID` definition in
2018-05-23 10:01:32 -04:00
[Blockchain](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/blockchain.md#blockid) section) that uniquely identifies each block. The block itself is
2018-01-03 11:29:19 +01:00
disseminated to validator processes using peer-to-peer gossiping protocol. It starts by having a
proposer first splitting a block into a number of block parts, that are then gossiped between
processes using `BlockPartMessage`.
2018-01-03 10:46:43 +01:00
Validators in Tendermint communicate by peer-to-peer gossiping protocol. Each validator is connected
only to a subset of processes called peers. By the gossiping protocol, a validator send to its peers
all needed information (`ProposalMessage`, `VoteMessage` and `BlockPartMessage`) so they can
2018-01-03 11:29:19 +01:00
reach agreement on some block, and also obtain the content of the chosen block (block parts). As
part of the gossiping protocol, processes also send auxiliary messages that inform peers about the
2018-01-03 10:46:43 +01:00
executed steps of the core consensus algorithm (`NewRoundStepMessage` and `CommitStepMessage`), and
also messages that inform peers what votes the process has seen (`HasVoteMessage`,
2018-01-03 11:29:19 +01:00
`VoteSetMaj23Message` and `VoteSetBitsMessage`). These messages are then used in the gossiping
protocol to determine what messages a process should send to its peers.
2018-01-03 10:46:43 +01:00
We now describe the content of each message exchanged during Tendermint consensus protocol.
## ProposalMessage
2018-01-03 10:46:43 +01:00
ProposalMessage is sent when a new block is proposed. It is a suggestion of what the
next block in the blockchain should be.
2018-01-03 10:46:43 +01:00
```go
type ProposalMessage struct {
2018-01-03 10:46:43 +01:00
Proposal Proposal
}
```
2018-01-03 10:46:43 +01:00
### Proposal
2018-01-03 10:46:43 +01:00
2018-01-03 11:29:19 +01:00
Proposal contains height and round for which this proposal is made, BlockID as a unique identifier
of proposed block, timestamp, and two fields (POLRound and POLBlockID) that are needed for
termination of the consensus. The message is signed by the validator private key.
2018-01-03 10:46:43 +01:00
```go
type Proposal struct {
2018-01-03 10:46:43 +01:00
Height int64
Round int
Timestamp Time
BlockID BlockID
POLRound int
POLBlockID BlockID
Signature Signature
}
```
NOTE: In the current version of the Tendermint, the consensus value in proposal is represented with
2018-01-03 10:46:43 +01:00
PartSetHeader, and with BlockID in vote message. It should be aligned as suggested in this spec as
BlockID contains PartSetHeader.
## VoteMessage
2018-01-03 10:46:43 +01:00
2018-01-03 11:29:19 +01:00
VoteMessage is sent to vote for some block (or to inform others that a process does not vote in the
2018-05-23 10:01:32 -04:00
current round). Vote is defined in the [Blockchain](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/blockchain.md#blockid) section and contains validator's
2018-01-03 11:29:19 +01:00
information (validator address and index), height and round for which the vote is sent, vote type,
blockID if process vote for some block (`nil` otherwise) and a timestamp when the vote is sent. The
message is signed by the validator private key.
2018-01-03 10:46:43 +01:00
```go
type VoteMessage struct {
2018-01-03 10:46:43 +01:00
Vote Vote
}
```
## BlockPartMessage
2018-01-03 10:46:43 +01:00
BlockPartMessage is sent when gossipping a piece of the proposed block. It contains height, round
and the block part.
```go
type BlockPartMessage struct {
2018-01-03 10:46:43 +01:00
Height int64
Round int
Part Part
}
```
2018-01-03 10:46:43 +01:00
## ProposalHeartbeatMessage
ProposalHeartbeatMessage is sent to signal that a node is alive and waiting for transactions
to be able to create a next block proposal.
2018-01-03 10:46:43 +01:00
```go
type ProposalHeartbeatMessage struct {
Heartbeat Heartbeat
}
```
### Heartbeat
2018-01-03 10:46:43 +01:00
Heartbeat contains validator information (address and index),
2018-01-03 10:46:43 +01:00
height, round and sequence number. It is signed by the private key of the validator.
2018-01-03 10:46:43 +01:00
```go
type Heartbeat struct {
2018-01-03 10:46:43 +01:00
ValidatorAddress []byte
ValidatorIndex int
Height int64
Round int
Sequence int
Signature Signature
}
```
## NewRoundStepMessage
2018-01-03 10:46:43 +01:00
2018-01-03 11:29:19 +01:00
NewRoundStepMessage is sent for every step transition during the core consensus algorithm execution.
It is used in the gossip part of the Tendermint protocol to inform peers about a current
height/round/step a process is in.
2018-01-03 10:46:43 +01:00
```go
type NewRoundStepMessage struct {
2018-01-03 10:46:43 +01:00
Height int64
Round int
Step RoundStepType
SecondsSinceStartTime int
LastCommitRound int
}
```
## CommitStepMessage
2018-01-03 10:46:43 +01:00
2018-01-03 11:29:19 +01:00
CommitStepMessage is sent when an agreement on some block is reached. It contains height for which
agreement is reached, block parts header that describes the decided block and is used to obtain all
block parts, and a bit array of the block parts a process currently has, so its peers can know what
parts it is missing so they can send them.
2018-01-03 10:46:43 +01:00
```go
type CommitStepMessage struct {
2018-01-03 10:46:43 +01:00
Height int64
BlockID BlockID
BlockParts BitArray
}
```
2018-01-03 10:46:43 +01:00
TODO: We use BlockID instead of BlockPartsHeader (in current implementation) for symmetry.
## ProposalPOLMessage
2018-01-03 10:46:43 +01:00
ProposalPOLMessage is sent when a previous block is re-proposed.
It is used to inform peers in what round the process learned for this block (ProposalPOLRound),
2018-01-03 10:46:43 +01:00
and what prevotes for the re-proposed block the process has.
```go
type ProposalPOLMessage struct {
2018-01-03 10:46:43 +01:00
Height int64
ProposalPOLRound int
ProposalPOL BitArray
}
```
## HasVoteMessage
2018-01-03 10:46:43 +01:00
HasVoteMessage is sent to indicate that a particular vote has been received. It contains height,
round, vote type and the index of the validator that is the originator of the corresponding vote.
```go
type HasVoteMessage struct {
2018-01-03 10:46:43 +01:00
Height int64
Round int
Type byte
Index int
}
```
## VoteSetMaj23Message
2018-01-03 10:46:43 +01:00
VoteSetMaj23Message is sent to indicate that a process has seen +2/3 votes for some BlockID.
2018-01-03 10:46:43 +01:00
It contains height, round, vote type and the BlockID.
2018-01-03 10:46:43 +01:00
```go
type VoteSetMaj23Message struct {
2018-01-03 10:46:43 +01:00
Height int64
Round int
Type byte
BlockID BlockID
}
```
## VoteSetBitsMessage
2018-01-03 10:46:43 +01:00
VoteSetBitsMessage is sent to communicate the bit-array of votes a process has seen for a given
BlockID. It contains height, round, vote type, BlockID and a bit array of
the votes a process has.
2018-01-03 10:46:43 +01:00
```go
type VoteSetBitsMessage struct {
2018-01-03 10:46:43 +01:00
Height int64
Round int
Type byte
BlockID BlockID
Votes BitArray
}
```