sui_adapter_latest/static_programmable_transactions/typing/
ast.rs1use crate::static_programmable_transactions::{
5 linkage::resolved_linkage::ResolvedLinkage, loading::ast as L, spanned::Spanned,
6};
7use indexmap::IndexSet;
8use move_core_types::{account_address::AccountAddress, u256::U256};
9use move_vm_types::values::VectorSpecialization;
10use std::cell::OnceCell;
11use sui_types::base_types::{ObjectID, ObjectRef};
12
13#[derive(Debug)]
18pub struct Transaction {
19 pub bytes: IndexSet<Vec<u8>>,
21 pub objects: Vec<ObjectInput>,
23 pub withdrawals: Vec<WithdrawalInput>,
25 pub pure: Vec<PureInput>,
27 pub receiving: Vec<ReceivingInput>,
29 pub commands: Commands,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
35pub struct InputIndex(pub u16);
36
37#[derive(Debug)]
38pub struct ObjectInput {
39 pub original_input_index: InputIndex,
40 pub arg: ObjectArg,
41 pub ty: Type,
42}
43
44pub type ByteIndex = usize;
45
46#[derive(Debug)]
47pub struct PureInput {
48 pub original_input_index: InputIndex,
49 pub byte_index: ByteIndex,
51 pub ty: Type,
53 pub constraint: BytesConstraint,
55}
56
57#[derive(Debug)]
58pub struct ReceivingInput {
59 pub original_input_index: InputIndex,
60 pub object_ref: ObjectRef,
61 pub ty: Type,
62 pub constraint: BytesConstraint,
64}
65
66#[derive(Debug)]
67pub struct WithdrawalInput {
68 pub original_input_index: InputIndex,
69 pub ty: Type,
71 pub owner: AccountAddress,
72 pub amount: U256,
74}
75
76pub type Commands = Vec<Command>;
77
78pub type ObjectArg = L::ObjectArg;
79
80pub type Type = L::Type;
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq)]
83pub struct BytesConstraint {
85 pub command: u16,
87 pub argument: u16,
89}
90
91pub type ResultType = Vec<Type>;
92
93pub type Command = Spanned<Command_>;
94
95#[derive(Debug)]
96pub struct Command_ {
97 pub command: Command__,
99 pub result_type: ResultType,
101 pub drop_values: Vec<bool>,
106 pub consumed_shared_objects: Vec<ObjectID>,
109}
110
111#[derive(Debug)]
112pub enum Command__ {
113 MoveCall(Box<MoveCall>),
114 TransferObjects(Vec<Argument>, Argument),
115 SplitCoins(Type, Argument, Vec<Argument>),
116 MergeCoins(Type, Argument, Vec<Argument>),
117 MakeMoveVec(Type, Vec<Argument>),
118 Publish(Vec<Vec<u8>>, Vec<ObjectID>, ResolvedLinkage),
119 Upgrade(
120 Vec<Vec<u8>>,
121 Vec<ObjectID>,
122 ObjectID,
123 Argument,
124 ResolvedLinkage,
125 ),
126}
127
128pub type LoadedFunctionInstantiation = L::LoadedFunctionInstantiation;
129
130pub type LoadedFunction = L::LoadedFunction;
131
132#[derive(Debug)]
133pub struct MoveCall {
134 pub function: LoadedFunction,
135 pub arguments: Vec<Argument>,
136}
137
138#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
139pub enum Location {
140 TxContext,
141 GasCoin,
142 ObjectInput(u16),
143 WithdrawalInput(u16),
144 PureInput(u16),
145 ReceivingInput(u16),
146 Result(u16, u16),
147}
148
149#[derive(Clone, Debug)]
151pub enum Usage {
152 Move(Location),
153 Copy {
154 location: Location,
155 borrowed: OnceCell<bool>,
158 },
159}
160
161pub type Argument = Spanned<Argument_>;
162pub type Argument_ = (Argument__, Type);
163
164#[derive(Clone, Debug)]
165pub enum Argument__ {
166 Use(Usage),
168 Borrow(bool, Location),
170 Read(Usage),
172 Freeze(Usage),
174}
175
176impl Transaction {
181 pub fn types(&self) -> impl Iterator<Item = &Type> {
182 let pure_types = self.pure.iter().map(|p| &p.ty);
183 let object_types = self.objects.iter().map(|o| &o.ty);
184 let receiving_types = self.receiving.iter().map(|r| &r.ty);
185 let command_types = self.commands.iter().flat_map(command_types);
186 pure_types
187 .chain(object_types)
188 .chain(receiving_types)
189 .chain(command_types)
190 }
191}
192
193impl Usage {
194 pub fn new_move(location: Location) -> Usage {
195 Usage::Move(location)
196 }
197
198 pub fn new_copy(location: Location) -> Usage {
199 Usage::Copy {
200 location,
201 borrowed: OnceCell::new(),
202 }
203 }
204
205 pub fn location(&self) -> Location {
206 match self {
207 Usage::Move(location) => *location,
208 Usage::Copy { location, .. } => *location,
209 }
210 }
211}
212
213impl Argument__ {
214 pub fn new_move(location: Location) -> Self {
215 Self::Use(Usage::new_move(location))
216 }
217
218 pub fn new_copy(location: Location) -> Self {
219 Self::Use(Usage::new_copy(location))
220 }
221
222 pub fn location(&self) -> Location {
223 match self {
224 Self::Use(usage) | Self::Read(usage) => usage.location(),
225 Self::Borrow(_, location) => *location,
226 Self::Freeze(usage) => usage.location(),
227 }
228 }
229}
230
231impl Command__ {
232 pub fn arguments(&self) -> Box<dyn Iterator<Item = &Argument> + '_> {
233 match self {
234 Command__::MoveCall(mc) => Box::new(mc.arguments.iter()),
235 Command__::TransferObjects(objs, addr) => {
236 Box::new(objs.iter().chain(std::iter::once(addr)))
237 }
238 Command__::SplitCoins(_, coin, amounts) => {
239 Box::new(std::iter::once(coin).chain(amounts))
240 }
241 Command__::MergeCoins(_, target, sources) => {
242 Box::new(std::iter::once(target).chain(sources))
243 }
244 Command__::MakeMoveVec(_, elems) => Box::new(elems.iter()),
245 Command__::Publish(_, _, _) => Box::new(std::iter::empty()),
246 Command__::Upgrade(_, _, _, arg, _) => Box::new(std::iter::once(arg)),
247 }
248 }
249
250 pub fn types(&self) -> Box<dyn Iterator<Item = &Type> + '_> {
251 match self {
252 Command__::TransferObjects(args, arg) => {
253 Box::new(std::iter::once(arg).chain(args.iter()).map(argument_type))
254 }
255 Command__::SplitCoins(ty, arg, args) | Command__::MergeCoins(ty, arg, args) => {
256 Box::new(
257 std::iter::once(arg)
258 .chain(args.iter())
259 .map(argument_type)
260 .chain(std::iter::once(ty)),
261 )
262 }
263 Command__::MakeMoveVec(ty, args) => {
264 Box::new(args.iter().map(argument_type).chain(std::iter::once(ty)))
265 }
266 Command__::MoveCall(call) => Box::new(
267 call.arguments
268 .iter()
269 .map(argument_type)
270 .chain(call.function.type_arguments.iter())
271 .chain(call.function.signature.parameters.iter())
272 .chain(call.function.signature.return_.iter()),
273 ),
274 Command__::Upgrade(_, _, _, arg, _) => {
275 Box::new(std::iter::once(arg).map(argument_type))
276 }
277 Command__::Publish(_, _, _) => Box::new(std::iter::empty()),
278 }
279 }
280
281 pub fn arguments_len(&self) -> usize {
282 let n = match self {
283 Command__::MoveCall(mc) => mc.arguments.len(),
284 Command__::TransferObjects(objs, _) => objs.len().saturating_add(1),
285 Command__::SplitCoins(_, _, amounts) => amounts.len().saturating_add(1),
286 Command__::MergeCoins(_, _, sources) => sources.len().saturating_add(1),
287 Command__::MakeMoveVec(_, elems) => elems.len(),
288 Command__::Publish(_, _, _) => 0,
289 Command__::Upgrade(_, _, _, _, _) => 1,
290 };
291 debug_assert_eq!(self.arguments().count(), n);
292 n
293 }
294}
295
296pub fn command_types(cmd: &Command) -> impl Iterator<Item = &Type> {
301 let result_types = cmd.value.result_type.iter();
302 let command_types = cmd.value.command.types();
303 result_types.chain(command_types)
304}
305
306pub fn argument_type(arg: &Argument) -> &Type {
307 &arg.value.1
308}
309
310impl TryFrom<Type> for VectorSpecialization {
315 type Error = &'static str;
316
317 fn try_from(value: Type) -> Result<Self, Self::Error> {
318 Ok(match value {
319 Type::U8 => VectorSpecialization::U8,
320 Type::U16 => VectorSpecialization::U16,
321 Type::U32 => VectorSpecialization::U32,
322 Type::U64 => VectorSpecialization::U64,
323 Type::U128 => VectorSpecialization::U128,
324 Type::U256 => VectorSpecialization::U256,
325 Type::Address => VectorSpecialization::Address,
326 Type::Bool => VectorSpecialization::Bool,
327 Type::Signer | Type::Vector(_) | Type::Datatype(_) => VectorSpecialization::Container,
328 Type::Reference(_, _) => return Err("unexpected reference in vector specialization"),
329 })
330 }
331}