Skip to content

valkyoth/eth

no_std-first Ethereum protocol building blocks for Rust.
Explicit domains, bounded decode policy, constant-time primitives, and security-gated release evidence.


eth Rust crate overview

eth

eth is a no_std-first Rust workspace for Ethereum execution-layer protocol building blocks.

The project target is a production-ready Ethereum crate at 1.0.0, reached through small releases with explicit security, conformance, and dependency evidence. The first implementation work is intentionally conservative: explicit domains, bounded decode policy, stable crate boundaries, and security documentation before RPC, signer, REVM, Reth, or P2P adapters become real dependencies.

Current Status

Status: v0.5.0 release; v0.4.0 previously published.

Implemented now:

  • Rust workspace pinned to stable 1.96.0.
  • MSRV policy for Rust 1.90.0 through 1.96.0.
  • no_std facade and focused first-party crates.
  • Explicit primitive domains for chain, block, gas, nonce, timestamp, address, hash, wei, and transaction type values.
  • Constant-time equality composition for fixed-width hash and wei values.
  • Bounded decode limits plus stateful cumulative allocation, item, and proof-node accounting.
  • Stable error codes, messages, categories, and formatting for codec, protocol, fork, feature, resource, and verification failures.
  • Optional sanitization and derive support crates outside the default feature set.
  • EUPL-1.2 license.
  • Security, modularity, supply-chain, implementation, and release planning docs.
  • Local check, release-gate, dependency-policy, SBOM, and pentest evidence.
  • Independent support-crate release planning for crates.io push limits.

Not implemented yet:

  • No RPC transport.
  • No signer or local key storage.
  • No EVM execution adapter.
  • No Reth or P2P integration.
  • No transaction or block parser yet.

Trust Dashboard

Area Status
License EUPL-1.2
MSRV Rust 1.90.0
Pinned toolchain Rust 1.96.0
Default target no_std
Default runtime dependencies protocol-core support crates only
Optional hardening dependencies sanitization and proc-macro tooling behind opt-in crates/features
Unsafe policy first-party crates use #![forbid(unsafe_code)]
Default features protocol-core only
Network/signing defaults none
Release evidence local gates, cargo-deny, cargo-audit, SBOM, pentest report
Crate versions tracked in docs/CRATE_VERSION_MATRIX.md
1.0 target serious production-ready Ethereum execution-layer toolkit

Install

[dependencies]
eth = "0.5"

For optional sanitization support:

[dependencies]
eth = { version = "0.5", features = ["sanitization"] }

Features

Feature Default Purpose
std no Enables std support in admitted core crates.
evm no Future explicit EVM adapter boundary.
rpc no Future explicit RPC trust-policy boundary.
sanitization no Re-exports optional secret sanitization bridge APIs.
signer no Future signer isolation boundary.
reth no Future Reth integration boundary.
testkit no Test fixtures, conformance helpers, and adversarial inputs.

Default builds do not enable networking, signing, local key storage, Reth, P2P, or EVM execution.

Primitive Domains

Use explicit Ethereum domains instead of unqualified integers and byte arrays:

use eth::primitives::{
    Address, B256, BlockNumber, ChainId, Gas, Nonce, TransactionType, Wei,
};

let chain = ChainId::new(1);
let block = BlockNumber::new(19_000_000);
let gas = Gas::new(21_000);
let nonce = Nonce::new(7);
let address = Address::from([0x11_u8; 20]);
let hash = B256::from([0x22_u8; 32]);
let value = Wei::from_u128(1_000_000_000_000_000_000);
let tx_type = TransactionType::try_new_typed(2);

assert_eq!(u64::from(chain), 1);
assert_eq!(u64::from(block), 19_000_000);
assert_eq!(u64::from(gas), 21_000);
assert_eq!(u64::from(nonce), 7);
assert_eq!(<[u8; 20]>::from(address), [0x11_u8; 20]);
assert_eq!(<[u8; 32]>::from(hash), [0x22_u8; 32]);
assert_eq!(value.to_be_bytes()[31], 0);
assert_eq!(tx_type.map(u8::from), Ok(2));

Constant-Time Composition

B256::ct_eq and Wei::ct_eq return subtle::Choice so compound checks can use & and | without short-circuiting:

use eth::primitives::B256;

let block_hash = B256::from([1_u8; 32]);
let expected_block_hash = B256::from([1_u8; 32]);
let receipts_root = B256::from([2_u8; 32]);
let expected_receipts_root = B256::from([2_u8; 32]);

