Skip to content
Yute Lin edited this page Oct 12, 2017 · 2 revisions

PR #166 Review Guide

This document is to help PR #166 review for Istanbul BFT to merge into Quorum.

The complete specification can be found in EIP 650

Commits

Commit breakdown

  • In Istanbul BFT implementation, we introduced another message exchange protocol 64 to support IBFT muplti-phrase consensus protocol. Therefore in consensus/consensus.go, we've added another function Protocol() for all consensus implementations to return their own supported protocols.
  • Handler interface in consensus/consensus.go: For consensus to handle incoming messages and new head blocks as well as to set the Broadcaster as the utility of block and message broadcasting.
  • Broadcaster interface in consensus/protocol.go:
    • Enqueue(): Adds a block into the fetcher queue, so the block will be inserted to blockchain through fetcher.
    • FindPeers(): Utility function to find validator peers.
  • In handleMsg() of eth/handler.go: If the consensus engine implements consensus.Handler, it would call handler.HandleMsg to handle the incoming message.
  • Istanbul implements consensus.Handler interface in consensus/istanbul/backend/handler.go.

Adds Istanbul config parameters in genesis.json. Inside the Istanbul configuration, Epoch and ProposerPolicy can be defined as well.

Sample configuration can be found in EIP 650

Adds validator running parameters. Usage details can be found in cmd/utils/flags.go.

Adds Istanbul configuration.

Adds function in node/service.go to return node key. We need this since we use node key's associated public key to whitelist the validator set. All consensus messages are going to be signed by the node key as well.

Adds Istanbul consensus engine interface, which inherits existing consensus engine and adds Start() and Stop() functions.

  • consensus/istanbul/backend.go: Defines the application backend interface for Istanbul core implementation.
  • consensus/istanbul/events.go: Defines events which are handled in backend core handler in consensus/istanbul/core/handler.go.
    • RequestEvent: Posted when a proposer proposes a block.
    • MessageEvent: Posted when receiving Istanbul consensus messages, which would essentially be handled in consensus/istanbul/core/handler.go and dispatched to different consensus message handlers.
    • FinalCommittedEvent: Posted when there is a new chain head (a proposal is committed).
  • consensus/istanbul/types.go: Defines data structures used in consensus.
    • Note that only PREPREPARE exchanges message with Proposal, other consensus phrases exchange with Subject. Check consensus/istanbul/core/preprepare.go#sendPreprepare() and consensus/istanbul/core/prepare.go#sendPrepare() for the comparison.
  • consensus/istanbul/validator.go: Defines the collection interface/data structure for peer validators.
  • ValidatorSet implementation: Validators are sorted by address so all validators can know who is the current proposer in each round and height.
  • Istanbul block headers are different from original ethereum in:
    • MixDigest: Must be equal to 0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365
    • ExtraData: Details defined in EIP 650 "Block hash, proposer seal, and committed seals" section.
    • Others can be found in EIP 650 "Block header" section.

Istanbul core implementation tests.

