From 3af38855f698f344655535dc4c5120610af72e7c Mon Sep 17 00:00:00 2001 From: Timothy Zakian Date: Tue, 4 Feb 2025 16:38:48 -0800 Subject: [PATCH] [10/n][vm-rewrite][adapter] Update type inputs so they are always converted to runtime IDs before entering the VM --- .../sui-adapter/src/linkage_resolution.rs | 72 ++++++++++++++++++- .../src/programmable_transactions/context.rs | 13 ++++ .../programmable_transactions/execution.rs | 32 +++++---- 3 files changed, 101 insertions(+), 16 deletions(-) diff --git a/sui-execution/latest/sui-adapter/src/linkage_resolution.rs b/sui-execution/latest/sui-adapter/src/linkage_resolution.rs index 4ec0286260bf7..41705cdfea9c4 100644 --- a/sui-execution/latest/sui-adapter/src/linkage_resolution.rs +++ b/sui-execution/latest/sui-adapter/src/linkage_resolution.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use move_binary_format::{binary_config::BinaryConfig, file_format::Visibility}; +use move_core_types::language_storage::StructTag; use move_vm_runtime::shared::linkage_context::LinkageContext; use std::collections::BTreeMap; use sui_protocol_config::ProtocolConfig; @@ -12,8 +13,8 @@ use sui_types::{ move_package::MovePackage, transaction::Command, type_input::TypeInput, - BRIDGE_PACKAGE_ID, DEEPBOOK_PACKAGE_ID, MOVE_STDLIB_PACKAGE_ID, SUI_FRAMEWORK_PACKAGE_ID, - SUI_SYSTEM_PACKAGE_ID, + TypeTag, BRIDGE_PACKAGE_ID, DEEPBOOK_PACKAGE_ID, MOVE_STDLIB_PACKAGE_ID, + SUI_FRAMEWORK_PACKAGE_ID, SUI_SYSTEM_PACKAGE_ID, }; use crate::programmable_transactions::datastore::PackageStore; @@ -115,6 +116,14 @@ pub trait LinkageAnalysis { linkage: &LinkageContext, store: &dyn PackageStore, ) -> Result; + + // Translate a type tag to a runtime type tag (where all addresses are the runtime ID of the + // package). + fn runtime_type_tag( + &mut self, + type_tag: &TypeTag, + store: &dyn PackageStore, + ) -> Result; } type ResolutionTable = BTreeMap; @@ -149,6 +158,14 @@ impl LinkageAnalysis for PerCommandLinkage { ) -> Result { self.internal.publication_linkage(linkage, store) } + + fn runtime_type_tag( + &mut self, + type_tag: &TypeTag, + store: &dyn PackageStore, + ) -> Result { + self.internal.runtime_type_tag(type_tag, store) + } } impl LinkageAnalysis for UnifiedLinkage { @@ -175,6 +192,14 @@ impl LinkageAnalysis for UnifiedLinkage { ) -> Result { self.internal.publication_linkage(linkage, store) } + + fn runtime_type_tag( + &mut self, + type_tag: &TypeTag, + store: &dyn PackageStore, + ) -> Result { + self.internal.runtime_type_tag(type_tag, store) + } } impl LinkageConfig { @@ -445,6 +470,49 @@ impl PTBLinkageMetadata { } Ok(ResolvedLinkage::from_resolution_table(unification_table)) } + + pub fn runtime_type_tag( + &mut self, + type_tag: &TypeTag, + store: &dyn PackageStore, + ) -> Result { + match type_tag { + x @ (TypeTag::Bool + | TypeTag::U8 + | TypeTag::U64 + | TypeTag::U128 + | TypeTag::Address + | TypeTag::Signer + | TypeTag::U16 + | TypeTag::U32 + | TypeTag::U256) => Ok(x.clone()), + TypeTag::Vector(type_tag) => { + let ty = self.runtime_type_tag(type_tag, store)?; + Ok(TypeTag::Vector(Box::new(ty))) + } + TypeTag::Struct(struct_tag) => { + let StructTag { + address, + module, + name, + type_params, + } = &**struct_tag; + let package = + Self::get_package(&mut self.all_packages, &ObjectID::from(*address), store)?; + let runtime_address = package.original_package_id().into(); + let type_params = type_params + .iter() + .map(|ty| self.runtime_type_tag(ty, store)) + .collect::, _>>()?; + Ok(TypeTag::Struct(Box::new(StructTag { + address: runtime_address, + module: module.clone(), + name: name.clone(), + type_params, + }))) + } + } + } } impl PTBLinkageMetadata { diff --git a/sui-execution/latest/sui-adapter/src/programmable_transactions/context.rs b/sui-execution/latest/sui-adapter/src/programmable_transactions/context.rs index a952aa526a44b..709898207e71b 100644 --- a/sui-execution/latest/sui-adapter/src/programmable_transactions/context.rs +++ b/sui-execution/latest/sui-adapter/src/programmable_transactions/context.rs @@ -201,6 +201,7 @@ mod checked { } /// Load a type. Linkage context is created ad-hoc for the type and its arguments. + /// NB: The type tag passed in must be a runtime type tag. pub fn load_type(&mut self, type_tag: &TypeTag) -> VMResult { self.vm_instance .load_type(type_tag) @@ -208,10 +209,22 @@ mod checked { } /// Load a type using the context's current session. + /// NB: The type tag passed in must be a runtime struct tag. pub fn load_type_from_struct(&mut self, struct_tag: &StructTag) -> VMResult { self.load_type(&TypeTag::Struct(Box::new(struct_tag.clone()))) } + /// Translates a `TypeTag` that uses defining IDs (or possilby other non-runtime ID IDs) + /// to one that only uses the runtime ID in all places. + pub fn runtime_type_tag_for_type_tag( + &mut self, + type_tag: &TypeTag, + ) -> Result { + self.ctx + .linkage_analyzer + .runtime_type_tag(type_tag, &SuiDataStore::new(&self.ctx.state_view, &[])) + } + //--------------------------------------------------------------------------- // Error Resolution //--------------------------------------------------------------------------- diff --git a/sui-execution/latest/sui-adapter/src/programmable_transactions/execution.rs b/sui-execution/latest/sui-adapter/src/programmable_transactions/execution.rs index 2e32f34bc57e2..d72f20ee45c28 100644 --- a/sui-execution/latest/sui-adapter/src/programmable_transactions/execution.rs +++ b/sui-execution/latest/sui-adapter/src/programmable_transactions/execution.rs @@ -165,11 +165,7 @@ mod checked { "input checker ensures if args are empty, there is a type specified" ); }; - let tag = to_type_tag(linked_context, tag)?; - - let elem_ty = linked_context - .load_type(&tag) - .map_err(|e| linked_context.convert_vm_error(e))?; + let elem_ty = load_type_input(linked_context, tag, 0)?; let ty = ExecutionType { type_: TypeTag::Vector(Box::new(elem_ty.type_)), abilities: vector_abilites(elem_ty.abilities), @@ -189,13 +185,7 @@ mod checked { leb128::write::unsigned(&mut res, args.len() as u64).unwrap(); let mut arg_iter = args.into_iter().enumerate(); let (mut used_in_non_entry_move_call, elem_ty) = match tag_opt { - Some(tag) => { - let tag = to_type_tag(linked_context, tag)?; - let elem_ty = linked_context - .load_type(&tag) - .map_err(|e| linked_context.convert_vm_error(e))?; - (false, elem_ty) - } + Some(tag) => (false, load_type_input(linked_context, tag, 0)?), // If no tag specified, it _must_ be an object None => { // empty args covered above @@ -373,11 +363,13 @@ mod checked { // Convert type arguments to `Type`s let mut loaded_type_arguments = Vec::with_capacity(type_arguments.len()); for (ix, type_arg) in type_arguments.into_iter().enumerate() { - let type_arg = to_type_tag(context, type_arg)?; + let defining_type_arg = to_type_tag(context, type_arg)?; + let runtime_type_arg = context.runtime_type_tag_for_type_tag(&defining_type_arg)?; let ty = context .vm_instance - .load_type(&type_arg) + .load_type(&runtime_type_arg) .map_err(|e| context.convert_type_argument_error(ix, e))?; + loaded_type_arguments.push(ty); } @@ -1466,6 +1458,18 @@ mod checked { } } + fn load_type_input( + linked_context: &mut LinkedContext<'_, '_, '_, '_>, + type_input: TypeInput, + idx: usize, + ) -> Result { + let tag = to_type_tag(linked_context, type_input)?; + let runtime_tag = linked_context.runtime_type_tag_for_type_tag(&tag)?; + linked_context + .load_type(&runtime_tag) + .map_err(|e| linked_context.convert_type_argument_error(idx, e)) + } + // Returns Some(kind) if the type is a reference to the TxnContext. kind being Mutable with // a MutableReference, and Immutable otherwise. // Returns None for all other types