Implement ExtendVote
First we’ll create theOracleVoteExtension
struct, this is the object that will be marshaled as bytes and signed by the validator.
In our example we’ll use JSON to marshal the vote extension for simplicity but we recommend to find an encoding that produces a smaller output, given that large vote extensions could impact CometBFT’s performance. Custom encodings and compressed bytes can be used out of the box.
VoteExtensionsHandler
struct that contains everything we need to query for prices.
sdk.ExtendVoteHandler
is needed too, and this is where our vote extension logic will live.
- Is the vote extension unmarshaled correctly?
- Is the vote extension for the right height?
- Some other validation, for example, are the prices from this extension too deviated from my own prices? Or maybe checks that can detect malicious behavior.
Implement PrepareProposal
PrepareProposalHandler
. In this step we’ll first check if the vote extensions’ signatures are correct using a helper function called ValidateVoteExtensions from the baseapp package.
Implement ProcessProposal
Now we can implement the method that all validators will execute to ensure the proposer is doing his work correctly. Here, if vote extensions are enabled, we’ll check if the tx at index 0 is an injected vote extensionImplement PreBlocker
Now validators are extending their vote, verifying other votes and including the result in the block. But how do we actually make use of this result? This is done in the PreBlocker which is code that is run before any other code during FinalizeBlock so we make sure we make this information available to the chain and its modules during the entire block execution (from BeginBlock). At this step we know that the injected tx is well-formatted and has been verified by the validators participating in consensus, so making use of it is straightforward. Just check if vote extensions are enabled, pick up the first transaction and use a method in your module’s keeper to set the result.Conclusion
In this tutorial, we’ve created a simple price oracle module that incorporates vote extensions. We’ve seen how to implementExtendVote
, VerifyVoteExtension
, PrepareProposal
, ProcessProposal
, and PreBlocker
to handle the voting and verification process of vote extensions, as well as how to make use of the results during the block execution.