Channels
Taken from the OP Stack specs, Channel
s are a set of
sequencer batches (for any L2 blocks) compressed together.
Where Channels fit in the OP Stack
L2 transactions are grouped into what are called sequencer batches. In order to obtain a better compression ratio when posting these L2 transactions to the data availability layer, sequencer batches are compressed together into what is called a Channel. This ultimately reduces data availability costs. As previously noted in the Frame section, Channels may not "fit" in a single batcher transaction, posting the data to the data availability layer. In order to accommodate large Channels, a tertiary Frame data type breaks the Channel up into multiple Frames where a batcher transaction then consists of one or multiple Frames.
Contents of a Channel
A Channel is comprised of the following items.
- A
ChannelId
which is a 16 byte long identifier for the channel. Notice, Frames also contain aChannelId
, which is the identical to this identifier, since frames "belong" to a given channel. - A
BlockInfo
that marks the L1 block at which the channel is "opened" at. - The estimated size of the channel (as a
usize
) used to drop the channel if there is a data overflow. - A
boolean
if the channel is "closed". This indicates if the last frame has been buffered, and added to the channel. - A
u16
indicating the highest frame number within the channel. - The frame number of the last frame (where
is_last
set totrue
). - A mapping from Frame number to the
Frame
itself. - A
BlockInfo
for highest L1 inclusion block that a frame was included in.
Channel Encoding
Channel
encoding is even more straightforward than that of a
Frame
. Simply, a Channel
is the concatenated list
of encoded Frame
s.
Since each Frame
contains the ChannelId
that corresponds
to the given Channel
, constructing a Channel
is as
simple as calling the Channel::add_frame
method for each of
its Frame
s.
Once the Channel
has ingested all of it's Frame
s,
it will be marked as "ready", with the Channel::is_ready
method returning true
.
The Channel
Type
As discussed above, the Channel
type is
expected to be populated with Frame
s using its
Channel::add_frame
method. Below we demonstrate constructing
a minimal Channel
using a few frames.
#![allow(unused)] fn main() { use op_alloy_protocol::{Channel, Frame}; // Construct a channel at the given L1 block. let id = [0xee; 16]; let block = BlockInfo::default(); let mut channel = Channel::new(id, block); // The channel will consist of 3 frames. let frame_0 = Frame { id: [0xee; 16], number: 0, ..Default::default() }; let frame_1 = Frame { id: [0xee; 16], number: 1, ..Default::default() }; let frame_2 = Frame { id: [0xee; 16], number: 2, is_last: true, ..Default::default() }; // Add the frames to the channel. channel.add_frame(frame_0); channel.add_frame(frame_1); channel.add_frame(frame_2); // Since the last frame was ingested, // the channel should be ready. assert!(channel.is_ready()); }
There are a few rules when adding a Frame
to a Channel
.
- The
Frame
's id must be the sameChannelId
as theChannel
s. Frame
s cannot be added once aChannel
is closed.Frame
s within aChannel
must have distinct numbers.
Notice, Frame
s can be added out-of-order so long as the Channel
is
still open, and the frame hasn't already been added.