Skip to content

Conversation

@randygrok
Copy link
Contributor

@randygrok randygrok commented Feb 10, 2026

Problem

The viem client (clients/) only had unit tests and manual scripts (basic.test.ts, flows.test.ts, sponsored.test.ts) that required a running ev-reth node externally. These scripts used console.log for verification instead of proper assertions and were not part of CI.

Solution

Add an automated e2e test infrastructure that:

Launches ev-reth as a subprocess with an in-memory datadir and the test genesis
Runs a mini-coordinator (TypeScript) that replicates ev-node’s happy path: polls txpoolExt_getTxs and drives the Engine API 4-step block production cycle (forkchoiceUpdated → getPayload → newPayload → forkchoiceUpdated)
Executes proper node:test tests with assertions against the live node
Cleans up automatically (stops coordinator, kills ev-reth, removes temp files)

@randygrok randygrok changed the base branch from main to randygrok/adr-phase2 February 10, 2026 12:54
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @randygrok, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new custom transaction type, EvNode (0x76), designed to support batch calls and transaction sponsorship within the EV-reth client. To ensure the correct functioning and integration of this new transaction type, a dedicated ev-primitives crate was created, and the EVM execution logic, node components (payload builder, RPC, transaction pool), and client-side testing infrastructure were significantly updated. The changes include a comprehensive refactor of the client's test suite to provide robust end-to-end validation for these new transaction flows.