let valid = block_hash.ct_eq(&expected_block_hash)
    & receipts_root.ct_eq(&expected_receipts_root);

assert!(bool::from(valid));

Convert Choice to bool only at the final trust boundary.

Stable Errors

Error values expose stable codes, messages, and categories. They do not carry input bytes, keys, signatures, or other secret-bearing payloads:

use eth::error::{DecodeError, DecodeErrorCategory, ResourceError};

let error = DecodeError::AllocationExceeded;

assert_eq!(error.code(), "ETH_CODEC_ALLOCATION_EXCEEDED");
assert_eq!(error.category(), DecodeErrorCategory::ResourceExhaustion);
assert_eq!(error.resource(), Some(ResourceError::AllocationBytes));
assert_eq!(error.to_string(), "decoder exceeded the active allocation limit");

Decode Budgets

Every future untrusted decoder is required to use explicit limits. Use DecodeAccumulator when more than one allocation can occur:

use eth::codec::{DecodeError, DecodeLimits};

let limits = DecodeLimits {
    max_input_bytes: 1024,
    max_list_items: 16,
    max_nesting_depth: 4,
    max_total_allocation: 64,
    max_proof_nodes: 8,
    max_total_items: 32,
};

assert_eq!(limits.check_input_len(512), Ok(()));

let mut budget = limits.accumulator();
assert_eq!(budget.check_allocation(32), Ok(()));
assert_eq!(budget.check_allocation(32), Ok(()));
assert_eq!(budget.check_allocation(1), Err(DecodeError::AllocationExceeded));
assert_eq!(budget.account_items(33), Err(DecodeError::ItemCountExceeded));

Optional Sanitization

The main facade stays small by default. Applications that handle local secret material can opt into the sanitization bridge:

use eth::sanitization::{SecretBytes32, SecureSanitize};

let mut key = SecretBytes32::from_array([0x42_u8; 32]);
key.secure_sanitize();
assert!(key.constant_time_eq(&[0_u8; 32]));

For derive macros, depend on the support crate directly:

[dependencies]
eth-valkyoth-sanitization = { version = "0.5", features = ["derive"] }

Workspace Shape

Most users should depend on the facade crate, eth. The support crates are published separately so implementation boundaries stay small, no_std friendly, and independently testable.

Crate Default Purpose
eth yes Facade crate over stable protocol-core crates.
eth-valkyoth-primitives yes Chain, fork, block, gas, nonce, address, hash, wei, and bounded value types.
eth-valkyoth-codec yes Bounded exact-consumption wire decoding policy.
eth-valkyoth-protocol yes Fork-aware validation states and protocol context.
eth-valkyoth-verify yes Verification boundaries for signatures, proofs, and replay domains.
eth-valkyoth-sanitization no Optional bridge to the sanitization crate for secret-bearing Ethereum data.
eth-valkyoth-derive no Optional sanitization derive macros.
eth-valkyoth-evm no Future REVM adapter boundary.
eth-valkyoth-rpc no Future explicit RPC trust-policy boundary.
eth-valkyoth-signer no Future signer isolation boundary.
eth-valkyoth-reth no Future Reth integration boundary.
eth-valkyoth-testkit no Test fixtures, conformance helpers, and adversarial inputs.

Rust Version Support

The minimum supported Rust version is Rust 1.90.0. New deployments should use the pinned stable Rust 1.96.0 until the toolchain policy is updated.

Compatibility evidence for 0.5.0:

Rust Local Evidence
1.90.0 cargo check --workspace --all-features
1.91.0 cargo check --workspace --all-features
1.92.0 cargo check --workspace --all-features
1.93.0 cargo check --workspace --all-features
1.94.0 cargo check --workspace --all-features
1.95.0 cargo check --workspace --all-features
1.96.0 full release gate

Checks

scripts/checks.sh
scripts/release_0_5_gate.sh
scripts/validate-release-readiness.sh v0.5.0

For dependency-policy checks, install cargo-deny and cargo-audit, then run:

cargo deny check
cargo audit

Documentation

License

Licensed under the European Union Public Licence 1.2.

About

no_std-first Ethereum execution-layer protocol toolkit for Rust, with security-focused primitives, bounded decoding, verification boundaries, and modular optional integrations.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

  •  

Packages

 
 
 

Contributors