feat: support no_std in stateless-core#126
Conversation
Tests hit three no_std gaps that only surfaced once the coverage script (`scripts/coverage_stateless_core.sh`) started building them with the `std` feature off: - `vec!` macro isn't in scope under no_std — add `use std::vec;` to the `withdrawals` and `data_types` test modules. - `ToString::to_string` needs the trait in scope — add `use std::string::ToString;` to the `chain_spec` and `db` test modules. - `validate_block`'s `trace_writer` param is `#[cfg(feature = "std")]`; cfg-gate the matching `None` argument in the executor mainnet-fixture test so the call compiles in both modes. No production code changed. Fixes the Coverage CI job. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The This PR adds |
Codecov Report❌ Patch coverage is
☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Clean no_std port. The Two things worth noting:
Both are nits — the PR improves the codebase and the no_std support is correct. |
|
Clean no_std port. The A few observations: Timing fields in
Everything else is mechanical and correct. LGTM pending the timing-fields nit. |
|
Overall this is a clean, well-prepared PR. The approach mirrors the One nit inline on |
|
Overall this is clean and well-structured. The approach (aliasing A few observations:
Nothing blocks merge. |
|
LGTM. The no_std implementation is clean and follows established patterns from the upstream A few notes:
The CI |
|
The approach is solid — the salt-style One nit in the CI job (inline). Otherwise LGTM. |
|
Overall this is clean and well-structured. The One design concern worth discussing before merge:
The idiomatic alternative is explicit Everything else looks correct — the |
Summary
Make
stateless-corea trueno_stdcrate so it can be consumed in constrained environments (zkVMs, bare-metal).saltandmega-evmalready supportno_std; this mirrors their pattern. Every public module exceptpipelinecompiles under--no-default-featureson bare-metal targets.Changes
stateless-corebecomesno_std#![cfg_attr(not(feature = "std"), no_std)]and the salt-style#[cfg(not(feature = "std"))] extern crate alloc as std;alias so existingstd::vec::Vec/std::sync::Arc/std::collections::BTreeMappaths keep resolving viaalloc.stdfeature (default-on) gates the std-only bits:pipelinemodule (tokio / kanal /num_cpus/CancellationToken)executor'strace_writer: Option<Box<dyn io::Write>>parameter,Instant/SystemTimetiming, andValidationResult.completed_atfieldstdfeature forwards to upstream{dep}/stdwhere applicable (mega-evm/default,revm/default,salt/default, alloy/reth*/std…), so perf-critical features (saltparallel/rayon, revmsecp256k1/blst/c-kzg/portable/tracer) stay enabled on the std side.no_std-compatible public surface
All modules except
pipelinecompile in no_std mode:chain_spec,data_types,db,evm_database,executor,light_witness,withdrawals.Supporting swaps:
std::collections::HashMap<B256, Arc<Bytecode>>→alloy_primitives::map::HashMap<…>inContractLookup,WitnessDatabase, andvalidate_block's signature. Cascaded throughstateless-db,binaries, and test fixtures (
HashMap::new()→HashMap::default()where hasher inference would otherwise pickRandomState).std::error::Error→core::error::Error(StoreError::Backend,StoreResultExtbound).rustc_hash::FxHashMap→ localtype FxHashMap<K, V> = hashbrown::HashMap<K, V, FxBuildHasher>;soLightWitness.levelsmatchessalt::SaltWitness.proof.levels(which is also hashbrown-based).reth_trie::Nibbles→reth_trie_common::Nibblesinwithdrawals.rs; drops the heavyreth-triedep.op_alloy_network::{TransactionResponse, eip2718::Encodable2718}→alloy_network_primitives::TransactionResponse+alloy_eips::eip2718::Encodable2718.op-alloy-networkremoved (it transitively pulledalloy-provider→getrandom, which breaks bare-metal).eyremadeoptional = true, gated behindstd. (eyrewas the last dep silently enablingonce_cell/default→once_cell/std, which fails on bare-metal.)chain_specunified onmega_mainnet_hardforks()Dropped the
pub static MEGA_MAINNET_HARDFORKS: LazyLock<ChainHardforks>(std-only). Replaced withpub fn mega_mainnet_hardforks() -> ChainHardforkswhich works in both modes.ChainSpec::from_genesisalready consumed the function; no other callers.Workspace
Cargo.tomldefault-features = falseadded toalloy-hardforks,alloy-op-hardforks,mega-evm,salt,op-alloy-network,rustc-hash,thiserror.serde/serde_jsongainfeatures = ["alloc", "derive"/"alloc"]so they compile in no_std.alloy-network-primitives,hashbrownworkspace deps.Test plan
cargo check -p stateless-core(std default)cargo check -p stateless-core --no-default-features(host no_std)cargo check -p stateless-core --no-default-features --target riscv64imac-unknown-none-elfcargo build -p stateless-core --no-default-features --target riscv64imac-unknown-none-elf(real codegen)cargo build -p stateless-core --no-default-features --target wasm32-unknown-unknown(second bare-metal target)cargo build --workspacecargo test --workspace— all suites passcargo test -p stateless-validator --test integration— 0.70s (baseline ~0.65s, no regression)cargo clippy --workspace --all-targets --all-featurescargo fmt --all --checkcargo sort --check --workspace --groupedpipelineremains#[cfg(feature = "std")]-gated inlib.rs