sui_verifier_latest/
tx_context_restrictions_verifier.rs1use move_binary_format::{
30 CompiledModule,
31 file_format::{FunctionDefinition, SignatureToken},
32};
33use move_vm_config::verifier::VerifierConfig;
34use sui_types::{
35 base_types::{TxContext, TxContextKind},
36 error::ExecutionError,
37 is_system_package,
38};
39
40use crate::verification_failure;
41
42pub fn verify_module(
43 module: &CompiledModule,
44 verifier_config: &VerifierConfig,
45) -> Result<(), ExecutionError> {
46 if !verifier_config.framework_tx_context_mut_restrictions {
47 return Ok(());
48 }
49 if !is_system_package(*module.self_id().address()) {
50 return Ok(());
51 }
52 for func_def in &module.function_defs {
53 verify_function(module, func_def).map_err(|error| {
54 let name = module.identifier_at(module.function_handle_at(func_def.function).name);
55 verification_failure(format!("{}::{}. {}", module.self_id(), name, error))
56 })?;
57 }
58 Ok(())
59}
60
61fn verify_function(module: &CompiledModule, fdef: &FunctionDefinition) -> Result<(), &'static str> {
62 let fhandle = module.function_handle_at(fdef.function);
63 let returns = &module.signature_at(fhandle.return_).0;
64 let safe_returns = returns
65 .iter()
66 .all(|t| !matches!(t, SignatureToken::MutableReference(_)));
67 if safe_returns {
68 return Ok(());
69 }
70 let params = &module.signature_at(fhandle.parameters).0;
71 let (tx_context_muts, other_muts): (Vec<_>, Vec<_>) = params
72 .iter()
73 .filter(|t| matches!(t, SignatureToken::MutableReference(_)))
74 .partition(|t| TxContext::kind(module, t) == TxContextKind::Mutable);
75 if !tx_context_muts.is_empty() && other_muts.is_empty() {
76 return Err(
77 "Function takes `&mut TxContext` and returns a mutable reference, \
78 but has no non-`TxContext` `&mut U` parameter. `TxContext` cannot \
79 serve as the mutable root for a returned reference; add a mutable \
80 reference parameter of another type or return by value.",
81 );
82 }
83 Ok(())
84}