Skip to content

Implementation ideas for IBFT2 block validation support #1430

@VladLupashevskyi

Description

@VladLupashevskyi

QBFT algorithm seems the preferred one to be used among IBFT, IBFT2 and QBFT on both Besu and GoQuorum clients. However there are no plans to add support for IBFT2 in GoQuorum as mentioned in this issue #1377. So I'd thought it would be nice idea to add support to GoQuorum for only block verification of IBFT2 chains that have switched to QBFT. I did some analysis and found out that BFT specific extra data which is stored per block has the same structure for IBFT2 and QBFT consensuses, however RLP encoding differs for some cases, therefore block hash would differ and validation during the sync would fail. As a conclusion by just introducing an IBFT2 block extra data encoder/decoder will make it possible to sync and validate IBFT2 blocks on GoQuorum.

Here are the differences that I found out:

  • In case there are no votes, IBFT2 represents the value as a null value, QBFT represents it as empty list.
  • Encoding for drop vote on IBFT2 is represented as zero byte 0x00, QBFT represents it as null value (according to Ethereum conventions).
  • Round is represented on IBFT2 always as 4 bytes value (0 as 0x00000000, 1 as 0x00000001), QBFT represents it as scalar according to Ethereum conventions (0 as 0x, 1 as 0x01).
  • For block hash calculations and for block signing when round number or/and block seals have to be excluded, IBFT2 drops excluded arguments completely from encoding (so <Vanity>, <Validators>, <Vote>, <Round> or <Vanity>, <Validators>, <Vote> structures are used), whereas QBFT puts zero as default for round number and empty list for seals in such cases. However on IBFT2 the full extra data is used for genesis block hash calculation.

I have made some changes to client to make QBFT extra data encoder/decoder behave as IBFT2 one and I have run it for IBFT2 chain which was successfully synced. The changes I've done can be found in this commit. It has to be mentioned that I'm a complete beginner in Go and this commit is just a proof of concept, however any comments are welcome :)

The proper solution would be to have some param in chain spec like useIBFT2ExtraDataValidationUntilBlock, that will enable this logic until some block which would be the block when IBFT2 chain have switched consensus to QBFT. But before starting to implement this, I wanted to gather opinions of more experienced devs here whether it makes sense and that I haven't missed anything. Also already implementation related question: What is the better way to submit chain params to QBFTFilteredHeader function that is used in the Hash function? (which is used in many places and adding extra argument for chain params to it would not be that convenient)

This approach of course does not enable mining on IBFT2 chain however I think it's a good solution for chains that have switched from IBFT2 to QBFT (where mining could be possible already) and requires much less effort to implement.

Thank you very much and I'm looking forward to your feedback!

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions