Implements a raw consensus algorithm. The system supports pluggable consensus per virtual machine, meaning multiple consensus algorithms running side by side on different virtual chains. Abstracts away the details of how the consensus algorithm works and provides the system with a single unified interface.
Controls and drives the timing of consensus, for example, when new blocks are committed or when new blocks need to be proposed and populated with transactions from the pool.
Note: ConsensusAlgo
is not in charge of block sync (BlockStorage
is), and it does not deal with block content (ConsensusContext
does).
Currently, a single instance per virtual chain per node (per supported algorithm).
ConsensusContext
- Calls it during consensus when system interface regarding the block content is required.BlockStorage
- Requests block headers from it to be on the consensus frontline and participate.Gossip
- Uses it to communicate with other nodes.
- Not persistent.
last_committed_block
- The last valid committed block from the previous round (persistent).
- Initialize the configuration.
- Load persistent data (if present)
- Subscribe to gossip messages by calling
Gossip.LeanHelix.RegisterLeanHelixHandler
. - Register to handle transactions and results blocks validation by calling
BlockStorage.ConsensusBlocksHandler
.- Wait until registered successfully.
- Wait for
HandleConsensusBlock
fromBlockStorage
to start the consensus algorithm.
Called internally when the consensus algorithm decides a new term (block height) starts, probably after the last block was committed.
- Assumes the block height for the upcoming round is known.
- Get the previously committed block pair by calling
BlockStorage.GetTransactionsBlockHeader
andBlockStorage.GetResultsBlockHeader
.- Store it in
last_committed_block
for the benefit of the next steps in this round. - It is recommended to cache the committed block from the previous round to prevent fetching this data.
- If fails or times out, skip this round and don't participate (the node is probably out of sync).
- Store it in
- Calculate the random seed from the previous block.
- Get the desired committee size from
config.LEAN_HELIX_CONSENSUS_MINIMUM_COMMITTEE_SIZE
. - Get a sorted list of committee members for the upcoming Transactions block (ordering phase) by calling
ConsensusContext.RequestOrderingCommittee
. - Get a sorted list of committee members for the upcoming Results block (validation phase) by calling
ConsensusContext.RequestValidationCommittee
. - Note: If the consensus algorithm relies on a single committee for both, call
ConsensusContext.RequestValidationCommittee
only based on the Results block random seed.
- Note to self that participating in this round as leader.
- Get the desired block size from
config.DESIRED_BLOCK_SIZE_IN_BYTES
. - Request new Transactions block proposal (ordering phase) by calling
ConsensusContext.RequestNewTransactionsBlock
. - Request new Results block proposal (validation phase) by calling
ConsensusContext.RequestNewResultsBlock
. - Sign both proposals (according to the algo spec) - on the hash of the header.
- Send signed proposals to the algo of all committee nodes (according to the algo spec) by calling
Gossip.SendMessage
.
- Note to self that participating in this round as non-leader committee member.
- Note to self that participating in this round as a non-committee member.
- Just waiting for the committed block, without taking part in the consensus.
Called internally when, during consensus, a non-leader committee member receives a proposal for a new block by the leader.
- Wait until decided if participating in this round or not (
OnNewConsensusRound
) as a non-leader committee member.
- Perform algorithm related checks on the proposal:
- Signature, block height, previous block pair hash pointers.
- Get the desired block size from
config.DESIRED_BLOCK_SIZE_IN_BYTES
and validate it. - Validate the Transactions block (ordering phase) by calling
ConsensusContext.ValidateTransactionsBlock
. - Validate the Results block (validation phase) by calling
ConsensusContext.ValidateResultsBlock
.
- Sign both approvals (according to the algo spec) - on the hash of the header.
- Send signed approvals to the algo of all committee nodes (according to the algo spec) by calling
Gossip.SendMessage
.
Called internally for committee members (leader or not) when the consensus algorithm has decided a block proposal can be committed.
- Wait until decided if participating in this round or not (
OnNewConsensusRound
) as a committee member (leader or not).
- Pass the committed block (including the block proofs) to block storage by calling
BlockStorage.CommitBlock
.
Called internally for non-committee members when they receive a new claimed committed block to validate that it was committed under consensus.
- Wait until decided if participating in this round or not (
OnNewConsensusRound
) as not a committee member.
- Correct block protocol version.
- Correct virtual chain.
- Check block height:
- If the block isn't the next of
last_commited_block
according to height, discard.
- If the block isn't the next of
- Check the block's
transactions_root_hash
:- Calculate the merkle root hash of the block's transactions and verify the hash in the header.
- Check the block's metadata hash:
- Calculate the hash of the block's metadata and verify the hash in the header.
- Correct block protocol version.
- Correct virtual chain.
- Check block height:
- If the block isn't the next of
last_commited_block
according to height, discard.
- If the block isn't the next of
- Check the block's
receipts_root_hash
:- Calculate the merkle root hash of the block's receipts and verify the hash in the header.
- Check the block's
state_diff_hash
:- Calculate the hash of the block's state diff and verify the hash in the header.
Note: The logic up to here also appears in BlockStorage
and should probably be extracted to avoid duplication.
- Check consensus of the block by calling
HandleBlockConsensus
.
- Pass the committed block (including the block proofs) to block storage by calling
BlockStorage.CommitBlock
.
Validates the consensus for an untrusted block header and updates the algo state based on the requested mode. Called internally and by block storage during block sync or init.
- If mode =
HANDLE_BLOCK_CONSENSUS_MODE_VERIFY_AND_UPDATE
orHANDLE_BLOCK_CONSENSUS_MODE_VERIFY_ONLY
, perform headers checks by callingVerifyBlockConsensus
.
- If mode =
HANDLE_BLOCK_CONSENSUS_MODE_VERIFY_AND_UPDATE
and all checks are valid or if mode =HANDLE_BLOCK_CONSENSUS_MODE_UPDATE_ONLY
, update the consensus algorithm about the block commit (with block height and consensus dependent data).
Validates the consensus for an untrusted block header. Ignores whether the block body (content) is valid and its relevant hash values match the ones in the header. Called by
HandleBlockConsensus
.
- For both Transaction block header and Results block header, verify the previous block hash pointer matches the hash of the previous block (given).
- Calculate the random seed from the previous block (given).
- Get the desired committee size from
config.LEAN_HELIX_CONSENSUS_MINIMUM_COMMITTEE_SIZE
. - Get a sorted list of committee members for the block by calling
ConsensusContext.RequestValidationCommittee
.- Note: When the consensus algorithm relies on a single committee for both, it uses the
ConsensusContext.RequestValidationCommittee
based on the Results block random seed.
- Note: When the consensus algorithm relies on a single committee for both, it uses the
- For both Transaction block and Results block, verify the block proof based on the committee members.
Handles a gossip message from another node. Relevant messages include algorithm-specific consensus messages.
- Depends on consensus algorithm.
Handles the transactions and results blocks validation requests, called by
BlockStorage
.
- Handle by calling
HandleBlockConsensus
.
Handles gossip messages from other nodes. Relevant messages include block sync messages.
- Handles
LEAN_HELIX_PRE_PREPARE
messages, seelean-helix
flow.
- Handles
LEAN_HELIX_PREPARE
messages, seelean-helix
flow.
- Handles
LEAN_HELIX_COMMIT
messages, seelean-helix
flow.
- Handles
LEAN_HELIX_VIEW_CHANGE
messages, seelean-helix
flow.
- Handles
LEAN_HELIX_NEW_VIEW
messages, seelean-helix
flow.