Highlights

  • New ev-primitives Crate: Introduced a new Rust crate, ev-primitives, to define core EV-specific types, including a custom EvNode transaction (type 0x76) that supports batch calls and transaction sponsorship. This crate also defines EvPrimitives as the NodePrimitives implementation for the EV-reth node.
  • EVM and Node Integration for EvNode Transactions: Integrated the new EvNode transaction type across the EVM execution layer (ev-revm) and the Reth node components (crates/node). This includes custom EVM handlers for batch execution and sponsor reimbursement, as well as modifications to the payload builder, RPC, and transaction pool to correctly process and validate these new transaction types.
  • Comprehensive E2E Test Suite: Replaced existing client tests with a new, robust end-to-end (e2e) test suite written in TypeScript. These tests validate the full lifecycle of both unsponsored and sponsored EvNode transactions, including scenarios for successful execution, state reversion on failure, and proper gas accounting for sponsors.
  • Updated Dependencies and Configuration: Numerous dependencies were added or updated across Cargo.toml and Cargo.lock files to support the new ev-primitives crate and its integration, including various alloy and reth components for consensus, RPC types, and codecs. The test genesis.json was also updated with a new chain ID.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • Cargo.lock
    • Added new dependencies for alloy-consensus-any, alloy-network, alloy-rlp, alloy-rpc-types-eth, c-kzg, ev-primitives, reth-codecs, reth-rpc, reth-rpc-convert, reth-rpc-eth-api, reth-rpc-eth-types, and reth-storage-api.
  • Cargo.toml
    • Added crates/ev-primitives to the workspace members.
    • Updated reth-ethereum-primitives dependency to include serde, serde-bincode-compat, and reth-codec features.
    • Added reth-db-api, reth-rpc, reth-rpc-convert, reth-codecs, alloy-serde, alloy-consensus-any, alloy-rlp, and bytes as dependencies.
    • Added ev-primitives as a path dependency to ev-revm, evolve, ev-node, and crates/tests.
    • Added reth-storage-api, reth-transaction-pool, alloy-rpc-types-eth, alloy-network, and c-kzg to crates/node dependencies.
  • clients/package.json
    • Updated test scripts to replace test:basic, test:flows, and test:sponsored with a single test:e2e command pointing to the new e2e test suite.
  • clients/tests/basic.test.ts
    • Removed the basic client test file.
  • clients/tests/e2e/coordinator.ts
    • Added a new TypeScript file to coordinate test node operations, including block mining and JWT authentication for engine API calls.
  • clients/tests/e2e/flows.e2e.test.ts
    • Added new TypeScript e2e tests for unsponsored and sponsored batch calls, verifying balance changes and transaction outcomes.
  • clients/tests/e2e/setup.ts
    • Added a new TypeScript file for setting up and tearing down a test ev-reth node for e2e testing.
  • clients/tests/flows.test.ts
    • Removed the flows client test file.
  • clients/tests/sponsored.test.ts
    • Removed the sponsored client test file.
  • crates/ev-primitives/Cargo.toml
    • Added a new crate manifest for ev-primitives, defining its dependencies.
  • crates/ev-primitives/src/lib.rs
    • Added the core ev-primitives library, defining EvPooledTxEnvelope, EvPooledTxType, EvNodeSignedTx, EvNodeTransaction, EvTxEnvelope, EvTxType, TransactionSigned, EVNODE_SPONSOR_DOMAIN, EVNODE_TX_TYPE_ID, and EvPrimitives for Reth's NodePrimitives.
  • crates/ev-primitives/src/pool.rs
    • Added EvPooledTxEnvelope and EvPooledTxType for transaction pool integration, wrapping standard Ethereum and EvNode transactions.
  • crates/ev-primitives/src/tx.rs
    • Added the EvNodeTransaction structure, Call structure, and related RLP encoding/decoding, signing, and hashing logic for the new 0x76 transaction type.
  • crates/ev-revm/Cargo.toml
    • Added ev-primitives as a dependency.
  • crates/ev-revm/src/api/exec.rs
    • Updated ExecuteEvm, ExecuteCommitEvm, InspectEvm, InspectCommitEvm, SystemCallEvm, and InspectSystemCallEvm traits to include SponsorPayerTx and BatchCallsTx bounds on the Tx generic parameter.
  • crates/ev-revm/src/evm.rs
    • Imported EvTxEnv and added AlloyEvm implementation for EvEvm to handle EvTxEnv transactions.
  • crates/ev-revm/src/factory.rs
    • Imported EvTxEnv and added EvTxEvmFactory to create EVM instances with EvTxEnv and EV-specific hooks.
  • crates/ev-revm/src/handler.rs
    • Modified EvHandler to implement custom validation for EvNode transactions (empty calls, CREATE position), batch execution logic, and sponsor reimbursement.
    • Added helper functions validate_account_nonce_and_code, calculate_caller_fee, validate_batch_initial_tx_gas, finalize_batch_gas, validate_and_deduct_sponsored_tx, and validate_and_deduct_normal_tx.
  • crates/ev-revm/src/lib.rs
    • Exported the tx_env module and EvTxEvmFactory, EvTxEnv.
  • crates/ev-revm/src/tx_env.rs
    • Added the EvTxEnv struct to wrap TxEnv and handle EV-specific transaction metadata (sponsor, batch calls).
    • Defined SponsorPayerTx and BatchCallsTx traits.
  • crates/evolve/Cargo.toml
    • Added ev-primitives as a dependency.
  • crates/evolve/src/consensus.rs
    • Updated imports to use ev_primitives types (Block, BlockBody, EvPrimitives, Receipt, SealedBlock) instead of reth_ethereum_primitives and reth_primitives.
    • Changed FullConsensus implementation to use EvPrimitives.
  • crates/evolve/src/types.rs
    • Updated TransactionSigned import to ev_primitives::TransactionSigned.
  • crates/node/Cargo.toml
    • Added ev-primitives as a dependency.
    • Added reth-storage-api, reth-transaction-pool, reth-codecs, alloy-rpc-types-eth, alloy-consensus-any, alloy-network, c-kzg, and alloy-rlp dependencies.
  • crates/node/src/attributes.rs
    • Updated TransactionSigned import to ev_primitives::TransactionSigned.
  • crates/node/src/builder.rs
    • Updated imports for EvTxEvmFactory, SealedBlock, and TxHashRef.
    • Changed EvolveEthEvmConfig to use EvTxEvmFactory.
    • Modified build_payload to return SealedBlock<ev_primitives::Block>.
    • Updated transaction hashing to use tx_hash().
  • crates/node/src/evm_executor.rs
    • Added a new module defining EvReceiptBuilder, EvBlockExecutor, and EvBlockExecutorFactory to handle EV-specific receipts and block execution.
  • crates/node/src/executor.rs
    • Refactored EvolveEvmConfig to use EvTxEvmFactory and EvBlockExecutorFactory.
    • Implemented ConfigureEvm and ConfigureEngineEvm for EvEvmConfig to integrate EV-specific primitives and transaction handling into the Reth EVM.
  • crates/node/src/lib.rs
    • Added new modules evm_executor, payload_types, rpc, and txpool.
    • Exported EvBuiltPayload.
  • crates/node/src/node.rs
    • Updated NodeTypes to use EvPrimitives and reth_ethereum::provider::EthStorage<ev_primitives::TransactionSigned>.
    • Changed EvolveNodeAddOns to use EvEthApiBuilder.
    • Changed ComponentsBuilder to use EvolvePoolBuilder.
    • Updated BuiltPayload type to EvBuiltPayload.
  • crates/node/src/payload_service.rs
    • Updated imports for EvPrimitives, TransactionSigned, and EvBuiltPayload.
    • Changed BuiltPayload type to EvBuiltPayload.
  • crates/node/src/payload_types.rs
    • Added a new module defining EvBuiltPayload and its conversion to various ExecutionPayloadEnvelope versions.
  • crates/node/src/rpc.rs
    • Added a new module defining EvRpcTypes, EvRpcTransaction, EvRpcReceipt, EvTransactionRequest, EvReceiptConverter, EvRpcConvert, EvEthApiBuilder, EvRpcTxConverter, EvSimTxConverter, and EvTxEnvConverter to support EvNode transactions in RPC.
  • crates/node/src/txpool.rs
    • Added a new module defining EvPooledTransaction, EvTxPoolError, EvTransactionValidator, and EvolvePoolBuilder to integrate EvNode transactions into the transaction pool.
  • crates/node/src/validator.rs
    • Updated imports for Header, Decodable2718, EvBlock, EvBlockBody, and EvTxEnvelope.
    • Changed PayloadValidator to use ev_primitives::Block.
    • Added convert_sealed_block and parse_evolve_payload functions to handle EvNode transactions during payload validation.
    • Added is_unknown_tx_type_error helper function.
  • crates/tests/Cargo.toml
    • Added ev-primitives as a dependency.
  • crates/tests/assets/genesis.json
    • Changed chainId from 1 to 1234.
  • crates/tests/src/common.rs
    • Updated imports for EvTxEnvelope, TransactionSigned, EvTxEvmFactory, and EvolveEvmConfig.
    • Added to_ev_envelope helper function.
    • Modified EvolveTestFixture to use EvTxEvmFactory and EvolveEvmConfig.
    • Updated create_test_transactions to use to_ev_envelope.
  • crates/tests/src/e2e_tests.rs
    • Updated imports for TxHashRef, SignableTransaction, AccessList, ReceiptResponse, and Signature.
    • Added EvRpcReceipt, EvRpcTransaction, EvTransactionRequest, Call, EvNodeTransaction, and EvTxEnvelope imports.
    • Added REVERT_INITCODE constant.
    • Added new e2e tests: test_e2e_sponsored_evnode_transaction, test_e2e_invalid_sponsor_signature_skipped, test_e2e_empty_calls_skipped, test_e2e_sponsor_insufficient_max_fee_skipped, and test_e2e_nonce_bumped_on_create_batch_failure.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/e2e.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@claude
