Skip to content

ADR 003 implementation: custom EvTransaction using EIP-2718, with sponsorship and atomic batch txs.#103

Open
randygrok wants to merge 36 commits intomainfrom
randygrok/adr-phase2
Open

ADR 003 implementation: custom EvTransaction using EIP-2718, with sponsorship and atomic batch txs.#103
randygrok wants to merge 36 commits intomainfrom
randygrok/adr-phase2

Conversation

@randygrok
Copy link
Contributor

Description

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Performance improvement
  • Refactoring

Related Issues

Fixes #(issue)

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Testing

Additional Notes

@claude
Copy link

claude bot commented Jan 14, 2026

Claude finished @randygrok's task —— View job


PR Review: ADR 003 Custom EvTransaction Implementation

📋 Review Summary

This PR implements ADR 003's custom EvTransaction type with EIP-2718 compliance, sponsorship support, and atomic batch transactions. After comprehensive analysis of the 5741-line addition across 32 files, here's my detailed assessment:

✅ Strengths

1. Robust EIP-2718 Implementation (crates/ev-primitives/src/tx.rs)

  • Correct Domain Separation: Uses distinct domains (0x76 for executor, 0x78 for sponsor) preventing signature replay attacks
  • Proper RLP Encoding/Decoding: Comprehensive implementation with all required traits
  • Clean Transaction Interface: Well-structured Call type for batch operations
  • Memory Management: Efficient InMemorySize implementations for pool management

2. Secure Sponsorship Model (crates/node/src/txpool.rs:395-419)

  • Multi-Layer Validation: Pool-level rejection of invalid sponsor signatures prevents DoS
  • Proper Error Handling: InvalidSponsorSignature correctly classified as "bad transaction"
  • Balance Validation: Sponsor balance checked appropriately for gas costs
  • Recovery Security: Uses proper address recovery with error handling

3. Thoughtful Architecture (crates/ev-revm/src/tx_env.rs)

  • Design Rationale: Well-documented trade-offs for single-type approach vs enum wrapper
  • Trait Integration: Clean integration with existing Reth traits while adding EV-specific behavior
  • Backward Compatibility: Standard Ethereum transactions work unchanged

4. Comprehensive Test Coverage

  • E2E Scenarios: Sponsored transaction tests with balance verification
  • Edge Cases: Invalid signature handling, empty calls validation
  • Integration Tests: Full Engine API workflow validation

⚠️ Issues Identified

1. Critical: Balance Check Bug (crates/node/src/txpool.rs:518)

.disable_balance_check()  // ← This disables ALL balance checks globally

Problem: The global balance check disable affects ALL transaction types, not just sponsored ones.

Impact: Non-sponsored EvNode and standard Ethereum transactions may bypass balance validation.

Fix Required: Remove .disable_balance_check() and ensure validate_evnode handles all balance scenarios correctly.

2. Security: Insufficient Atomic Execution (crates/ev-revm/src/handler.rs:170-195)

The current batch execution doesn't guarantee atomicity across calls. If one call fails mid-batch, previous calls may have already modified state.

Recommendation: Consider implementing transaction-level rollback for failed batches.

3. Performance: Redundant Signature Recovery (crates/ev-revm/src/tx_env.rs:219-224)

Sponsor signatures are recovered multiple times:

  • Once in EvTxEnv::from_recovered_tx
  • Again in pool validation
  • Potentially again during execution

Recommendation: Cache recovered sponsor address to avoid repeated ECDSA operations.

4. Documentation: Missing Changelog Entry

Per reviewer request, this major feature needs changelog documentation.

🔍 Code Quality Assessment

Excellent

  • Consistent error handling patterns
  • Comprehensive trait implementations
  • Clear separation of concerns
  • Well-structured test organization

Good

  • Documentation coverage (though could be enhanced)
  • Memory efficiency considerations
  • Integration with existing Reth patterns

Needs Improvement

  • Global balance check disable (critical fix needed)
  • Some complex trait bounds need more explanation
  • Missing changelog/README updates

🛡️ Security Review

Secure Aspects

  • ✅ Proper domain separation for signature schemes
  • ✅ Multi-layer validation (pool + execution)
  • ✅ Correct sponsor balance verification
  • ✅ Protected against signature replay attacks

Security Concerns

  • ⚠️ Global balance check disable could allow insufficient balance transactions
  • ⚠️ Batch execution lacks full atomicity guarantees
  • ⚠️ No rate limiting on sponsor signature failures

📊 Test Coverage Analysis

Well Tested

  • Core transaction encoding/decoding
  • Sponsor signature validation
  • E2E sponsored transaction flows
  • Invalid signature scenarios

Could Use More Tests

  • Batch execution failure scenarios
  • Edge cases in gas limit calculations
  • Race conditions in pool validation
  • Performance benchmarks for large batches

🔧 Required Changes

Critical (Must Fix)

  1. Remove global balance check disable (crates/node/src/txpool.rs:518)
  2. Update changelog with ADR 003 implementation details
  3. Test balance validation for all transaction types after fix

Important (Should Fix)

  1. Add sponsor address caching to avoid redundant signature recovery
  2. Document atomic execution limitations for batch transactions
  3. Add README section on EvNode transaction format

Nice to Have

  1. Performance benchmarks for batch execution
  2. Enhanced error messages for batch failures
  3. Metrics for sponsor signature validation

🎯 Overall Assessment

