Consensus Protocol
#
Consensus Message Format#
ExtensiblePayloadSize | 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 |
#
ConsensusMessageConsensusMessage 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 |
#
ChangeViewSize | Field | Type | Description |
---|---|---|---|
8 | Timestamp | ulong | Timestamp when the ChangeView message is created |
1 | Reason | ChangeViewReason | Reason for the view change |
#
CommitSize | Field | Type | Description |
---|---|---|---|
? | Signature | byte[] | Message signature |
#
PrepareRequestSize | 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 |
#
PrepareResponseSize | Field | Type | Description |
---|---|---|---|
32 | PreparationHash | UInt256 | Hash of corresponding prepare request |
#
RecoveryMessageSize | 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 |
#
RecoveryRequestSize | Field | Type | Description |
---|---|---|---|
8 | Timestamp | ulong | Timestamp when the message is created |
#
Transport ProtocolWhen 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
consensus
message, node B firstly process the received consensus message and then forwards it. Before forwarding the consensus message, it sends aninv
message which carries the hash data of thepayload
of theconsensus
message (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
getdata
message to node B, with the hash data in theinv
message.After receiving the
getdata
message, node B sends aconsensus
message to node C.After receiving the
consensus
message, 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:
#
InvPayloadSize | Field | Type | Description |
---|---|---|---|
1 | Type | InventoryType | Message type |
? | Hashes | UInt256[] | Hashes broadcasted / requested |
There are 3 kinds of InventoryType
:
0x2b
: Transaction.Hashes
is assigned to the transaction.0x2c
: Block.Hashes
is assigned to the block.0x2e
: Consensus.Hashes
is assigned to theConsensusPayload
message.
#
Consensus Message Process#
VerificationIgnore the message if
ValidBlockStart
is 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
Category
is 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.BlockIndex
is lower than the current block height.Ignore the message if the
ConsensusPayload.ValidatorIndex
is out of index of the current consensus nodes array, orpayload.Sender
is different from the correct hash.
#
ProcessOn receiving a
PrepareRequest
sent by speaker, attached with proposal block data.Ignore if the
PrepareRequest
has already been received or the node is trying to change the view.Ignore if the
message.ValidatorIndex
is not the index of the current round speaker or thePrepareRequest.ViewNumber
is not equal to the current view number.Ignore if
message.Version
ormessage.PrevHash
is different from the local context.Ignore if transactions' amount is over
MaxTransactionsPerBlock
.Ignore if the
message.Timestamp
is 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 theCommit
message in case of enoughPrepareResponse
collected.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
getdata
message with a list of transaction hashes if they were missed in the block.
On receiving a
PrepareResponse
sent 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-f
signatures, broadcastCommit
and generate the block if there areN-f
Commit
messages have been received.
On receiving a
Changeview
sent by consensus nodes.Send
RecoveryMessage
if 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-f
ChangeView
messages 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
Commit
send by consensus nodes after receivingN-f
PrepareResponse
.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-f
Commit messages has been received.
On receiving a
RecoveryRequest
sent 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
Commit
message before or the node index is no more than f numbers later than the sender indexSend
RecoveryMessage
if the node is obligated to response.
On receiving a
RecoveryMessage
broadcast by consensus nodes when receiving an accessibleRecoveryRequest
or time out after a Commit message has been sent.Receive and handle
ChangeView
inside if the message view number is greater than the node view number.Then receive and handle
PrepareRequest
andPrepareResponse
inside 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 sentCommit
before.Then receive and handle
Commit
inside if the message view number is not greater than the node view number.
On receiving an
OnTimer
Ignore if timer's height or view number is different from local context.
If the speaker timeout, the consensus node will broadcast
PrepareRequest
for the first timeout. For subsequent timeouts, it will broadcastRecoveryMessage
ifCommit
message has been sent, otherwiseChangeView
.If the delegate timeout, the consensus node will broadcast
RecoveryMessage
ifCommit
message has been sent, otherwiseChangeView
.
On receiving a
PersistCompleted
Resetting consensus process
On receiving a
New Transaction
for consensusIgnore if the current node has sent
PrepareRequest
orPrepareResponse
message, 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
ChangeView
if 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
ChangeView
message if the new block doesn't accord withMaxBlockSize
orMaxBlockSystemFee
. It also checks local collection ofPrepareResponse
, and broadcasts theCommit
message in case of enoughPrepareResponse
collected.