Copy link

claude bot commented Feb 10, 2026

Claude finished @randygrok's task —— View job


Code Review: E2E Tests for EvNode Transaction Type

Review Checklist:

  • Read and understand the PR changes
  • Review new e2e test infrastructure
  • Analyze test coverage and completeness
  • Check for potential bugs and issues
  • Evaluate security considerations
  • Assess performance implications
  • Provide comprehensive feedback

Overall Assessment

This PR successfully introduces a robust end-to-end testing infrastructure for the new EvNode transaction type (0x76). The implementation replaces previous test files with a well-structured, comprehensive test suite that validates both sponsored and unsponsored transaction flows.

Strengths

1. Excellent Test Infrastructure Design

  • Modular Architecture: Clean separation between setup (setup.ts), coordination (coordinator.ts), and test execution (flows.e2e.test.ts)
  • Realistic Environment: Uses actual ev-reth binary with proper genesis configuration
  • Proper Cleanup: Robust resource management with process cleanup and temporary directory handling

2. Comprehensive Test Coverage

  • Transaction Types: Both sponsored and unsponsored EvNode transactions
  • Batch Operations: Single calls and multi-call batches
  • Balance Verification: Proper assertions for gas payment and balance changes
  • Error Scenarios: Implicitly tested through proper setup and execution

3. Professional Code Quality

  • TypeScript Best Practices: Proper typing, async/await usage, and error handling
  • Clear Test Structure: Well-organized test cases with descriptive names
  • Good Documentation: Clear comments and variable naming

Issues and Recommendations

1. Security Concerns

🚨 Critical: The test setup uses hardcoded private keys:

const EXECUTOR_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'

While this is a well-known Hardhat test key, it should be explicitly documented as such for clarity.

Recommendation: Add a comment clarifying this is a standard test key:

// Hardhat account #0 - standard test key, safe for testing
const EXECUTOR_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' as const;

2. Performance Considerations

