edb_engine/rpc/methods/mod.rs
1// EDB - Ethereum Debugger
2// Copyright (C) 2024 Zhuo Zhang and Wuqi Zhang
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Affero General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Affero General Public License for more details.
13//
14// You should have received a copy of the GNU Affero General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17//! JSON-RPC method implementations for EDB debugging API.
18//!
19//! This module contains all the RPC method implementations organized by functionality.
20//! Each sub-module provides specific debugging capabilities:
21//!
22//! # Method Categories
23//!
24//! ## Artifact Management ([`artifact`])
25//! - `edb_getCode` - Retrieve contract bytecode
26//! - `edb_getConstructorArgs` - Get constructor arguments
27//!
28//! ## Expression Evaluation ([`expr`])
29//! - `edb_evalOnSnapshot` - Evaluate expressions against snapshots
30//!
31//! ## Navigation ([`navigation`])
32//! - `edb_getNextCall` - Navigate to next function call
33//! - `edb_getPrevCall` - Navigate to previous function call
34//!
35//! ## Resolution ([`resolve`])
36//! - `edb_getContractABI` - Resolve contract ABI information
37//! - `edb_getCallableABI` - Get callable function ABI details
38//!
39//! ## Snapshot Management ([`snapshot`])
40//! - `edb_getSnapshotCount` - Get total number of snapshots
41//! - `edb_getSnapshotInfo` - Get detailed snapshot information
42//!
43//! ## Storage Inspection ([`storage`])
44//! - `edb_getStorage` - Read contract storage at specific snapshot
45//! - `edb_getStorageDiff` - Compare storage between snapshots
46//!
47//! ## Trace Analysis ([`trace`])
48//! - `edb_getTrace` - Get complete execution trace
49//!
50//! # Architecture
51//!
52//! All methods are stateless and operate through the [`MethodHandler`] which
53//! provides access to the immutable debugging context. Methods follow a consistent
54//! pattern of parameter validation, operation execution, and result serialization.
55
56mod artifact;
57mod expr;
58mod navigation;
59mod resolve;
60mod snapshot;
61mod storage;
62mod trace;
63
64use super::types::RpcError;
65use crate::{error_codes, EngineContext};
66use revm::{database::CacheDB, Database, DatabaseCommit, DatabaseRef};
67use std::sync::Arc;
68use tracing::debug;
69
70/// Stateless RPC method dispatcher for EDB debugging API.
71///
72/// This handler provides a centralized entry point for all RPC methods.
73/// It maintains a reference to the immutable debugging context and routes
74/// method calls to their appropriate implementation modules.
75///
76/// The handler is designed to be thread-safe and stateless, allowing
77/// concurrent processing of RPC requests without side effects.
78pub struct MethodHandler<DB>
79where
80 DB: Database + DatabaseCommit + DatabaseRef + Clone + Send + Sync + 'static,
81 <CacheDB<DB> as Database>::Error: Clone + Send + Sync,
82 <DB as Database>::Error: Clone + Send + Sync,
83{
84 /// Immutable debugging context providing read-only access to debugging data
85 context: Arc<EngineContext<DB>>,
86}
87
88impl<DB> MethodHandler<DB>
89where
90 DB: Database + DatabaseCommit + DatabaseRef + Clone + Send + Sync + 'static,
91 <CacheDB<DB> as Database>::Error: Clone + Send + Sync,
92 <DB as Database>::Error: Clone + Send + Sync,
93{
94 /// Create a new method handler
95 pub fn new(context: Arc<EngineContext<DB>>) -> Self {
96 Self { context }
97 }
98
99 /// Handle an RPC method call with client-provided state
100 pub async fn handle_method(
101 &self,
102 method: &str,
103 params: Option<serde_json::Value>,
104 ) -> Result<serde_json::Value, RpcError> {
105 debug!("Handling RPC method: {}", method);
106
107 match method {
108 "edb_getTrace" => trace::get_trace(&self.context),
109 "edb_getCode" => artifact::get_code(&self.context, params),
110 "edb_getConstructorArgs" => artifact::get_constructor_args(&self.context, params),
111 "edb_getSnapshotCount" => snapshot::get_snapshot_count(&self.context),
112 "edb_getSnapshotInfo" => snapshot::get_snapshot_info(&self.context, params),
113 "edb_getContractABI" => resolve::get_contract_abi(&self.context, params),
114 "edb_getCallableABI" => resolve::get_callable_abi(&self.context, params),
115 "edb_getNextCall" => navigation::get_next_call(&self.context, params),
116 "edb_getPrevCall" => navigation::get_prev_call(&self.context, params),
117 "edb_getStorage" => storage::get_storage(&self.context, params),
118 "edb_getStorageDiff" => storage::get_storage_diff(&self.context, params),
119 "edb_evalOnSnapshot" => expr::eval_on_snapshot(&self.context, params),
120 // Unimplemented methods
121 _ => Err(RpcError {
122 code: error_codes::METHOD_NOT_FOUND,
123 message: format!("Method '{method}' not found"),
124 data: None,
125 }),
126 }
127 }
128}