Skip to content

Commit

Permalink
op-node: Record genesis as being safe from L1 genesis
Browse files Browse the repository at this point in the history
  • Loading branch information
ajsutton committed Feb 28, 2024
1 parent 8d59c7a commit c0e0ff3
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 20 deletions.
14 changes: 9 additions & 5 deletions op-e2e/actions/safedb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ func TestRecordSafeHeadUpdates(gt *testing.T) {
require.Equal(t, eth.HeaderBlockID(l1Head), response.L1Block)
require.Equal(t, verifier.L2Unsafe().ID(), response.SafeHead)

// Should get not found error before the L1 block because we have no earlier safe head recorded
_, err = verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block-1)
require.ErrorContains(t, err, safedb.ErrNotFound.Error())
// Only genesis is safe at this point
response, err = verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block-1)
require.NoError(t, err)
require.Equal(t, eth.HeaderBlockID(miner.l1Chain.Genesis().Header()), response.L1Block)
require.Equal(t, sd.RollupCfg.Genesis.L2, response.SafeHead)

// orphan the L1 block that included the batch tx, and build a new different L1 block
miner.ActL1RewindToParent(t)
Expand All @@ -78,9 +80,11 @@ func TestRecordSafeHeadUpdates(gt *testing.T) {
require.NoError(t, err)
require.Equal(t, verifier.L2Safe(), ref, "verifier engine matches rollup client")

// The safe head has been reorged so the record should have been deleted
// The safe head has been reorged so the record should have been deleted, leaving us back with just genesis safe
response, err = verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block)
require.ErrorContainsf(t, err, safedb.ErrNotFound.Error(), "Expected error but got %v", response)
require.NoError(t, err)
require.Equal(t, eth.HeaderBlockID(miner.l1Chain.Genesis().Header()), response.L1Block)
require.Equal(t, sd.RollupCfg.Genesis.L2, response.SafeHead)

// Now replay the batch tx in a new L1 block
miner.ActL1StartBlock(12)(t)
Expand Down
17 changes: 2 additions & 15 deletions op-e2e/faultproofs/output_cannon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,20 +693,10 @@ func TestInvalidateUnsafeProposal(t *testing.T) {
test := test
t.Run(test.name, func(t *testing.T) {
op_e2e.InitParallel(t, op_e2e.UsesCannon)
sys, l1Client := startFaultDisputeSystem(t, withSequencerWindowSize(100000))
sys, l1Client := startFaultDisputeSystem(t, withSequencerWindowSize(100000), withBatcherStopped())
t.Cleanup(sys.Close)

// Wait for the safe head to advance at least one block to init the safe head database
require.NoError(t, wait.ForSafeBlock(ctx, sys.RollupClient("sequencer"), 1))

// Now stop the batcher so the safe head doesn't advance any further
require.NoError(t, sys.BatchSubmitter.Stop(ctx))

// Wait for the unsafe head to advance to be sure it is beyond the safe head
require.NoError(t, wait.ForNextBlock(ctx, sys.NodeClient("sequencer")))
blockNum, err := sys.NodeClient("sequencer").BlockNumber(ctx)
require.NoError(t, err)

blockNum := uint64(1)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys)
// Root claim is _dishonest_ because the required data is not available on L1
game := disputeGameFactory.StartOutputCannonGameWithCorrectRoot(ctx, "sequencer", blockNum, disputegame.WithUnsafeProposal())
Expand Down Expand Up @@ -768,9 +758,6 @@ func TestInvalidateProposalForFutureBlock(t *testing.T) {
sys, l1Client := startFaultDisputeSystem(t, withSequencerWindowSize(100000))
t.Cleanup(sys.Close)

// Wait for the safe head to advance at least one block to init the safe head database
require.NoError(t, wait.ForSafeBlock(ctx, sys.RollupClient("sequencer"), 1))

farFutureBlockNum := uint64(10_000_000)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys)
// Root claim is _dishonest_ because the required data is not available on L1
Expand Down
15 changes: 15 additions & 0 deletions op-node/rollup/derive/engine_queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,21 @@ func (eq *EngineQueue) Reset(ctx context.Context, _ eth.L1BlockRef, _ eth.System
if err := eq.safeHeadNotifs.SafeHeadReset(safe); err != nil {
return err
}
if eq.cfg.Genesis.L2.Number == 0 && safe.Hash == eq.cfg.Genesis.L2.Hash {
// The L2 genesis/bedrock activation block is always safe by definition
// So if the pipeline resets this far back we know we will process all safe head updates
// and can record genesis as always safe from L1 genesis.
// Note that it is not safe to use cfg.Genesis.L1 here as it is the block immediately before the L2 genesis
// but the contracts may have been deployed earlier than that, allowing creating a dispute game
// with a L1 head prior to cfg.Genesis.L1
l1Genesis, err := eq.l1Fetcher.L1BlockRefByNumber(ctx, 0)
if err != nil {
return fmt.Errorf("failed to retrieve L1 genesis: %w", err)
}
if err := eq.safeHeadNotifs.SafeHeadUpdated(safe, l1Genesis.ID()); err != nil {
return err
}
}
eq.logSyncProgress("reset derivation work")
return io.EOF
}
Expand Down
1 change: 1 addition & 0 deletions op-node/rollup/derive/engine_queue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,7 @@ func TestBlockBuildingRace(t *testing.T) {
l1F.ExpectL1BlockRefByNumber(refA.Number, refA, nil)
l1F.ExpectL1BlockRefByHash(refA.Hash, refA, nil)
l1F.ExpectL1BlockRefByHash(refA.Hash, refA, nil)
l1F.ExpectL1BlockRefByNumber(0, refA, nil)

eng.ExpectSystemConfigByL2Hash(refA0.Hash, cfg.Genesis.SystemConfig, nil)

Expand Down

0 comments on commit c0e0ff3

Please sign in to comment.