1use crate::{
9 data_store::{VerifiedPackageStore, cached_package_store::CachedPackageStore},
10 execution_mode::ExecutionMode,
11 execution_value::ExecutionState,
12 static_programmable_transactions::{
13 execution::context::subst_signature,
14 linkage::{analysis::LinkageAnalyzer, resolved_linkage::ExecutableLinkage},
15 loading::ast::{
16 self as L, Datatype, DeserializedPackage, LoadedFunction, LoadedFunctionInstantiation,
17 Type,
18 },
19 },
20};
21use move_binary_format::{
22 CompiledModule,
23 errors::{Location, VMError, VMResult},
24 file_format::{Ability, AbilitySet, TypeParameterIndex},
25};
26use move_core_types::{
27 annotated_value,
28 identifier::IdentStr,
29 language_storage::{ModuleId, StructTag},
30 resolver::IntraPackageName,
31 runtime_value::{self, MoveTypeLayout},
32 vm_status::StatusCode,
33};
34use move_vm_runtime::{
35 execution::{self as vm_runtime, vm::MoveVM},
36 runtime::MoveRuntime,
37};
38use std::{cell::OnceCell, marker::PhantomData, rc::Rc};
39use sui_protocol_config::ProtocolConfig;
40use sui_types::{
41 Identifier, SUI_FRAMEWORK_PACKAGE_ID, TypeTag,
42 allowance::RESOLVED_ALLOWANCE_WITHDRAWAL_STRUCT,
43 balance::RESOLVED_BALANCE_STRUCT,
44 base_types::{ObjectID, TxContext},
45 coin::RESOLVED_COIN_STRUCT,
46 error::ExecutionErrorTrait,
47 execution_status::{ExecutionErrorKind, TypeArgumentError},
48 funds_accumulator::RESOLVED_WITHDRAWAL_STRUCT,
49 gas_coin::GasCoin,
50 move_package::{MovePackage, UpgradeCap, UpgradeReceipt, UpgradeTicket},
51 object::Object,
52 type_input::{StructInput, TypeInput},
53};
54
55pub struct Env<'pc, 'vm, 'state, 'linkage, 'extensions, Mode>
56where
57 Mode: ExecutionMode,
58{
59 pub protocol_config: &'pc ProtocolConfig,
60 pub vm: &'vm MoveRuntime,
61 pub state_view: &'state mut dyn ExecutionState,
62 pub linkable_store: &'linkage CachedPackageStore<'state, 'vm>,
63 pub linkage_analysis: &'linkage LinkageAnalyzer,
64 gas_coin_type: OnceCell<Type>,
65 upgrade_ticket_type: OnceCell<Type>,
66 upgrade_receipt_type: OnceCell<Type>,
67 upgrade_cap_type: OnceCell<Type>,
68 tx_context_type: OnceCell<Type>,
69 input_type_resolution_vm: &'linkage MoveVM<'extensions>,
73 _mode: PhantomData<fn() -> Mode>,
74}
75
76macro_rules! get_or_init_ty {
77 ($env:expr, $ident:ident, $tag:expr) => {{
78 let env = $env;
79 if env.$ident.get().is_none() {
80 let tag = $tag;
81 let ty = env.load_type_from_struct(&tag)?;
82 env.$ident.set(ty.clone()).unwrap();
83 }
84 Ok(env.$ident.get().unwrap().clone())
85 }};
86}
87
88impl<'pc, 'vm, 'state, 'linkage, 'extensions, Mode>
89 Env<'pc, 'vm, 'state, 'linkage, 'extensions, Mode>
90where
91 Mode: ExecutionMode,
92{
93 pub fn new(
94 protocol_config: &'pc ProtocolConfig,
95 vm: &'vm MoveRuntime,
96 state_view: &'state mut dyn ExecutionState,
97 linkable_store: &'linkage CachedPackageStore<'state, 'vm>,
98 linkage_analysis: &'linkage LinkageAnalyzer,
99 input_type_resolution_vm: &'linkage MoveVM<'extensions>,
100 ) -> Self {
101 Self {
102 protocol_config,
103 vm,
104 state_view,
105 linkable_store,
106 linkage_analysis,
107 gas_coin_type: OnceCell::new(),
108 upgrade_ticket_type: OnceCell::new(),
109 upgrade_receipt_type: OnceCell::new(),
110 upgrade_cap_type: OnceCell::new(),
111 tx_context_type: OnceCell::new(),
112 input_type_resolution_vm,
113 _mode: PhantomData,
114 }
115 }
116
117 pub fn convert_linked_vm_error(&self, e: VMError, linkage: &ExecutableLinkage) -> Mode::Error {
118 convert_vm_error(e, self.linkable_store, Some(linkage), self.protocol_config)
119 }
120
121 pub fn convert_vm_error(&self, e: VMError) -> Mode::Error {
122 convert_vm_error(e, self.linkable_store, None, self.protocol_config)
123 }
124
125 pub fn convert_type_argument_error(
126 &self,
127 idx: usize,
128 e: VMError,
129 linkage: &ExecutableLinkage,
130 ) -> Mode::Error {
131 use move_core_types::vm_status::StatusCode;
132 let argument_idx = match checked_as!(idx, TypeParameterIndex) {
133 Err(e) => return e.into(),
134 Ok(v) => v,
135 };
136 match e.major_status() {
137 StatusCode::NUMBER_OF_TYPE_ARGUMENTS_MISMATCH => {
138 Mode::Error::from_kind(ExecutionErrorKind::TypeArityMismatch)
139 }
140 StatusCode::EXTERNAL_RESOLUTION_REQUEST_ERROR => {
141 Mode::Error::from_kind(ExecutionErrorKind::TypeArgumentError {
142 argument_idx,
143 kind: TypeArgumentError::TypeNotFound,
144 })
145 }
146 StatusCode::CONSTRAINT_NOT_SATISFIED => {
147 Mode::Error::from_kind(ExecutionErrorKind::TypeArgumentError {
148 argument_idx,
149 kind: TypeArgumentError::ConstraintNotSatisfied,
150 })
151 }
152 _ => self.convert_linked_vm_error(e, linkage),
153 }
154 }
155
156 pub fn fully_annotated_layout(
157 &self,
158 ty: &Type,
159 ) -> Result<annotated_value::MoveTypeLayout, Mode::Error> {
160 let tag: TypeTag = ty.clone().try_into().map_err(|s| {
161 Mode::Error::new_with_source(ExecutionErrorKind::VMInvariantViolation, s)
162 })?;
163 let objects = tag.all_addresses();
164 let tag_linkage = ExecutableLinkage::type_linkage::<_, Mode::Error>(
165 self.linkage_analysis.config().clone(),
166 objects.into_iter().map(ObjectID::from),
167 self.linkable_store,
168 )?;
169 self.input_type_resolution_vm
170 .annotated_type_layout(&tag)
171 .map_err(|e| self.convert_linked_vm_error(e, &tag_linkage))
172 }
173
174 pub fn runtime_layout(&self, ty: &Type) -> Result<runtime_value::MoveTypeLayout, Mode::Error> {
175 let tag: TypeTag = ty.clone().try_into().map_err(|s| {
176 Mode::Error::new_with_source(ExecutionErrorKind::VMInvariantViolation, s)
177 })?;
178 let objects = tag.all_addresses();
179 let tag_linkage = ExecutableLinkage::type_linkage::<_, Mode::Error>(
180 self.linkage_analysis.config().clone(),
181 objects.into_iter().map(ObjectID::from),
182 self.linkable_store,
183 )?;
184 self.input_type_resolution_vm
185 .runtime_type_layout(&tag)
186 .map_err(|e| self.convert_linked_vm_error(e, &tag_linkage))
187 }
188
189 pub fn load_framework_function(
190 &self,
191 module: &IdentStr,
192 function: &IdentStr,
193 type_arguments: Vec<Type>,
194 unified_linkage: Option<&ExecutableLinkage>,
195 ) -> Result<LoadedFunction, Mode::Error> {
196 let mut loaded = self.load_function(
197 SUI_FRAMEWORK_PACKAGE_ID,
198 module.to_string(),
199 function.to_string(),
200 type_arguments,
201 )?;
202 if self.protocol_config.harden_linkage_consistency() {
203 let Some(unified_linkage) = unified_linkage else {
204 invariant_violation!(
205 "Unified linkage is required when hardened linkage consistency is enabled"
206 )
207 };
208 assert_invariant!(
209 loaded
210 .linkage
211 .0
212 .linkage
213 .keys()
214 .all(|original_id| unified_linkage.0.linkage.contains_key(original_id)),
215 "transaction linkage drops a package resolved by a framework MoveCall"
216 );
217 loaded.linkage = unified_linkage.clone();
218 }
219 Ok(loaded)
220 }
221
222 pub fn load_function(
223 &self,
224 package: ObjectID,
225 module: String,
226 function: String,
227 type_arguments: Vec<Type>,
228 ) -> Result<LoadedFunction, Mode::Error> {
229 let module = to_identifier(module)?;
230 let name = to_identifier(function)?;
231
232 let linkage = self.linkage_analysis.compute_call_linkage::<Mode::Error>(
233 &package,
234 module.as_ident_str(),
235 name.as_ident_str(),
236 &type_arguments,
237 self.linkable_store,
238 )?;
239
240 let Some(original_id) = linkage.0.resolve_to_original_id(&package) else {
241 invariant_violation!(
242 "Package ID {:?} is not found in linkage generated for that package",
243 package
244 );
245 };
246 let version_mid = ModuleId::new(package.into(), module.clone());
247 let original_mid = ModuleId::new(original_id.into(), module);
248 let loaded_type_arguments = type_arguments
249 .iter()
250 .enumerate()
251 .map(|(idx, ty)| self.load_vm_type_argument_from_adapter_type(idx, ty))
252 .collect::<Result<Vec<_>, _>>()?;
253 let vm = self
257 .vm
258 .make_vm(
259 &self.linkable_store.package_store,
260 linkage.linkage_context::<Mode::Error>()?,
261 )
262 .map_err(|e| self.convert_linked_vm_error(e, &linkage))?;
263 let runtime_signature = vm
264 .function_information(&original_mid, name.as_ident_str(), &loaded_type_arguments)
265 .map_err(|e| {
266 if e.major_status() == StatusCode::EXTERNAL_RESOLUTION_REQUEST_ERROR {
267 Mode::Error::new_with_source(
268 ExecutionErrorKind::FunctionNotFound,
269 format!(
270 "Could not resolve function '{}' in module '{}'",
271 name, &version_mid,
272 ),
273 )
274 } else {
275 self.convert_linked_vm_error(e, &linkage)
276 }
277 })?;
278 let runtime_signature = subst_signature(runtime_signature, &loaded_type_arguments)
279 .map_err(|e| self.convert_linked_vm_error(e, &linkage))?;
280 let parameters = runtime_signature
281 .parameters
282 .into_iter()
283 .map(|ty| self.adapter_type_from_vm_type(&vm, &ty))
284 .collect::<Result<Vec<_>, _>>()?;
285 let return_ = runtime_signature
286 .return_
287 .into_iter()
288 .map(|ty| self.adapter_type_from_vm_type(&vm, &ty))
289 .collect::<Result<Vec<_>, _>>()?;
290 let signature = LoadedFunctionInstantiation {
291 parameters,
292 return_,
293 };
294 Ok(LoadedFunction {
295 version_mid,
296 original_mid,
297 name,
298 type_arguments,
299 signature,
300 linkage,
301 instruction_length: runtime_signature.instruction_count,
302 definition_index: runtime_signature.index,
303 visibility: runtime_signature.visibility,
304 is_entry: runtime_signature.is_entry,
305 is_native: runtime_signature.is_native,
306 })
307 }
308
309 pub fn load_type_input(&self, idx: usize, ty: TypeInput) -> Result<Type, Mode::Error> {
310 let vm_type = self.load_vm_type_from_type_input(idx, ty)?;
311 self.adapter_type_from_vm_type(self.input_type_resolution_vm, &vm_type)
312 }
313
314 pub fn load_type_tag(&self, idx: usize, ty: &TypeTag) -> Result<Type, Mode::Error> {
315 let vm_type = self.load_vm_type_from_type_tag(Some(idx), ty)?;
316 self.adapter_type_from_vm_type(self.input_type_resolution_vm, &vm_type)
317 }
318
319 pub fn load_type_from_struct(&self, tag: &StructTag) -> Result<Type, Mode::Error> {
321 let vm_type =
322 self.load_vm_type_from_type_tag(None, &TypeTag::Struct(Box::new(tag.clone())))?;
323 self.adapter_type_from_vm_type(self.input_type_resolution_vm, &vm_type)
324 }
325
326 pub fn type_layout_for_struct(&self, tag: &StructTag) -> Result<MoveTypeLayout, Mode::Error> {
327 let ty: Type = self.load_type_from_struct(tag)?;
328 self.runtime_layout(&ty)
329 }
330
331 pub fn gas_coin_type(&self) -> Result<Type, Mode::Error> {
332 get_or_init_ty!(self, gas_coin_type, GasCoin::type_())
333 }
334
335 pub fn upgrade_ticket_type(&self) -> Result<Type, Mode::Error> {
336 get_or_init_ty!(self, upgrade_ticket_type, UpgradeTicket::type_())
337 }
338
339 pub fn upgrade_receipt_type(&self) -> Result<Type, Mode::Error> {
340 get_or_init_ty!(self, upgrade_receipt_type, UpgradeReceipt::type_())
341 }
342
343 pub fn upgrade_cap_type(&self) -> Result<Type, Mode::Error> {
344 get_or_init_ty!(self, upgrade_cap_type, UpgradeCap::type_())
345 }
346
347 pub fn tx_context_type(&self) -> Result<Type, Mode::Error> {
348 get_or_init_ty!(self, tx_context_type, TxContext::type_())
349 }
350
351 pub fn coin_type(&self, inner_type: Type) -> Result<Type, Mode::Error> {
352 const COIN_ABILITIES: AbilitySet =
353 AbilitySet::singleton(Ability::Key).union(AbilitySet::singleton(Ability::Store));
354 let (a, m, n) = RESOLVED_COIN_STRUCT;
355 let module = ModuleId::new(*a, m.to_owned());
356 Ok(Type::Datatype(Rc::new(Datatype {
357 abilities: COIN_ABILITIES,
358 module,
359 name: n.to_owned(),
360 type_arguments: vec![inner_type],
361 })))
362 }
363
364 pub fn balance_type(&self, inner_type: Type) -> Result<Type, Mode::Error> {
365 const BALANCE_ABILITIES: AbilitySet = AbilitySet::singleton(Ability::Store);
366 let (a, m, n) = RESOLVED_BALANCE_STRUCT;
367 let module = ModuleId::new(*a, m.to_owned());
368 Ok(Type::Datatype(Rc::new(Datatype {
369 abilities: BALANCE_ABILITIES,
370 module,
371 name: n.to_owned(),
372 type_arguments: vec![inner_type],
373 })))
374 }
375
376 pub fn withdrawal_type(&self, inner_type: Type) -> Result<Type, Mode::Error> {
377 const WITHDRAWAL_ABILITIES: AbilitySet = AbilitySet::singleton(Ability::Drop);
378 let (a, m, n) = RESOLVED_WITHDRAWAL_STRUCT;
379 let module = ModuleId::new(*a, m.to_owned());
380 Ok(Type::Datatype(Rc::new(Datatype {
381 abilities: WITHDRAWAL_ABILITIES,
382 module,
383 name: n.to_owned(),
384 type_arguments: vec![inner_type],
385 })))
386 }
387
388 pub fn allowance_withdrawal_type(&self, inner_type: Type) -> Result<Type, Mode::Error> {
389 const ALLOWANCE_WITHDRAWAL_ABILITIES: AbilitySet = AbilitySet::singleton(Ability::Drop);
390 let (a, m, n) = RESOLVED_ALLOWANCE_WITHDRAWAL_STRUCT;
391 let module = ModuleId::new(*a, m.to_owned());
392 Ok(Type::Datatype(Rc::new(Datatype {
393 abilities: ALLOWANCE_WITHDRAWAL_ABILITIES,
394 module,
395 name: n.to_owned(),
396 type_arguments: vec![inner_type],
397 })))
398 }
399
400 pub fn withdrawal_type_for_source(
402 &self,
403 source: &L::WithdrawalSource,
404 funds_type: Type,
405 ) -> Result<Type, Mode::Error> {
406 match source {
407 L::WithdrawalSource::Direct { .. } => self.withdrawal_type(funds_type),
408 L::WithdrawalSource::Allowance { .. } => self.allowance_withdrawal_type(funds_type),
409 }
410 }
411
412 pub fn vector_type(&self, element_type: Type) -> Result<Type, Mode::Error> {
413 let abilities = AbilitySet::polymorphic_abilities(
414 AbilitySet::VECTOR,
415 [false],
416 [element_type.abilities()],
417 )
418 .map_err(|e| {
419 Mode::Error::new_with_source(ExecutionErrorKind::VMInvariantViolation, e.to_string())
420 })?;
421 Ok(Type::Vector(Rc::new(L::Vector {
422 abilities,
423 element_type,
424 })))
425 }
426
427 pub fn read_object(&self, id: &ObjectID) -> Result<&Object, Mode::Error> {
428 let Some(obj) = self.state_view.read_object(id) else {
429 invariant_violation!("Object {:?} does not exist", id);
431 };
432 Ok(obj)
433 }
434
435 pub fn load_vm_type_argument_from_adapter_type(
437 &self,
438 idx: usize,
439 ty: &Type,
440 ) -> Result<vm_runtime::Type, Mode::Error> {
441 self.load_vm_type_from_adapter_type(Some(idx), ty)
442 }
443
444 fn load_vm_type_from_adapter_type(
445 &self,
446 type_arg_idx: Option<usize>,
447 ty: &Type,
448 ) -> Result<vm_runtime::Type, Mode::Error> {
449 let tag: TypeTag = ty.clone().try_into().map_err(|s| {
450 Mode::Error::new_with_source(ExecutionErrorKind::VMInvariantViolation, s)
451 })?;
452 self.load_vm_type_from_type_tag(type_arg_idx, &tag)
453 }
454
455 fn load_vm_type_from_type_tag(
457 &self,
458 type_arg_idx: Option<usize>,
459 tag: &TypeTag,
460 ) -> Result<vm_runtime::Type, Mode::Error> {
461 fn execution_error<Mode: ExecutionMode>(
462 env: &Env<Mode>,
463 type_arg_idx: Option<usize>,
464 e: VMError,
465 linkage: &ExecutableLinkage,
466 ) -> Mode::Error {
467 if let Some(idx) = type_arg_idx {
468 env.convert_type_argument_error(idx, e, linkage)
469 } else {
470 env.convert_linked_vm_error(e, linkage)
471 }
472 }
473
474 let objects = tag.all_addresses();
475
476 let tag_linkage = ExecutableLinkage::type_linkage::<_, Mode::Error>(
477 self.linkage_analysis.config().clone(),
478 objects.iter().map(|a| ObjectID::from(*a)),
479 self.linkable_store,
480 )?;
481 let ty = self
482 .input_type_resolution_vm
483 .load_type(tag)
484 .map_err(|e| execution_error(self, type_arg_idx, e, &tag_linkage))?;
485 Ok(ty)
486 }
487
488 pub(crate) fn adapter_type_from_vm_type(
490 &self,
491 vm: &MoveVM,
492 vm_type: &vm_runtime::Type,
493 ) -> Result<Type, Mode::Error> {
494 use vm_runtime as VRT;
495
496 Ok(match vm_type {
497 VRT::Type::Bool => Type::Bool,
498 VRT::Type::U8 => Type::U8,
499 VRT::Type::U16 => Type::U16,
500 VRT::Type::U32 => Type::U32,
501 VRT::Type::U64 => Type::U64,
502 VRT::Type::U128 => Type::U128,
503 VRT::Type::U256 => Type::U256,
504 VRT::Type::Address => Type::Address,
505 VRT::Type::Signer => Type::Signer,
506
507 VRT::Type::Reference(ref_ty) => {
508 let inner_ty = self.adapter_type_from_vm_type(vm, ref_ty)?;
509 Type::Reference(false, Rc::new(inner_ty))
510 }
511 VRT::Type::MutableReference(ref_ty) => {
512 let inner_ty = self.adapter_type_from_vm_type(vm, ref_ty)?;
513 Type::Reference(true, Rc::new(inner_ty))
514 }
515
516 VRT::Type::Vector(inner) => {
517 let element_type = self.adapter_type_from_vm_type(vm, inner)?;
518 self.vector_type(element_type)?
519 }
520 VRT::Type::Datatype(_) => {
521 let type_information = vm
522 .type_information(vm_type)
523 .map_err(|e| self.convert_vm_error(e))?;
524 let Some(data_type_info) = type_information.datatype_info else {
525 invariant_violation!("Expected datatype info for datatype type {:?}", vm_type);
526 };
527 let datatype = Datatype {
528 abilities: type_information.abilities,
529 module: ModuleId::new(data_type_info.defining_id, data_type_info.module_name),
530 name: data_type_info.type_name,
531 type_arguments: vec![],
532 };
533 Type::Datatype(Rc::new(datatype))
534 }
535 ty @ VRT::Type::DatatypeInstantiation(inst) => {
536 let (_, type_arguments) = &**inst;
537 let type_information = vm
538 .type_information(ty)
539 .map_err(|e| self.convert_vm_error(e))?;
540 let Some(data_type_info) = type_information.datatype_info else {
541 invariant_violation!("Expected datatype info for datatype type {:?}", vm_type);
542 };
543
544 let abilities = type_information.abilities;
545 let module = ModuleId::new(data_type_info.defining_id, data_type_info.module_name);
546 let name = data_type_info.type_name;
547 let type_arguments = type_arguments
548 .iter()
549 .map(|t| self.adapter_type_from_vm_type(vm, t))
550 .collect::<Result<Vec<_>, _>>()?;
551
552 Type::Datatype(Rc::new(Datatype {
553 abilities,
554 module,
555 name,
556 type_arguments,
557 }))
558 }
559
560 VRT::Type::TyParam(_) => {
561 invariant_violation!(
562 "Unexpected type parameter in VM type: {:?}. This should not happen as we should \
563 have resolved all type parameters before this point.",
564 vm_type
565 );
566 }
567 })
568 }
569
570 fn load_vm_type_from_type_input(
574 &self,
575 type_arg_idx: usize,
576 ty: TypeInput,
577 ) -> Result<vm_runtime::Type, Mode::Error> {
578 fn to_type_tag_internal<Mode: ExecutionMode>(
579 env: &Env<Mode>,
580 type_arg_idx: usize,
581 ty: TypeInput,
582 ) -> Result<TypeTag, Mode::Error> {
583 Ok(match ty {
584 TypeInput::Bool => TypeTag::Bool,
585 TypeInput::U8 => TypeTag::U8,
586 TypeInput::U16 => TypeTag::U16,
587 TypeInput::U32 => TypeTag::U32,
588 TypeInput::U64 => TypeTag::U64,
589 TypeInput::U128 => TypeTag::U128,
590 TypeInput::U256 => TypeTag::U256,
591 TypeInput::Address => TypeTag::Address,
592 TypeInput::Signer => TypeTag::Signer,
593 TypeInput::Vector(type_input) => {
594 let inner = to_type_tag_internal(env, type_arg_idx, *type_input)?;
595 TypeTag::Vector(Box::new(inner))
596 }
597 TypeInput::Struct(struct_input) => {
598 let StructInput {
599 address,
600 module,
601 name,
602 type_params,
603 } = *struct_input;
604
605 let pkg = env
606 .linkable_store
607 .get_package(&address.into())
608 .ok()
609 .flatten()
610 .ok_or_else(|| {
611 let argument_idx = match checked_as!(type_arg_idx, u16) {
612 Err(e) => return e.into(),
613 Ok(v) => v,
614 };
615 Mode::Error::from_kind(ExecutionErrorKind::TypeArgumentError {
616 argument_idx,
617 kind: TypeArgumentError::TypeNotFound,
618 })
619 })?;
620 let module = to_identifier(module)?;
621 let name = to_identifier(name)?;
622 let tid = IntraPackageName {
623 module_name: module,
624 type_name: name,
625 };
626 let Some(resolved_address) = pkg.type_origin_table().get(&tid).cloned() else {
627 return Err(Mode::Error::from_kind(
628 ExecutionErrorKind::TypeArgumentError {
629 argument_idx: checked_as!(type_arg_idx, u16)?,
630 kind: TypeArgumentError::TypeNotFound,
631 },
632 ));
633 };
634
635 let tys = type_params
636 .into_iter()
637 .map(|tp| to_type_tag_internal(env, type_arg_idx, tp))
638 .collect::<Result<Vec<_>, _>>()?;
639 TypeTag::Struct(Box::new(StructTag {
640 address: resolved_address,
641 module: tid.module_name,
642 name: tid.type_name,
643 type_params: tys,
644 }))
645 }
646 })
647 }
648 let tag = to_type_tag_internal(self, type_arg_idx, ty)?;
649 self.load_vm_type_from_type_tag(Some(type_arg_idx), &tag)
650 }
651
652 pub fn deserialize_package(
653 &self,
654 module_bytes: &[Vec<u8>],
655 dep_ids: &[ObjectID],
656 ) -> Result<DeserializedPackage, Mode::Error> {
657 assert_invariant!(
658 !module_bytes.is_empty(),
659 "empty package is checked in transaction input checker"
660 );
661
662 let total_bytes = module_bytes.iter().map(|v| v.len()).sum();
663
664 let binary_config = self.protocol_config.binary_config(None);
665 let deserialized_modules = module_bytes
666 .iter()
667 .map(|b| {
668 CompiledModule::deserialize_with_config(b, &binary_config)
669 .map_err(|e| e.finish(Location::Undefined))
670 })
671 .collect::<VMResult<Vec<CompiledModule>>>()
672 .map_err(|e| self.convert_vm_error(e))?;
673 let computed_digest = MovePackage::compute_digest_for_modules_and_deps(
674 module_bytes,
675 dep_ids,
676 true,
677 );
678 Ok(DeserializedPackage::new(
679 deserialized_modules,
680 total_bytes,
681 computed_digest,
682 ))
683 }
684}
685
686fn to_identifier<E: ExecutionErrorTrait>(name: String) -> Result<Identifier, E> {
687 Identifier::new(name)
688 .map_err(|e| E::new_with_source(ExecutionErrorKind::VMInvariantViolation, e.to_string()))
689}
690
691fn convert_vm_error<E: ExecutionErrorTrait>(
692 error: VMError,
693 store: &VerifiedPackageStore<'_>,
694 linkage: Option<&ExecutableLinkage>,
695 _protocol_config: &ProtocolConfig,
696) -> E {
697 use crate::error::convert_vm_error_impl;
698 convert_vm_error_impl(
699 error,
700 &|id| {
701 debug_assert!(
702 linkage.is_some(),
703 "Linkage should be set anywhere where runtime errors may occur in order to resolve abort locations to package IDs"
704 );
705 linkage
706 .and_then(|linkage| {
707 linkage
708 .0
709 .linkage
710 .get(&(*id.address()).into())
711 .map(|new_id| ModuleId::new((*new_id).into(), id.name().to_owned()))
712 })
713 .unwrap_or_else(|| id.clone())
714 },
715 &|id, function| {
717 debug_assert!(
718 linkage.is_some(),
719 "Linkage should be set anywhere where runtime errors may occur in order to resolve abort locations to package IDs"
720 );
721 linkage.and_then(|linkage| {
722 let version_id = linkage
723 .0
724 .linkage
725 .get(&(*id.address()).into())
726 .cloned()
727 .unwrap_or_else(|| ObjectID::from_address(*id.address()));
728 store.get_package(&version_id).ok().flatten().and_then(|p| {
729 p.modules().get(id).map(|module| {
730 let module = module.compiled_module();
731 let fdef = module.function_def_at(function);
732 let fhandle = module.function_handle_at(fdef.function);
733 module.identifier_at(fhandle.name).to_string()
734 })
735 })
736 })
737 },
738 )
739 .into()
740}