hyperledger / besu

An enterprise-grade Java-based, Apache 2.0 licensed Ethereum client https://wiki.hyperledger.org/display/besu
https://www.hyperledger.org/projects/besu
Apache License 2.0
1.48k stars 803 forks source link

IBFT2 to QBFT migration #2991

Open jframe opened 2 years ago

jframe commented 2 years ago

This feature is for migrating between the IBFT2 and the QBFT.

The migration will use a hard fork approach specifying which blocks each consensus mechanism will start from.

QBFT is the planned long term support BFT consensus algorithm, and we’d like to provide a pathway for existing networks to migrate across

ItayPodhajcer commented 2 years ago

Hi @jframe @lucassaldanha , Haven't found any updates on this since November 2021. Is there anything new on this migration feature?

iamhsk commented 2 years ago

Hi @ItayPodhajcer, thank you for your inquiry! Currently the Besu maintainers are not planning on working on this migration feature for the foreseeable future. We welcome any community contribution though 🙂

ItayPodhajcer commented 2 years ago

Hi @iamhsk,

This is a very disappointing answer, as IBFT 2.0 was THE way to go with Hyperledger Besu based PoA networks before QBFT reached production grade. Expecting someone in the community with no prior experience on this codebase, to go into the heart of the consensus mechanism and implement a migration path seems highly unrealistic.

This significantly lowers the reliability of this software (and we are running three networks with it, one of them is a production network), as taking the risk that something that's being used now won't be supported in the future, and no migration path to whatever replaced that something isn't provided, isn't something that can be afforded on production workloads.

We chose Hyperledger Besu because it seemed like the best option available for a private permissioned network with enterprise capabilities, WE TOOK THE RISK, and now we are pretty much stuck with something that's very hard to upgrade, as upgrade means creating an additional network (with all the members deploying nodes to that new network in addition to the current one) and "copy" the data somehow from the existing contracts to the one in the new network.

This shouldn't happen with software that's considered ready for production!

iamhsk commented 2 years ago

Hello @ItayPodhajcer,

Thank you for sharing your feedback and I can see how my previous answer might have caused some frustration there with seemly unrealistic expectation. I meant to say that contribution in any way (however small or big) is welcomed not to mean that we are expecting a community member to implement the entire migration.

IBFT 2.0 is equally production-grade and we have several enterprise customers using it in their production environment. We are only encouraging new users to use QBFT because we’d like to converge on a single PoA consensus protocol and sunset IBFT 2.0 in the future. When we plan on doing that is still to be determined at the moment. However till we make that decision, we are going to support both IBFT 2.0 and QBFT plus before we sunset IBFT 2.0, we will provide a migration path so that the upgrade process is seamless.

May I ask you why you’d like to migrate to QBFT? There shouldn’t be much difference between IBFT 2.0 and QBFT in terms of user experience but I’d like to understand what you are looking for in QBFT. Thank you!

ItayPodhajcer commented 2 years ago

Thanks for the clarification @iamhsk!

The need to migrate was triggered by the docs leading to believe that QBFT is the long-term support consensus algorithm starting from the point it reached a production grade release. So, to make sure we are not caught by surprise by IBFT 2.0 being retired, cause as I mentioned before, we are running three networks, one of which is a production network, we wanted to start looking at the migration path as early as possible.

Your last answer made it clear that IBFT 2.0 won't be going away that fast, and once it does, a migration path will already be available.

Thank you!

feed755x commented 2 years ago

@ItayPodhajcer @iamhsk https://consensys.net/docs/goquorum/en/latest/configure-and-manage/configure/consensus-protocols/qbft/ this information would work for the migration from ibft to qbft in hyperledger?

ItayPodhajcer commented 2 years ago

Looks pretty good!!

Two questions:

  1. Why is geth init required?
  2. Can the transition update be done gradually and not all nodes at once if the transition block is far enough in the future?

Thanks for all your great work!!

non-fungible-nelson commented 1 year ago

@iamhsk - status on this?

SimowTopos commented 1 year ago

Hello team, any news on this feature? I found in this doc : https://consensys.net/blog/quorum/consensys-quorum-21-7-0-product-update-london-hard-fork-qbft-and-more/ "Because QBFT is an early access feature, we currently recommend it for new networks. Existing networks using IBFT2.0 cannot currently migrate to QBFT. This will become available in a future release. The ConsenSys Quorum team would also welcome any community feedback on the feature and their experience using it in their networks."

The link proposed by @feed755x is for Quorum consensus switch and not besu....Can we have some help on this please? Thanks

