Skip to content

Commit

Permalink
fix(batcher): include checksum in zlib-compressed channel encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
0xbenyun committed Nov 22, 2024
1 parent a820693 commit c27a652
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
55 changes: 55 additions & 0 deletions op-batcher/batcher/channel_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package batcher

import (
"bytes"
"encoding/binary"
"errors"
"hash/adler32"
"math"
"math/big"
"math/rand"
Expand All @@ -14,6 +16,7 @@ import (
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -810,3 +813,55 @@ func blockBatchRlpSize(t *testing.T, b *types.Block) int {
require.NoError(t, batch.EncodeRLP(&buf), "RLP-encoding batch")
return buf.Len()
}

func l2BlockToRlpSpanBatch(rollupCfg *rollup.Config, l2block *types.Block) ([]byte, error) {
sbb := derive.NewSpanBatchBuilder(rollupCfg.Genesis.L2Time, rollupCfg.L2ChainID)
batch, l1Info, err := derive.BlockToSingularBatch(rollupCfg, l2block)
if err != nil {
return nil, err
}
sbb.AppendSingularBatch(batch, l1Info.SequenceNumber)
rawSpanBatch, err := sbb.GetRawSpanBatch()
if err != nil {
return nil, err
}
var buf bytes.Buffer
err = rlp.Encode(&buf, derive.NewBatchData(rawSpanBatch))
return buf.Bytes(), nil
}

func TestChannelBuilder_SpanBatchEncodingIncludesChecksum(t *testing.T) {
require := require.New(t)
cfg := ChannelConfig{
MaxFrameSize: 10000,
TargetNumFrames: 1,
BatchType: derive.SpanBatchType,
}
cfg.InitShadowCompressor()
cb, err := NewChannelBuilder(cfg, defaultTestRollupConfig, latestL1BlockOrigin)
require.NoError(err)

rng := rand.New(rand.NewSource(200))
l2block := dtest.RandomL2BlockWithChainId(rng, 2, defaultTestRollupConfig.L2ChainID)

_, err = cb.AddBlock(l2block)
require.NoError(err)

cb.Close()
require.NoError(cb.OutputFrames())

outputFrames := cb.frames
require.Equal(len(outputFrames), 1)

buf := bytes.NewBuffer(outputFrames[0].data)
f := new(derive.Frame)
err = f.UnmarshalBinary(buf)
require.NoError(err)

rlpBatch, err := l2BlockToRlpSpanBatch(&defaultTestRollupConfig, l2block)
require.NoError(err)
require.Greater(len(f.Data), 4)
actualChecksum := f.Data[len(f.Data)-4:]
expectedChecksum := adler32.Checksum(rlpBatch)
require.Equal(binary.BigEndian.Uint32(actualChecksum), expectedChecksum)
}
12 changes: 10 additions & 2 deletions op-node/rollup/derive/span_channel_out.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,18 @@ func (co *SpanChannelOut) Close() error {
return ErrChannelOutAlreadyClosed
}
co.closed = true
if err := co.Flush(); err != nil {
if err := co.compress.Close(); err != nil {
return err
}
return co.compress.Close()
if co.ReadyBytes() == 0 && co.compress.Len() > 0 {
_, err := io.Copy(co.reader, co.compress)
if err != nil {
// Must reset reader to avoid partial output
co.reader.Reset()
return fmt.Errorf("failed to flush compressed data to reader: %w", err)
}
}
return nil
}

// OutputFrame writes a frame to w with a given max size and returns the frame
Expand Down

0 comments on commit c27a652

Please sign in to comment.