Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

feat(driver): optimize reorg handling && add more tests #256

Merged
merged 6 commits into from
Jun 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bindings/.githead
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d2823ece45f3bda8cda8aec0657748196ac2a31a
6a8029519c6170a9240972f82d11271bafd0e2d3
37 changes: 23 additions & 14 deletions driver/chain_syncer/calldata/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Syncer struct {
txListValidator *txListValidator.TxListValidator // Transactions list validator
// Used by BlockInserter
lastInsertedBlockID *big.Int
reorgDetectedFlag bool
}

// NewSyncer creates a new syncer instance.
Expand Down Expand Up @@ -74,20 +75,26 @@ func NewSyncer(
// ProcessL1Blocks fetches all `TaikoL1.BlockProposed` events between given
// L1 block heights, and then tries inserting them into L2 execution engine's block chain.
func (s *Syncer) ProcessL1Blocks(ctx context.Context, l1End *types.Header) error {
iter, err := eventIterator.NewBlockProposedIterator(ctx, &eventIterator.BlockProposedIteratorConfig{
Client: s.rpc.L1,
TaikoL1: s.rpc.TaikoL1,
StartHeight: s.state.GetL1Current().Number,
EndHeight: l1End.Number,
FilterQuery: nil,
OnBlockProposedEvent: s.onBlockProposed,
})
if err != nil {
return err
}
firstTry := true
for firstTry || s.reorgDetectedFlag {
s.reorgDetectedFlag = false
firstTry = false

iter, err := eventIterator.NewBlockProposedIterator(ctx, &eventIterator.BlockProposedIteratorConfig{
Client: s.rpc.L1,
TaikoL1: s.rpc.TaikoL1,
StartHeight: s.state.GetL1Current().Number,
EndHeight: l1End.Number,
FilterQuery: nil,
OnBlockProposedEvent: s.onBlockProposed,
})
if err != nil {
return err
}

if err := iter.Iter(); err != nil {
return err
if err := iter.Iter(); err != nil {
return err
}
}

s.state.SetL1Current(l1End)
Expand Down Expand Up @@ -129,8 +136,10 @@ func (s *Syncer) onBlockProposed(
)
s.state.SetL1Current(l1CurrentToReset)
s.lastInsertedBlockID = lastInsertedBlockIDToReset
s.reorgDetectedFlag = true
endIter()

return fmt.Errorf("reorg detected, reset l1Current cursor to %d", l1CurrentToReset.Number)
return nil
}
}

Expand Down
53 changes: 53 additions & 0 deletions driver/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,59 @@ func (s *DriverTestSuite) TestProcessL1Blocks() {
}
}

func (s *DriverTestSuite) TestCheckL1Reorg() {
var testnetL1SnapshotID string
s.Nil(s.RpcClient.L1RawRPC.CallContext(context.Background(), &testnetL1SnapshotID, "evm_snapshot"))
s.NotEmpty(testnetL1SnapshotID)

l1Head1, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
l2Head1, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
s.Nil(err)

// Propose two L2 blocks
testutils.ProposeAndInsertValidBlock(&s.ClientTestSuite, s.p, s.d.ChainSyncer().CalldataSyncer())
testutils.ProposeAndInsertValidBlock(&s.ClientTestSuite, s.p, s.d.ChainSyncer().CalldataSyncer())

l1Head2, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
l2Head2, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
s.Nil(err)
s.Greater(l2Head2.Number.Uint64(), l2Head1.Number.Uint64())
s.Greater(l1Head2.Number.Uint64(), l1Head1.Number.Uint64())

reorged, _, _, err := s.RpcClient.CheckL1Reorg(context.Background(), l2Head2.Number)
s.Nil(err)
s.False(reorged)

// Reorg back to l2Head1
var revertRes bool
s.Nil(s.RpcClient.L1RawRPC.CallContext(context.Background(), &revertRes, "evm_revert", testnetL1SnapshotID))
s.True(revertRes)

l1Head3, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)
s.Equal(l1Head3.Number.Uint64(), l1Head1.Number.Uint64())
s.Equal(l1Head3.Hash(), l1Head1.Hash())

