Skip to content

Conversation

@0xMuang
Copy link
Collaborator

@0xMuang 0xMuang commented Jan 24, 2026

Summary

  • Add debug namespace with tracing support (RPC-4)
  • Add eth_getProof for EIP-1186 Merkle proofs (RPC-5)
  • Implement real EVM tracing with CallTracer and OpcodeTracer
  • Integrate BlockStore and ReceiptStore for full trace support

New RPC Methods

Method Status Notes
debug_traceCall ✅ Full support Works without storage
debug_traceTransaction ✅ Full support Requires storage integration
debug_traceBlockByNumber ✅ Full support Requires storage integration
debug_traceBlockByHash ✅ Full support Requires storage integration
eth_getProof ✅ Full support EIP-1186 Merkle proofs

Architecture

EvmDebugExecutionApi

// Basic usage (trace_call only)
let debug_api = EvmDebugExecutionApi::new(provider, chain_id);

// Full functionality with storage
let debug_api = EvmDebugExecutionApi::with_storage(
    provider,
    block_store,    // Arc<BlockStore>
    receipt_store,  // Arc<ReceiptStore>
    chain_id,
);

Storage Integration

  • Uses cipherbft_storage::BlockStore for block data
  • Uses cipherbft_storage::ReceiptStore for transaction/receipt data
  • Graceful fallback: methods return MethodNotSupported if storage not configured

Test plan

  • All existing tests pass
  • Build succeeds with no errors
  • cargo fmt check passes
  • cargo clippy passes

🤖 Generated with Claude Code

@0xMuang 0xMuang requested a review from dokpark21 January 24, 2026 11:19
@qj0r9j0vc2 qj0r9j0vc2 self-requested a review January 24, 2026 14:57
@qj0r9j0vc2
Copy link
Member

qj0r9j0vc2 commented Jan 24, 2026

debug_executor.latest_block is never updated by consensus event loop

When consensus decides on a new height, rpc_storage.set_latest_block(height.0) is called at line 865, but there is no corresponding call to update debug_executor.set_latest_block().

The EvmDebugExecutionApi uses latest_block for EVM execution context in trace_call, trace_transaction, and trace_block methods.

Since latest_block is initialized to 0 and never updated, all debug traces will execute against block 0 context instead of the actual consensus height.

This was established as a pattern in commit 5e68970 which added the rpc_storage.set_latest_block() call.

// Update RPC layer with the new block height
// This enables eth_blockNumber to return the actual consensus height
if let Some(ref storage) = rpc_storage {
storage.set_latest_block(height.0);
debug!("Updated RPC block number to {}", height.0);
}

@0xMuang
Copy link
Collaborator Author

0xMuang commented Jan 24, 2026

Fixed in c6ac6b8:

  • Added set_latest_block() to StubDebugExecutionApi
  • Stored rpc_debug_executor reference for later updates
  • Added debug_executor.set_latest_block(height) call when consensus decides

Thanks for catching this! 👍

@0xMuang 0xMuang force-pushed the feat/rpc-debug-trace-proof branch 2 times, most recently from 8ee42e3 to 9aac2b9 Compare January 24, 2026 16:34
@0xMuang 0xMuang requested a review from Copilot January 24, 2026 17:20
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to add debug namespace RPC methods for transaction tracing and the eth_getProof method for EIP-1186 Merkle proof generation to CipherBFT. The changes include new trait definitions (DebugExecutionApi, RpcProofStorage), real EVM inspector implementations (CallTracer, OpcodeTracer), and Merkle proof generation infrastructure.

