1use crate::{
5 gas_charger::GasPayment,
6 static_programmable_transactions::{
7 linkage::resolved_linkage::ResolvedLinkage,
8 loading::ast::{self as L, PackagePayload},
9 spanned::Spanned,
10 },
11};
12use indexmap::{IndexMap, IndexSet};
13use move_core_types::{account_address::AccountAddress, u256::U256};
14use move_vm_runtime::execution::values::VectorSpecialization;
15use std::cell::OnceCell;
16use sui_types::base_types::{ObjectID, ObjectRef};
17
18#[derive(Debug)]
23pub struct Transaction {
24 pub gas_payment: Option<GasPayment>,
25 pub bytes: IndexSet<Vec<u8>>,
27 pub objects: Vec<ObjectInput>,
29 pub withdrawals: Vec<WithdrawalInput>,
31 pub pure: Vec<PureInput>,
33 pub receiving: Vec<ReceivingInput>,
35 pub withdrawal_compatibility_conversions: IndexMap<Location, WithdrawalCompatibilityConversion>,
36 pub original_command_len: usize,
39 pub commands: Commands,
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45pub struct InputIndex(pub u16);
46
47#[derive(Debug)]
48pub struct ObjectInput {
49 pub original_input_index: InputIndex,
50 pub arg: ObjectArg,
51 pub ty: Type,
52}
53
54pub type ByteIndex = usize;
55
56#[derive(Debug)]
57pub struct PureInput {
58 pub original_input_index: InputIndex,
59 pub byte_index: ByteIndex,
61 pub ty: Type,
63 pub constraint: BytesConstraint,
65}
66
67#[derive(Debug)]
68pub struct ReceivingInput {
69 pub original_input_index: InputIndex,
70 pub object_ref: ObjectRef,
71 pub ty: Type,
72 pub constraint: BytesConstraint,
74}
75
76#[derive(Debug)]
77pub struct WithdrawalInput {
78 pub original_input_index: InputIndex,
79 pub ty: Type,
81 pub owner: AccountAddress,
82 pub amount: U256,
84}
85
86#[derive(Debug, Clone, Copy)]
87pub struct WithdrawalCompatibilityConversion {
88 pub owner: Location,
90 pub conversion_result: u16,
92}
93
94pub type Commands = Vec<Command>;
95
96pub type ObjectArg = L::ObjectArg;
97
98pub type Type = L::Type;
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub struct BytesConstraint {
103 pub command: u16,
105 pub argument: u16,
107}
108
109pub type ResultType = Vec<Type>;
110
111pub type Command = Spanned<Command_>;
112
113#[derive(Debug)]
114pub struct Command_ {
115 pub command: Command__,
117 pub result_type: ResultType,
119 pub drop_values: Vec<bool>,
124 pub incurs_post_execution_checks: bool,
128}
129
130#[derive(Debug)]
131pub enum Command__ {
132 MoveCall(Box<MoveCall>),
133 TransferObjects(Vec<Argument>, Argument),
134 SplitCoins(Type, Argument, Vec<Argument>),
135 MergeCoins(Type, Argument, Vec<Argument>),
136 MakeMoveVec(Type, Vec<Argument>),
137 Publish(PackagePayload, Vec<ObjectID>, ResolvedLinkage),
138 Upgrade(
139 PackagePayload,
140 Vec<ObjectID>,
141 ObjectID,
142 Argument,
143 ResolvedLinkage,
144 ),
145}
146
147pub type LoadedFunctionInstantiation = L::LoadedFunctionInstantiation;
148
149pub type LoadedFunction = L::LoadedFunction;
150
151#[derive(Debug)]
152pub struct MoveCall {
153 pub function: LoadedFunction,
154 pub arguments: Vec<Argument>,
155}
156
157#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
158pub enum Location {
159 TxContext,
160 GasCoin,
161 ObjectInput(u16),
162 WithdrawalInput(u16),
163 PureInput(u16),
164 ReceivingInput(u16),
165 Result(u16, u16),
166}
167
168#[derive(Clone, Debug)]
170pub enum Usage {
171 Move(Location),
172 Copy {
173 location: Location,
174 borrowed: OnceCell<bool>,
177 },
178}
179
180pub type Argument = Spanned<Argument_>;
181pub type Argument_ = (Argument__, Type);
182
183#[derive(Clone, Debug)]
184pub enum Argument__ {
185 Use(Usage),
187 Borrow(bool, Location),
189 Read(Usage),
191 Freeze(Usage),
193}
194
195impl Transaction {
200 pub fn types(&self) -> impl Iterator<Item = &Type> {
201 let pure_types = self.pure.iter().map(|p| &p.ty);
202 let object_types = self.objects.iter().map(|o| &o.ty);
203 let receiving_types = self.receiving.iter().map(|r| &r.ty);
204 let command_types = self.commands.iter().flat_map(command_types);
205 pure_types
206 .chain(object_types)
207 .chain(receiving_types)
208 .chain(command_types)
209 }
210}
211
212impl Usage {
213 pub fn new_move(location: Location) -> Usage {
214 Usage::Move(location)
215 }
216
217 pub fn new_copy(location: Location) -> Usage {
218 Usage::Copy {
219 location,
220 borrowed: OnceCell::new(),
221 }
222 }
223
224 pub fn location(&self) -> Location {
225 match self {
226 Usage::Move(location) => *location,
227 Usage::Copy { location, .. } => *location,
228 }
229 }
230}
231
232impl Argument__ {
233 pub fn new_move(location: Location) -> Self {
234 Self::Use(Usage::new_move(location))
235 }
236
237 pub fn new_copy(location: Location) -> Self {
238 Self::Use(Usage::new_copy(location))
239 }
240
241 pub fn location(&self) -> Location {
242 match self {
243 Self::Use(usage) | Self::Read(usage) => usage.location(),
244 Self::Borrow(_, location) => *location,
245 Self::Freeze(usage) => usage.location(),
246 }
247 }
248}
249
250impl Command__ {
251 pub fn arguments(&self) -> Box<dyn Iterator<Item = &Argument> + '_> {
252 match self {
253 Command__::MoveCall(mc) => Box::new(mc.arguments.iter()),
254 Command__::TransferObjects(objs, addr) => {
255 Box::new(objs.iter().chain(std::iter::once(addr)))
256 }
257 Command__::SplitCoins(_, coin, amounts) => {
258 Box::new(std::iter::once(coin).chain(amounts))
259 }
260 Command__::MergeCoins(_, target, sources) => {
261 Box::new(std::iter::once(target).chain(sources))
262 }
263 Command__::MakeMoveVec(_, elems) => Box::new(elems.iter()),
264 Command__::Publish(_, _, _) => Box::new(std::iter::empty()),
265 Command__::Upgrade(_, _, _, arg, _) => Box::new(std::iter::once(arg)),
266 }
267 }
268
269 pub fn types(&self) -> Box<dyn Iterator<Item = &Type> + '_> {
270 match self {
271 Command__::TransferObjects(args, arg) => {
272 Box::new(std::iter::once(arg).chain(args.iter()).map(argument_type))
273 }
274 Command__::SplitCoins(ty, arg, args) | Command__::MergeCoins(ty, arg, args) => {
275 Box::new(
276 std::iter::once(arg)
277 .chain(args.iter())
278 .map(argument_type)
279 .chain(std::iter::once(ty)),
280 )
281 }
282 Command__::MakeMoveVec(ty, args) => {
283 Box::new(args.iter().map(argument_type).chain(std::iter::once(ty)))
284 }
285 Command__::MoveCall(call) => Box::new(
286 call.arguments
287 .iter()
288 .map(argument_type)
289 .chain(call.function.type_arguments.iter())
290 .chain(call.function.signature.parameters.iter())
291 .chain(call.function.signature.return_.iter()),
292 ),
293 Command__::Upgrade(_, _, _, arg, _) => {
294 Box::new(std::iter::once(arg).map(argument_type))
295 }
296 Command__::Publish(_, _, _) => Box::new(std::iter::empty()),
297 }
298 }
299
300 pub fn arguments_len(&self) -> usize {
301 let n = match self {
302 Command__::MoveCall(mc) => mc.arguments.len(),
303 Command__::TransferObjects(objs, _) => objs.len().saturating_add(1),
304 Command__::SplitCoins(_, _, amounts) => amounts.len().saturating_add(1),
305 Command__::MergeCoins(_, _, sources) => sources.len().saturating_add(1),
306 Command__::MakeMoveVec(_, elems) => elems.len(),
307 Command__::Publish(_, _, _) => 0,
308 Command__::Upgrade(_, _, _, _, _) => 1,
309 };
310 debug_assert_eq!(self.arguments().count(), n);
311 n
312 }
313}
314
315pub fn command_types(cmd: &Command) -> impl Iterator<Item = &Type> {
320 let result_types = cmd.value.result_type.iter();
321 let command_types = cmd.value.command.types();
322 result_types.chain(command_types)
323}
324
325pub fn argument_type(arg: &Argument) -> &Type {
326 &arg.value.1
327}
328
329impl TryFrom<Type> for VectorSpecialization {
334 type Error = &'static str;
335
336 fn try_from(value: Type) -> Result<Self, Self::Error> {
337 Ok(match value {
338 Type::U8 => VectorSpecialization::U8,
339 Type::U16 => VectorSpecialization::U16,
340 Type::U32 => VectorSpecialization::U32,
341 Type::U64 => VectorSpecialization::U64,
342 Type::U128 => VectorSpecialization::U128,
343 Type::U256 => VectorSpecialization::U256,
344 Type::Address => VectorSpecialization::Address,
345 Type::Bool => VectorSpecialization::Bool,
346 Type::Signer | Type::Vector(_) | Type::Datatype(_) => VectorSpecialization::Container,
347 Type::Reference(_, _) => return Err("unexpected reference in vector specialization"),
348 })
349 }
350}