// Propose two blocks in another fork
testutils.ProposeInvalidTxListBytes(&s.ClientTestSuite, s.p)
testutils.ProposeInvalidTxListBytes(&s.ClientTestSuite, s.p)

l1Head4, err := s.d.rpc.L1.HeaderByNumber(context.Background(), nil)
s.Nil(err)

s.Nil(s.d.ChainSyncer().CalldataSyncer().ProcessL1Blocks(context.Background(), l1Head4))

l2Head3, err := s.d.rpc.L2.HeaderByNumber(context.Background(), nil)
s.Nil(err)

parent, err := s.d.rpc.L2.HeaderByHash(context.Background(), l2Head3.ParentHash)
s.Nil(err)
s.Equal(l2Head3.Number.Uint64(), l2Head2.Number.Uint64())
s.Equal(parent.ParentHash, l2Head1.Hash())
}

func (s *DriverTestSuite) TestDoSyncNoNewL2Blocks() {
s.Nil(s.d.doSync())
}
Expand Down
1 change: 1 addition & 0 deletions pkg/rpc/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ func (c *Client) CheckL1Reorg(ctx context.Context, blockID *big.Int) (bool, *typ
return false, nil, nil, err
}

blockIDToReset = blockID
break
}

Expand Down
32 changes: 22 additions & 10 deletions prover/prover.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Prover struct {
latestVerifiedL1Height uint64
lastHandledBlockID uint64
l1Current uint64
reorgDetectedFlag bool

// Proof submitters
validProofSubmitter proofSubmitter.ProofSubmitter
Expand Down Expand Up @@ -280,17 +281,27 @@ func (p *Prover) Close() {
// proveOp performs a proving operation, find current unproven blocks, then
// request generating proofs for them.
func (p *Prover) proveOp() error {
iter, err := eventIterator.NewBlockProposedIterator(p.ctx, &eventIterator.BlockProposedIteratorConfig{
Client: p.rpc.L1,
TaikoL1: p.rpc.TaikoL1,
StartHeight: new(big.Int).SetUint64(p.l1Current),
OnBlockProposedEvent: p.onBlockProposed,
})
if err != nil {
return err
firstTry := false
for firstTry || p.reorgDetectedFlag {
p.reorgDetectedFlag = false
firstTry = false

iter, err := eventIterator.NewBlockProposedIterator(p.ctx, &eventIterator.BlockProposedIteratorConfig{
Client: p.rpc.L1,
TaikoL1: p.rpc.TaikoL1,
StartHeight: new(big.Int).SetUint64(p.l1Current),
OnBlockProposedEvent: p.onBlockProposed,
})
if err != nil {
return err
}

if err := iter.Iter(); err != nil {
return err
}
}

return iter.Iter()
return nil
}

// onBlockProposed tries to prove that the newly proposed block is valid/invalid.
Expand Down Expand Up @@ -324,8 +335,9 @@ func (p *Prover) onBlockProposed(
)
p.l1Current = l1CurrentToReset.Number.Uint64()
p.lastHandledBlockID = lastHandledBlockIDToReset.Uint64()
p.reorgDetectedFlag = true

return fmt.Errorf("reorg detected, reset l1Current cursor to %d", l1CurrentToReset.Number)
return nil
}

if event.Id.Uint64() <= p.lastHandledBlockID {
Expand Down
4 changes: 1 addition & 3 deletions testutils/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,9 @@ func ProposeAndInsertValidBlock(

s.Nil(calldataSyncer.ProcessL1Blocks(ctx, newL1Head))

newL2Head, err := s.RpcClient.L2.HeaderByNumber(context.Background(), nil)
_, err = s.RpcClient.L2.HeaderByNumber(context.Background(), nil)
s.Nil(err)

s.Greater(newL2Head.Number.Uint64(), l2Head.Number.Uint64())

return event
}

Expand Down