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 }