Commit f05b0eb8 authored by Joshua Gutow's avatar Joshua Gutow Committed by Joshua Gutow

op-node: Audit use of L1 State

The L1 State can return uninitialized values. I have checked every
usage in the op-node and either check the return value from L1
state if is important or let the empty value through.
parent ee7abf3b
...@@ -6,7 +6,6 @@ import ( ...@@ -6,7 +6,6 @@ import (
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
) )
// confDepth is an util that wraps the L1 input fetcher used in the pipeline, // confDepth is an util that wraps the L1 input fetcher used in the pipeline,
...@@ -33,7 +32,10 @@ func (c *confDepth) L1BlockRefByNumber(ctx context.Context, num uint64) (eth.L1B ...@@ -33,7 +32,10 @@ func (c *confDepth) L1BlockRefByNumber(ctx context.Context, num uint64) (eth.L1B
// Don't apply the conf depth is l1Head is empty (as it is during the startup case before the l1State is initialized). // Don't apply the conf depth is l1Head is empty (as it is during the startup case before the l1State is initialized).
l1Head := c.l1Head() l1Head := c.l1Head()
if num == 0 || c.depth == 0 || num+c.depth <= l1Head.Number || l1Head.Hash == (common.Hash{}) { if l1Head == (eth.L1BlockRef{}) {
return c.L1Fetcher.L1BlockRefByNumber(ctx, num)
}
if num == 0 || c.depth == 0 || num+c.depth <= l1Head.Number {
return c.L1Fetcher.L1BlockRefByNumber(ctx, num) return c.L1Fetcher.L1BlockRefByNumber(ctx, num)
} }
return eth.L1BlockRef{}, ethereum.NotFound return eth.L1BlockRef{}, ethereum.NotFound
......
...@@ -63,14 +63,20 @@ func (s *L1State) HandleNewL1FinalizedBlock(finalized eth.L1BlockRef) { ...@@ -63,14 +63,20 @@ func (s *L1State) HandleNewL1FinalizedBlock(finalized eth.L1BlockRef) {
s.l1Finalized = finalized s.l1Finalized = finalized
} }
// L1Head returns either the stored L1 head or an empty block reference
// if the L1 Head has not been initialized yet.
func (s *L1State) L1Head() eth.L1BlockRef { func (s *L1State) L1Head() eth.L1BlockRef {
return s.l1Head return s.l1Head
} }
// L1Safe returns either the stored L1 safe block or an empty block reference
// if the L1 safe block has not been initialized yet.
func (s *L1State) L1Safe() eth.L1BlockRef { func (s *L1State) L1Safe() eth.L1BlockRef {
return s.l1Safe return s.l1Safe
} }
// L1Finalized returns either the stored L1 finalized block or an empty block reference
// if the L1 finalized block has not been initialized yet.
func (s *L1State) L1Finalized() eth.L1BlockRef { func (s *L1State) L1Finalized() eth.L1BlockRef {
return s.l1Finalized return s.l1Finalized
} }
...@@ -134,8 +134,13 @@ func (s *Driver) createNewL2Block(ctx context.Context) error { ...@@ -134,8 +134,13 @@ func (s *Driver) createNewL2Block(ctx context.Context) error {
l2Safe := s.derivation.SafeL2Head() l2Safe := s.derivation.SafeL2Head()
l2Finalized := s.derivation.Finalized() l2Finalized := s.derivation.Finalized()
l1Head := s.l1State.L1Head()
if l1Head == (eth.L1BlockRef{}) {
return derive.NewTemporaryError(errors.New("L1 Head in L1 State is not initizalited yet"))
}
// Figure out which L1 origin block we're going to be building on top of. // Figure out which L1 origin block we're going to be building on top of.
l1Origin, err := s.l1OriginSelector.FindL1Origin(ctx, s.l1State.L1Head(), l2Head) l1Origin, err := s.l1OriginSelector.FindL1Origin(ctx, l1Head, l2Head)
if err != nil { if err != nil {
s.log.Error("Error finding next L1 Origin", "err", err) s.log.Error("Error finding next L1 Origin", "err", err)
return err return err
...@@ -261,9 +266,8 @@ func (s *Driver) eventLoop() { ...@@ -261,9 +266,8 @@ func (s *Driver) eventLoop() {
case <-l2BlockCreationReqCh: case <-l2BlockCreationReqCh:
s.snapshot("L2 Block Creation Request") s.snapshot("L2 Block Creation Request")
l1Head := s.l1State.L1Head()
if !s.idleDerivation { if !s.idleDerivation {
s.log.Warn("not creating block, node is deriving new l2 data", "head_l1", l1Head) s.log.Warn("not creating block, node is deriving new l2 data", "head_l1", s.l1State.L1Head())
break break
} }
ctx, cancel := context.WithTimeout(ctx, 20*time.Minute) ctx, cancel := context.WithTimeout(ctx, 20*time.Minute)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment