sui_adapter_v2/
adapter.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4pub use checked::*;
5#[sui_macros::with_checked_arithmetic]
6mod checked {
7    use std::{collections::BTreeMap, sync::Arc};
8
9    use anyhow::Result;
10    use move_binary_format::file_format::CompiledModule;
11    use move_bytecode_verifier::verify_module_with_config_metered;
12    use move_bytecode_verifier_meter::Meter;
13    use move_core_types::account_address::AccountAddress;
14    use move_vm_config::{
15        runtime::{VMConfig, VMRuntimeLimitsConfig},
16        verifier::VerifierConfig,
17    };
18    use move_vm_runtime::{
19        move_vm::MoveVM, native_extensions::NativeContextExtensions,
20        native_functions::NativeFunctionTable,
21    };
22    use sui_move_natives::object_runtime;
23    use sui_types::{error::SuiErrorKind, metrics::BytecodeVerifierMetrics};
24    use sui_verifier::check_for_verifier_timeout;
25    use tracing::instrument;
26
27    use sui_move_natives::{object_runtime::ObjectRuntime, NativesCostTable};
28    use sui_protocol_config::ProtocolConfig;
29    use sui_types::{
30        base_types::*,
31        error::{ExecutionError, SuiError},
32        execution_status::ExecutionErrorKind,
33        metrics::LimitsMetrics,
34        storage::ChildObjectResolver,
35    };
36    use sui_verifier::verifier::sui_verify_module_metered_check_timeout_only;
37
38    pub fn new_move_vm(
39        natives: NativeFunctionTable,
40        protocol_config: &ProtocolConfig,
41    ) -> Result<MoveVM, SuiError> {
42        MoveVM::new_with_config(
43            natives,
44            VMConfig {
45                verifier: protocol_config.verifier_config(/* signing_limits */ None),
46                max_binary_format_version: protocol_config.move_binary_format_version(),
47                runtime_limits_config: VMRuntimeLimitsConfig {
48                    vector_len_max: protocol_config.max_move_vector_len(),
49                    max_value_nest_depth: protocol_config.max_move_value_depth_as_option(),
50                    hardened_otw_check: protocol_config.hardened_otw_check(),
51                },
52                enable_invariant_violation_check_in_swap_loc: !protocol_config
53                    .disable_invariant_violation_check_in_swap_loc(),
54                check_no_extraneous_bytes_during_deserialization: protocol_config
55                    .no_extraneous_module_bytes(),
56                // Don't augment errors with execution state on-chain
57                error_execution_state: false,
58                binary_config: protocol_config.binary_config(None),
59                rethrow_serialization_type_layout_errors: protocol_config
60                    .rethrow_serialization_type_layout_errors(),
61                max_type_to_layout_nodes: protocol_config.max_type_to_layout_nodes_as_option(),
62                variant_nodes: protocol_config.variant_nodes(),
63                deprecate_global_storage_ops_during_deserialization: protocol_config
64                    .deprecate_global_storage_ops_during_deserialization(),
65                normalize_depth_formula: protocol_config.normalize_depth_formula(),
66            },
67        )
68        .map_err(|_| SuiErrorKind::ExecutionInvariantViolation.into())
69    }
70
71    pub fn new_native_extensions<'r>(
72        child_resolver: &'r dyn ChildObjectResolver,
73        input_objects: BTreeMap<ObjectID, object_runtime::InputObject>,
74        is_metered: bool,
75        protocol_config: &'r ProtocolConfig,
76        metrics: Arc<LimitsMetrics>,
77        current_epoch_id: EpochId,
78    ) -> NativeContextExtensions<'r> {
79        let mut extensions = NativeContextExtensions::default();
80        extensions.add(ObjectRuntime::new(
81            child_resolver,
82            input_objects,
83            is_metered,
84            protocol_config,
85            metrics,
86            current_epoch_id,
87        ));
88        extensions.add(NativesCostTable::from_protocol_config(protocol_config));
89        extensions
90    }
91
92    /// Given a list of `modules` and an `object_id`, mutate each module's self ID (which must be
93    /// 0x0) to be `object_id`.
94    pub fn substitute_package_id(
95        modules: &mut [CompiledModule],
96        object_id: ObjectID,
97    ) -> Result<(), ExecutionError> {
98        let new_address = AccountAddress::from(object_id);
99
100        for module in modules.iter_mut() {
101            let self_handle = module.self_handle().clone();
102            let self_address_idx = self_handle.address;
103
104            let addrs = &mut module.address_identifiers;
105            let Some(address_mut) = addrs.get_mut(self_address_idx.0 as usize) else {
106                let name = module.identifier_at(self_handle.name);
107                return Err(ExecutionError::new_with_source(
108                    ExecutionErrorKind::PublishErrorNonZeroAddress,
109                    format!("Publishing module {name} with invalid address index"),
110                ));
111            };
112
113            if *address_mut != AccountAddress::ZERO {
114                let name = module.identifier_at(self_handle.name);
115                return Err(ExecutionError::new_with_source(
116                    ExecutionErrorKind::PublishErrorNonZeroAddress,
117                    format!("Publishing module {name} with non-zero address is not allowed"),
118                ));
119            };
120
121            *address_mut = new_address;
122        }
123
124        Ok(())
125    }
126
127    pub fn missing_unwrapped_msg(id: &ObjectID) -> String {
128        format!(
129        "Unable to unwrap object {}. Was unable to retrieve last known version in the parent sync",
130        id
131    )
132    }
133
134    /// Run the bytecode verifier with a meter limit
135    ///
136    /// This function only fails if the verification does not complete within the limit.  If the
137    /// modules fail to verify but verification completes within the meter limit, the function
138    /// succeeds.
139    #[instrument(level = "trace", skip_all)]
140    pub fn run_metered_move_bytecode_verifier(
141        modules: &[CompiledModule],
142        verifier_config: &VerifierConfig,
143        meter: &mut (impl Meter + ?Sized),
144        metrics: &Arc<BytecodeVerifierMetrics>,
145    ) -> Result<(), SuiError> {
146        // run the Move verifier
147        for module in modules.iter() {
148            let per_module_meter_verifier_timer = metrics
149                .verifier_runtime_per_module_success_latency
150                .start_timer();
151
152            if let Err(e) = verify_module_with_config_metered(verifier_config, module, meter) {
153                // Check that the status indicates mtering timeout
154                if check_for_verifier_timeout(&e.major_status()) {
155                    // Discard success timer, but record timeout/failure timer
156                    metrics
157                        .verifier_runtime_per_module_timeout_latency
158                        .observe(per_module_meter_verifier_timer.stop_and_discard());
159                    metrics
160                        .verifier_timeout_metrics
161                        .with_label_values(&[
162                            BytecodeVerifierMetrics::MOVE_VERIFIER_TAG,
163                            BytecodeVerifierMetrics::TIMEOUT_TAG,
164                        ])
165                        .inc();
166                    return Err(SuiErrorKind::ModuleVerificationFailure {
167                        error: format!("Verification timedout: {}", e),
168                    }
169                    .into());
170                };
171            } else if let Err(err) = sui_verify_module_metered_check_timeout_only(
172                module,
173                &BTreeMap::new(),
174                meter,
175                verifier_config,
176            ) {
177                // We only checked that the failure was due to timeout
178                // Discard success timer, but record timeout/failure timer
179                metrics
180                    .verifier_runtime_per_module_timeout_latency
181                    .observe(per_module_meter_verifier_timer.stop_and_discard());
182                metrics
183                    .verifier_timeout_metrics
184                    .with_label_values(&[
185                        BytecodeVerifierMetrics::SUI_VERIFIER_TAG,
186                        BytecodeVerifierMetrics::TIMEOUT_TAG,
187                    ])
188                    .inc();
189                return Err(err.into());
190            }
191            // Save the success timer
192            per_module_meter_verifier_timer.stop_and_record();
193            metrics
194                .verifier_timeout_metrics
195                .with_label_values(&[
196                    BytecodeVerifierMetrics::OVERALL_TAG,
197                    BytecodeVerifierMetrics::SUCCESS_TAG,
198                ])
199                .inc();
200        }
201        Ok(())
202    }
203}