1use move_binary_format::{
5 errors::{Location, VMError},
6 file_format::FunctionDefinitionIndex,
7};
8use move_core_types::vm_status::{StatusCode, StatusType};
9use move_vm_runtime::move_vm::MoveVM;
10use move_vm_types::data_store::MoveResolver;
11use sui_types::error::{ExecutionError, SuiError};
12use sui_types::execution_status::{ExecutionErrorKind, MoveLocation, MoveLocationOpt};
13
14pub(crate) fn convert_vm_error<S: MoveResolver<Err = SuiError>>(
15 error: VMError,
16 vm: &MoveVM,
17 state_view: &S,
18) -> ExecutionError {
19 let kind = match (error.major_status(), error.sub_status(), error.location()) {
20 (StatusCode::EXECUTED, _, _) => {
21 debug_assert!(false, "VmError shouldn't ever report successful execution");
23 ExecutionErrorKind::VMInvariantViolation
24 }
25 (StatusCode::ABORTED, None, _) => {
26 debug_assert!(false, "No abort code");
27 ExecutionErrorKind::VMInvariantViolation
29 }
30 (StatusCode::ABORTED, Some(code), Location::Module(id)) => {
31 let offset = error.offsets().first().copied().map(|(f, i)| (f.0, i));
32 debug_assert!(offset.is_some(), "Move should set the location on aborts");
33 let (function, instruction) = offset.unwrap_or((0, 0));
34 let function_name = vm.load_module(id, state_view).ok().map(|module| {
35 let fdef = module.function_def_at(FunctionDefinitionIndex(function));
36 let fhandle = module.function_handle_at(fdef.function);
37 module.identifier_at(fhandle.name).to_string()
38 });
39 ExecutionErrorKind::MoveAbort(
40 MoveLocation {
41 module: id.clone(),
42 function,
43 instruction,
44 function_name,
45 },
46 code,
47 )
48 }
49 (StatusCode::OUT_OF_GAS, _, _) => ExecutionErrorKind::InsufficientGas,
50 (_, _, location) => match error.major_status().status_type() {
51 StatusType::Execution => {
52 debug_assert!(error.major_status() != StatusCode::ABORTED);
53 let location = match location {
54 Location::Module(id) => {
55 let offset = error.offsets().first().copied().map(|(f, i)| (f.0, i));
56 debug_assert!(
57 offset.is_some(),
58 "Move should set the location on all execution errors. Error {error}"
59 );
60 let (function, instruction) = offset.unwrap_or((0, 0));
61 let function_name = vm.load_module(id, state_view).ok().map(|module| {
62 let fdef = module.function_def_at(FunctionDefinitionIndex(function));
63 let fhandle = module.function_handle_at(fdef.function);
64 module.identifier_at(fhandle.name).to_string()
65 });
66 Some(MoveLocation {
67 module: id.clone(),
68 function,
69 instruction,
70 function_name,
71 })
72 }
73 _ => None,
74 };
75 ExecutionErrorKind::MovePrimitiveRuntimeError(MoveLocationOpt(location))
76 }
77 StatusType::Validation
78 | StatusType::Verification
79 | StatusType::Deserialization
80 | StatusType::Unknown => ExecutionErrorKind::VMVerificationOrDeserializationError,
81 StatusType::InvariantViolation => ExecutionErrorKind::VMInvariantViolation,
82 },
83 };
84 ExecutionError::new_with_source(kind, error)
85}