Skip to content

Commit

Permalink
op-challenger: Fix run-trace disputed block selection
Browse files Browse the repository at this point in the history
Previously it assumed the safe head at SafeL1 was before the safe head at HeadL1 in the sync status, but that is not guaranteed. As a result it could select an L2 block to check that was unsafe at the specified L1 head.
  • Loading branch information
ajsutton committed Aug 12, 2024
1 parent 5a4fbce commit a02d8df
Showing 1 changed file with 34 additions and 5 deletions.
39 changes: 34 additions & 5 deletions op-challenger/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,16 @@ func (r *Runner) createGameInputs(ctx context.Context, client *sources.RollupCli
return utils.LocalGameInputs{}, fmt.Errorf("failed to get rollup sync status: %w", err)
}

if status.SafeL2.Number == 0 {
if status.FinalizedL2.Number == 0 {
return utils.LocalGameInputs{}, errors.New("safe head is 0")
}
blockNumber := status.SafeL2.Number
blockNumber, err := r.findL2BlockNumberToDispute(ctx, client, status.FinalizedL1.Number, status.FinalizedL2.Number)
if err != nil {
return utils.LocalGameInputs{}, fmt.Errorf("failed to find l2 block number to dispute: %w", err)
}
// When possible, execute the first block in the submitted batch
if status.SafeL1.Number > 0 {
priorSafeHead, err := client.SafeHeadAtL1Block(ctx, status.SafeL1.Number-1)
if status.FinalizedL1.Number > 0 {
priorSafeHead, err := client.SafeHeadAtL1Block(ctx, status.FinalizedL1.Number-32)
if err != nil {
r.log.Warn("Failed to get prior safe head", "err", err)
} else if priorSafeHead.SafeHead.Number != 0 { // Sanity check to avoid trying to execute genesis
Expand All @@ -183,7 +186,7 @@ func (r *Runner) createGameInputs(ctx context.Context, client *sources.RollupCli
return utils.LocalGameInputs{}, fmt.Errorf("failed to get claim output: %w", err)
}
localInputs := utils.LocalGameInputs{
L1Head: status.HeadL1.Hash,
L1Head: status.FinalizedL1.Hash,
L2Head: parentOutput.BlockRef.Hash,
L2OutputRoot: common.Hash(parentOutput.OutputRoot),
L2Claim: common.Hash(claimOutput.OutputRoot),
Expand All @@ -192,6 +195,32 @@ func (r *Runner) createGameInputs(ctx context.Context, client *sources.RollupCli
return localInputs, nil
}

func (r *Runner) findL2BlockNumberToDispute(ctx context.Context, client *sources.RollupClient, l1HeadNum uint64, l2BlockNum uint64) (uint64, error) {
// Try to find a L1 block prior to the batch that make l2BlockNum safe
// Limits how far back we search to 10 * 32 blocks
const skipSize = uint64(32)
for i := 0; i < 10; i++ {
if l1HeadNum < skipSize {
// Too close to genesis, give up and just use the original block
r.log.Info("Failed to find prior batch.")
return l2BlockNum, nil
}
l1HeadNum -= skipSize
priorSafeHead, err := client.SafeHeadAtL1Block(ctx, l1HeadNum)
if err != nil {
return 0, fmt.Errorf("failed to get prior safe head at L1 block %v: %w", l1HeadNum, err)
}
if priorSafeHead.SafeHead.Number < l2BlockNum {
// We walked back far enough to be before the batch that included l2BlockNum
// So use the first block after the prior safe head as the disputed block.
// It must be the first block in a batch.
return priorSafeHead.SafeHead.Number + 1, nil
}
}
r.log.Warn("Failed to find prior batch", "l2BlockNum", l2BlockNum, "earliestCheckL1Block", l1HeadNum)
return l2BlockNum, nil
}

func (r *Runner) getPrestateHash(ctx context.Context, traceType types.TraceType, caller *batching.MultiCaller) (common.Hash, error) {
gameFactory := contracts.NewDisputeGameFactoryContract(r.m, r.cfg.GameFactoryAddress, caller)
gameImplAddr, err := gameFactory.GetGameImpl(ctx, traceType.GameType())
Expand Down

0 comments on commit a02d8df

Please sign in to comment.