Skip to content

Commit

Permalink
Merge pull request #1881 from OffchainLabs/fix-blocknum-in-nodeinterface
Browse files Browse the repository at this point in the history
Fix nil pointer dereference in BlockNum precompile
  • Loading branch information
anodar authored Sep 26, 2023
2 parents c86cf05 + 000a97b commit 8f89a85
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 13 deletions.
3 changes: 3 additions & 0 deletions nodeInterface/NodeInterface.go
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,9 @@ func (n NodeInterface) BlockL1Num(c ctx, evm mech, l2BlockNum uint64) (uint64, e
if err != nil {
return 0, err
}
if blockHeader == nil {
return 0, fmt.Errorf("nil header for l2 block: %d", l2BlockNum)
}
blockL1Num := types.DeserializeHeaderExtraInformation(blockHeader).L1BlockNumber
return blockL1Num, nil
}
Expand Down
32 changes: 19 additions & 13 deletions system_tests/nodeinterface_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,40 +30,46 @@ func TestL2BlockRangeForL1(t *testing.T) {
}

nodeInterface, err := node_interfacegen.NewNodeInterface(types.NodeInterfaceAddress, l2client)
Require(t, err)
if err != nil {
t.Fatalf("Error creating node interface: %v", err)
}

l1BlockNums := map[uint64]*[2]uint64{}
latestL2, err := l2client.BlockNumber(ctx)
Require(t, err)
if err != nil {
t.Fatalf("Error querying most recent l2 block: %v", err)
}
for l2BlockNum := uint64(0); l2BlockNum <= latestL2; l2BlockNum++ {
l1BlockNum, err := nodeInterface.BlockL1Num(&bind.CallOpts{}, l2BlockNum)
Require(t, err)
if err != nil {
t.Fatalf("Error quering l1 block number for l2 block: %d, error: %v", l2BlockNum, err)
}
if _, ok := l1BlockNums[l1BlockNum]; !ok {
l1BlockNums[l1BlockNum] = &[2]uint64{l2BlockNum, l2BlockNum}
} else {
l1BlockNums[l1BlockNum][1] = l2BlockNum
}
l1BlockNums[l1BlockNum][1] = l2BlockNum
}

// Test success
// Test success.
for l1BlockNum := range l1BlockNums {
rng, err := nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, l1BlockNum)
Require(t, err)
if err != nil {
t.Fatalf("Error getting l2 block range for l1 block: %d, error: %v", l1BlockNum, err)
}
expected := l1BlockNums[l1BlockNum]
if rng.FirstBlock != expected[0] || rng.LastBlock != expected[1] {
unexpectedL1BlockNum, err := nodeInterface.BlockL1Num(&bind.CallOpts{}, rng.LastBlock)
Require(t, err)
if err != nil {
t.Fatalf("Error quering l1 block number for l2 block: %d, error: %v", rng.LastBlock, err)
}
// Handle the edge case when new l2 blocks are produced between latestL2 was last calculated and now.
if unexpectedL1BlockNum != l1BlockNum || rng.LastBlock < expected[1] || rng.FirstBlock != expected[0] {
t.Errorf("L2BlockRangeForL1(%d) = (%d %d) want (%d %d)", l1BlockNum, rng.FirstBlock, rng.LastBlock, expected[0], expected[1])
}
}
}
// Test invalid case
finalValidL1BlockNumber, err := nodeInterface.BlockL1Num(&bind.CallOpts{}, latestL2)
Require(t, err)
if _, err := nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, finalValidL1BlockNumber+1); err == nil {
// Test invalid case.
if _, err := nodeInterface.L2BlockRangeForL1(&bind.CallOpts{}, 1e5); err == nil {
t.Fatalf("GetL2BlockRangeForL1 didn't fail for an invalid input")
}

}

0 comments on commit 8f89a85

Please sign in to comment.