x/consensus v2

In a server v2 world, x/consensus will work as a companion module to the consensus engine of choice. So very likely every consensus module that has a server/plugin for Cosmos SDK will have its own x/consensus.

Consensus messages

The AppManager's BlockRequest (of the DeliverBlock method) contains a list of "consensus messages", to be handled by the x/consensus module.

These messages can be:

  • Pre defined: like the CometInfo which is inserted during FinalizeBlock with no intervention from the block proposer.
  • Proposer defined: like the result of block extensions.

CometBFT x/consensus

This module will handle everything related to CometBFT:

  • Consensus Params
  • Comet/Header Info
  • Vote Extensions

Consensus Params

This is some pseudo-code, but it should be a properly defined query handler, so we can query it from the consensus engine when needed.

func (m Module) GetParams(ctx context.Context, refresh bool) (Params, error) {
    if m.cached != nil && !refresh {
        return m.cached, nil
    }
    
    return store.Params.Get()
}

This could create a complication for callers which will have to know wether or not set refresh to true, if that's the case we can just always return the cached version if available and only refresh it with a different method call. Like RefreshCachedParams or maybe when its being set.

Qs: where does the cache is stored? in-mem kv store? as a context value? <- I think any of these options should be valid.

Note: in the InitChainRequest we receive ConsensusParams for the first time, so we might also need to have a ConsensusMessage handler for setting the params.

HeaderInfo

This contains the data from the block that is specific to Comet: evidences, votes, etc. We should be able to store this in a similar way to ConsensusParams, although we don't need it stored in disk given that we get these from FinalizeBlockRequest.

To set it, we have a Consensus Message handler registered and the consensus engine will always append this message to BlockRequest.ConsensusMessages.

This value should be discarded at the end of a block execution.

func SetHeaderInfo(ctx, proto.Message) error
func HeaderInfo(ctx) (HeaderInfo, error)

Vote Extensions

Here we need 3 things:

  • Creating a vote extension
  • Verifying other validators vote extensions
  • Creating a result for the block's vote extensions (to be injected at PrepareProposal)
  • Validate a VE result in a block (ProcessProposal)
  • Writing to disk the result

From the listed things above only the last one will be able to write to state, the rest are read-only (at least in our state machine).

Creating a vote extension

x/consensus will have a query handler called ExtendVote, this will contain all the same information the ABCI handler has. Users will be able to set this handler when they set up the module in app.go.

So from the consensus engine we'll call this query route and return the response to Comet.

Verifying a vote extension

Same as above

Create a result from vote extensions to be injected in PrepareProposal

This works as the others above, the difference is that we'll return a ConsensusMessage that will get converted into bytes and pre-pended to the tx list in PrepareProposal.

Validate a VE result in a block (ProcessProposal)

x/consensus will have a query handler to which we'll pass the ConsensusMessage that contains the votes result. This will return true or false depending on app defined validity checks.

Writing the result to disk

Developers should be able to define a handler for the vote extensions result that has access to other modules in other to do the actual processing of the VE result, for example writing the oracle votes to disk. This handler will be executed during DeliverBlock, handling the specified ConsensusMessage.