sui_adapter_latest/static_programmable_transactions/typing/verify/
move_functions.rs1use crate::execution_mode::ExecutionMode;
5use crate::sp;
6use crate::static_programmable_transactions::{env::Env, loading::ast::Type, typing::ast as T};
7use move_binary_format::file_format::Visibility;
8use move_core_types::identifier::IdentStr;
9use move_core_types::language_storage::ModuleId;
10use sui_types::error::ExecutionError;
11use sui_types::execution_status::ExecutionErrorKind;
12use sui_verifier::private_generics_verifier_v2;
13
14pub fn verify<Mode: ExecutionMode>(env: &Env, txn: &T::Transaction) -> Result<(), ExecutionError> {
22 for c in &txn.commands {
23 command::<Mode>(env, c).map_err(|e| e.with_command_index(c.idx as usize))?;
24 }
25 Ok(())
26}
27
28fn command<Mode: ExecutionMode>(env: &Env, sp!(_, c): &T::Command) -> Result<(), ExecutionError> {
29 let T::Command_ {
30 command,
31 result_type: _,
32 drop_values: _,
33 consumed_shared_objects: _,
34 } = c;
35 match command {
36 T::Command__::MoveCall(call) => move_call::<Mode>(env, call)?,
37 T::Command__::TransferObjects(_, _)
38 | T::Command__::SplitCoins(_, _, _)
39 | T::Command__::MergeCoins(_, _, _)
40 | T::Command__::MakeMoveVec(_, _)
41 | T::Command__::Publish(_, _, _)
42 | T::Command__::Upgrade(_, _, _, _, _) => (),
43 }
44 Ok(())
45}
46
47fn move_call<Mode: ExecutionMode>(env: &Env, call: &T::MoveCall) -> Result<(), ExecutionError> {
52 let T::MoveCall {
53 function,
54 arguments: _,
55 } = call;
56 check_signature::<Mode>(env, function)?;
57 check_private_generics_v2(&function.original_mid, function.name.as_ident_str())?;
58 check_visibility::<Mode>(env, function)?;
59 Ok(())
60}
61
62fn check_signature<Mode: ExecutionMode>(
63 env: &Env,
64 function: &T::LoadedFunction,
65) -> Result<(), ExecutionError> {
66 fn check_return_type<Mode: ExecutionMode>(
67 idx: usize,
68 return_type: &T::Type,
69 ) -> Result<(), ExecutionError> {
70 if let Type::Reference(_, _) = return_type
71 && !Mode::allow_arbitrary_values()
72 {
73 return Err(ExecutionError::from_kind(
74 ExecutionErrorKind::InvalidPublicFunctionReturnType {
75 idx: checked_as!(idx, u16)?,
76 },
77 ));
78 }
79 Ok(())
80 }
81
82 if env.protocol_config.allow_references_in_ptbs() {
83 return Ok(());
84 }
85
86 for (idx, ty) in function.signature.return_.iter().enumerate() {
87 check_return_type::<Mode>(idx, ty)?;
88 }
89 Ok(())
90}
91
92fn check_visibility<Mode: ExecutionMode>(
93 _env: &Env,
94 function: &T::LoadedFunction,
95) -> Result<(), ExecutionError> {
96 let visibility = function.visibility;
97 let is_entry = function.is_entry;
98 match (visibility, is_entry) {
99 (Visibility::Private | Visibility::Friend, true) => (),
101 (Visibility::Public, true) => (),
103 (Visibility::Public, false) => (),
105 (Visibility::Private | Visibility::Friend, false) => {
107 if !Mode::allow_arbitrary_function_calls() {
108 return Err(ExecutionError::new_with_source(
109 ExecutionErrorKind::NonEntryFunctionInvoked,
110 "Can only call `entry` or `public` functions",
111 ));
112 }
113 }
114 };
115 Ok(())
116}
117
118fn check_private_generics_v2(
119 callee_package: &ModuleId,
120 callee_function: &IdentStr,
121) -> Result<(), ExecutionError> {
122 let callee_address = *callee_package.address();
123 let callee_module = callee_package.name();
124 let callee = (callee_address, callee_module, callee_function);
125 let Some((_f, internal_type_parameters)) = private_generics_verifier_v2::FUNCTIONS_TO_CHECK
126 .iter()
127 .find(|(f, _)| &callee == f)
128 else {
129 return Ok(());
130 };
131 let Some((internal_idx, _)) = internal_type_parameters
134 .iter()
135 .enumerate()
136 .find(|(_, is_internal)| **is_internal)
137 else {
138 return Ok(());
140 };
141 let callee_package_name = private_generics_verifier_v2::callee_package_name(&callee_address);
142 let help =
143 private_generics_verifier_v2::help_message(&callee_address, callee_module, callee_function);
144 let msg = format!(
145 "Cannot directly call function '{}::{}::{}' since type parameter #{} can \
146 only be instantiated with types defined within the caller's module.{}",
147 callee_package_name, callee_module, callee_function, internal_idx, help,
148 );
149 Err(ExecutionError::new_with_source(
150 ExecutionErrorKind::NonEntryFunctionInvoked,
151 msg,
152 ))
153}