Grade: B+ (Good with Critical Issues)

This is a solid implementation of a complex feature with good architectural decisions and comprehensive testing. The EIP-2718 compliance is excellent, and the sponsorship model is well-designed. However, the global balance check disable is a critical issue that must be addressed before merge.

Recommendation: Conditional Approval - Fix the balance check issue and update documentation, then this is ready for merge. The core implementation demonstrates strong understanding of Ethereum transaction mechanics and proper integration with Reth's architecture.


@randygrok randygrok changed the title adr 003 impl reference WIP ADR 003 implementation: custom EvTransaction using EIP-2718, with sponsorship and atomic batch txs. Jan 22, 2026
@randygrok randygrok marked this pull request as ready for review January 22, 2026 10:01
@randygrok randygrok requested a review from a team as a code owner January 22, 2026 10:01
@randygrok
Copy link
Contributor Author

@claude check crates/node/src/txpool.rs, your point

  1. Insufficient Sponsor Validation Logic (crates/ev-revm/src/tx_env.rs:238-241)

is covered on the tx pool, method validate_transaction

@claude
Copy link

claude bot commented Jan 22, 2026

Claude finished @randygrok's task —— View job


Todo List

  • Read crates/node/src/txpool.rs to examine validate_transaction method
  • Analyze sponsor validation logic
  • Verify if security concern about insufficient sponsor validation is addressed
  • Provide updated assessment

Security Assessment Update: Sponsor Validation

You're absolutely correct! After examining crates/node/src/txpool.rs, I can confirm that the sponsor validation concern I previously raised is properly addressed in the transaction pool validation layer.

Analysis of the Fix

Transaction Pool Validation (crates/node/src/txpool.rs:395-399)

if let Some(signature) = tx.fee_payer_signature.as_ref() {
    let executor = pooled.transaction().signer();
    let sponsor = tx.recover_sponsor(executor, signature).map_err(|_| {
        InvalidPoolTransactionError::other(EvTxPoolError::InvalidSponsorSignature)
    })?;
    // ... sponsor balance validation follows
}

Key Improvements:

  1. Proper Error Handling: Invalid sponsor signatures now cause InvalidPoolTransactionError::other(EvTxPoolError::InvalidSponsorSignature) which properly rejects the transaction
  2. Pool-Level Rejection: The ? operator ensures transactions with invalid sponsor signatures are rejected at the pool level, preventing them from entering the transaction pool
  3. Explicit Error Type: EvTxPoolError::InvalidSponsorSignature provides clear error reporting

Error Classification (crates/node/src/txpool.rs:287-292)

impl PoolTransactionError for EvTxPoolError {
    fn is_bad_transaction(&self) -> bool {
        matches!(
            self,
            Self::EmptyCalls | Self::InvalidCreatePosition | Self::InvalidSponsorSignature
        )
    }
}

The InvalidSponsorSignature error is correctly classified as a "bad transaction", ensuring proper rejection.

Execution Layer Behavior (crates/ev-revm/src/tx_env.rs:238-243)

let (sponsor, sponsor_signature_invalid) = 
    if let Some(signature) = ev.tx().fee_payer_signature.as_ref() {
        match ev.tx().recover_sponsor(sender, signature) {
            Ok(sponsor) => (Some(sponsor), false),
            Err(_) => (None, true),
        }
    } else {
        (None, false)
    };

This code in the execution layer is now correct by design because:

  • Invalid sponsor signatures are already filtered out by the transaction pool
  • Only valid transactions reach the execution layer
  • The sponsor_signature_invalid flag serves as a defensive check for edge cases

Conclusion

The security concern is resolved. The two-layer approach is actually well-designed:

  1. Transaction Pool: Strict validation that rejects invalid sponsor signatures
  2. Execution Layer: Defensive handling of edge cases with proper flag tracking

This prevents the DoS attack vector I mentioned while maintaining robust error handling throughout the system.

Updated Recommendation: The original concern can be removed from the critical issues list. The implementation correctly validates sponsor signatures at the appropriate layer (transaction pool) where rejection should occur.


Copy link

@chatton chatton left a comment

Choose a reason for hiding this comment

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

Slowly getting through! Reviewed the first chunk, will continue after lunch

@julienrbrt julienrbrt self-requested a review January 22, 2026 12:55
Copy link

@chatton chatton left a comment

Choose a reason for hiding this comment

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

Left a few more comments and suggestions, will try and take a final pass soon 🚀

Copy link

@chatton chatton left a comment

Choose a reason for hiding this comment

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

LGTM thanks for the work on this, happy to merge this as is.

We will probably need to make some changes due to #106 but I think we can probably merge this PR first then just handle them in the upgrade PR as there should be fewer conflicts that way.

@tac0turtle
Copy link
Contributor

still reviewing but we need a follow up to complete the js part and a demo of how to integrate it

@randygrok
Copy link
Contributor Author

Related #109

.set_tx_fee_cap(ctx.config().rpc.rpc_tx_fee_cap)
.with_max_tx_gas_limit(ctx.config().txpool.max_tx_gas_limit)
.with_minimum_priority_fee(ctx.config().txpool.minimum_priority_fee)
.disable_balance_check()
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need to disable balance check here?

@@ -0,0 +1,22 @@
[package]
Copy link
Contributor

Choose a reason for hiding this comment

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

can you update the changelog and the root readme with this feature

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.

4 participants