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