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 {
194 fn on_trace(&self, process: &ProcessorState) -> Result<(), TraceError>;
196}
197
198impl<F> TraceHandler for F
201where
202 F: for<'a> Fn(&'a ProcessorState) -> Result<(), TraceError> + Send + Sync + 'static,
203{
204 fn on_trace(&self, process: &ProcessorState) -> Result<(), TraceError> {
205 self(process)
206 }
207}
208
209pub type TraceError = Box<dyn Error + Send + Sync + 'static>;
217
218#[derive(Default)]
223pub struct TraceHandlerRegistry {
224 handlers: BTreeMap<EventId, (EventName, Arc<dyn TraceHandler>)>,
225}
226
227impl TraceHandlerRegistry {
228 pub fn new() -> Self {
229 Self { handlers: BTreeMap::new() }
230 }
231
232 pub fn register(
241 &mut self,
242 event: EventName,
243 handler: Arc<dyn TraceHandler>,
244 ) -> Result<(), ExecutionError> {
245 if SystemEvent::from_name(event.as_str()).is_some() {
247 return Err(crate::errors::HostError::ReservedEventNamespace { event }.into());
248 }
249
250 let id = event.to_event_id();
251 match self.handlers.entry(id) {
252 Entry::Vacant(e) => e.insert((event, handler)),
253 Entry::Occupied(_) => {
254 return Err(crate::errors::HostError::DuplicateEventHandler { event }.into());
255 },
256 };
257 Ok(())
258 }
259
260 pub fn unregister(&mut self, id: EventId) -> bool {
263 self.handlers.remove(&id).is_some()
264 }
265
266 pub fn resolve_trace(&self, id: EventId) -> Option<&EventName> {
268 self.handlers.get(&id).map(|(event, _)| event)
269 }
270
271 pub fn handle_trace(
276 &self,
277 id: EventId,
278 process: &ProcessorState,
279 ) -> Result<Option<()>, TraceError> {
280 if let Some((_event_name, handler)) = self.handlers.get(&id) {
281 handler.on_trace(process)?;
282 return Ok(Some(()));
283 }
284
285 Ok(None)
286 }
287}
288
289impl Debug for TraceHandlerRegistry {
290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291 let traces: Vec<_> = self.handlers.values().map(|(event, _)| event).collect();
292 f.debug_struct("TraceHandlerRegistry").field("handlers", &traces).finish()
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use alloc::{sync::Arc, vec::Vec};
299
300 use miden_core::events::{EventId, EventName, SystemEvent};
301
302 use super::{
303 EventError, EventHandler, EventHandlerRegistry, NoopEventHandler, TraceError, TraceHandler,
304 TraceHandlerRegistry,
305 };
306 use crate::{
307 BaseHost, DefaultHost, ExecutionError, FastProcessor, HostError, ProcessorState,
308 StackInputs, advice::AdviceMutation,
309 };
310
311 #[derive(Debug, thiserror::Error)]
312 #[error("handler intentionally failed")]
313 struct HandlerFailed;
314
315 struct FailingEventHandler;
317 impl EventHandler for FailingEventHandler {
318 fn on_event(&self, _process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError> {
319 Err(HandlerFailed.into())
320 }
321 }
322
323 struct FailingTraceHandler;
325 impl TraceHandler for FailingTraceHandler {
326 fn on_trace(&self, _process: &ProcessorState) -> Result<(), TraceError> {
327 Err(HandlerFailed.into())
328 }
329 }
330
331 struct NoopTraceHandler;
332 impl TraceHandler for NoopTraceHandler {
333 fn on_trace(&self, _process: &ProcessorState) -> Result<(), TraceError> {
334 Ok(())
335 }
336 }
337
338 fn with_fresh_processor_state(f: impl FnOnce(&ProcessorState)) {
343 let processor = FastProcessor::new(StackInputs::default());
344 let state = processor.state();
345 f(&state);
346 }
347
348 #[test]
349 fn event_registry_resolve() {
350 const NAME: EventName = EventName::new("test::event::register_resolve");
351 let id = NAME.to_event_id();
352
353 let mut registry = EventHandlerRegistry::new();
354 assert!(registry.resolve_event(id).is_none());
355
356 registry.register(NAME, Arc::new(NoopEventHandler)).unwrap();
357 assert_eq!(registry.resolve_event(id), Some(&NAME));
358 }
359
360 #[test]
361 fn event_registry_handle_hit_and_miss() {
362 const NAME: EventName = EventName::new("test::event::handle");
363 let id = NAME.to_event_id();
364
365 let mut registry = EventHandlerRegistry::new();
366 registry.register(NAME, Arc::new(NoopEventHandler)).unwrap();
367
368 with_fresh_processor_state(|state| {
369 let handled =
370 registry.handle_event(id, state).expect("registered handler should not error");
371 assert!(handled.is_some(), "registered id should be handled");
372
373 let missed = registry
374 .handle_event(EventId::from_u64(999), state)
375 .expect("unregistered id should not error");
376 assert!(missed.is_none(), "unknown id should not be handled");
377 });
378 }
379
380 #[test]
381 fn event_registry_handle_propagates_handler_error() {
382 const NAME: EventName = EventName::new("test::event::handle_error");
383 let id = NAME.to_event_id();
384
385 let mut registry = EventHandlerRegistry::new();
386 registry.register(NAME, Arc::new(FailingEventHandler)).unwrap();
387
388 with_fresh_processor_state(|state| {
389 let err = registry.handle_event(id, state).unwrap_err();
390 assert!(
391 err.downcast_ref::<HandlerFailed>().is_some(),
392 "expected the handler's HandlerFailed to propagate, got {err}"
393 );
394 });
395 }
396
397 #[test]
398 fn event_registry_unregister() {
399 const NAME: EventName = EventName::new("test::event::unregister");
400 let id = NAME.to_event_id();
401
402 let mut registry = EventHandlerRegistry::new();
403 registry.register(NAME, Arc::new(NoopEventHandler)).unwrap();
404
405 assert!(registry.unregister(id), "unregistering a known id should return true");
406 assert!(registry.resolve_event(id).is_none());
407 assert!(!registry.unregister(id), "unregistering again should return false");
408 }
409
410 #[test]
411 fn event_register_rejects_reserved_namespace() {
412 let reserved = SystemEvent::MerkleNodeMerge.event_name();
413 let mut registry = EventHandlerRegistry::new();
414 let err = registry.register(reserved.clone(), Arc::new(NoopEventHandler)).unwrap_err();
415 match err {
416 ExecutionError::HostError(HostError::ReservedEventNamespace { event }) => {
417 assert_eq!(event, reserved);
418 },
419 other => panic!("expected ReservedEventNamespace, got {other:?}"),
420 }
421 }
422
423 #[test]
424 fn event_register_rejects_duplicate() {
425 const NAME: EventName = EventName::new("test::event::duplicate");
426 let mut registry = EventHandlerRegistry::new();
427 registry.register(NAME, Arc::new(NoopEventHandler)).unwrap();
428
429 let err = registry.register(NAME, Arc::new(NoopEventHandler)).unwrap_err();
430 match err {
431 ExecutionError::HostError(HostError::DuplicateEventHandler { event }) => {
432 assert_eq!(event, NAME);
433 },
434 other => panic!("expected DuplicateEventHandler, got {other:?}"),
435 }
436 }
437
438 #[test]
439 fn trace_registry_register_then_resolve() {
440 const NAME: EventName = EventName::new("test::trace::register_resolve");
441 let id = NAME.to_event_id();
442
443 let mut registry = TraceHandlerRegistry::new();
444 assert!(registry.resolve_trace(id).is_none());
445
446 registry.register(NAME, Arc::new(NoopTraceHandler)).unwrap();
447 assert_eq!(registry.resolve_trace(id), Some(&NAME));
448 }
449
450 #[test]
451 fn trace_registry_handle_hit_and_miss() {
452 const NAME: EventName = EventName::new("test::trace::handle");
453 let id = NAME.to_event_id();
454
455 let mut registry = TraceHandlerRegistry::new();
456 registry.register(NAME, Arc::new(NoopTraceHandler)).unwrap();
457
458 with_fresh_processor_state(|state| {
459 let handled =
460 registry.handle_trace(id, state).expect("registered handler should not error");
461 assert_eq!(handled, Some(()), "registered id should be handled");
462
463 let missed = registry
464 .handle_trace(EventId::from_u64(999), state)
465 .expect("unregistered id should not error");
466 assert_eq!(missed, None, "unknown id should not be handled");
467 });
468 }
469
470 #[test]
471 fn trace_registry_handle_propagates_handler_error() {
472 const NAME: EventName = EventName::new("test::trace::handle_error");
473 let id = NAME.to_event_id();
474
475 let mut registry = TraceHandlerRegistry::new();
476 registry.register(NAME, Arc::new(FailingTraceHandler)).unwrap();
477
478 with_fresh_processor_state(|state| {
479 let err = registry.handle_trace(id, state).unwrap_err();
480 assert!(
481 err.downcast_ref::<HandlerFailed>().is_some(),
482 "expected the handler's HandlerFailed to propagate, got {err}"
483 );
484 });
485 }
486
487 #[test]
488 fn trace_registry_unregister() {
489 const NAME: EventName = EventName::new("test::trace::unregister");
490 let id = NAME.to_event_id();
491
492 let mut registry = TraceHandlerRegistry::new();
493 registry.register(NAME, Arc::new(NoopTraceHandler)).unwrap();
494
495 assert!(registry.unregister(id), "unregistering a known id should return true");
496 assert!(registry.resolve_trace(id).is_none());
497 assert!(!registry.unregister(id), "unregistering again should return false");
498 }
499
500 #[test]
501 fn trace_register_rejects_reserved_namespace() {
502 let reserved = SystemEvent::TraceEvent.event_name();
504 let mut registry = TraceHandlerRegistry::new();
505 let err = registry.register(reserved.clone(), Arc::new(NoopTraceHandler)).unwrap_err();
506 match err {
507 ExecutionError::HostError(HostError::ReservedEventNamespace { event }) => {
508 assert_eq!(event, reserved);
509 },
510 other => panic!("expected ReservedEventNamespace, got {other:?}"),
511 }
512 }
513
514 #[test]
515 fn trace_register_rejects_duplicate() {
516 const NAME: EventName = EventName::new("test::trace::duplicate");
517 let mut registry = TraceHandlerRegistry::new();
518 registry.register(NAME, Arc::new(NoopTraceHandler)).unwrap();
519
520 let err = registry.register(NAME, Arc::new(NoopTraceHandler)).unwrap_err();
521 match err {
522 ExecutionError::HostError(HostError::DuplicateEventHandler { event }) => {
523 assert_eq!(event, NAME);
524 },
525 other => panic!("expected DuplicateEventHandler, got {other:?}"),
526 }
527 }
528
529 #[test]
530 fn default_host_event_handler_lifecycle() {
531 const NAME: EventName = EventName::new("test::host::event_lifecycle");
532 let id = NAME.to_event_id();
533 let mut host = DefaultHost::default();
534
535 let existed = host.replace_handler(NAME, Arc::new(NoopEventHandler));
538 assert!(!existed, "replace before register should report no prior handler");
539 assert_eq!(host.resolve_event(id), Some(&NAME));
540
541 assert!(host.replace_handler(NAME, Arc::new(NoopEventHandler)));
543
544 assert!(matches!(
546 host.register_handler(NAME, Arc::new(NoopEventHandler)),
547 Err(ExecutionError::HostError(HostError::DuplicateEventHandler { .. }))
548 ));
549
550 assert!(host.unregister_handler(id));
551 assert!(host.resolve_event(id).is_none());
552 assert!(!host.unregister_handler(id));
553 }
554
555 #[test]
556 fn default_host_trace_handler_lifecycle() {
557 const NAME: EventName = EventName::new("test::host::trace_lifecycle");
558 let id = NAME.to_event_id();
559 let mut host = DefaultHost::default();
560
561 let existed = host.replace_trace_handler(NAME, Arc::new(NoopTraceHandler));
562 assert!(!existed, "replace before register should report no prior handler");
563 assert_eq!(host.resolve_trace(id), Some(&NAME));
564
565 assert!(host.replace_trace_handler(NAME, Arc::new(NoopTraceHandler)));
566
567 assert!(matches!(
568 host.register_trace_handler(NAME, Arc::new(NoopTraceHandler)),
569 Err(ExecutionError::HostError(HostError::DuplicateEventHandler { .. }))
570 ));
571
572 assert!(host.unregister_trace_handler(id));
573 assert!(host.resolve_trace(id).is_none());
574 assert!(!host.unregister_trace_handler(id));
575 }
576}