sui_adapter_v0/
error.rs

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