Skip to content

refactor(handler): polish TxValidator API and add preset constructors#3400

Draft
rakita wants to merge 8 commits intomainfrom
rakita/txvalidator
Draft

refactor(handler): polish TxValidator API and add preset constructors#3400
rakita wants to merge 8 commits intomainfrom
rakita/txvalidator

Conversation

@rakita
Copy link
Member

@rakita rakita commented Feb 5, 2026

Summary

This PR polishes the TxValidator module for better usability, performance, and L2 integration support. The improvements were identified through multiple iterations of analysis focusing on:

  1. API usability - Easy to use with minimal boilerplate
  2. Performance - Low initialization overhead with Copy semantics
  3. Configurability - Projects like op-revm and Tempo can reuse validation logic with configurable flows

Changes

API Improvements

  • Add Copy derive to TxValidator and CallerFee for efficient passing
  • Add preset constructors for common use cases:
    • for_deposit() - L2 deposit transactions (skips fees, balance, nonce)
    • for_tx_pool() - Transaction pool validation (stateless checks only)
    • for_block_builder() - Block builder with lenient checks
  • Add composite GAS_FEES flag for all gas/fee related checks
  • Add missing skip methods:
    • skip_tx_gas_limit_check()
    • skip_blob_fee_check()
    • skip_auth_list_check()
    • skip_max_initcode_size_check()
    • skip_caller_checks() (composite)
    • skip_gas_fee_checks() (composite)
  • Add missing enable methods for ALL checks (symmetric with skip methods)
  • Add query methods: has_any_checks(), has_all_checks(), enabled_checks()

Performance Improvements

  • Add #[inline] annotations to all builder methods and validation hot paths
  • Derive Copy to avoid unnecessary cloning

Tests

  • Add tests for preset constructors
  • Add tests for composite skip/enable methods
  • Add tests for query methods
  • Add test verifying TxValidator is Copy

Usage Examples

// L2 deposit transaction
let validator = TxValidator::for_deposit(SpecId::CANCUN)
    .with_chain_id(10);

// Transaction pool validation
let validator = TxValidator::for_tx_pool(SpecId::CANCUN)
    .with_chain_id(1)
    .with_base_fee(30_000_000_000);

// Custom configuration
let validator = TxValidator::new(SpecId::CANCUN)
    .skip_gas_fee_checks()
    .skip_caller_checks()
    .enable_chain_id_check();

Test plan

  • cargo check -p revm-handler passes
  • cargo test -p revm-handler -- tx_validation passes (12 tests)

Add a new TxValidator struct that uses bitflags for fine-grained control
over which validation checks to perform. This allows L2s and custom EVM
implementations to easily skip specific validations (e.g., for deposit
transactions) without duplicating validation logic.

The existing validation functions in validation.rs and pre_execution.rs
now delegate to the new module internally, maintaining backward compatibility.
Improvements to the TxValidator module for better usability and performance:

## API Improvements
- Add `Copy` derive to TxValidator and CallerFee for efficient passing
- Add preset constructors: `for_deposit()`, `for_tx_pool()`, `for_block_builder()`
- Add composite `GAS_FEES` flag for all gas/fee related checks
- Add missing skip methods: `skip_tx_gas_limit_check()`, `skip_blob_fee_check()`,
  `skip_auth_list_check()`, `skip_max_initcode_size_check()`, `skip_caller_checks()`,
  `skip_gas_fee_checks()`
- Add missing enable methods for all checks: `enable_tx_gas_limit_check()`,
  `enable_base_fee_check()`, `enable_priority_fee_check()`, `enable_blob_fee_check()`,
  `enable_auth_list_check()`, `enable_block_gas_limit_check()`,
  `enable_max_initcode_size_check()`, `enable_eip3607_check()`, `enable_eip7623_check()`,
  `enable_header_check()`, `enable_all()`, `enable_caller_checks()`
- Add query methods: `has_any_checks()`, `has_all_checks()`, `enabled_checks()`

## Performance Improvements
- Add `#[inline]` annotations to all builder methods and validation hot paths
- Derive `Copy` to avoid unnecessary cloning

## Tests
- Add tests for preset constructors
- Add tests for composite skip/enable methods
- Add tests for query methods
- Add test verifying TxValidator is Copy
@codspeed-hq
Copy link

codspeed-hq bot commented Feb 5, 2026

CodSpeed Performance Report

Merging this PR will degrade performance by 3.59%

Comparing rakita/txvalidator (88cf36a) with main (8bf5191)

Summary

❌ 1 regressed benchmark
✅ 172 untouched benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
ecrecover precompile 197.7 µs 205.1 µs -3.59%

@rakita rakita marked this pull request as draft February 5, 2026 05:15
… method

Move ValidationChecks bitflags from handler to primitives crate to avoid
circular dependencies and enable broader usage.

Add `disabled_validation_checks()` method to Cfg trait that aggregates
all 8 individual `is_*_disabled()` calls into a single method returning
a ValidationChecks bitflags. This reduces TxValidator initialization
overhead by computing disabled checks once.

Key changes:
- Move ValidationChecks to primitives/src/validation.rs
- Add bitflags dependency to primitives
- Add disabled_validation_checks() to Cfg trait with default impl
- Simplify TxValidator::from_cfg_and_block to use single method call
- Remove bitflags dependency from handler (now imports from primitives)
Polish the transaction validation API based on review feedback:

ValidationChecks (primitives):
- Change Default to return ALL instead of empty for safety
- Add comprehensive documentation with examples
- Add tests for composite flags (TX_STATELESS, CALLER, GAS_FEES)

Cfg trait (context-interface):
- Add #[inline] to disabled_validation_checks
- Add enabled_validation_checks() convenience method
- Improve documentation listing covered/uncovered checks

TxValidator (handler):
- Add with_spec(), with_disabled_checks(), with_enabled_checks() builders
- Fix validate_caller to avoid Bytecode::default() allocation
- Fix pre_execution.rs to use CALLER instead of ALL for caller validation
- Add comprehensive tests for new builder methods
- Rename enable_gas_checks to enable_gas_fee_checks for consistency
  with skip_gas_fee_checks
- Add #[must_use] to TxValidator struct for builder safety
- Improve CallerFee documentation with usage examples
- TxValidator is now `TxValidator<C: Cfg, B: Block>` to work with references
- Added `disabled_checks: ValidationChecks` field to CfgEnv for pre-computed checks
- Added builder methods for fluent ValidationChecks configuration
- Cfg trait now provides `disabled_validation_checks()` method
- Simplified validation.rs to use new TxValidator API directly
- Maintains backwards compatibility with legacy feature-gated boolean fields
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.

1 participant