Node Startup Time: The test setup spawns a full ev-reth node, which may be slow in CI/CD environments.

Recommendations:

  • Consider adding timeout configuration based on environment
  • Implement parallel test execution safeguards if multiple test suites run simultaneously
  • Add logging for debugging slow startup times

3. Test Coverage Gaps

Missing Error Cases: The current tests focus on success paths but lack explicit failure scenarios:

// Missing test cases:
it('should handle insufficient gas limit', async () => { /* ... */ });
it('should reject invalid sponsor signature', async () => { /* ... */ });
it('should handle CREATE call validation errors', async () => { /* ... */ });
it('should handle sponsor with insufficient balance', async () => { /* ... */ });

4. Code Quality Improvements

Magic Numbers: Several hardcoded values could be better documented:

  • pollIntervalMs: 200 - why 200ms?
  • timeoutMs: 30_000 - receipt timeout reasoning
  • Block time of 12 seconds in coordinator

Type Safety: The waitForReceipt function uses any type:

// Current
async function waitForReceipt(client: any, hash: Hex, timeoutMs: number)

// Better
interface MinimalClient {
  request(args: { method: string; params: unknown[] }): Promise<unknown>;
}
async function waitForReceipt(client: MinimalClient, hash: Hex, timeoutMs: number)

5. Process Management

Potential Race Condition: In killProcess, there's a small window where the process might exit between the check and SIGKILL:

if (!exited && child.exitCode === null) {
  child.kill('SIGKILL'); // Process might have exited here

Recommendation: Add additional null check or use a more robust process management library.

6. CI/CD Integration

GitHub Workflow: The workflow looks well-structured, but consider:

  • Adding test result artifacts for failed runs
  • Implementing test parallelization for faster execution
  • Adding environment variable validation

Minor Issues

1. Error Messages

Some error messages could be more descriptive:

// Current
throw new Error(`ev-reth binary not found. Run 'make build' or 'make build-dev' first.\n` +
  `Checked: ${releaseBin}\n         ${debugBin}`,
);

// Better - include current working directory context

2. Resource Cleanup

The cleanup function should handle partial failures:

const cleanup = async () => {
  try {
    coordinator.stop();
  } catch (error) {
    console.warn('Failed to stop coordinator:', error);
  }
  try {
    await killProcess(child);
  } catch (error) {
    console.warn('Failed to kill process:', error);
  }
  // ... etc
};

Recommendations Summary

High Priority

  1. Add explicit error case testing for robustness
  2. Improve type safety by removing any types
  3. Add timeout configuration for CI environments

Medium Priority

  1. Extract magic numbers to named constants with documentation
  2. Enhance error messages with more context
  3. Improve resource cleanup with partial failure handling

Low Priority

  1. Add performance monitoring for test execution times
  2. Consider test parallelization strategies
  3. Add more detailed logging for debugging

Conclusion

This is a high-quality PR that significantly improves the testing infrastructure for the EvNode transaction type. The code is well-structured, comprehensive, and follows TypeScript best practices. The identified issues are mostly minor improvements that would enhance robustness and maintainability. The PR demonstrates a solid understanding of both the EV-reth system and testing best practices.

Overall Rating: ✅ Approved with minor recommendations


| feat/client-e2e-tests branch

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a comprehensive end-to-end testing suite for the client, which is a significant improvement over the previous test scripts. The new tests use a dedicated test runner (node:test), programmatically set up and tear down an ev-reth node, and include a coordinator to simulate a consensus client for block production. The test cases cover various scenarios including unsponsored and sponsored transactions, both single and batch calls, with clear assertions to validate the behavior. The code is well-structured and robust. I have one minor suggestion to improve error handling in the test setup code for better debuggability.

Comment on lines +111 to +113
} catch {
// not ready yet
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Swallowing errors with an empty catch block can hide underlying issues and make debugging harder. While the intention is to ignore connection errors during polling, it would be more robust to log the error if a debug flag is enabled. This can help diagnose problems if the RPC server fails to start for reasons other than just taking a while to be ready.

    } catch (e) {
      if (process.env.DEBUG) {
        console.log(`[waitForRpc] retrying after error: ${e.message}`);
      }
      // not ready yet
    }

@randygrok randygrok marked this pull request as ready for review February 10, 2026 13:55
@randygrok randygrok requested a review from a team as a code owner February 10, 2026 13: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.

LGTM thank you 🚀

Base automatically changed from randygrok/adr-phase2 to main February 10, 2026 17:44
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