SimowTopos commented 1 year ago

Hello @jframe , @lucassaldanha , @iamhsk , I deep dived on the besu code related to this issue...mainly MigratingProtocolContext in Besu consensys common. In getConsensusContext : @Override public <C extends ConsensusContext> C getConsensusContext(final Class<C> klass) { final long chainHeadBlockNumber = getBlockchain().getChainHeadBlockNumber(); return consensusContextSchedule.getFork(chainHeadBlockNumber).getValue().as(klass); } We encounter a java.lang.ClassCastException when we have a genesis configuration to trigger a migration from IBFT2 to QBFT : "ibft2" : { "blockperiodseconds" : 2, "epochlength" : 30000, "requesttimeoutseconds" : 4 }, "qbft": { "blockperiodseconds": 2, "epochlength": 30000, "requesttimeoutseconds": 10, "startBlock": 1520 }

The issue seems understandable as we try to do a downcasting from BftContext to QbftContext ( QbftContext inherit from BftContext) which is forbiden !!

I saw also that this downcasting is due to this code :
`/**

....which return BftContext as the Treeset is reversed....

I m trying to propose a fix but needs some help from you :

Thanks a lot for your time. Mohamed.

Error occured : 2023-08-19 19:58:27.869+02:00 | BftProcessorExecutor-QBFT-0 | ERROR | EventMultiplexer | State machine threw exception while processing event \{BlockTimerExpiry{Round Identifier=ConsensusRoundIdentifier{Sequence=1520, Round=0}}\} java.lang.ClassCastException: Cannot cast org.hyperledger.besu.consensus.common.bft.BftContext to org.hyperledger.besu.consensus.qbft.QbftContext at java.base/java.lang.Class.cast(Class.java:3921) at org.hyperledger.besu.consensus.common.bft.BftContext.as(BftContext.java:70) at org.hyperledger.besu.consensus.common.MigratingProtocolContext.getConsensusContext(MigratingProtocolContext.java:78) at org.hyperledger.besu.consensus.qbft.blockcreation.QbftBlockCreatorFactory.create(QbftBlockCreatorFactory.java:71) at org.hyperledger.besu.consensus.qbft.statemachine.QbftRoundFactory.createNewRoundWithState(QbftRoundFactory.java:103) at org.hyperledger.besu.consensus.qbft.statemachine.QbftRoundFactory.createNewRound(QbftRoundFactory.java:90) at org.hyperledger.besu.consensus.qbft.statemachine.QbftBlockHeightManager.startNewRound(QbftBlockHeightManager.java:291) at org.hyperledger.besu.consensus.qbft.statemachine.QbftBlockHeightManager.handleBlockTimerExpiry(QbftBlockHeightManager.java:126) at org.hyperledger.besu.consensus.common.bft.statemachine.BaseBftController.handleBlockTimerExpiry(BaseBftController.java:167) at org.hyperledger.besu.consensus.common.bft.EventMultiplexer.handleBftEvent(EventMultiplexer.java:65) at java.base/java.util.Optional.ifPresent(Optional.java:178) at org.hyperledger.besu.consensus.common.bft.BftProcessor.run(BftProcessor.java:65) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:833)

jframe commented 1 year ago

I've updated this ticket with the progress that we have made with this feature. Development on this is currently paused and we won't be getting back to this for a while. If you want to pick this up though, would be happy to help get you started and point you in the right direction.

Creating a new QbftContext from a BftContext could work. That is similar to the solution we were working on. The approach we were taking was to have a ProtocolContext that could switch protocol contexts when reaching the Qbft block. To do this we created a MigratingProtocolContext and a MigratingContext which allows switching ProtocolContexts.

There is also a ConsensusScheduleBesuControllerBuilder that will switch consensus mechanisms at a particular block.

The general approach we took was to have components for BesuControllerBuilder, ProtocolSchedule, ProtocolContext, MiningCoordinator that could switch between consensus mechanisms. In the BesuController fromGensisConfig if we have both IBFT2 and QBFT configured in the genesis then we create a create a ConsensusScheduleBesuControllerBuilder using the IbftBesuControllerBuilder and the QbftBesuControllerBuilder which allows for switching between the consensus mechanisms at runtime.

What's missing is changing subprotocols at the fork from the IBFT2 protocol to the QBFT protocol, edge cases around the extra data codec, RPCs and lots of testing.

Alexander-Herranz commented 10 months ago

Any update on IBFT2 to QBFT migration feature?