Consensus Protocol
Consensus Message Format#
ExtensiblePayload#
| Size | Field | Type | Description |
|---|---|---|---|
| ? | Category | String | Message category, currently is dBFT |
| 4 | ValidBlockStart | uint | Starting height where message is valid |
| 4 | ValidBlockEnd | uint | Ending height where message is valid |
| 20 | Sender | UInt160 | The address hash of the current consensus node |
| ? | Data | byte[] | The data includes ChangeView, PrepareRequest, PrepareResponse, Commit, RecoveryMessage, RecoveryRequest |
| ? | Witness | Witness | Witness contains invocation script and verification script |
ConsensusMessage#
ConsensusMessage is the basic abstract type of all consensus message types. Other consensus message types are all inherited from this type.
| Size | Field | Type | Description |
|---|---|---|---|
| 1 | Type | ConsensusMessageType | Includes ChangeView, PrepareRequest, PrepareResponse, Commit, RecoveryMessage, RecoveryRequest |
| 4 | BlockIndex | uint | Height where message is created |
| 1 | ValidatorIndex | byte | The index of the sender in validators array |
| 1 | ViewNumber | byte | View number where message is created |
ChangeView#
| Size | Field | Type | Description |
|---|---|---|---|
| 8 | Timestamp | ulong | Timestamp when the ChangeView message is created |
| 1 | Reason | ChangeViewReason | Reason for the view change |
Commit#
| Size | Field | Type | Description |
|---|---|---|---|
| ? | Signature | byte[] | Message signature |
PrepareRequest#
| Size | Field | Type | Description |
|---|---|---|---|
| 4 | Version | uint | Default value is 0 |
| 32 | PrevHash | UInt256 | Previous block's hash |
| 8 | Timestamp | ulong | Timestamp when the PrepareRequest message is created |
| ? | TransactionHashes | UInt256[] | The transaction hashes in the block |
PrepareResponse#
| Size | Field | Type | Description |
|---|---|---|---|
| 32 | PreparationHash | UInt256 | Hash of corresponding prepare request |
RecoveryMessage#
| Size | Field | Type | Description |
|---|---|---|---|
| ? | ChangeViewMessages | Dictionary<int, ChangeViewPayloadCompact> | ChangeView messages |
| ? | PrepareRequestMessage | PrepareRequest | The current PrepareRequest message |
| 32 | PreparationHash | UInt256 | Hash of prepare request |
| ? | PreparationMessages | Dictionary<int, PreparationPayloadCompact> | Preparation messages that have been collected |
| ? | CommitMessages | Dictionary<int, CommitPayloadCompact> | Commit messages that have been collected |
RecoveryRequest#
| Size | Field | Type | Description |
|---|---|---|---|
| 8 | Timestamp | ulong | Timestamp when the message is created |
Transport Protocol#
When a consensus message enters the P2P network, it's broadcasted and transmitted like other messages. That is because consensus nodes do not have IP address of other consensus nodes. Consensus nodes are not directly connected. That is to say, ordinary nodes can also receive consensus message. The broadcast flow of consensus messages is as follows.