Istanbul core implementation.

  • consensus/istanbul/core/roundstate.go: defines data structure for one consensus round, including round, sequence, preprepare message set, commit message set, lockedHash, pendingRequest, and hasBadProposal() function for blacklisting validators. Note that we haven't implemented blacklisting in this PR yet.
  • consensus/istanbul/core/request.go: Istanbul BFT depends on worker to generate blocks for consensus, defined in miner/agent.go#mine(), it calls engine.Seal() to deal with the newly generated blocks. In Istanbul engine implementation in consensus/istanbul/backend/engine.go#Seal(), it posts istanbul.RequestEvent event to start the consensus process. The event will first go through consensus/istanbul/core/handler.go#handleEvents() to do some preprocessing then be dispatched to handleRequest() function. Since there is only one validator can be proposer, there will be only one validator can successfully broadcast PREPREPARE message at each round. However, there are chances round change would happen, so another validator would have chance to broadcast PREPREPARE message. To handle this, processPendingRequests() would check the pending requests and post istanbul.RequestEvent event again to attempt to send PREPREPARE.
    • handleRequest(): Tries to broadcast PREPREPARE message if it is the proposer.
    • storeRequestMsg(): Called by consensus/istanbul/core/handler.go#handleEvents() to store the request to pending requests.
    • processPendingRequests(): Called when current state is changed to StateAcceptRequest.
  • consensus/istanbul/core/backlog.go: Backlog is used to store future consensus messages, which can be processed later when the receiving validator reaches the proper state.
  • consensus/istanbul/core/core.go: Implements shared core consensus utility functions.
    • finalizeMessage(): Called before broadcasting consensus message for validator to sign the message. Note that when the message is COMMIT message, it signs COMMITTED_SEAL for other validators to compose consensus proof as well. For details about consensus proof, please reference EIP 650.
    • commit(): Commits current consensus block. Before inserting to blockchain, it composes consensus proof in committedSeals and let consensus/istanbul/backend/backend.go#Commit() to handle the rest.
    • startNewRound(): Starts a new consensus round.
  • consensus/istanbul/core/events.go:
    • backlogEvent: Posted when a backlog message can be processed or receiving future PREPREPARE message. Reference consensus/istanbul/core/backlog.go#processBacklog() and consensus/istanbul/core/preprepare.go#handlePreprepare().
    • timeoutEvent: Posted when round change timer expires, essentially triggers consensus/istanbul/core/handler.go#handleTimeoutMsg() function to handle round change timeout.
  • consensus/istanbul/core/handler.go: Core handler which handles istanbul.RequestEvent, istanbul.MessageEvent, istanbul.FinalCommittedEvent, backlogEvent, and timeoutEvent.
  • consensus/istanbul/core/message_set.go: Defines the data structure to store consensus message set for each message type. For example, in each round there will be one message set for PREPREPARE messages, one message set for PREPARE messages, and one message set for COMMIT messages.
  • Consensus message handling: Pre-prepare, Prepare, and Commit.
    • Pre-prepare: consensus/istanbul/core/preprepare.go, function handlePreprepare() handles PREPREPARE message.
    • Prepare: consensus/istanbul/core/prepare.go, function handlePrepare() handles PREPARE message. Upon receiving 2 * F PREPARE messages, the receiving validator enters PREPARED state. Note that it checks IsHashLocked() for block locking mechanism. Please reference EIP 650 "Block locking mechanism" section for detail.
    • Commit: consensus/istanbul/core/commit.go, function handleCommit() handles COMMIT message. Upon receiving 2 * F COMMIT messages, the receiving validator enters COMMITTED state, as defined in consensus/istanbul/core/core.go#commit(). Then it inserts the block into blockchain, as in consensus/istanbul/backend/backend.go#Commit(), which calls Enqueue() to enqueue the block to fetcher through its broadcaster.
    • Final committed: consensus/istanbul/core/commit.go, starts a new consensus round.
  • consensus/istanbul/core/roundchange.go: Implements round change protocol. Details can be found in EIP 650 "Round change flow" section.
  • consensus/istanbul/core/types.go: Defines consensus message type.

Istanbul consensus backend implementation.

  • consensus/istanbul/backend/api.go: Istanbul command line api.
  • consensus/istanbul/backend/snapshot.go: Define Snapshot data structure for handling validator voting in each epoch. The data would be stored in local db.
  • consensus/istanbul/backend/backend.go: Implements istanbul.Backend interface.
  • consensus/istanbul/backend/engine.go: Implements consensus.Istanbul interfaces which includes consensus.Engine interface.
  • consensus/istanbul/backend/handler.go: Implements consensus.Handler.HandleMsg, which handles protocol 64 messages and posts istanbul.MessageEvent events for consensus/istanbul/core/handler.go to handle consensus messages.

Implements Istanbul console commands.

Enables Istanbul in current geth.

Adds Ottoman testnet configuration.

Enables private transactions in worker.