github.com/ethereum-optimism/optimism@v1.7.2/op-node/rollup/derive/l1_traversal.go (about)

     1  package derive
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  
     9  	"github.com/ethereum/go-ethereum"
    10  	"github.com/ethereum/go-ethereum/common"
    11  	"github.com/ethereum/go-ethereum/core/types"
    12  	"github.com/ethereum/go-ethereum/log"
    13  
    14  	"github.com/ethereum-optimism/optimism/op-node/rollup"
    15  	"github.com/ethereum-optimism/optimism/op-service/eth"
    16  )
    17  
    18  // L1 Traversal fetches the next L1 block and exposes it through the progress API
    19  
    20  type L1BlockRefByNumberFetcher interface {
    21  	L1BlockRefByNumber(context.Context, uint64) (eth.L1BlockRef, error)
    22  	FetchReceipts(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Receipts, error)
    23  }
    24  
    25  type L1Traversal struct {
    26  	block    eth.L1BlockRef
    27  	done     bool
    28  	l1Blocks L1BlockRefByNumberFetcher
    29  	log      log.Logger
    30  	sysCfg   eth.SystemConfig
    31  	cfg      *rollup.Config
    32  }
    33  
    34  var _ ResettableStage = (*L1Traversal)(nil)
    35  
    36  func NewL1Traversal(log log.Logger, cfg *rollup.Config, l1Blocks L1BlockRefByNumberFetcher) *L1Traversal {
    37  	return &L1Traversal{
    38  		log:      log,
    39  		l1Blocks: l1Blocks,
    40  		cfg:      cfg,
    41  	}
    42  }
    43  
    44  func (l1t *L1Traversal) Origin() eth.L1BlockRef {
    45  	return l1t.block
    46  }
    47  
    48  // NextL1Block returns the next block. It does not advance, but it can only be
    49  // called once before returning io.EOF
    50  func (l1t *L1Traversal) NextL1Block(_ context.Context) (eth.L1BlockRef, error) {
    51  	if !l1t.done {
    52  		l1t.done = true
    53  		return l1t.block, nil
    54  	} else {
    55  		return eth.L1BlockRef{}, io.EOF
    56  	}
    57  }
    58  
    59  // AdvanceL1Block advances the internal state of L1 Traversal
    60  func (l1t *L1Traversal) AdvanceL1Block(ctx context.Context) error {
    61  	origin := l1t.block
    62  	nextL1Origin, err := l1t.l1Blocks.L1BlockRefByNumber(ctx, origin.Number+1)
    63  	if errors.Is(err, ethereum.NotFound) {
    64  		l1t.log.Debug("can't find next L1 block info (yet)", "number", origin.Number+1, "origin", origin)
    65  		return io.EOF
    66  	} else if err != nil {
    67  		return NewTemporaryError(fmt.Errorf("failed to find L1 block info by number, at origin %s next %d: %w", origin, origin.Number+1, err))
    68  	}
    69  	if l1t.block.Hash != nextL1Origin.ParentHash {
    70  		return NewResetError(fmt.Errorf("detected L1 reorg from %s to %s with conflicting parent %s", l1t.block, nextL1Origin, nextL1Origin.ParentID()))
    71  	}
    72  
    73  	// Parse L1 receipts of the given block and update the L1 system configuration
    74  	_, receipts, err := l1t.l1Blocks.FetchReceipts(ctx, nextL1Origin.Hash)
    75  	if err != nil {
    76  		return NewTemporaryError(fmt.Errorf("failed to fetch receipts of L1 block %s (parent: %s) for L1 sysCfg update: %w", nextL1Origin, origin, err))
    77  	}
    78  	if err := UpdateSystemConfigWithL1Receipts(&l1t.sysCfg, receipts, l1t.cfg, nextL1Origin.Time); err != nil {
    79  		// the sysCfg changes should always be formatted correctly.
    80  		return NewCriticalError(fmt.Errorf("failed to update L1 sysCfg with receipts from block %s: %w", nextL1Origin, err))
    81  	}
    82  
    83  	l1t.block = nextL1Origin
    84  	l1t.done = false
    85  	return nil
    86  }
    87  
    88  // Reset sets the internal L1 block to the supplied base.
    89  func (l1t *L1Traversal) Reset(ctx context.Context, base eth.L1BlockRef, cfg eth.SystemConfig) error {
    90  	l1t.block = base
    91  	l1t.done = false
    92  	l1t.sysCfg = cfg
    93  	l1t.log.Info("completed reset of derivation pipeline", "origin", base)
    94  	return io.EOF
    95  }
    96  
    97  func (l1c *L1Traversal) SystemConfig() eth.SystemConfig {
    98  	return l1c.sysCfg
    99  }