0xMiden / 0xMiden/protocol

Allow tests to register custom event handlers on the mock host

未關閉
#3,441 1 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
rust tests
主要語言
Rust
星號
132
分支
167
平均合併
1 天 23 小時
30 天內合併 PR
110

描述

## Motivation

Various procedures treat host responses as *hints* that MASM must validate. For example, [#3424](https://github.com/0xMiden/protocol/pull/3424) makes `input_note::find_note` ask the host for `[note_idx, is_found]` and then proves the answer in the VM. The security of such procedures rests entirely on that validation, so we need tests that run them against a *malicious* host response.

Today the only knob is `MockHost::handled_events`: an event handler can be turned on or off. Off means the advice provider is left untouched, which exercises "host returns nothing", but never "host returns plausible-looking but wrong data". Consequently #3424 had to thread a canned response through the mock types:

- `MockTransaction::execute_code_with_input_note_index_response(code, [Felt; 2])`
- an `input_note_index_response: Option<[Felt; 2]>` parameter on `execute_code_inner`
- a matching field/branch on `MockHost`

That is event-specific test logic living in the general-purpose `Mock*` types. Every further adversarial test would add another such field, so this should be replaced before it spreads.

The generic version - registering arbitrary `EventHandler`s for a single execution - also unlocks adversarial tests for the many other procedures that consume advice-provider data and have no such coverage yet (link map, account procedure index, storage-map and vault witnesses, output note building).

## Goal

A testing-only API to register custom `EventHandler`s for one `execute_code` run, so that tests can define malicious or stubbed handlers locally, and the `Mock*` types carry no per-event logic.

## Design

### 1. `ExecutionConfig` in `miden-testing`

Replace the boolean/`Option` parameter list of `execute_code_inner` with a config struct (as suggested in the [#3424 review](https://github.com/0xMiden/protocol/pull/3424#discussion_r3674243568)):

```rust
#[derive(Default)]
pub(crate) struct ExecutionConfig {
lazy_loading: bool, // default: enabled, matching today's `execute_code`
event_handlers: Vec<(EventName, Arc)>,
}

impl ExecutionConfig {
pub(crate) fn without_lazy_loading() -> Self { ... }
pub(crate) fn with_event_handler(self, event: EventName, handler: Arc) -> Self { ... }
}
```

`MockTransaction` then exposes exactly two entry points:

```rust
pub(crate) async fn execute_code(&self, code: &str) -> Result;
pub(crate) async fn execute_code_with(&self, code: &str, config: ExecutionConfig) -> Result;
```

`execute_code_without_lazy_loading` and `execute_code_with_input_note_index_response` disappear.

### 2. Handler registry on `TransactionBaseHost`

`TransactionBaseHost` already owns an `EventHandlerRegistry` for the core library handlers. Rename this to a more general `event_handlers`.

- `pub fn register_event_handler(&mut self, event: EventName, handler: Arc)`,
also `testing`-gated
- rename `handle_core_lib_events` to something like `handle_registered_events`

To allow shadowing an already defined handler, the register API should unregister first and then register. For testing purposes, this is fine. If we ever make this API public, we should reject duplicate event handlers or allow overriding with an explicit flag.

### 3. Passthrough on the executor host and mock host

- `TransactionExecutorHost::register_event_handler(...)`, testing-gated, forwarding to the base host.
- `MockHost::new(exec_host, &config)` registers the config's handlers through that passthrough. It also adds all provided handlers to the `handled_events` set, to make them actually fire.

For now this only supports overriding sync host events, not async ones.

## Follow-ups (out of scope)

- Add adversarial coverage for the other procedures that consume advice-provider data.

貢獻指南

開啟貢獻指南

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。