Changes:

  • Added debug_* RPC namespace with four methods (traceTransaction, traceCall, traceBlockByNumber, traceBlockByHash)
  • Added EIP-1186 proof generation infrastructure in execution crate
  • Integrated BlockStore and ReceiptStore for historical transaction replay

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
crates/rpc/src/traits.rs Added DebugExecutionApi and RpcProofStorage trait definitions
crates/rpc/src/server.rs Updated RpcServer to require RpcProofStorage and accept DebugExecutionApi
crates/rpc/src/lib.rs Exported new debug API types and implementations
crates/rpc/src/debug/mod.rs New debug namespace implementation with trace methods
crates/rpc/src/eth/api.rs Removed comments indicating eth_getProof is unsupported
crates/rpc/src/adapters.rs Added StubDebugExecutionApi, EvmDebugExecutionApi, and RpcProofStorage implementations
crates/execution/src/lib.rs Re-exported inspector and proof types
crates/execution/src/proof.rs New EIP-1186 Merkle proof generation implementation
crates/execution/src/inspector/mod.rs New inspector module with CallTracer and OpcodeTracer
crates/execution/src/inspector/types.rs Trace result types compatible with Geth debug API
crates/execution/src/inspector/call_tracer.rs CallTracer inspector implementation
crates/execution/src/inspector/opcode_tracer.rs OpcodeTracer inspector implementation
crates/execution/Cargo.toml Added serde_json dependency
crates/node/src/node.rs Updated node to create and pass StubDebugExecutionApi to RpcServer
crates/rpc/tests/e2e_transaction_test.rs Updated test to include StubDebugExecutionApi parameter
.gitignore Changed debug/ and release/ to /debug/ and /release/

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Add revm Inspector implementations for debug/trace RPC methods:
- CallTracer: tracks call stack during execution (call/create ops)
- OpcodeTracer: step-by-step opcode execution tracing
- Trace types: CallFrame, OpcodeStep, TraceResult, TraceOptions

These tracers enable debug_traceTransaction, debug_traceCall, and
similar RPC endpoints for Ethereum-compatible debugging.
Add Merkle proof generation for EIP-1186 eth_getProof:
- AccountProof struct with account state and proofs
- StorageProof struct for storage slot proofs
- generate_account_proof function using alloy-trie ProofRetainer

Enables verification of account state and storage against state root.
- Add DebugApi with debug_traceTransaction, debug_traceCall,
  debug_traceBlockByNumber, debug_traceBlockByHash methods
- Add eth_getProof method to EthApi for EIP-1186 account proofs
- Add DebugExecutionApi and RpcProofStorage traits
- Add StubDebugExecutionApi for testing
- Implement RpcProofStorage for StubRpcStorage and ProviderBasedRpcStorage
- Register debug namespace in RPC server
- Update e2e tests for new server signature
- Implement EvmDebugExecutionApi using actual revm Inspector integration
- trace_call supports both callTracer and opcode tracer (structLogs)
- CallTracer builds nested call frame trees
- OpcodeTracer records step-by-step opcode execution
- trace_transaction and trace_block return not-implemented until
  block indexing is available
- Export EvmDebugExecutionApi for production use
- Apply cargo fmt to all modified files
- Auto-fix clippy lints where possible
- Add missing crates/rpc/src/debug/mod.rs (was previously ignored by .gitignore)
- Fix .gitignore to only ignore root /debug/ directory
- Add StubDebugExecutionApi to node RpcServer initialization
- Add #[allow(dead_code)] for unused but reserved code
- Fix unused import in opcode_tracer
Fix clippy::iter_cloned_collect warning in opcode_tracer.
These trace functions need multiple parameters for the EVM call context.
… storage

- Add cipherbft-storage dependency to rpc crate
- Update EvmDebugExecutionApi to optionally use BlockStore and ReceiptStore
- Implement trace_transaction: fetches tx from receipt store, traces it
- Implement trace_block: fetches all txs in block, traces each one
- Add EvmDebugExecutionApi::with_storage() constructor for full functionality
- Methods still work without storage (return MethodNotSupported)

The implementation uses the actual cipherbft_storage::BlockStore and
ReceiptStore traits to fetch transaction and block data for tracing.
Address code review feedback:
- Add set_latest_block() to StubDebugExecutionApi for consistency
- Store rpc_debug_executor reference outside RPC block
- Pass debug_executor to run_event_loop
- Update debug_executor.set_latest_block() when consensus decides

This ensures debug trace methods use the correct block context
instead of always using block 0.
@0xMuang 0xMuang force-pushed the feat/rpc-debug-trace-proof branch from 9aac2b9 to 5d0fbf4 Compare January 25, 2026 16:17
}

/// Push a new call frame onto the stack.
fn push_frame(&mut self, frame: CallFrame) {
Copy link
Member

Choose a reason for hiding this comment

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

When only_top_call is enabled, push_frame skips nested calls without incrementing depth, but pop_frame still executes for those nested call ends because its guard depth > 1 is false (depth remains 1).

I think this causes the root frame to be popped prematurely when a nested call ends.

@0xMuang 0xMuang merged commit 93390db into main Jan 26, 2026
9 checks passed
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