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_vm_types::values::VectorSpecialization;
9use std::{cell::OnceCell, vec};
10use sui_types::base_types::{ObjectID, ObjectRef};
11
12#[derive(Debug)]
17pub struct Transaction {
18 pub bytes: IndexSet<Vec<u8>>,
20 pub objects: Vec<ObjectInput>,
22 pub pure: Vec<PureInput>,
24 pub receiving: Vec<ReceivingInput>,
26 pub commands: Commands,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
32pub struct InputIndex(pub u16);
33
34#[derive(Debug)]
35pub struct ObjectInput {
36 pub original_input_index: InputIndex,
37 pub arg: ObjectArg,
38 pub ty: Type,
39}
40
41pub type ByteIndex = usize;
42
43#[derive(Debug)]
44pub struct PureInput {
45 pub original_input_index: InputIndex,
46 pub byte_index: ByteIndex,
48 pub ty: Type,
50 pub constraint: BytesConstraint,
52}
53
54#[derive(Debug)]
55pub struct ReceivingInput {
56 pub original_input_index: InputIndex,
57 pub object_ref: ObjectRef,
58 pub ty: Type,
59 pub constraint: BytesConstraint,
61}
62
63pub type Commands = Vec<Command>;
64
65pub type ObjectArg = L::ObjectArg;
66
67pub type Type = L::Type;
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub struct BytesConstraint {
72 pub command: u16,
74 pub argument: u16,
76}
77
78pub type ResultType = Vec<Type>;
79
80pub type Command = Spanned<Command_>;
81
82#[derive(Debug)]
83pub struct Command_ {
84 pub command: Command__,
86 pub result_type: ResultType,
88 pub drop_values: Vec<bool>,
93 pub consumed_shared_objects: Vec<ObjectID>,
96}
97
98#[derive(Debug)]
99pub enum Command__ {
100 MoveCall(Box<MoveCall>),
101 TransferObjects(Vec<Argument>, Argument),
102 SplitCoins(Type, Argument, Vec<Argument>),
103 MergeCoins(Type, Argument, Vec<Argument>),
104 MakeMoveVec(Type, Vec<Argument>),
105 Publish(Vec<Vec<u8>>, Vec<ObjectID>, ResolvedLinkage),
106 Upgrade(
107 Vec<Vec<u8>>,
108 Vec<ObjectID>,
109 ObjectID,
110 Argument,
111 ResolvedLinkage,
112 ),
113}
114
115pub type LoadedFunctionInstantiation = L::LoadedFunctionInstantiation;
116
117pub type LoadedFunction = L::LoadedFunction;
118
119#[derive(Debug)]
120pub struct MoveCall {
121 pub function: LoadedFunction,
122 pub arguments: Vec<Argument>,
123}
124
125#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
126pub enum Location {
127 TxContext,
128 GasCoin,
129 ObjectInput(u16),
130 PureInput(u16),
131 ReceivingInput(u16),
132 Result(u16, u16),
133}
134
135#[derive(Clone, Debug)]
137pub enum Usage {
138 Move(Location),
139 Copy {
140 location: Location,
141 borrowed: OnceCell<bool>,
144 },
145}
146
147pub type Argument = Spanned<Argument_>;
148pub type Argument_ = (Argument__, Type);
149
150#[derive(Clone, Debug)]
151pub enum Argument__ {
152 Use(Usage),
154 Borrow(bool, Location),
156 Read(Usage),
158 Freeze(Usage),
160}
161
162impl Transaction {
167 pub fn types(&self) -> impl Iterator<Item = &Type> {
168 let pure_types = self.pure.iter().map(|p| &p.ty);
169 let object_types = self.objects.iter().map(|o| &o.ty);
170 let receiving_types = self.receiving.iter().map(|r| &r.ty);
171 let command_types = self.commands.iter().flat_map(command_types);
172 pure_types
173 .chain(object_types)
174 .chain(receiving_types)
175 .chain(command_types)
176 }
177}
178
179impl Usage {
180 pub fn new_move(location: Location) -> Usage {
181 Usage::Move(location)
182 }
183
184 pub fn new_copy(location: Location) -> Usage {
185 Usage::Copy {
186 location,
187 borrowed: OnceCell::new(),
188 }
189 }
190
191 pub fn location(&self) -> Location {
192 match self {
193 Usage::Move(location) => *location,
194 Usage::Copy { location, .. } => *location,
195 }
196 }
197}
198
199impl Argument__ {
200 pub fn new_move(location: Location) -> Self {
201 Self::Use(Usage::new_move(location))
202 }
203
204 pub fn new_copy(location: Location) -> Self {
205 Self::Use(Usage::new_copy(location))
206 }
207
208 pub fn location(&self) -> Location {
209 match self {
210 Self::Use(usage) | Self::Read(usage) => usage.location(),
211 Self::Borrow(_, location) => *location,
212 Self::Freeze(usage) => usage.location(),
213 }
214 }
215}
216
217impl Command__ {
218 pub fn arguments(&self) -> Vec<&Argument> {
219 match self {
220 Command__::MoveCall(mc) => mc.arguments.iter().collect(),
221 Command__::TransferObjects(objs, addr) => {
222 objs.iter().chain(std::iter::once(addr)).collect()
223 }
224 Command__::SplitCoins(_, coin, amounts) => {
225 std::iter::once(coin).chain(amounts).collect()
226 }
227 Command__::MergeCoins(_, target, sources) => {
228 std::iter::once(target).chain(sources).collect()
229 }
230 Command__::MakeMoveVec(_, elems) => elems.iter().collect(),
231 Command__::Publish(_, _, _) => vec![],
232 Command__::Upgrade(_, _, _, arg, _) => vec![arg],
233 }
234 }
235
236 pub fn types(&self) -> Box<dyn Iterator<Item = &Type> + '_> {
237 match self {
238 Command__::TransferObjects(args, arg) => {
239 Box::new(std::iter::once(arg).chain(args.iter()).map(argument_type))
240 }
241 Command__::SplitCoins(ty, arg, args) | Command__::MergeCoins(ty, arg, args) => {
242 Box::new(
243 std::iter::once(arg)
244 .chain(args.iter())
245 .map(argument_type)
246 .chain(std::iter::once(ty)),
247 )
248 }
249 Command__::MakeMoveVec(ty, args) => {
250 Box::new(args.iter().map(argument_type).chain(std::iter::once(ty)))
251 }
252 Command__::MoveCall(call) => Box::new(
253 call.arguments
254 .iter()
255 .map(argument_type)
256 .chain(call.function.type_arguments.iter())
257 .chain(call.function.signature.parameters.iter())
258 .chain(call.function.signature.return_.iter()),
259 ),
260 Command__::Upgrade(_, _, _, arg, _) => {
261 Box::new(std::iter::once(arg).map(argument_type))
262 }
263 Command__::Publish(_, _, _) => Box::new(std::iter::empty()),
264 }
265 }
266}
267
268pub fn command_types(cmd: &Command) -> impl Iterator<Item = &Type> {
273 let result_types = cmd.value.result_type.iter();
274 let command_types = cmd.value.command.types();
275 result_types.chain(command_types)
276}
277
278pub fn argument_type(arg: &Argument) -> &Type {
279 &arg.value.1
280}
281
282impl TryFrom<Type> for VectorSpecialization {
287 type Error = &'static str;
288
289 fn try_from(value: Type) -> Result<Self, Self::Error> {
290 Ok(match value {
291 Type::U8 => VectorSpecialization::U8,
292 Type::U16 => VectorSpecialization::U16,
293 Type::U32 => VectorSpecialization::U32,
294 Type::U64 => VectorSpecialization::U64,
295 Type::U128 => VectorSpecialization::U128,
296 Type::U256 => VectorSpecialization::U256,
297 Type::Address => VectorSpecialization::Address,
298 Type::Bool => VectorSpecialization::Bool,
299 Type::Signer | Type::Vector(_) | Type::Datatype(_) => VectorSpecialization::Container,
300 Type::Reference(_, _) => return Err("unexpected reference in vector specialization"),
301 })
302 }
303}