sui_adapter_v2/
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::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            // If we have an error the status probably shouldn't ever be Executed
22            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            // this is a Move VM invariant violation, the code should always be there
28            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}