Skip to content

Conversation

tbenr
Copy link
Contributor

@tbenr tbenr commented Mar 24, 2025

  • adds a new SyncReorgManager which is triggered at each successful batch import.
  • SyncReorgManager will call a protoarray's reorgWhileSyncing (via ForkChoiceTrigger->ForkChoice) which will "switch" votes from the old chain to the new chain. This logic only applies to protoarray in "syncing state" (no votes applied)

It is designed to reorg only if we import a block at a more recent slot than our current head (+ 10 slot).
There could be use-cases in which we want to reorg sooner: if our DB contains a long non-canonical chain we will keep the tip of that as our canonical head until the contending chain we are syncing overcome that tip.
But for now this implementation solves the problem in which our chain tip is just on a reorged block and we just keep syncing from its parent.

fixes #9195

Documentation

  • I thought about documentation and added the doc-change-required label to this PR if updates are required.

Changelog

  • I thought about adding a changelog entry, and added one if I deemed necessary.

@tbenr tbenr marked this pull request as ready for review March 24, 2025 19:54
@tbenr tbenr force-pushed the allow-reorg-while-syncing branch from c64aad0 to 3a0c94a Compare March 25, 2025 12:40
long subscribeToBlocksImportedEvent(BlocksImportedSubscriber subscriber);

interface BlocksImportedSubscriber {
void onBlocksImported(SignedBeaconBlock lastImportedBlock);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why 's, plural?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well cose I don't want this to look like you can subscribe to it and pretend to get all blocks.
Maybe I should rename everything to be onBatchImported(SignedBeaconBlock lastImportedBlock)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, problem is that I put that on Sync interface, and not BatchSync interface. So the concept of "batch" is not part of that...
Suggestions? :)

public void onBlocksImported(final SignedBeaconBlock lastImportedBlock) {
eventThread.execute(
() -> {
if (isSyncSpeculative()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we skip this case?
(sorry, I just don't understand what is speculative sync)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

speculative syncing is when we are on sync but we "hear" about a chain that we speculatively sync. So we don't want the sync reorg logic to be applied in that case (we are actually in sync in that scenario)

.get()
.getSlot()
.plus(REORG_SLOT_THRESHOLD)
.isGreaterThan(lastImportedBlock.getSlot())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this rule, we determinate best chain by votes, two chains could have similar length having a big difference in votes. I guess we don't want ot switch back and forth and it could help. Is this a purpose?

Copy link
Contributor Author

@tbenr tbenr Sep 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed, the sync reorg logic only applies during initial syncing when all protoarray votes are 0

ProtoArray::reorgWhileSyncing

    // check we are in syncing mode where all nodes have a max weight of 1
    if (commonAncestorNode.getWeight().isGreaterThan(1)) {
      return;
    }

and it is actually ok to switch back and forth, as long as we keep as canonical the longest chain we are syncing to

* <p>The function set all weights to 0 to the reorged chain and set all weights to 1 to the new
* chain.
*/
public void reorgWhileSyncing(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so we just removed weight from old chain and put it to the new chain undoubtely? We need some reasons for this. Could we get real weights? There is no clue new chain is better than old

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the idea is to make it the chain we want to reorg to as canonical only by 1 vote. So once we start counting actual votes that +1 becomes irrelevant and goes away as we follow the chain (latest imported block won't have that +1 anymore)

@tbenr tbenr force-pushed the allow-reorg-while-syncing branch from ffb369a to 6a90496 Compare September 5, 2025 15:16
break;
}
node = getNodeByIndex(node.getParentIndex().get());
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Reorg Method Misaligns Weighting Chain

The reorgWhileSyncing method starts adding weight from newHeadNode.getBestDescendantIndex() instead of newHeadNode itself. This can lead to weighting an unintended descendant chain, as getBestDescendantIndex() relies on existing weights that may not align with the reorg's target path.

Fix in Cursor Fix in Web

Copy link
Contributor Author

@tbenr tbenr Sep 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is actually intended. The idea is to select the tip of that chain where new head is (if in the meantime we added a new block on top of it) and set all chain's nodes to weight 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

During syncing we should be able to reorg blocks

2 participants