From f740013e0e2e1d215b411b45766fa7977ce76b67 Mon Sep 17 00:00:00 2001 From: David Date: Sat, 22 Jul 2023 04:19:23 +0800 Subject: [PATCH] feat(driver): improve `ProcessL1Blocks` for reorg handling (#325) --- driver/chain_syncer/calldata/syncer.go | 21 +++++++++++- pkg/rpc/methods.go | 47 ++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/driver/chain_syncer/calldata/syncer.go b/driver/chain_syncer/calldata/syncer.go index df31d08cb..d621170a2 100644 --- a/driver/chain_syncer/calldata/syncer.go +++ b/driver/chain_syncer/calldata/syncer.go @@ -80,10 +80,29 @@ func (s *Syncer) ProcessL1Blocks(ctx context.Context, l1End *types.Header) error s.reorgDetectedFlag = false firstTry = false + startHeight := s.state.GetL1Current().Number + // If there is a L1 reorg, sometimes this will happen. + if startHeight.Uint64() >= l1End.Number.Uint64() { + startHeight = new(big.Int).Sub(l1End.Number, common.Big1) + newL1Current, err := s.rpc.L1.HeaderByNumber(ctx, startHeight) + if err != nil { + return err + } + s.state.SetL1Current(newL1Current) + s.lastInsertedBlockID = nil + + log.Info( + "Reorg detected", + "oldL1Current", s.state.GetL1Current().Number, + "newL1Current", startHeight, + "l1Head", l1End.Number, + ) + } + iter, err := eventIterator.NewBlockProposedIterator(ctx, &eventIterator.BlockProposedIteratorConfig{ Client: s.rpc.L1, TaikoL1: s.rpc.TaikoL1, - StartHeight: s.state.GetL1Current().Number, + StartHeight: startHeight, EndHeight: l1End.Number, FilterQuery: nil, OnBlockProposedEvent: s.onBlockProposed, diff --git a/pkg/rpc/methods.go b/pkg/rpc/methods.go index eb309f45b..16451d5c0 100644 --- a/pkg/rpc/methods.go +++ b/pkg/rpc/methods.go @@ -356,11 +356,33 @@ func (c *Client) CheckL1Reorg(ctx context.Context, blockID *big.Int) (bool, *typ l1Origin, err := c.L2.L1OriginByID(ctx, blockID) if err != nil { - // If the L2 EE is just synced through P2P, there is a chance that the EE do not have - // the chain head L1Origin information recorded. if err.Error() == ethereum.NotFound.Error() { log.Info("L1Origin not found", "blockID", blockID) - return false, nil, nil, nil + + // If the L2 EE is just synced through P2P, there is a chance that the EE do not have + // the chain head L1Origin information recorded. + justSyncedByP2P, err := c.IsJustSyncedByP2P(ctx) + if err != nil { + return false, + nil, + nil, + fmt.Errorf("failed to check whether the L2 execution engine has just finished a P2P sync: %w", err) + } + + log.Info( + "Check whether the L2 execution engine has just finished a P2P sync", + "justSyncedByP2P", + justSyncedByP2P, + ) + + if justSyncedByP2P { + return false, nil, nil, nil + } + + log.Info("Reorg detected due to L1Origin not found", "blockID", blockID) + reorged = true + blockID = new(big.Int).Sub(blockID, common.Big1) + continue } return false, nil, nil, err } @@ -401,3 +423,22 @@ func (c *Client) CheckL1Reorg(ctx context.Context, blockID *big.Int) (bool, *typ return reorged, l1CurrentToReset, blockIDToReset, nil } + +// IsJustSyncedByP2P checks whether the given L2 execution engine has just finished a P2P +// sync. +func (c *Client) IsJustSyncedByP2P(ctx context.Context) (bool, error) { + l2Head, err := c.L2.HeaderByNumber(ctx, nil) + if err != nil { + return false, err + } + + if _, err = c.L2.L1OriginByID(ctx, l2Head.Number); err != nil { + if err.Error() == ethereum.NotFound.Error() { + return true, nil + } + + return false, err + } + + return false, nil +}