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