Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#### Bug Fixes

- Fixed host event and advice-mutation diagnostics to point to the triggering `emit.event(...)` instruction ([#3042](https://github.com/0xMiden/miden-vm/pull/3042)).
- Fixed debug-only underflow in memory range-check trace generation when the first memory access is at `clk = 0` ([#2976](https://github.com/0xMiden/miden-vm/pull/2976)).
- Replaced unsound `ptr::read` with safe unbox in panic recovery, removing UB from potential double-drop ([#2934](https://github.com/0xMiden/miden-vm/pull/2934)).
- Reverted `InvokeKind::ProcRef` back to `InvokeKind::Exec` in `visit_mut_procref` and added an explanatory comment (#2893).
Expand Down
8 changes: 5 additions & 3 deletions processor/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,9 @@ pub fn advice_error_with_context(
mast_forest: &MastForest,
node_id: MastNodeId,
host: &impl BaseHost,
op_idx: Option<usize>,
) -> ExecutionError {
let (label, source_file) = get_label_and_source_file(None, mast_forest, node_id, host);
let (label, source_file) = get_label_and_source_file(op_idx, mast_forest, node_id, host);
ExecutionError::AdviceError { label, source_file, err }
}

Expand All @@ -427,10 +428,11 @@ pub fn event_error_with_context(
mast_forest: &MastForest,
node_id: MastNodeId,
host: &impl BaseHost,
op_idx: Option<usize>,
event_id: EventId,
event_name: Option<EventName>,
) -> ExecutionError {
let (label, source_file) = get_label_and_source_file(None, mast_forest, node_id, host);
let (label, source_file) = get_label_and_source_file(op_idx, mast_forest, node_id, host);
ExecutionError::EventError {
label,
source_file,
Expand Down Expand Up @@ -559,7 +561,7 @@ impl<T> MapExecErr<T> for Result<T, AdviceError> {
) -> Result<T, ExecutionError> {
match self {
Ok(v) => Ok(v),
Err(err) => Err(advice_error_with_context(err, mast_forest, node_id, host)),
Err(err) => Err(advice_error_with_context(err, mast_forest, node_id, host, None)),
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions processor/src/fast/basic_block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ impl FastProcessor {
current_forest: &MastForest,
node_id: MastNodeId,
host: &impl BaseHost,
op_idx: usize,
event_id: EventId,
mutations: Result<Vec<AdviceMutation>, EventError>,
) -> ControlFlow<BreakReason> {
Expand All @@ -57,6 +58,7 @@ impl FastProcessor {
current_forest,
node_id,
host,
Some(op_idx),
event_id,
event_name,
)));
Expand All @@ -70,6 +72,7 @@ impl FastProcessor {
current_forest,
node_id,
host,
Some(op_idx),
))),
}
}
Expand Down Expand Up @@ -115,7 +118,7 @@ impl FastProcessor {

let processor_state = self.state();
let mutations = host.on_event(&processor_state);
self.apply_host_event_mutations(current_forest, node_id, host, event_id, mutations)
self.apply_host_event_mutations(current_forest, node_id, host, op_idx, event_id, mutations)
}

#[inline(always)]
Expand All @@ -134,6 +137,6 @@ impl FastProcessor {

let processor_state = self.state();
let mutations = host.on_event(&processor_state).await;
self.apply_host_event_mutations(current_forest, node_id, host, event_id, mutations)
self.apply_host_event_mutations(current_forest, node_id, host, op_idx, event_id, mutations)
}
}
96 changes: 94 additions & 2 deletions processor/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,38 @@ use miden_utils_testing::{

/// Tests in this file make sure that diagnostics presented to the user are as expected.
use crate::{
DefaultHost, FastProcessor, Kernel, ONE, Program, StackInputs, Word, ZERO,
advice::{AdviceInputs, AdviceMap},
DefaultHost, FastProcessor, Kernel, ONE, ProcessorState, Program, StackInputs, Word, ZERO,
advice::{AdviceInputs, AdviceMap, AdviceMutation},
event::{EventError, EventHandler, EventName},
operation::Operation,
};

mod debug;
mod debug_mode_decorator_tests;

#[derive(Debug, thiserror::Error)]
#[error("dummy host event failure")]
struct DummyHostEventError;

struct AlwaysFailEventHandler;

impl EventHandler for AlwaysFailEventHandler {
fn on_event(&self, _process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError> {
Err(DummyHostEventError.into())
}
}

struct DuplicateMapMutationHandler;

impl EventHandler for DuplicateMapMutationHandler {
fn on_event(&self, _process: &ProcessorState) -> Result<Vec<AdviceMutation>, EventError> {
Ok(vec![AdviceMutation::extend_map(AdviceMap::from_iter([(
Word::default(),
vec![ONE],
)]))])
}
}

// AdviceMap inlined in the script
// ------------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -140,6 +164,74 @@ fn test_diagnostic_advice_map_key_not_found_2() {
);
}

// Host event diagnostics
// ------------------------------------------------------------------------------------------------

#[test]
fn test_diagnostic_host_event_error_uses_emit_location() {
let event = EventName::new("test::host_event_error");
let source_manager = Arc::new(DefaultSourceManager::default());
let source = format!(
"
begin
push.1 emit.event(\"{event}\")
end"
);
let program = Assembler::new(source_manager.clone()).assemble_program(source).unwrap();
let mut host = DefaultHost::default().with_source_manager(source_manager);
host.register_handler(event.clone(), Arc::new(AlwaysFailEventHandler)).unwrap();

let processor = FastProcessor::new(StackInputs::default())
.with_advice(AdviceInputs::default())
.with_debugging(true)
.with_tracing(true);
let err = processor.execute_sync(&program, &mut host).expect_err("expected error");
assert_diagnostic_lines!(
err,
format!(" x error during processing of event '{event}' (ID: {})", event.to_event_id()),
" `-> dummy host event failure",
regex!(r#",-\[::\$exec:3:20\]"#),
" 2 | begin",
format!(" 3 | push.1 emit.event(\"{event}\")"),
" : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^",
" 4 | end",
" `----"
);
}

#[test]
fn test_diagnostic_host_event_advice_error_uses_emit_location() {
let event = EventName::new("test::host_event_advice_error");
let source_manager = Arc::new(DefaultSourceManager::default());
let source = format!(
"
begin
push.1 emit.event(\"{event}\")
end"
);
let program = Assembler::new(source_manager.clone()).assemble_program(source).unwrap();
let mut host = DefaultHost::default().with_source_manager(source_manager);
host.register_handler(event.clone(), Arc::new(DuplicateMapMutationHandler))
.unwrap();

let processor = FastProcessor::new(StackInputs::default())
.with_advice(AdviceInputs::default().with_map([(Word::default(), vec![ZERO])]))
.with_debugging(true)
.with_tracing(true);
let err = processor.execute_sync(&program, &mut host).expect_err("expected error");
assert_diagnostic_lines!(
err,
" x value for key 0x0000000000000000000000000000000000000000000000000000000000000000 already present in the advice map",
regex!(r#",-\[::\$exec:3:20\]"#),
" 2 | begin",
format!(" 3 | push.1 emit.event(\"{event}\")"),
" : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^",
" 4 | end",
" `----",
"help: previous values at key were '[0]'. Operation would have replaced them with '[1]'"
);
}

// AdviceStackReadFailed
// ------------------------------------------------------------------------------------------------

Expand Down
Loading