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