relayer/test-support/Design.md
Technical architecture and implementation details for the ethereum_rpc_mock library.
MockServer (Public API)
↓
JsonRPSeeServer (Hidden Implementation)
↓
PatternMatcher → BlockchainState → EventEmitter
Purpose: Public facade that hides JsonRPSee complexity
Key Methods:
new(config: MockConfig) -> MockServerstart() -> anyhow::Result<ServerHandle>shutdown() -> anyhow::Result<()>set_balance(address: Address, amount: U256)set_code(address: Address, bytecode: Bytes)on_transaction(predicate: impl Fn(TxParams) -> bool, response: TxResponse, usage: UsageLimit)on_call(predicate: impl Fn(CallParams) -> bool, response: CallResponse, usage: UsageLimit)reset_state()Purpose: Handle JSON-RPC HTTP/WebSocket requests using JsonRPSee
RPC Methods Supported:
chain_id(), block_number(), get_balance(), get_transaction_count()get_code(), get_storage_at(), get_transaction_receipt()estimate_gas(), gas_price(), fee_history()get_block_by_number(), get_logs()call(), send_raw_transaction()subscribe() (WebSocket subscriptions)Implementation: Filter parameters are ignored for simplicity. All log subscribers receive all logs, all head subscribers receive all block headers.
Purpose: Match incoming requests against user-defined patterns
Key Methods:
add_transaction_pattern(predicate: PredicateFn<TxParams>, response: TxResponse, usage: UsageLimit)add_call_pattern(predicate: PredicateFn<CallParams>, response: CallResponse, usage: UsageLimit)find_transaction_match(tx_params: &TxParams) -> Option<TxResponse>find_call_match(call_params: &CallParams) -> Option<CallResponse>Pattern Matching Rules:
Purpose: Track minimal blockchain state for RPC responses
Key Methods:
get_balance(address: Address) -> U256set_balance(address: Address, amount: U256)get_nonce(address: Address) -> u64get_code(address: Address) -> Bytesget_storage(address: Address, slot: U256) -> U256store_transaction_receipt(hash: B256, receipt: TransactionReceipt)get_current_block() -> u64increment_block() -> u64Purpose: Broadcast WebSocket events to all subscribers
Key Methods:
emit_to_log_subscribers(log: Log) -> anyhow::Result<()>emit_to_head_subscribers(block: Block) -> anyhow::Result<()>Implementation: Uses shared references to subscription maps managed by JsonRPSee server. Broadcasts to all active sinks and removes inactive sinks automatically.
pub struct MockConfig {
pub port: u16,
pub chain_id: u64,
pub gas_price: u64,
pub gas_limit: u64,
pub block_time_ms: u64,
}
pub struct TxParams {
pub to: Option<Address>,
pub value: U256,
pub data: Bytes,
pub gas: u64,
pub gas_price: U256,
pub nonce: u64,
}
pub struct CallParams {
pub from: Option<Address>,
pub to: Address,
pub data: Bytes,
pub gas: Option<u64>,
pub gas_price: Option<U256>,
}
pub enum TxResponse {
Success { hash: B256, logs: Vec<Log> },
Revert { hash: B256, reason: Option<String> },
Error(String),
}
pub enum CallResponse {
Success(Bytes),
Revert(Option<String>),
Error(String),
}
pub enum UsageLimit {
Unlimited,
Once,
}
pub struct Account {
pub balance: U256,
pub nonce: u64,
pub code: Bytes,
pub storage: HashMap<U256, U256>,
}
type PredicateFn<T> = Arc<dyn Fn(&T) -> bool + Send + Sync>;
For complete implementation examples, see:
tests/test_fhevm.rs - Full FHEVM workflow with pattern matchingtests/test_core_rpc.rs - Basic RPC functionality examplestests/fhevm_event_signatures.rs - Event handling patterns