Commit 00950152 authored by Roberto Bayardo's avatar Roberto Bayardo Committed by GitHub

export ChannelBuilder so we can use it in external analysis scripts (#9784)

parent 1786bce8
......@@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum/log"
)
// channel is a lightweight wrapper around a channelBuilder which keeps track of pending
// channel is a lightweight wrapper around a ChannelBuilder which keeps track of pending
// and confirmed transactions for a single channel.
type channel struct {
log log.Logger
......@@ -20,7 +20,7 @@ type channel struct {
cfg ChannelConfig
// pending channel builder
channelBuilder *channelBuilder
channelBuilder *ChannelBuilder
// Set of unconfirmed txID -> frame data. For tx resubmission
pendingTransactions map[txID]txData
// Set of confirmed txID -> inclusion block. For determining if the channel is timed out
......@@ -35,7 +35,7 @@ type channel struct {
}
func newChannel(log log.Logger, metr metrics.Metricer, cfg ChannelConfig, rollupCfg *rollup.Config) (*channel, error) {
cb, err := newChannelBuilder(cfg, *rollupCfg)
cb, err := NewChannelBuilder(cfg, *rollupCfg)
if err != nil {
return nil, fmt.Errorf("creating new channel: %w", err)
}
......
......@@ -74,7 +74,7 @@ func (cc *ChannelConfig) Check() error {
// If the [MaxFrameSize] is set to 0, the channel builder
// will infinitely loop when trying to create frames in the
// [channelBuilder.OutputFrames] function.
// [ChannelBuilder.OutputFrames] function.
if cc.MaxFrameSize == 0 {
return errors.New("max frame size cannot be zero")
}
......@@ -104,9 +104,9 @@ type frameData struct {
id frameID
}
// channelBuilder uses a ChannelOut to create a channel with output frame
// ChannelBuilder uses a ChannelOut to create a channel with output frame
// size approximation.
type channelBuilder struct {
type ChannelBuilder struct {
cfg ChannelConfig
rollupCfg rollup.Config
......@@ -136,7 +136,7 @@ type channelBuilder struct {
// newChannelBuilder creates a new channel builder or returns an error if the
// channel out could not be created.
func newChannelBuilder(cfg ChannelConfig, rollupCfg rollup.Config) (*channelBuilder, error) {
func NewChannelBuilder(cfg ChannelConfig, rollupCfg rollup.Config) (*ChannelBuilder, error) {
c, err := cfg.CompressorConfig.NewCompressor()
if err != nil {
return nil, err
......@@ -150,41 +150,41 @@ func newChannelBuilder(cfg ChannelConfig, rollupCfg rollup.Config) (*channelBuil
return nil, err
}
return &channelBuilder{
return &ChannelBuilder{
cfg: cfg,
rollupCfg: rollupCfg,
co: co,
}, nil
}
func (c *channelBuilder) ID() derive.ChannelID {
func (c *ChannelBuilder) ID() derive.ChannelID {
return c.co.ID()
}
// InputBytes returns the total amount of input bytes added to the channel.
func (c *channelBuilder) InputBytes() int {
func (c *ChannelBuilder) InputBytes() int {
return c.co.InputBytes()
}
// ReadyBytes returns the amount of bytes ready in the compression pipeline to
// output into a frame.
func (c *channelBuilder) ReadyBytes() int {
func (c *ChannelBuilder) ReadyBytes() int {
return c.co.ReadyBytes()
}
func (c *channelBuilder) OutputBytes() int {
func (c *ChannelBuilder) OutputBytes() int {
return c.outputBytes
}
// Blocks returns a backup list of all blocks that were added to the channel. It
// can be used in case the channel needs to be rebuilt.
func (c *channelBuilder) Blocks() []*types.Block {
func (c *ChannelBuilder) Blocks() []*types.Block {
return c.blocks
}
// Reset resets the internal state of the channel builder so that it can be
// reused. Note that a new channel id is also generated by Reset.
func (c *channelBuilder) Reset() error {
func (c *ChannelBuilder) Reset() error {
c.blocks = c.blocks[:0]
c.frames = c.frames[:0]
c.timeout = 0
......@@ -203,7 +203,7 @@ func (c *channelBuilder) Reset() error {
// first transaction for subsequent use by the caller.
//
// Call OutputFrames() afterwards to create frames.
func (c *channelBuilder) AddBlock(block *types.Block) (*derive.L1BlockInfo, error) {
func (c *ChannelBuilder) AddBlock(block *types.Block) (*derive.L1BlockInfo, error) {
if c.IsFull() {
return nil, c.FullErr()
}
......@@ -236,7 +236,7 @@ func (c *channelBuilder) AddBlock(block *types.Block) (*derive.L1BlockInfo, erro
//
// It ensures proper tracking of all possible timeouts (max channel duration,
// close to consensus channel timeout, close to end of sequencing window).
func (c *channelBuilder) RegisterL1Block(l1BlockNum uint64) {
func (c *ChannelBuilder) RegisterL1Block(l1BlockNum uint64) {
c.updateDurationTimeout(l1BlockNum)
c.checkTimeout(l1BlockNum)
}
......@@ -244,7 +244,7 @@ func (c *channelBuilder) RegisterL1Block(l1BlockNum uint64) {
// FramePublished should be called whenever a frame of this channel got
// published with the L1-block number of the block that the frame got included
// in.
func (c *channelBuilder) FramePublished(l1BlockNum uint64) {
func (c *ChannelBuilder) FramePublished(l1BlockNum uint64) {
timeout := l1BlockNum + c.cfg.ChannelTimeout - c.cfg.SubSafetyMargin
c.updateTimeout(timeout, ErrChannelTimeoutClose)
}
......@@ -254,7 +254,7 @@ func (c *channelBuilder) FramePublished(l1BlockNum uint64) {
// forward if the derived timeout is earlier than the currently set timeout.
//
// It does nothing if the max channel duration is set to 0.
func (c *channelBuilder) updateDurationTimeout(l1BlockNum uint64) {
func (c *ChannelBuilder) updateDurationTimeout(l1BlockNum uint64) {
if c.cfg.MaxChannelDuration == 0 {
return
}
......@@ -266,7 +266,7 @@ func (c *channelBuilder) updateDurationTimeout(l1BlockNum uint64) {
// derived from the batch's origin L1 block. The timeout is only moved forward
// if the derived sequencer window timeout is earlier than the currently set
// timeout.
func (c *channelBuilder) updateSwTimeout(batch *derive.SingularBatch) {
func (c *ChannelBuilder) updateSwTimeout(batch *derive.SingularBatch) {
timeout := uint64(batch.EpochNum) + c.cfg.SeqWindowSize - c.cfg.SubSafetyMargin
c.updateTimeout(timeout, ErrSeqWindowClose)
}
......@@ -276,7 +276,7 @@ func (c *channelBuilder) updateSwTimeout(batch *derive.SingularBatch) {
//
// If the timeout is updated, the provided reason will be set as the channel
// full error reason in case the timeout is hit in the future.
func (c *channelBuilder) updateTimeout(timeoutBlockNum uint64, reason error) {
func (c *ChannelBuilder) updateTimeout(timeoutBlockNum uint64, reason error) {
if c.timeout == 0 || c.timeout > timeoutBlockNum {
c.timeout = timeoutBlockNum
c.timeoutReason = reason
......@@ -285,7 +285,7 @@ func (c *channelBuilder) updateTimeout(timeoutBlockNum uint64, reason error) {
// checkTimeout checks if the channel is timed out at the given block number and
// in this case marks the channel as full, if it wasn't full already.
func (c *channelBuilder) checkTimeout(blockNum uint64) {
func (c *ChannelBuilder) checkTimeout(blockNum uint64) {
if !c.IsFull() && c.TimedOut(blockNum) {
c.setFullErr(c.timeoutReason)
}
......@@ -293,13 +293,13 @@ func (c *channelBuilder) checkTimeout(blockNum uint64) {
// TimedOut returns whether the passed block number is after the timeout block
// number. If no block timeout is set yet, it returns false.
func (c *channelBuilder) TimedOut(blockNum uint64) bool {
func (c *ChannelBuilder) TimedOut(blockNum uint64) bool {
return c.timeout != 0 && blockNum >= c.timeout
}
// IsFull returns whether the channel is full.
// FullErr returns the reason for the channel being full.
func (c *channelBuilder) IsFull() bool {
func (c *ChannelBuilder) IsFull() bool {
return c.fullErr != nil
}
......@@ -317,11 +317,11 @@ func (c *channelBuilder) IsFull() bool {
// - ErrChannelTimeoutClose if the consensus channel timeout got too close,
// - ErrSeqWindowClose if the end of the sequencer window got too close,
// - ErrTerminated if the channel was explicitly terminated.
func (c *channelBuilder) FullErr() error {
func (c *ChannelBuilder) FullErr() error {
return c.fullErr
}
func (c *channelBuilder) setFullErr(err error) {
func (c *ChannelBuilder) setFullErr(err error) {
c.fullErr = &ChannelFullError{Err: err}
}
......@@ -333,7 +333,7 @@ func (c *channelBuilder) setFullErr(err error) {
// pull readily available frames from the compression output.
// If it is full, the channel is closed and all remaining
// frames will be created, possibly with a small leftover frame.
func (c *channelBuilder) OutputFrames() error {
func (c *ChannelBuilder) OutputFrames() error {
if c.IsFull() {
err := c.closeAndOutputAllFrames()
if err != nil {
......@@ -349,7 +349,7 @@ func (c *channelBuilder) OutputFrames() error {
//
// This is part of an optimization to already generate frames and send them off
// as txs while still collecting blocks in the channel builder.
func (c *channelBuilder) outputReadyFrames() error {
func (c *ChannelBuilder) outputReadyFrames() error {
// TODO: Decide whether we want to fill frames to max size and use target
// only for estimation, or use target size.
for c.co.ReadyBytes() >= int(c.cfg.MaxFrameSize) {
......@@ -362,7 +362,7 @@ func (c *channelBuilder) outputReadyFrames() error {
return nil
}
func (c *channelBuilder) closeAndOutputAllFrames() error {
func (c *ChannelBuilder) closeAndOutputAllFrames() error {
if err := c.co.Close(); err != nil {
return fmt.Errorf("closing channel out: %w", err)
}
......@@ -379,7 +379,7 @@ func (c *channelBuilder) closeAndOutputAllFrames() error {
// outputFrame creates one new frame and adds it to the frames queue.
// Note that compressed output data must be available on the underlying
// ChannelOut, or an empty frame will be produced.
func (c *channelBuilder) outputFrame() error {
func (c *ChannelBuilder) outputFrame() error {
var buf bytes.Buffer
fn, err := c.co.OutputFrame(&buf, c.cfg.MaxFrameSize)
if err != io.EOF && err != nil {
......@@ -409,7 +409,7 @@ func (c *channelBuilder) outputFrame() error {
// Close immediately marks the channel as full with an ErrTerminated
// if the channel is not already full.
func (c *channelBuilder) Close() {
func (c *ChannelBuilder) Close() {
if !c.IsFull() {
c.setFullErr(ErrTerminated)
}
......@@ -417,7 +417,7 @@ func (c *channelBuilder) Close() {
// TotalFrames returns the total number of frames that were created in this channel so far.
// It does not decrease when the frames queue is being emptied.
func (c *channelBuilder) TotalFrames() int {
func (c *ChannelBuilder) TotalFrames() int {
return c.numFrames
}
......@@ -426,20 +426,20 @@ func (c *channelBuilder) TotalFrames() int {
//
// Call OutputFrames before to create new frames from the channel out
// compression pipeline.
func (c *channelBuilder) HasFrame() bool {
func (c *ChannelBuilder) HasFrame() bool {
return len(c.frames) > 0
}
// PendingFrames returns the number of pending frames in the frames queue.
// It is larger zero iff HasFrames() returns true.
func (c *channelBuilder) PendingFrames() int {
func (c *ChannelBuilder) PendingFrames() int {
return len(c.frames)
}
// NextFrame returns the next available frame.
// HasFrame must be called prior to check if there's a next frame available.
// Panics if called when there's no next frame.
func (c *channelBuilder) NextFrame() frameData {
func (c *ChannelBuilder) NextFrame() frameData {
if len(c.frames) == 0 {
panic("no next frame")
}
......@@ -451,7 +451,7 @@ func (c *channelBuilder) NextFrame() frameData {
// PushFrame adds the frame back to the internal frames queue. Panics if not of
// the same channel.
func (c *channelBuilder) PushFrame(frame frameData) {
func (c *ChannelBuilder) PushFrame(frame frameData) {
if frame.id.chID != c.ID() {
panic("wrong channel")
}
......
......@@ -116,8 +116,8 @@ func FuzzChannelConfig_CheckTimeout(f *testing.F) {
}
// addMiniBlock adds a minimal valid L2 block to the channel builder using the
// channelBuilder.AddBlock method.
func addMiniBlock(cb *channelBuilder) error {
// ChannelBuilder.AddBlock method.
func addMiniBlock(cb *ChannelBuilder) error {
a := newMiniL2Block(0)
_, err := cb.AddBlock(a)
return err
......@@ -163,7 +163,7 @@ func newMiniL2BlockWithNumberParent(numTx int, number *big.Int, parent common.Ha
// addTooManyBlocks adds blocks to the channel until it hits an error,
// which is presumably ErrTooManyRLPBytes.
func addTooManyBlocks(cb *channelBuilder) error {
func addTooManyBlocks(cb *ChannelBuilder) error {
rng := rand.New(rand.NewSource(1234))
for i := 0; i < 10_000; i++ {
block := dtest.RandomL2BlockWithChainId(rng, 1000, defaultTestRollupConfig.L2ChainID)
......@@ -185,7 +185,7 @@ func FuzzDurationTimeoutZeroMaxChannelDuration(f *testing.F) {
f.Fuzz(func(t *testing.T, l1BlockNum uint64) {
channelConfig := defaultTestChannelConfig
channelConfig.MaxChannelDuration = 0
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
cb.timeout = 0
cb.updateDurationTimeout(l1BlockNum)
......@@ -208,7 +208,7 @@ func FuzzChannelBuilder_DurationZero(f *testing.F) {
// Create the channel builder
channelConfig := defaultTestChannelConfig
channelConfig.MaxChannelDuration = maxChannelDuration
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Whenever the timeout is set to 0, the channel builder should have a duration timeout
......@@ -235,7 +235,7 @@ func FuzzDurationTimeoutMaxChannelDuration(f *testing.F) {
// Create the channel builder
channelConfig := defaultTestChannelConfig
channelConfig.MaxChannelDuration = maxChannelDuration
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Whenever the timeout is greater than the l1BlockNum,
......@@ -269,7 +269,7 @@ func FuzzChannelCloseTimeout(f *testing.F) {
channelConfig := defaultTestChannelConfig
channelConfig.ChannelTimeout = channelTimeout
channelConfig.SubSafetyMargin = subSafetyMargin
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Check the timeout
......@@ -297,7 +297,7 @@ func FuzzChannelZeroCloseTimeout(f *testing.F) {
channelConfig := defaultTestChannelConfig
channelConfig.ChannelTimeout = channelTimeout
channelConfig.SubSafetyMargin = subSafetyMargin
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Check the timeout
......@@ -324,7 +324,7 @@ func FuzzSeqWindowClose(f *testing.F) {
channelConfig := defaultTestChannelConfig
channelConfig.SeqWindowSize = seqWindowSize
channelConfig.SubSafetyMargin = subSafetyMargin
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Check the timeout
......@@ -352,7 +352,7 @@ func FuzzSeqWindowZeroTimeoutClose(f *testing.F) {
channelConfig := defaultTestChannelConfig
channelConfig.SeqWindowSize = seqWindowSize
channelConfig.SubSafetyMargin = subSafetyMargin
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Check the timeout
......@@ -399,10 +399,10 @@ func TestChannelBuilder_NextFrame(t *testing.T) {
channelConfig := defaultTestChannelConfig
// Create a new channel builder
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Mock the internals of `channelBuilder.outputFrame`
// Mock the internals of `ChannelBuilder.outputFrame`
// to construct a single frame
co := cb.co
var buf bytes.Buffer
......@@ -439,10 +439,10 @@ func TestChannelBuilder_OutputWrongFramePanic(t *testing.T) {
channelConfig := defaultTestChannelConfig
// Construct a channel builder
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Mock the internals of `channelBuilder.outputFrame`
// Mock the internals of `ChannelBuilder.outputFrame`
// to construct a single frame
c, err := channelConfig.CompressorConfig.NewCompressor()
require.NoError(t, err)
......@@ -472,7 +472,7 @@ func TestChannelBuilder_OutputFramesWorks(t *testing.T) {
channelConfig.MaxFrameSize = 24
// Construct the channel builder
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
require.False(t, cb.IsFull())
require.Equal(t, 0, cb.PendingFrames())
......@@ -515,7 +515,7 @@ func TestChannelBuilder_OutputFramesWorks_SpanBatch(t *testing.T) {
channelConfig.BatchType = derive.SpanBatchType
// Construct the channel builder
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
require.False(t, cb.IsFull())
require.Equal(t, 0, cb.PendingFrames())
......@@ -557,7 +557,7 @@ func TestChannelBuilder_OutputFramesWorks_SpanBatch(t *testing.T) {
require.LessOrEqual(t, len(cb.frames[len(cb.frames)-1].data), int(channelConfig.MaxFrameSize))
}
// ChannelBuilder_MaxRLPBytesPerChannel tests the [channelBuilder.OutputFrames]
// ChannelBuilder_MaxRLPBytesPerChannel tests the [ChannelBuilder.OutputFrames]
// function errors when the max RLP bytes per channel is reached.
func ChannelBuilder_MaxRLPBytesPerChannel(t *testing.T, batchType uint) {
t.Parallel()
......@@ -568,7 +568,7 @@ func ChannelBuilder_MaxRLPBytesPerChannel(t *testing.T, batchType uint) {
channelConfig.BatchType = batchType
// Construct the channel builder
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Add a block that overflows the [ChannelOut]
......@@ -589,9 +589,9 @@ func ChannelBuilder_OutputFramesMaxFrameIndex(t *testing.T, batchType uint) {
rng := rand.New(rand.NewSource(123))
// Continuously add blocks until the max frame index is reached
// This should cause the [channelBuilder.OutputFrames] function
// This should cause the [ChannelBuilder.OutputFrames] function
// to error
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
require.False(t, cb.IsFull())
require.Equal(t, 0, cb.PendingFrames())
......@@ -624,7 +624,7 @@ func ChannelBuilder_AddBlock(t *testing.T, batchType uint) {
channelConfig.CompressorConfig.ApproxComprRatio = 1
// Construct the channel builder
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Add a nonsense block to the channel builder
......@@ -657,7 +657,7 @@ func ChannelBuilder_Reset(t *testing.T, batchType uint) {
channelConfig.CompressorConfig.TargetFrameSize = 24
channelConfig.CompressorConfig.ApproxComprRatio = 1
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Add a nonsense block to the channel builder
......@@ -698,7 +698,7 @@ func TestBuilderRegisterL1Block(t *testing.T) {
channelConfig := defaultTestChannelConfig
// Construct the channel builder
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Assert params modified in RegisterL1Block
......@@ -721,7 +721,7 @@ func TestBuilderRegisterL1BlockZeroMaxChannelDuration(t *testing.T) {
channelConfig.MaxChannelDuration = 0
// Construct the channel builder
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Assert params modified in RegisterL1Block
......@@ -742,7 +742,7 @@ func TestFramePublished(t *testing.T) {
channelConfig := defaultTestChannelConfig
// Construct the channel builder
cb, err := newChannelBuilder(channelConfig, defaultTestRollupConfig)
cb, err := NewChannelBuilder(channelConfig, defaultTestRollupConfig)
require.NoError(t, err)
// Let's say the block number is fed in as 100
......@@ -768,7 +768,7 @@ func ChannelBuilder_PendingFrames_TotalFrames(t *testing.T, batchType uint) {
cfg.CompressorConfig.TargetNumFrames = tnf
cfg.CompressorConfig.Kind = "shadow"
cfg.BatchType = batchType
cb, err := newChannelBuilder(cfg, defaultTestRollupConfig)
cb, err := NewChannelBuilder(cfg, defaultTestRollupConfig)
require.NoError(err)
// initial builder should be empty
......@@ -812,7 +812,7 @@ func ChannelBuilder_InputBytes(t *testing.T, batchType uint) {
chainId := big.NewInt(1234)
spanBatchBuilder = derive.NewSpanBatchBuilder(uint64(0), chainId)
}
cb, err := newChannelBuilder(cfg, defaultTestRollupConfig)
cb, err := NewChannelBuilder(cfg, defaultTestRollupConfig)
require.NoError(err)
require.Zero(cb.InputBytes())
......@@ -848,8 +848,8 @@ func ChannelBuilder_OutputBytes(t *testing.T, batchType uint) {
cfg.CompressorConfig.TargetNumFrames = 16
cfg.CompressorConfig.ApproxComprRatio = 1.0
cfg.BatchType = batchType
cb, err := newChannelBuilder(cfg, defaultTestRollupConfig)
require.NoError(err, "newChannelBuilder")
cb, err := NewChannelBuilder(cfg, defaultTestRollupConfig)
require.NoError(err, "NewChannelBuilder")
require.Zero(cb.OutputBytes())
......
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