Skip to content

Commit

Permalink
[10/n][vm-rewrite][adapter] Update type inputs so they are always con…
Browse files Browse the repository at this point in the history
…verted to runtime IDs before entering the VM
  • Loading branch information
tzakian committed Feb 19, 2025
1 parent 64bed54 commit 3af3885
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 16 deletions.
72 changes: 70 additions & 2 deletions sui-execution/latest/sui-adapter/src/linkage_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -115,6 +116,14 @@ pub trait LinkageAnalysis {
linkage: &LinkageContext,
store: &dyn PackageStore,
) -> Result<ResolvedLinkage, ExecutionError>;

// 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<TypeTag, ExecutionError>;
}

type ResolutionTable = BTreeMap<ObjectID, ConflictResolution>;
Expand Down Expand Up @@ -149,6 +158,14 @@ impl LinkageAnalysis for PerCommandLinkage {
) -> Result<ResolvedLinkage, ExecutionError> {
self.internal.publication_linkage(linkage, store)
}

fn runtime_type_tag(
&mut self,
type_tag: &TypeTag,
store: &dyn PackageStore,
) -> Result<TypeTag, ExecutionError> {
self.internal.runtime_type_tag(type_tag, store)
}
}

impl LinkageAnalysis for UnifiedLinkage {
Expand All @@ -175,6 +192,14 @@ impl LinkageAnalysis for UnifiedLinkage {
) -> Result<ResolvedLinkage, ExecutionError> {
self.internal.publication_linkage(linkage, store)
}

fn runtime_type_tag(
&mut self,
type_tag: &TypeTag,
store: &dyn PackageStore,
) -> Result<TypeTag, ExecutionError> {
self.internal.runtime_type_tag(type_tag, store)
}
}

impl LinkageConfig {
Expand Down Expand Up @@ -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<TypeTag, ExecutionError> {
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::<Result<Vec<_>, _>>()?;
Ok(TypeTag::Struct(Box::new(StructTag {
address: runtime_address,
module: module.clone(),
name: name.clone(),
type_params,
})))
}
}
}
}

impl PTBLinkageMetadata {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,17 +201,30 @@ 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<ExecutionType> {
self.vm_instance
.load_type(type_tag)
.and_then(|runtime_type| self.execution_type_for_runtime_type(&runtime_type))
}

/// 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<ExecutionType> {
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<TypeTag, ExecutionError> {
self.ctx
.linkage_analyzer
.runtime_type_tag(type_tag, &SuiDataStore::new(&self.ctx.state_view, &[]))
}

//---------------------------------------------------------------------------
// Error Resolution
//---------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -1466,6 +1458,18 @@ mod checked {
}
}

fn load_type_input(
linked_context: &mut LinkedContext<'_, '_, '_, '_>,
type_input: TypeInput,
idx: usize,
) -> Result<ExecutionType, ExecutionError> {
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
Expand Down

0 comments on commit 3af3885

Please sign in to comment.