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

     1  package derive
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/ethereum/go-ethereum/common"
     9  	"github.com/ethereum/go-ethereum/log"
    10  
    11  	"github.com/ethereum-optimism/optimism/op-service/eth"
    12  )
    13  
    14  type DataAvailabilitySource interface {
    15  	OpenData(ctx context.Context, ref eth.L1BlockRef, batcherAddr common.Address) (DataIter, error)
    16  }
    17  
    18  type NextBlockProvider interface {
    19  	NextL1Block(context.Context) (eth.L1BlockRef, error)
    20  	Origin() eth.L1BlockRef
    21  	SystemConfig() eth.SystemConfig
    22  }
    23  
    24  type L1Retrieval struct {
    25  	log     log.Logger
    26  	dataSrc DataAvailabilitySource
    27  	prev    NextBlockProvider
    28  
    29  	datas DataIter
    30  }
    31  
    32  var _ ResettableStage = (*L1Retrieval)(nil)
    33  
    34  func NewL1Retrieval(log log.Logger, dataSrc DataAvailabilitySource, prev NextBlockProvider) *L1Retrieval {
    35  	return &L1Retrieval{
    36  		log:     log,
    37  		dataSrc: dataSrc,
    38  		prev:    prev,
    39  	}
    40  }
    41  
    42  func (l1r *L1Retrieval) Origin() eth.L1BlockRef {
    43  	return l1r.prev.Origin()
    44  }
    45  
    46  // NextData does an action in the L1 Retrieval stage
    47  // If there is data, it pushes it to the next stage.
    48  // If there is no more data open ourselves if we are closed or close ourselves if we are open
    49  func (l1r *L1Retrieval) NextData(ctx context.Context) ([]byte, error) {
    50  	if l1r.datas == nil {
    51  		next, err := l1r.prev.NextL1Block(ctx)
    52  		if err == io.EOF {
    53  			return nil, io.EOF
    54  		} else if err != nil {
    55  			return nil, err
    56  		}
    57  		if l1r.datas, err = l1r.dataSrc.OpenData(ctx, next, l1r.prev.SystemConfig().BatcherAddr); err != nil {
    58  			return nil, fmt.Errorf("failed to open data source: %w", err)
    59  		}
    60  	}
    61  
    62  	l1r.log.Debug("fetching next piece of data")
    63  	data, err := l1r.datas.Next(ctx)
    64  	if err == io.EOF {
    65  		l1r.datas = nil
    66  		return nil, io.EOF
    67  	} else if err != nil {
    68  		// CalldataSource appropriately wraps the error so avoid double wrapping errors here.
    69  		return nil, err
    70  	} else {
    71  		return data, nil
    72  	}
    73  }
    74  
    75  // Reset re-initializes the L1 Retrieval stage to block of it's `next` progress.
    76  // Note that we open up the `l1r.datas` here because it is required to maintain the
    77  // internal invariants that later propagate up the derivation pipeline.
    78  func (l1r *L1Retrieval) Reset(ctx context.Context, base eth.L1BlockRef, sysCfg eth.SystemConfig) error {
    79  	var err error
    80  	if l1r.datas, err = l1r.dataSrc.OpenData(ctx, base, sysCfg.BatcherAddr); err != nil {
    81  		return fmt.Errorf("failed to open data source: %w", err)
    82  	}
    83  	l1r.log.Info("Reset of L1Retrieval done", "origin", base)
    84  	return io.EOF
    85  }