Allow tests to register custom event handlers on the mock host
- Lingua principale
- Rust
- Stelle
- 132
- Fork
- 167
- Merge medio
- 1g 23h
- PR unite (30g)
- 110
Descrizione
## 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.
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.