Consensus node A will directly broadcast 'consensus' message to connected nodes(e.g. node B).
After receiving the
consensusmessage, node B firstly process the received consensus message and then forwards it. Before forwarding the consensus message, it sends aninvmessage which carries the hash data of thepayloadof theconsensusmessage (to node C).If the node C has already known the data corresponding to the hash, it does not process the inv message. Otherwise, it proceeds to step 4.
Node C sends a
getdatamessage to node B, with the hash data in theinvmessage.After receiving the
getdatamessage, node B sends aconsensusmessage to node C.After receiving the
consensusmessage, the node C triggers the consensus module to process the message, and forwards the consensus message, and then returns to step 2.
Both inv and getdata messages use InvPayload as the message carrier, which is defined as follows:
InvPayload#
| Size | Field | Type | Description |
|---|---|---|---|
| 1 | Type | InventoryType | Message type |
| ? | Hashes | UInt256[] | Hashes broadcasted / requested |
There are 3 kinds of InventoryType:
0x2b: Transaction.Hashesis assigned to the transaction.0x2c: Block.Hashesis assigned to the block.0x2e: Consensus.Hashesis assigned to theConsensusPayloadmessage.
Consensus Message Process#
Verification#
Ignore the message if
ValidBlockStartis lower thanValidBlockEnd.Ignore the message if current block height is out of
[ValidBlockStart, ValidBlockEnd).Ignore the message if sender is not listed in the consensus white list.
Ignore the message if the verification script failed or
Categoryis not "dBFT".Ignore the message if the node has sent out the new block.
Ignore the message if the consensus message data is in a wrong format.
Ignore the message if the
message.BlockIndexis lower than the current block height.Ignore the message if the
ConsensusPayload.ValidatorIndexis out of index of the current consensus nodes array, orpayload.Senderis different from the correct hash.
Process#
On receiving a
PrepareRequestsent by speaker, attached with proposal block data.Ignore if the
PrepareRequesthas already been received or the node is trying to change the view.Ignore if the
message.ValidatorIndexis not the index of the current round speaker or thePrepareRequest.ViewNumberis not equal to the current view number.Ignore if
message.Versionormessage.PrevHashis different from the local context.Ignore if transactions' amount is over
MaxTransactionsPerBlock.Ignore if the
message.Timestampis not more than the timestamp of the previous block, or is more than 8 blocks above current time.Ignore if any proposed transaction has already been included in the blockchain
Renew consensus context and clear invalid signatures that have been received (Prepare-Reponse may arrive first)
Save the signature of the speaker into current context.
If there's no transaction in this request, directly check the local collection of
PrepareResponse, and broadcast theCommitmessage in case of enoughPrepareResponsecollected.Collect and verify transactions in the proposal block from memory pool.
Ignore if the transaction failed to pass verification or the transaction did not meet strategic requirements.
Otherwise the transaction will be saved into current consensus context.
Verify the transactions required by blocks in the unconfirmed transaction pool and add them into current context.
Broadcast a
getdatamessage with a list of transaction hashes if they were missed in the block.
On receiving a
PrepareResponsesent by consensus nodes with their signature.Ignore it if the message view is not the same as the current view
Ignore it if current node has already saved the sender's signature or the current node is trying to change the view.
Save it temporarily if current node has not received PrepareResponse yet (Clear it after receiving PrepareResponse), or go to next step.
Verify the signature. Save the signature if it pass the verification. Ignore it if not.
Ignore it if the node has already sent
Commit.Verify the signature number if the node has already sent or received
PrepareRequest. If there are at leastN-fsignatures, broadcastCommitand generate the block if there areN-fCommitmessages have been received.
On receiving a
Changeviewsent by consensus nodes.Send
RecoveryMessageif the new view number in the message is less than or equal to the view number in current context.Ignore it if the node has sent
Commit.If current node received at least
N-fChangeViewmessages with the same new view number, then ViewChange will happen. The current node reset the consensus process with the new view number.
On receiving a
Commitsend by consensus nodes after receivingN-fPrepareResponse.Ignore it if it has been received from the same node before.
Save the message into the consensus context if the signature passed verification, generate a block and broadcast if
N-fCommit messages has been received.
On receiving a
RecoveryRequestsent by consensus nodes when initiating a consensus or the sum of committed and failed nodes is greater thanf.Ignore it if it has been received before.
Response it if the node has sent the
Commitmessage before or the node index is no more than f numbers later than the sender indexSend
RecoveryMessageif the node is obligated to response.
On receiving a
RecoveryMessagebroadcast by consensus nodes when receiving an accessibleRecoveryRequestor time out after a Commit message has been sent.Receive and handle
ChangeViewinside if the message view number is greater than the node view number.Then receive and handle
PrepareRequestandPrepareResponseinside if the message view number is equal to the node view number, and the node is not in the process of changing view or has not sentCommitbefore.Then receive and handle
Commitinside if the message view number is not greater than the node view number.
On receiving an
OnTimerIgnore if timer's height or view number is different from local context.
If the speaker timeout, the consensus node will broadcast
PrepareRequestfor the first timeout. For subsequent timeouts, it will broadcastRecoveryMessageifCommitmessage has been sent, otherwiseChangeView.If the delegate timeout, the consensus node will broadcast
RecoveryMessageifCommitmessage has been sent, otherwiseChangeView.
On receiving a
PersistCompletedResetting consensus process
On receiving a
New Transactionfor consensusIgnore if the current node has sent
PrepareRequestorPrepareResponsemessage, or in process of change view, or has sent new block in this roundIgnore if the transaction has been received before.
Ignore if the received transaction isn't in the proposal block.
Broadcast
ChangeViewif the transaction verification fails.Save the transaction into the proposal block.
Handle the corresponding logic if this is an Oracle transaction.
If the receiver is a delegate, broadcast the
ChangeViewmessage if the new block doesn't accord withMaxBlockSizeorMaxBlockSystemFee. It also checks local collection ofPrepareResponse, and broadcasts theCommitmessage in case of enoughPrepareResponsecollected.