1use alloc::{
2 boxed::Box,
3 collections::{BTreeMap, btree_map::Entry},
4 sync::Arc,
5 vec::Vec,
6};
7use core::{error::Error, fmt, fmt::Debug};
8
9use miden_core::events::{EventId, EventName, SystemEvent};
10
11use crate::{ExecutionError, ProcessorState, advice::AdviceMutation};
12
13pub trait EventHandler: Send + Sync + 'static {
22 fn on_event(&self, process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError>;
24}
25
26impl<F> EventHandler for F
29where
30 F: for<'a> Fn(&'a ProcessorState) -> Result<Vec<AdviceMutation>, EventError>
31 + Send
32 + Sync
33 + 'static,
34{
35 fn on_event(&self, process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError> {
36 self(process)
37 }
38}
39
40pub struct NoopEventHandler;
42
43impl EventHandler for NoopEventHandler {
44 fn on_event(&self, _process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError> {
45 Ok(Vec::new())
46 }
47}
48
49pub type EventError = Box<dyn Error + Send + Sync + 'static>;
72
73#[derive(Default)]
103pub struct EventHandlerRegistry {
104 handlers: BTreeMap<EventId, (EventName, Arc<dyn EventHandler>)>,
105}
106
107impl EventHandlerRegistry {
108 pub fn new() -> Self {
109 Self { handlers: BTreeMap::new() }
110 }
111
112 pub fn register(
121 &mut self,
122 event: EventName,
123 handler: Arc<dyn EventHandler>,
124 ) -> Result<(), ExecutionError> {
125 if SystemEvent::from_name(event.as_str()).is_some() {
127 return Err(crate::errors::HostError::ReservedEventNamespace { event }.into());
128 }
129
130 let id = event.to_event_id();
132 match self.handlers.entry(id) {
133 Entry::Vacant(e) => e.insert((event, handler)),
134 Entry::Occupied(_) => {
135 return Err(crate::errors::HostError::DuplicateEventHandler { event }.into());
136 },
137 };
138 Ok(())
139 }
140
141 pub fn unregister(&mut self, id: EventId) -> bool {
144 self.handlers.remove(&id).is_some()
145 }
146
147 pub fn resolve_event(&self, id: EventId) -> Option<&EventName> {
149 self.handlers.get(&id).map(|(event, _)| event)
150 }
151
152 pub fn handle_event(
158 &self,
159 id: EventId,
160 process: &ProcessorState,
161 ) -> Result<Option<Vec<AdviceMutation>>, EventError> {
162 if let Some((_event_name, handler)) = self.handlers.get(&id) {
163 let mutations = handler.on_event(process)?;
164 return Ok(Some(mutations));
165 }
166
167 Ok(None)
168 }
169}
170
171impl Debug for EventHandlerRegistry {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 let events: Vec<_> = self.handlers.values().map(|(event, _)| event).collect();
174 f.debug_struct("EventHandlerRegistry").field("handlers", &events).finish()
175 }
176}
177
178pub trait TraceHandler: Send + Sync + 'static {
188 fn on_trace(&self, process: &ProcessorState) -> Result<(), TraceError>;
190}
191
192impl<F> TraceHandler for F
195where
196 F: for<'a> Fn(&'a ProcessorState) -> Result<(), TraceError> + Send + Sync + 'static,
197{
198 fn on_trace(&self, process: &ProcessorState) -> Result<(), TraceError> {
199 self(process)
200 }
201}
202
203pub type TraceError = Box<dyn Error + Send + Sync + 'static>;
211
212#[derive(Default)]
217pub struct TraceHandlerRegistry {
218 handlers: BTreeMap<EventId, (EventName, Arc<dyn TraceHandler>)>,
219}
220
221impl TraceHandlerRegistry {
222 pub fn new() -> Self {
223 Self { handlers: BTreeMap::new() }
224 }
225
226 pub fn register(
235 &mut self,
236 event: EventName,
237 handler: Arc<dyn TraceHandler>,
238 ) -> Result<(), ExecutionError> {
239 if SystemEvent::from_name(event.as_str()).is_some() {
241 return Err(crate::errors::HostError::ReservedEventNamespace { event }.into());
242 }
243
244 let id = event.to_event_id();
245 match self.handlers.entry(id) {
246 Entry::Vacant(e) => e.insert((event, handler)),
247 Entry::Occupied(_) => {
248 return Err(crate::errors::HostError::DuplicateEventHandler { event }.into());
249 },
250 };
251 Ok(())
252 }
253
254 pub fn unregister(&mut self, id: EventId) -> bool {
257 self.handlers.remove(&id).is_some()
258 }
259
260 pub fn resolve_trace(&self, id: EventId) -> Option<&EventName> {
262 self.handlers.get(&id).map(|(event, _)| event)
263 }
264
265 pub fn handle_trace(
270 &self,
271 id: EventId,
272 process: &ProcessorState,
273 ) -> Result<Option<()>, TraceError> {
274 if let Some((_event_name, handler)) = self.handlers.get(&id) {
275 handler.on_trace(process)?;
276 return Ok(Some(()));
277 }
278
279 Ok(None)
280 }
281}
282
283impl Debug for TraceHandlerRegistry {
284 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285 let traces: Vec<_> = self.handlers.values().map(|(event, _)| event).collect();
286 f.debug_struct("TraceHandlerRegistry").field("handlers", &traces).finish()
287 }
288}
289
290#[cfg(test)]
291mod tests {
292 use alloc::{sync::Arc, vec::Vec};
293
294 use miden_core::events::{EventId, EventName, SystemEvent};
295
296 use super::{
297 EventError, EventHandler, EventHandlerRegistry, NoopEventHandler, TraceError, TraceHandler,
298 TraceHandlerRegistry,
299 };
300 use crate::{
301 BaseHost, DefaultHost, ExecutionError, FastProcessor, HostError, ProcessorState,
302 StackInputs, advice::AdviceMutation,
303 };
304
305 #[derive(Debug, thiserror::Error)]
306 #[error("handler intentionally failed")]
307 struct HandlerFailed;
308
309 struct FailingEventHandler;
311 impl EventHandler for FailingEventHandler {
312 fn on_event(&self, _process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError> {
313 Err(HandlerFailed.into())
314 }
315 }
316
317 struct FailingTraceHandler;
319 impl TraceHandler for FailingTraceHandler {
320 fn on_trace(&self, _process: &ProcessorState) -> Result<(), TraceError> {
321 Err(HandlerFailed.into())
322 }
323 }
324
325 struct NoopTraceHandler;
326 impl TraceHandler for NoopTraceHandler {
327 fn on_trace(&self, _process: &ProcessorState) -> Result<(), TraceError> {
328 Ok(())
329 }
330 }
331
332 fn with_fresh_processor_state(f: impl FnOnce(&ProcessorState)) {
337 let processor = FastProcessor::new(StackInputs::default());
338 let state = processor.state();
339 f(&state);
340 }
341
342 #[test]
343 fn event_registry_resolve() {
344 const NAME: EventName = EventName::new("test::event::register_resolve");
345 let id = NAME.to_event_id();
346
347 let mut registry = EventHandlerRegistry::new();
348 assert!(registry.resolve_event(id).is_none());
349
350 registry.register(NAME, Arc::new(NoopEventHandler)).unwrap();
351 assert_eq!(registry.resolve_event(id), Some(&NAME));
352 }
353
354 #[test]
355 fn event_registry_handle_hit_and_miss() {
356 const NAME: EventName = EventName::new("test::event::handle");
357 let id = NAME.to_event_id();
358
359 let mut registry = EventHandlerRegistry::new();
360 registry.register(NAME, Arc::new(NoopEventHandler)).unwrap();
361
362 with_fresh_processor_state(|state| {
363 let handled =
364 registry.handle_event(id, state).expect("registered handler should not error");
365 assert!(handled.is_some(), "registered id should be handled");
366
367 let missed = registry
368 .handle_event(EventId::from_u64(999), state)
369 .expect("unregistered id should not error");
370 assert!(missed.is_none(), "unknown id should not be handled");
371 });
372 }
373
374 #[test]
375 fn event_registry_handle_propagates_handler_error() {
376 const NAME: EventName = EventName::new("test::event::handle_error");
377 let id = NAME.to_event_id();
378
379 let mut registry = EventHandlerRegistry::new();
380 registry.register(NAME, Arc::new(FailingEventHandler)).unwrap();
381
382 with_fresh_processor_state(|state| {
383 let err = registry.handle_event(id, state).unwrap_err();
384 assert!(
385 err.downcast_ref::<HandlerFailed>().is_some(),
386 "expected the handler's HandlerFailed to propagate, got {err}"
387 );
388 });
389 }
390
391 #[test]
392 fn event_registry_unregister() {
393 const NAME: EventName = EventName::new("test::event::unregister");
394 let id = NAME.to_event_id();
395
396 let mut registry = EventHandlerRegistry::new();
397 registry.register(NAME, Arc::new(NoopEventHandler)).unwrap();
398
399 assert!(registry.unregister(id), "unregistering a known id should return true");
400 assert!(registry.resolve_event(id).is_none());
401 assert!(!registry.unregister(id), "unregistering again should return false");
402 }
403
404 #[test]
405 fn event_register_rejects_reserved_namespace() {
406 let reserved = SystemEvent::MerkleNodeMerge.event_name();
407 let mut registry = EventHandlerRegistry::new();
408 let err = registry.register(reserved.clone(), Arc::new(NoopEventHandler)).unwrap_err();
409 match err {
410 ExecutionError::HostError(HostError::ReservedEventNamespace { event }) => {
411 assert_eq!(event, reserved);
412 },
413 other => panic!("expected ReservedEventNamespace, got {other:?}"),
414 }
415 }
416
417 #[test]
418 fn event_register_rejects_duplicate() {
419 const NAME: EventName = EventName::new("test::event::duplicate");
420 let mut registry = EventHandlerRegistry::new();
421 registry.register(NAME, Arc::new(NoopEventHandler)).unwrap();
422
423 let err = registry.register(NAME, Arc::new(NoopEventHandler)).unwrap_err();
424 match err {
425 ExecutionError::HostError(HostError::DuplicateEventHandler { event }) => {
426 assert_eq!(event, NAME);
427 },
428 other => panic!("expected DuplicateEventHandler, got {other:?}"),
429 }
430 }
431
432 #[test]
433 fn trace_registry_register_then_resolve() {
434 const NAME: EventName = EventName::new("test::trace::register_resolve");
435 let id = NAME.to_event_id();
436
437 let mut registry = TraceHandlerRegistry::new();
438 assert!(registry.resolve_trace(id).is_none());
439
440 registry.register(NAME, Arc::new(NoopTraceHandler)).unwrap();
441 assert_eq!(registry.resolve_trace(id), Some(&NAME));
442 }
443
444 #[test]
445 fn trace_registry_handle_hit_and_miss() {
446 const NAME: EventName = EventName::new("test::trace::handle");
447 let id = NAME.to_event_id();
448
449 let mut registry = TraceHandlerRegistry::new();
450 registry.register(NAME, Arc::new(NoopTraceHandler)).unwrap();
451
452 with_fresh_processor_state(|state| {
453 let handled =
454 registry.handle_trace(id, state).expect("registered handler should not error");
455 assert_eq!(handled, Some(()), "registered id should be handled");
456
457 let missed = registry
458 .handle_trace(EventId::from_u64(999), state)
459 .expect("unregistered id should not error");
460 assert_eq!(missed, None, "unknown id should not be handled");
461 });
462 }
463
464 #[test]
465 fn trace_registry_handle_propagates_handler_error() {
466 const NAME: EventName = EventName::new("test::trace::handle_error");
467 let id = NAME.to_event_id();
468
469 let mut registry = TraceHandlerRegistry::new();
470 registry.register(NAME, Arc::new(FailingTraceHandler)).unwrap();
471
472 with_fresh_processor_state(|state| {
473 let err = registry.handle_trace(id, state).unwrap_err();
474 assert!(
475 err.downcast_ref::<HandlerFailed>().is_some(),
476 "expected the handler's HandlerFailed to propagate, got {err}"
477 );
478 });
479 }
480
481 #[test]
482 fn trace_registry_unregister() {
483 const NAME: EventName = EventName::new("test::trace::unregister");
484 let id = NAME.to_event_id();
485
486 let mut registry = TraceHandlerRegistry::new();
487 registry.register(NAME, Arc::new(NoopTraceHandler)).unwrap();
488
489 assert!(registry.unregister(id), "unregistering a known id should return true");
490 assert!(registry.resolve_trace(id).is_none());
491 assert!(!registry.unregister(id), "unregistering again should return false");
492 }
493
494 #[test]
495 fn trace_register_rejects_reserved_namespace() {
496 let reserved = SystemEvent::TraceEvent.event_name();
498 let mut registry = TraceHandlerRegistry::new();
499 let err = registry.register(reserved.clone(), Arc::new(NoopTraceHandler)).unwrap_err();
500 match err {
501 ExecutionError::HostError(HostError::ReservedEventNamespace { event }) => {
502 assert_eq!(event, reserved);
503 },
504 other => panic!("expected ReservedEventNamespace, got {other:?}"),
505 }
506 }
507
508 #[test]
509 fn trace_register_rejects_duplicate() {
510 const NAME: EventName = EventName::new("test::trace::duplicate");
511 let mut registry = TraceHandlerRegistry::new();
512 registry.register(NAME, Arc::new(NoopTraceHandler)).unwrap();
513
514 let err = registry.register(NAME, Arc::new(NoopTraceHandler)).unwrap_err();
515 match err {
516 ExecutionError::HostError(HostError::DuplicateEventHandler { event }) => {
517 assert_eq!(event, NAME);
518 },
519 other => panic!("expected DuplicateEventHandler, got {other:?}"),
520 }
521 }
522
523 #[test]
524 fn default_host_event_handler_lifecycle() {
525 const NAME: EventName = EventName::new("test::host::event_lifecycle");
526 let id = NAME.to_event_id();
527 let mut host = DefaultHost::default();
528
529 let existed = host.replace_handler(NAME, Arc::new(NoopEventHandler));
532 assert!(!existed, "replace before register should report no prior handler");
533 assert_eq!(host.resolve_event(id), Some(&NAME));
534
535 assert!(host.replace_handler(NAME, Arc::new(NoopEventHandler)));
537
538 assert!(matches!(
540 host.register_handler(NAME, Arc::new(NoopEventHandler)),
541 Err(ExecutionError::HostError(HostError::DuplicateEventHandler { .. }))
542 ));
543
544 assert!(host.unregister_handler(id));
545 assert!(host.resolve_event(id).is_none());
546 assert!(!host.unregister_handler(id));
547 }
548
549 #[test]
550 fn default_host_trace_handler_lifecycle() {
551 const NAME: EventName = EventName::new("test::host::trace_lifecycle");
552 let id = NAME.to_event_id();
553 let mut host = DefaultHost::default();
554
555 let existed = host.replace_trace_handler(NAME, Arc::new(NoopTraceHandler));
556 assert!(!existed, "replace before register should report no prior handler");
557 assert_eq!(host.resolve_trace(id), Some(&NAME));
558
559 assert!(host.replace_trace_handler(NAME, Arc::new(NoopTraceHandler)));
560
561 assert!(matches!(
562 host.register_trace_handler(NAME, Arc::new(NoopTraceHandler)),
563 Err(ExecutionError::HostError(HostError::DuplicateEventHandler { .. }))
564 ));
565
566 assert!(host.unregister_trace_handler(id));
567 assert!(host.resolve_trace(id).is_none());
568 assert!(!host.unregister_trace_handler(id));
569 }
570}