Skip to content

feat(l1): make rlp crate no_std#6412

Closed
kevaundray wants to merge 3 commits intolambdaclass:mainfrom
kevaundray:kw/no-std-rlp
Closed

feat(l1): make rlp crate no_std#6412
kevaundray wants to merge 3 commits intolambdaclass:mainfrom
kevaundray:kw/no-std-rlp

Conversation

@kevaundray
Copy link
Copy Markdown
Contributor

Motivation

Part of #6339

  • Adds a CI job to ensure that it stays no_std

Description

Checklist

  • Updated STORE_SCHEMA_VERSION (crates/storage/lib.rs) if the PR includes breaking changes to the Store requiring a re-sync.

Closes #issue_number

Comment on lines -17 to +18
InvalidCompression(#[from] snap::Error),
#[error("InvalidCompression: {0}")]
InvalidCompression(String),
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was pulling in the snap dependency only for this error variant

let compressed_size = snappy_encoder.compress(&encoded_data, &mut msg_data)?;
let compressed_size = snappy_encoder
.compress(&encoded_data, &mut msg_data)
.map_err(|e| RLPEncodeError::InvalidCompression(e.to_string()))?;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since InvaliadCompression variant now uses a string, we modify its callsite to convert to a string first

Comment on lines -10 to -16
tinyvec = "1.6.0"
thiserror.workspace = true
bytes.workspace = true
hex.workspace = true
lazy_static.workspace = true
ethereum-types.workspace = true
snap.workspace = true
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some of these deps were unused

@kevaundray kevaundray changed the title feat(1l): Make rlp crate no_std feat(l1): Make rlp crate no_std Mar 26, 2026
@kevaundray kevaundray changed the title feat(l1): Make rlp crate no_std feat(l1): make rlp crate no_std Mar 26, 2026
@kevaundray kevaundray marked this pull request as ready for review March 26, 2026 22:03
@kevaundray kevaundray requested a review from a team as a code owner March 26, 2026 22:03
Copilot AI review requested due to automatic review settings March 26, 2026 22:03
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 26, 2026

Greptile Summary

This PR makes the ethrex-rlp crate no_std compatible as part of the broader effort tracked in #6339. It achieves this by adding #![no_std] + extern crate alloc, replacing std:: imports with core::/alloc:: equivalents, removing the snap, hex, lazy_static, and tinyvec dependencies from the rlp crate, and moving compression responsibilities to the networking layer (rlpx/utils.rs). A new CI job is added to verify no_std compatibility against the riscv64imac-unknown-none-elf target on every PR touching common or vm crates.

Key changes:

  • rlp.rs: Adds #![no_std] and extern crate alloc
  • decode.rs / encode.rs / structs.rs: Swaps std::netcore::net, std::anycore::any, and adds explicit alloc imports
  • error.rs: Replaces #[from] snap::Error with String in InvalidCompression variants, decoupling the error type from the snap crate
  • rlpx/utils.rs: Updates both snappy functions to manually map snap::Error to String via .map_err(|e| ...InvalidCompression(e.to_string()))
  • Cargo.toml: All three remaining dependencies (thiserror, bytes, ethereum-types) are pinned with default-features = false
  • Two non-critical suggestions: (1) the Cargo.toml lacks a conventional std feature gate; (2) the CI workflow's crates/vm/** path trigger doesn't correspond to any crate being checked

Confidence Score: 5/5

Safe to merge — all changes are well-scoped, the CI no_std check will enforce correctness, and the only callsite for the changed error variants has been correctly updated.

The changes are mechanical and correct: std → core/alloc substitutions are straightforward, the snap dependency was cleanly extracted to the networking layer, and every former ?-based snap error conversion in utils.rs has been updated to use map_err. The two open suggestions (missing std feature flag, overly-broad CI trigger) are non-blocking best-practice items that don't affect correctness or runtime behaviour.

No files require special attention.

Important Files Changed

Filename Overview
crates/common/rlp/rlp.rs Adds #![no_std] and extern crate alloc to make the library no_std compatible.
crates/common/rlp/Cargo.toml Removes snap, hex, lazy_static, and tinyvec dependencies; switches remaining deps to default-features = false. Missing a std feature flag for idiomatic dual std/no_std support.
crates/common/rlp/error.rs Replaces #[from] snap::Error with String in InvalidCompression variants, removing the snap dependency from the error types.
crates/networking/p2p/rlpx/utils.rs Updates snappy_compress/decompress to use `.map_err(
.github/workflows/pr_nostd.yaml New CI workflow that checks no_std compatibility against riscv64imac-unknown-none-elf. The crates/vm/** path trigger is overly broad given only ethrex-rlp is checked.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["ethrex-rlp (no_std)"] -->|"alloc::String, alloc::Vec"| B[encode.rs]
    A -->|"alloc::String, alloc::Vec"| C[decode.rs]
    A -->|"alloc::format, alloc::Vec"| D[structs.rs]
    A -->|"alloc::String"| E[error.rs]

    B -->|"core::net types"| F[core]
    C -->|"core::net types"| F
    D -->|"core::any::type_name"| F

    E --> G["RLPDecodeError::InvalidCompression(String)"]
    E --> H["RLPEncodeError::InvalidCompression(String)"]

    I["ethrex-networking rlpx/utils.rs (std)"] -->|"snap::Error via map_err"| G
    I -->|"snap::Error via map_err"| H
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: crates/common/rlp/Cargo.toml
Line: 9-12

Comment:
**Missing `std` feature gate for downstream consumers**

The crate is now unconditionally `no_std`, but there is no `[features]` section with a `std` feature. The idiomatic pattern for library crates that want to support both environments is to expose a `std` feature that re-enables std support in transitive dependencies. Without it, downstream crates that want std-level functionality from `bytes`, `ethereum-types`, or `thiserror` through this crate cannot opt in.

In the current workspace this is not a practical problem because Cargo's feature unification ensures std features get enabled via other crates in the graph, but as a standalone library dependency it means callers have no explicit lever to control this.

Suggested approach:

```toml
[features]
default = ["std"]
std = [
    "bytes/std",
    "ethereum-types/std",
    "thiserror/std",
]

[dependencies]
thiserror = { version = "2.0.9", default-features = false }
bytes = { version = "1.6.0", default-features = false }
ethereum-types = { version = "0.15.1", default-features = false, features = ["ethbloom"] }
```

And in `rlp.rs`:
```rust
#![cfg_attr(not(feature = "std"), no_std)]
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: .github/workflows/pr_nostd.yaml
Line: 10-12

Comment:
**`crates/vm/**` trigger doesn't match the check being run**

The workflow triggers on changes to `crates/vm/**`, but the actual check step only runs `cargo check -p ethrex-rlp`. Changes to `crates/vm/` won't affect the `ethrex-rlp` build, so this path trigger will waste CI minutes without providing any signal about the vm crates' no_std compatibility.

If the intent is to eventually also verify that vm crates are no_std (per the parent issue #6339), the `run` step should be updated when those crates are converted. For now, removing `crates/vm/**` from the path triggers would reduce unnecessary CI runs.

```suggestion
    paths:
      - "crates/common/**"
      - ".github/workflows/pr_nostd.yaml"
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "make crate no_std unconditionally" | Re-trigger Greptile

Comment on lines 9 to +12
[dependencies]
tinyvec = "1.6.0"
thiserror.workspace = true
bytes.workspace = true
hex.workspace = true
lazy_static.workspace = true
ethereum-types.workspace = true
snap.workspace = true
thiserror = { version = "2.0.9", default-features = false }
bytes = { version = "1.6.0", default-features = false }
ethereum-types = { version = "0.15.1", default-features = false, features = ["ethbloom"] }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing std feature gate for downstream consumers

The crate is now unconditionally no_std, but there is no [features] section with a std feature. The idiomatic pattern for library crates that want to support both environments is to expose a std feature that re-enables std support in transitive dependencies. Without it, downstream crates that want std-level functionality from bytes, ethereum-types, or thiserror through this crate cannot opt in.

In the current workspace this is not a practical problem because Cargo's feature unification ensures std features get enabled via other crates in the graph, but as a standalone library dependency it means callers have no explicit lever to control this.

Suggested approach:

[features]
default = ["std"]
std = [
    "bytes/std",
    "ethereum-types/std",
    "thiserror/std",
]

[dependencies]
thiserror = { version = "2.0.9", default-features = false }
bytes = { version = "1.6.0", default-features = false }
ethereum-types = { version = "0.15.1", default-features = false, features = ["ethbloom"] }

And in rlp.rs:

#![cfg_attr(not(feature = "std"), no_std)]
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/common/rlp/Cargo.toml
Line: 9-12

Comment:
**Missing `std` feature gate for downstream consumers**

The crate is now unconditionally `no_std`, but there is no `[features]` section with a `std` feature. The idiomatic pattern for library crates that want to support both environments is to expose a `std` feature that re-enables std support in transitive dependencies. Without it, downstream crates that want std-level functionality from `bytes`, `ethereum-types`, or `thiserror` through this crate cannot opt in.

In the current workspace this is not a practical problem because Cargo's feature unification ensures std features get enabled via other crates in the graph, but as a standalone library dependency it means callers have no explicit lever to control this.

Suggested approach:

```toml
[features]
default = ["std"]
std = [
    "bytes/std",
    "ethereum-types/std",
    "thiserror/std",
]

[dependencies]
thiserror = { version = "2.0.9", default-features = false }
bytes = { version = "1.6.0", default-features = false }
ethereum-types = { version = "0.15.1", default-features = false, features = ["ethbloom"] }
```

And in `rlp.rs`:
```rust
#![cfg_attr(not(feature = "std"), no_std)]
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +10 to +12
- "crates/common/**"
- "crates/vm/**"
- ".github/workflows/pr_nostd.yaml"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 crates/vm/** trigger doesn't match the check being run

The workflow triggers on changes to crates/vm/**, but the actual check step only runs cargo check -p ethrex-rlp. Changes to crates/vm/ won't affect the ethrex-rlp build, so this path trigger will waste CI minutes without providing any signal about the vm crates' no_std compatibility.

If the intent is to eventually also verify that vm crates are no_std (per the parent issue #6339), the run step should be updated when those crates are converted. For now, removing crates/vm/** from the path triggers would reduce unnecessary CI runs.

Suggested change
- "crates/common/**"
- "crates/vm/**"
- ".github/workflows/pr_nostd.yaml"
paths:
- "crates/common/**"
- ".github/workflows/pr_nostd.yaml"
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/pr_nostd.yaml
Line: 10-12

Comment:
**`crates/vm/**` trigger doesn't match the check being run**

The workflow triggers on changes to `crates/vm/**`, but the actual check step only runs `cargo check -p ethrex-rlp`. Changes to `crates/vm/` won't affect the `ethrex-rlp` build, so this path trigger will waste CI minutes without providing any signal about the vm crates' no_std compatibility.

If the intent is to eventually also verify that vm crates are no_std (per the parent issue #6339), the `run` step should be updated when those crates are converted. For now, removing `crates/vm/**` from the path triggers would reduce unnecessary CI runs.

```suggestion
    paths:
      - "crates/common/**"
      - ".github/workflows/pr_nostd.yaml"
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes the ethrex-rlp crate buildable in no_std (+alloc) environments as part of the broader effort to support upstream Rust bare-metal targets for guest programs.

Changes:

  • Convert ethrex-rlp to #![no_std] and replace remaining std usages with core/alloc.
  • Remove std-leaning dependencies from ethrex-rlp and adjust dependency feature flags to support no_std.
  • Add a GitHub Actions workflow to cargo check ethrex-rlp for riscv64imac-unknown-none-elf.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
crates/networking/p2p/rlpx/utils.rs Adjust snappy (de)compression error mapping to the updated RLP error types.
crates/common/rlp/structs.rs Replace std type introspection with core and use alloc for formatting/Vec.
crates/common/rlp/rlp.rs Mark the crate as no_std and enable alloc.
crates/common/rlp/error.rs Remove snap::Error from public error enums; store compression errors as String.
crates/common/rlp/encode.rs Switch networking types import to core::net and use alloc types.
crates/common/rlp/decode.rs Switch networking types import to core::net and use alloc types.
crates/common/rlp/Cargo.toml Update dependencies to default-features = false for no_std compatibility and drop unused deps.
Cargo.lock Reflect dependency removals/adjustments for ethrex-rlp.
.github/workflows/pr_nostd.yaml Add CI job to verify ethrex-rlp no_std compatibility on a RISC-V bare-metal target.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

branches: ["**"]
paths:
- "crates/common/**"
- "crates/vm/**"
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow is filtered to run on changes under crates/vm/**, but the job currently only checks -p ethrex-rlp. This will trigger extra CI runs for VM-only PRs without providing additional coverage; consider narrowing the paths filter to the crates actually being checked (e.g. crates/common/rlp/** or crates/common/** only).

Suggested change
- "crates/vm/**"

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@ElFantasma ElFantasma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution. The migration looks correct, we have to fix the CI failing, though.

- uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This installs the riscv target on stable, but the repo pins Rust 1.90.0 via rust-toolchain.toml — so cargo check uses 1.90.0 which doesn't have the target. Fix:

      - name: Setup Rust
        uses: ./.github/actions/setup-rust

      - name: Add riscv target
        run: rustup target add riscv64imac-unknown-none-elf

This reuses the shared setup action (reads version from rust-toolchain.toml) and adds the target to the correct toolchain.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good point 🫡 Currently on a plane, can change this when I land

@kevaundray
Copy link
Copy Markdown
Contributor Author

closing since it will be done internally!

github-merge-queue bot pushed a commit that referenced this pull request Mar 30, 2026
## Motivation

Continuation of #6412. Part of #6339.

## Description

Cherry-picked from #6412 onto current main. Makes the RLP crate `no_std`
unconditionally and adds a CI job to ensure it stays that way.

## Checklist

- [ ] Updated `STORE_SCHEMA_VERSION` (crates/storage/lib.rs) if the PR
includes breaking changes to the `Store` requiring a re-sync.

---------

Co-authored-by: Kevaundray Wedderburn <kevtheappdev@gmail.com>
edg-l pushed a commit that referenced this pull request Apr 8, 2026
## Motivation

Continuation of #6412. Part of #6339.

## Description

Cherry-picked from #6412 onto current main. Makes the RLP crate `no_std`
unconditionally and adds a CI job to ensure it stays that way.

## Checklist

- [ ] Updated `STORE_SCHEMA_VERSION` (crates/storage/lib.rs) if the PR
includes breaking changes to the `Store` requiring a re-sync.

---------

Co-authored-by: Kevaundray Wedderburn <kevtheappdev@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants