Skip to main content

sui_adapter_v0/
adapter.rs

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