Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(book): Frames to Batches Example #232

Merged
merged 8 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/book.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Setup mdbook
run: |
cargo install --version 0.4.40 mdbook
cargo install mdbook-mermaid mdbook-template
cargo install mdbook-mermaid mdbook-template mdbook-alerts
- name: Build book
working-directory: ./book
run: mdbook build
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
snap = "1.1.1"
bincode = "1.3.3"
ethereum_ssz = "0.8"
brotli = { version = "7.0.0", default-features = false }

# rpc
jsonrpsee = { version = "0.24", features = [
Expand Down
2 changes: 1 addition & 1 deletion book/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This repository contains the source code for the op-alloy book, which is availab

To build the book locally, a few dependencies are required:
```sh
cargo install mdbook mdbook-mermaid mdbook-template
cargo install mdbook mdbook-mermaid mdbook-template mdbook-alerts
```

Then, to run the book locally during development, run:
Expand Down
2 changes: 2 additions & 0 deletions book/book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ command = "mdbook-mermaid"

[preprocessor.template]

[preprocessor.alerts]

[output.html]
default-theme = "ferra"
preferred-dark-theme = "ferra"
Expand Down
8 changes: 7 additions & 1 deletion book/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ table tbody tr:nth-child(2n) {
--searchresults-header-fg: #fce2d4;
--searchresults-border-color: #feceb454;
--search-mark-bg: #f6b6c9ba;

}

.ferra .content .header {
Expand Down Expand Up @@ -105,6 +104,13 @@ table tbody tr:nth-child(2n) {
color: #fecdb2;
}

:where(.ferra) .mdbook-callouts-info {
background-color: #f0f0f0;
border-left: 4px solid #3498db;
padding: 1em;
margin: 1em 0;
}

:where(.ferra) .hljs-built_in,
:where(.ferra) .hljs-deletion,
:where(.ferra) .hljs-literal,
Expand Down
2 changes: 2 additions & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
- [Batches](./building/protocol/batches.md)
- [Examples](./examples/README.md)
- [Load a Rollup Config](./examples/load-a-rollup-config.md)
- [Transform Frames to a Batch](./examples/frames-to-batch.md)
- [Transform a Batch into Frames](./examples/batch-to-frames.md)
- [Contributing](./CONTRIBUTING.md)
- [Licensing](./LICENSE.md)
- [Glossary](./glossary.md)
2 changes: 2 additions & 0 deletions book/src/examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
Examples for working with `op-alloy-*` crates.

- [Load a Rollup Config for a Chain ID](./load-a-rollup-config.md)
- [Transform Frames to a Batch](./frames-to-batch.md)
- [Transform a Batch to Frames](./batch-to-frames.md)
68 changes: 68 additions & 0 deletions book/src/examples/batch-to-frames.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Transform a Batch into Frames

> [!NOTE]
>
> This example performs the reverse transformation as the [frames-to-batch][frames-to-batch] example.

> [!CAUTION]
>
> Steps and handling of types with respect to chain tip, ordering of frames, re-orgs, and
> more are not covered by this example. This example solely demonstrates the most trivial
> way to transform an individual [`SingleBatch`][batch] into [`Frame`][frame]s.

This example walks through transforming a [`SingleBatch`][single-batch] into [`Frame`][frame]s.

Effectively, this example demonstrates the _encoding_ process from an L2 batch into the
serialized bytes that are posted to the data availability layer.

## Walkthrough

The high level transformation is the following.

```
SingleBatch -> decompressed batch data -> ChannelOut -> frames[] -> bytes[]
```

Given the [`SingleBatch`][single-batch], the first step to encode the batch
using the [`SingleBatch::encode()`][encode-batch] method. The output bytes
need to then be compressed prior to adding them to the
[`ChannelOut`][channel-out].

> [!NOTE]
>
> The [`ChannelOut`][channel-out] type also provides a method for adding
> the [`SingleBatch`][single-batch] itself, handling encoding and
> compression, but this method is not available yet.

Once compressed using the helper `compress_brotli` method, the compressed
bytes can be added to a newly constructed [`ChannelOut`][channel-out].
As long as the [`ChannelOut`][channel-out] has [`ready_bytes()`][ready-bytes],
[`Frame`][frame]s can be constructed using the
[`ChannelOut::output_frame()`][output-frame] method, specifying the maximum
frame size.

Once [`Frame`][frame]s are returned from the [`ChannelOut`][channel-out],
they can be [`Frame::encode`][encode-frame] into raw, serialized data
ready to be batch-submitted to the data-availability layer.


> [!Note]
>
> In the example below, the additional `example_transactions()` and `compress_brotli()`
> methods are helper functions that can be ignored for the sake of the example.


## Running this example:

- Clone the examples repository: `git clone [email protected]:alloy-rs/op-alloy.git`
- Run: `cargo run --example batch_to_frames`

```rust
{{#include ../../../crates/protocol/examples/batch_to_frames.rs}}
```

<!-- Links -->

[frames-to-batch]: ./frames-to-batch.md

{{#include ../links.md}}
65 changes: 65 additions & 0 deletions book/src/examples/frames-to-batch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Transform Frames into a Batch

> [!NOTE]
>
> This example performs the reverse transformation as the [batch-to-frames][batch-to-frames] example.

> [!CAUTION]
>
> Steps and handling of types with respect to chain tip, ordering of frames, re-orgs, and
> more are not covered by this example. This example solely demonstrates the most trivial
> way to transform individual [`Frame`][frame]s into a [`SingleBatch`][batch] type.

This example walks through transforming [`Frame`][frame]s into the [`SingleBatch`][single-batch]
types.

## Walkthrough

The high level transformation is the following.

```
raw bytes[] -> frames[] -> channel -> decompressed channel data -> SingleBatch
```

Given the raw, batch-submitted frame data as bytes (read in with the [`hex!` macro][hex]),
the first step is to decode the frame data into [`Frame`][frame]s using
[`Frame::decode`][decode-frame]. Once all the [`Frame`][frame]s are decoded,
the [`Channel`][channel] can be constructed using the [`ChannelId`][channel-id]
of the first frame.

> [!Note]
>
> [`Frame`][frame]s may also be added to a [`Channel`][channel]
> once decoded with the [`Channel::add_frame`][add-frame] method.

When the [`Channel`][channel] is [`Channel::is_ready()`][is-ready],
the frame data can taken from the [`Channel`][channel] using
[`Channel::frame_data()`][frame-data]. This data is represented as [`Bytes`][bytes]
and needs to be decompressed using the respective compression algorithm depending on
which hardforks are activated (using the `RollupConfig`). For the sake of this example,
`brotli` is used (which was activated in the [Fjord hardfork][fjord]). Decompressed
brotli bytes can then be passed right into [`SingleBatch::decode`][decode-batch]
to wind up with the example's desired [`SingleBatch`][single-batch].


> [!Note]
>
> In the example below, the additional `example_transactions()` and `decompress_brotli()`
> methods are helper functions that can be ignored for the sake of the example.



## Running this example:

- Clone the examples repository: `git clone [email protected]:alloy-rs/op-alloy.git`
- Run: `cargo run --example frames_to_batch`

```rust
{{#include ../../../crates/protocol/examples/frames_to_batch.rs}}
```

<!-- Links -->

[batch-to-frames]: ./batch-to-frames.md

{{#include ../links.md}}
20 changes: 20 additions & 0 deletions book/src/links.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@
[update]: https://docs.rs/op-alloy-genesis/latest/op_alloy_genesis/system/struct.SystemConfig.html#method.update_with_receipts
[system-config]: https://docs.rs/op-alloy-genesis/latest/op_alloy_genesis/system/struct.SystemConfig.html

<!-- op-alloy-protocol -->

[encode-batch]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.SingleBatch.html#method.encode
[encode-frame]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.Frame.html#method.encode
[add-frame]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.Channel.html#method.add_frame
[decode-batch]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.SingleBatch.html#method.decode
[single-batch]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.SingleBatch.html
[bytes]: https://docs.rs/alloy-primitives/latest/alloy_primitives/struct.Bytes.html
[channel-id]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/type.ChannelId.html
[channel]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.Channel.html
[channel-out]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.ChannelOut.html
[ready-bytes]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.ChannelOut.html#method.ready_bytes
[output-frame]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.ChannelOut.html#method.output_frame
[decode-frame]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.Frame.html#method.decode
[hex]: https://docs.rs/hex-literal/latest/hex_literal/macro.hex.html
[fjord]: https://specs.optimism.io/protocol/fjord/overview.html
[frame-data]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.Channel.html#method.frame_data
[is-ready]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.Channel.html#method.is_ready
[frame]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/struct.Frame.html
[batch]: https://docs.rs/op-alloy-protocol/latest/op_alloy_protocol/enum.Batch.html

<!-- op-alloy-consensus -->

Expand Down
24 changes: 24 additions & 0 deletions crates/consensus/src/transaction/envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,4 +675,28 @@ mod tests {
let deposit = tx.as_deposit().unwrap();
assert!(deposit.mint.is_none());
}

#[test]
fn eip1559_decode() {
use alloy_consensus::SignableTransaction;
use alloy_primitives::PrimitiveSignature;
let tx = TxEip1559 {
chain_id: 1u64,
nonce: 2,
max_fee_per_gas: 3,
max_priority_fee_per_gas: 4,
gas_limit: 5,
to: Address::left_padding_from(&[6]).into(),
value: U256::from(7_u64),
input: vec![8].into(),
access_list: Default::default(),
};
let sig = PrimitiveSignature::test_signature();
let tx_signed = tx.into_signed(sig);
let envelope: OpTxEnvelope = tx_signed.into();
let encoded = envelope.encoded_2718();
let mut slice = encoded.as_slice();
let decoded = OpTxEnvelope::decode_2718(&mut slice).unwrap();
assert!(matches!(decoded, OpTxEnvelope::Eip1559(_)));
}
}
1 change: 1 addition & 0 deletions crates/protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ spin = { workspace = true, optional = true }
tracing-subscriber = { workspace = true, features = ["fmt"], optional = true }

[dev-dependencies]
brotli = { workspace = true, features = ["std"] }
revm.workspace = true
spin.workspace = true
rand.workspace = true
Expand Down
Loading
Loading