sui_adapter_latest/static_programmable_transactions/loading/
translate.rs1use crate::static_programmable_transactions::{
5 env::Env,
6 linkage::resolved_linkage::RootedLinkage,
7 loading::ast as L,
8 metering::{self, translation_meter::TranslationMeter},
9};
10use move_core_types::language_storage::StructTag;
11use sui_types::{
12 error::ExecutionError,
13 object::Owner,
14 transaction::{self as P, CallArg, ObjectArg, SharedObjectMutability},
15};
16
17pub fn transaction(
18 meter: &mut TranslationMeter<'_, '_>,
19 env: &Env,
20 pt: P::ProgrammableTransaction,
21) -> Result<L::Transaction, ExecutionError> {
22 metering::pre_translation::meter(meter, &pt)?;
23 let P::ProgrammableTransaction { inputs, commands } = pt;
24 let inputs = inputs
25 .into_iter()
26 .map(|arg| input(env, arg))
27 .collect::<Result<Vec<_>, _>>()?;
28 let commands = commands
29 .into_iter()
30 .enumerate()
31 .map(|(idx, cmd)| command(env, cmd).map_err(|e| e.with_command_index(idx)))
32 .collect::<Result<Vec<_>, _>>()?;
33 let loaded_tx = L::Transaction { inputs, commands };
34 metering::loading::meter(meter, &loaded_tx)?;
35 Ok(loaded_tx)
36}
37
38fn input(env: &Env, arg: CallArg) -> Result<(L::InputArg, L::InputType), ExecutionError> {
39 Ok(match arg {
40 CallArg::Pure(bytes) => (L::InputArg::Pure(bytes), L::InputType::Bytes),
41 CallArg::Object(ObjectArg::Receiving(oref)) => {
42 (L::InputArg::Receiving(oref), L::InputType::Bytes)
43 }
44 CallArg::Object(ObjectArg::ImmOrOwnedObject(oref)) => {
45 let id = &oref.0;
46 let obj = env.read_object(id)?;
47 let Some(ty) = obj.type_() else {
48 invariant_violation!("Object {:?} has does not have a Move type", id);
49 };
50 let tag: StructTag = ty.clone().into();
51 let ty = env.load_type_from_struct(&tag)?;
52 let arg = match obj.owner {
53 Owner::AddressOwner(_) => L::ObjectArg::OwnedObject(oref),
54 Owner::Immutable => L::ObjectArg::ImmObject(oref),
55 Owner::ObjectOwner(_)
56 | Owner::Shared { .. }
57 | Owner::ConsensusAddressOwner { .. } => {
58 invariant_violation!("Unexpected owner for ImmOrOwnedObject: {:?}", obj.owner);
59 }
60 };
61 (L::InputArg::Object(arg), L::InputType::Fixed(ty))
62 }
63 CallArg::Object(ObjectArg::SharedObject {
64 id,
65 initial_shared_version,
66 mutability,
67 }) => {
68 let obj = env.read_object(&id)?;
69 let Some(ty) = obj.type_() else {
70 invariant_violation!("Object {:?} has does not have a Move type", id);
71 };
72 let tag: StructTag = ty.clone().into();
73 let ty = env.load_type_from_struct(&tag)?;
74 let kind = match obj.owner {
75 Owner::AddressOwner(_) | Owner::ObjectOwner(_) | Owner::Immutable => {
76 invariant_violation!("Unexpected owner for SharedObject: {:?}", obj.owner)
77 }
78 Owner::Shared { .. } => L::SharedObjectKind::Legacy,
79 Owner::ConsensusAddressOwner { .. } => L::SharedObjectKind::Party,
80 };
81 (
82 L::InputArg::Object(L::ObjectArg::SharedObject {
83 id,
84 initial_shared_version,
85 mutability: object_mutability(mutability),
86 kind,
87 }),
88 L::InputType::Fixed(ty),
89 )
90 }
91 CallArg::FundsWithdrawal(_) => {
92 todo!("Load balance withdraw call arg")
94 }
95 })
96}
97
98fn object_mutability(mutability: SharedObjectMutability) -> L::ObjectMutability {
99 match mutability {
100 SharedObjectMutability::Mutable => L::ObjectMutability::Mutable,
101 SharedObjectMutability::NonExclusiveWrite => L::ObjectMutability::NonExclusiveWrite,
102 SharedObjectMutability::Immutable => L::ObjectMutability::Immutable,
103 }
104}
105
106fn command(env: &Env, command: P::Command) -> Result<L::Command, ExecutionError> {
107 Ok(match command {
108 P::Command::MoveCall(pmc) => {
109 let resolved_linkage = env
110 .linkage_analysis
111 .compute_call_linkage(&pmc, env.linkable_store)?;
112 let P::ProgrammableMoveCall {
113 package,
114 module,
115 function: name,
116 type_arguments: ptype_arguments,
117 arguments,
118 } = *pmc;
119 let linkage = RootedLinkage::new(*package, resolved_linkage);
120 let type_arguments = ptype_arguments
121 .into_iter()
122 .enumerate()
123 .map(|(idx, ty)| env.load_type_input(idx, ty))
124 .collect::<Result<Vec<_>, _>>()?;
125 let function = env.load_function(package, module, name, type_arguments, linkage)?;
126 L::Command::MoveCall(Box::new(L::MoveCall {
127 function,
128 arguments,
129 }))
130 }
131 P::Command::MakeMoveVec(ptype_argument, arguments) => {
132 let type_argument = ptype_argument
133 .map(|ty| env.load_type_input(0, ty))
134 .transpose()?;
135 L::Command::MakeMoveVec(type_argument, arguments)
136 }
137 P::Command::TransferObjects(objects, address) => {
138 L::Command::TransferObjects(objects, address)
139 }
140 P::Command::SplitCoins(coin, amounts) => L::Command::SplitCoins(coin, amounts),
141 P::Command::MergeCoins(target, coins) => L::Command::MergeCoins(target, coins),
142 P::Command::Publish(items, object_ids) => {
143 let resolved_linkage = env
144 .linkage_analysis
145 .compute_publication_linkage(&object_ids, env.linkable_store)?;
146 L::Command::Publish(items, object_ids, resolved_linkage)
147 }
148 P::Command::Upgrade(items, object_ids, object_id, argument) => {
149 let resolved_linkage = env
150 .linkage_analysis
151 .compute_publication_linkage(&object_ids, env.linkable_store)?;
152 L::Command::Upgrade(items, object_ids, object_id, argument, resolved_linkage)
153 }
154 })
155}