Skip to content

Commit 9b36813

Browse files
authored
fix: some methods operating on wrong near call (#69)
There was a bug that only affected methods like `.gas()`, which look at the near call on top of the targeted call to get the stat. Added a regression test along with the fix.
1 parent cdda579 commit 9b36813

File tree

1 file changed

+26
-34
lines changed

1 file changed

+26
-34
lines changed

crates/vm2/src/tracing.rs

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@ impl<T: Tracer, W> StateInterface for VirtualMachine<T, W> {
4949
for far_frame in std::iter::once(&mut self.state.current_frame)
5050
.chain(self.state.previous_frames.iter_mut().rev())
5151
{
52-
match n.cmp(&far_frame.near_calls.len()) {
52+
let near_calls = far_frame.near_calls.len();
53+
match n.cmp(&near_calls) {
5354
Ordering::Less => {
5455
return CallframeWrapper {
5556
frame: far_frame,
56-
near_call: Some(n),
57+
near_call: Some(near_calls - 1 - n),
5758
}
5859
}
5960
Ordering::Equal => {
@@ -62,7 +63,7 @@ impl<T: Tracer, W> StateInterface for VirtualMachine<T, W> {
6263
near_call: None,
6364
}
6465
}
65-
Ordering::Greater => n -= far_frame.near_calls.len() + 1,
66+
Ordering::Greater => n -= near_calls + 1,
6667
}
6768
}
6869
panic!("Callframe index out of bounds")
@@ -309,21 +310,24 @@ impl<T: Tracer, W> CallframeInterface for CallframeWrapper<'_, T, W> {
309310
}
310311

311312
fn set_program_counter(&mut self, value: u16) {
312-
self.frame.set_pc_from_u16(value);
313+
if let Some(call) = self.near_call_on_top_mut() {
314+
call.previous_frame_pc = value;
315+
} else {
316+
self.frame.set_pc_from_u16(value);
317+
}
313318
}
314319

315320
fn exception_handler(&self) -> u16 {
316321
if let Some(i) = self.near_call {
317-
self.frame.near_calls[self.frame.near_calls.len() - i - 1].exception_handler
322+
self.frame.near_calls[i].exception_handler
318323
} else {
319324
self.frame.exception_handler
320325
}
321326
}
322327

323328
fn set_exception_handler(&mut self, value: u16) {
324329
if let Some(i) = self.near_call {
325-
let idx = self.frame.near_calls.len() - i - 1;
326-
self.frame.near_calls[idx].exception_handler = value;
330+
self.frame.near_calls[i].exception_handler = value;
327331
} else {
328332
self.frame.exception_handler = value;
329333
}
@@ -332,29 +336,13 @@ impl<T: Tracer, W> CallframeInterface for CallframeWrapper<'_, T, W> {
332336

333337
impl<T, W> CallframeWrapper<'_, T, W> {
334338
fn near_call_on_top(&self) -> Option<&NearCallFrame> {
335-
if self.frame.near_calls.is_empty() || self.near_call == Some(0) {
336-
None
337-
} else {
338-
let index = if let Some(i) = self.near_call {
339-
i - 1
340-
} else {
341-
self.frame.near_calls.len() - 1
342-
};
343-
Some(&self.frame.near_calls[index])
344-
}
339+
let index = self.near_call.map_or(0, |i| i + 1);
340+
self.frame.near_calls.get(index)
345341
}
346342

347343
fn near_call_on_top_mut(&mut self) -> Option<&mut NearCallFrame> {
348-
if self.frame.near_calls.is_empty() || self.near_call == Some(0) {
349-
None
350-
} else {
351-
let index = if let Some(i) = self.near_call {
352-
i - 1
353-
} else {
354-
self.frame.near_calls.len() - 1
355-
};
356-
Some(&mut self.frame.near_calls[index])
357-
}
344+
let index = self.near_call.map_or(0, |i| i + 1);
345+
self.frame.near_calls.get_mut(index)
358346
}
359347
}
360348

@@ -391,26 +379,32 @@ mod test {
391379
},
392380
);
393381

382+
vm.state.current_frame.gas = 0;
383+
vm.state.current_frame.exception_handler = 0;
394384
let mut frame_count = 1;
395385

396386
let add_far_frame = |vm: &mut VirtualMachine<(), TestWorld<()>>, counter: &mut u16| {
397387
vm.push_frame::<opcodes::Normal>(
398388
H160::from_low_u64_be(1),
399389
program.clone(),
400-
0,
390+
(*counter).into(),
401391
0,
402392
*counter,
403393
false,
404394
HeapId::from_u32_unchecked(5),
405395
vm.world_diff.snapshot(),
406396
);
397+
assert_eq!(vm.current_frame().gas(), (*counter).into());
407398
*counter += 1;
408399
};
409400

410401
let add_near_frame = |vm: &mut VirtualMachine<(), TestWorld<()>>, counter: &mut u16| {
402+
let count_u32 = (*counter).into();
403+
vm.state.current_frame.gas += count_u32;
411404
vm.state
412405
.current_frame
413-
.push_near_call(0, *counter, vm.world_diff.snapshot());
406+
.push_near_call(count_u32, *counter, vm.world_diff.snapshot());
407+
assert_eq!(vm.current_frame().gas(), (*counter).into());
414408
*counter += 1;
415409
};
416410

@@ -421,11 +415,9 @@ mod test {
421415
add_near_frame(&mut vm, &mut frame_count);
422416
add_near_frame(&mut vm, &mut frame_count);
423417

424-
for i in 0..frame_count {
425-
assert_eq!(
426-
vm.callframe(i as usize).exception_handler(),
427-
frame_count - i - 1
428-
);
418+
for (fwd, rev) in (0..frame_count.into()).zip((0..frame_count).rev()) {
419+
assert_eq!(vm.callframe(fwd).exception_handler(), rev);
420+
assert_eq!(vm.callframe(fwd).gas(), rev.into());
429421
}
430422
}
431423
}

0 commit comments

Comments
 (0)