1use crate::static_programmable_transactions::linkage::resolved_linkage::{
5 ResolvedLinkage, RootedLinkage,
6};
7use indexmap::IndexSet;
8use move_binary_format::file_format::{AbilitySet, CodeOffset, FunctionDefinitionIndex};
9use move_core_types::{
10 account_address::AccountAddress,
11 identifier::IdentStr,
12 language_storage::{ModuleId, StructTag},
13};
14use std::rc::Rc;
15use sui_types::{
16 Identifier, TypeTag,
17 base_types::{ObjectID, ObjectRef, RESOLVED_TX_CONTEXT, SequenceNumber, TxContextKind},
18};
19
20#[derive(Debug)]
25pub struct Transaction {
26 pub inputs: Inputs,
27 pub commands: Commands,
28}
29
30pub type Inputs = Vec<(InputArg, InputType)>;
31
32pub type Commands = Vec<Command>;
33
34#[derive(Debug)]
35#[cfg_attr(debug_assertions, derive(Clone))]
36pub enum InputArg {
37 Pure(Vec<u8>),
38 Receiving(ObjectRef),
39 Object(ObjectArg),
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub enum SharedObjectKind {
44 Legacy,
45 Party,
46}
47
48#[derive(Debug)]
49#[cfg_attr(debug_assertions, derive(Clone))]
50pub enum ObjectArg {
51 ImmObject(ObjectRef),
52 OwnedObject(ObjectRef),
53 SharedObject {
54 id: ObjectID,
55 initial_shared_version: SequenceNumber,
56 mutability: ObjectMutability,
57 kind: SharedObjectKind,
58 },
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub enum ObjectMutability {
63 Mutable,
64 Immutable,
65 NonExclusiveWrite,
66}
67
68#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
69pub enum Type {
70 Bool,
71 U8,
72 U16,
73 U32,
74 U64,
75 U128,
76 U256,
77 Address,
78 Signer,
79 Vector(Rc<Vector>),
80 Datatype(Rc<Datatype>),
81 Reference(bool, Rc<Type>),
82}
83
84#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
85pub struct Vector {
86 pub abilities: AbilitySet,
87 pub element_type: Type,
88}
89
90#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
91pub struct Datatype {
92 pub abilities: AbilitySet,
93 pub module: ModuleId,
94 pub name: Identifier,
95 pub type_arguments: Vec<Type>,
96}
97
98#[derive(Debug, Clone)]
99pub enum InputType {
100 Bytes,
101 Fixed(Type),
102}
103
104#[derive(Debug)]
105pub enum Command {
106 MoveCall(Box<MoveCall>),
107 TransferObjects(Vec<Argument>, Argument),
108 SplitCoins(Argument, Vec<Argument>),
109 MergeCoins(Argument, Vec<Argument>),
110 MakeMoveVec(Option<Type>, Vec<Argument>),
111 Publish(Vec<Vec<u8>>, Vec<ObjectID>, ResolvedLinkage),
112 Upgrade(
113 Vec<Vec<u8>>,
114 Vec<ObjectID>,
115 ObjectID,
116 Argument,
117 ResolvedLinkage,
118 ),
119}
120
121#[derive(Debug)]
122pub struct LoadedFunctionInstantiation {
123 pub parameters: Vec<Type>,
124 pub return_: Vec<Type>,
125}
126
127#[derive(Debug)]
128pub struct LoadedFunction {
129 pub storage_id: ModuleId,
130 pub runtime_id: ModuleId,
131 pub name: Identifier,
132 pub type_arguments: Vec<Type>,
133 pub signature: LoadedFunctionInstantiation,
134 pub linkage: RootedLinkage,
135 pub instruction_length: CodeOffset,
136 pub definition_index: FunctionDefinitionIndex,
137}
138
139#[derive(Debug)]
140pub struct MoveCall {
141 pub function: LoadedFunction,
142 pub arguments: Vec<Argument>,
143}
144
145pub use sui_types::transaction::Argument;
146
147impl ObjectArg {
152 pub fn id(&self) -> ObjectID {
153 match self {
154 ObjectArg::ImmObject(oref) | ObjectArg::OwnedObject(oref) => oref.0,
155 ObjectArg::SharedObject { id, .. } => *id,
156 }
157 }
158
159 pub fn mutability(&self) -> ObjectMutability {
160 match self {
161 ObjectArg::ImmObject(_) => ObjectMutability::Immutable,
162 ObjectArg::OwnedObject(_) => ObjectMutability::Mutable,
163 ObjectArg::SharedObject { mutability, .. } => *mutability,
164 }
165 }
166}
167
168impl Type {
169 pub fn abilities(&self) -> AbilitySet {
170 match self {
171 Type::Bool
172 | Type::U8
173 | Type::U16
174 | Type::U32
175 | Type::U64
176 | Type::U128
177 | Type::U256
178 | Type::Address => AbilitySet::PRIMITIVES,
179 Type::Signer => AbilitySet::SIGNER,
180 Type::Reference(_, _) => AbilitySet::REFERENCES,
181 Type::Vector(v) => v.abilities,
182 Type::Datatype(dt) => dt.abilities,
183 }
184 }
185
186 pub fn is_tx_context(&self) -> TxContextKind {
187 let (is_mut, inner) = match self {
188 Type::Reference(is_mut, inner) => (*is_mut, inner),
189 _ => return TxContextKind::None,
190 };
191 let Type::Datatype(dt) = &**inner else {
192 return TxContextKind::None;
193 };
194 if dt.qualified_ident() == RESOLVED_TX_CONTEXT {
195 if is_mut {
196 TxContextKind::Mutable
197 } else {
198 TxContextKind::Immutable
199 }
200 } else {
201 TxContextKind::None
202 }
203 }
204 pub fn all_addresses(&self) -> IndexSet<AccountAddress> {
205 match self {
206 Type::Bool
207 | Type::U8
208 | Type::U16
209 | Type::U32
210 | Type::U64
211 | Type::U128
212 | Type::U256
213 | Type::Address
214 | Type::Signer => IndexSet::new(),
215 Type::Vector(v) => v.element_type.all_addresses(),
216 Type::Reference(_, inner) => inner.all_addresses(),
217 Type::Datatype(dt) => dt.all_addresses(),
218 }
219 }
220
221 pub fn node_count(&self) -> u64 {
222 use Type::*;
223 let mut total = 0u64;
224 let mut stack = vec![self];
225
226 while let Some(ty) = stack.pop() {
227 total = total.saturating_add(1);
228 match ty {
229 Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address | Signer => {}
230 Vector(v) => stack.push(&v.element_type),
231 Reference(_, inner) => stack.push(inner),
232 Datatype(dt) => {
233 stack.extend(&dt.type_arguments);
234 }
235 }
236 }
237
238 total
239 }
240
241 pub fn is_reference(&self) -> bool {
242 match self {
243 Type::Bool
244 | Type::U8
245 | Type::U16
246 | Type::U32
247 | Type::U64
248 | Type::U128
249 | Type::U256
250 | Type::Address
251 | Type::Signer
252 | Type::Vector(_)
253 | Type::Datatype(_) => false,
254 Type::Reference(_, _) => true,
255 }
256 }
257}
258
259impl Datatype {
260 pub fn qualified_ident(&self) -> (&AccountAddress, &IdentStr, &IdentStr) {
261 (
262 self.module.address(),
263 self.module.name(),
264 self.name.as_ident_str(),
265 )
266 }
267
268 pub fn all_addresses(&self) -> IndexSet<AccountAddress> {
269 let mut addresses = IndexSet::new();
270 addresses.insert(*self.module.address());
271 for arg in &self.type_arguments {
272 addresses.extend(arg.all_addresses());
273 }
274 addresses
275 }
276}
277
278impl TryFrom<Type> for TypeTag {
283 type Error = &'static str;
284 fn try_from(ty: Type) -> Result<Self, Self::Error> {
285 Ok(match ty {
286 Type::Bool => TypeTag::Bool,
287 Type::U8 => TypeTag::U8,
288 Type::U16 => TypeTag::U16,
289 Type::U32 => TypeTag::U32,
290 Type::U64 => TypeTag::U64,
291 Type::U128 => TypeTag::U128,
292 Type::U256 => TypeTag::U256,
293 Type::Address => TypeTag::Address,
294 Type::Signer => TypeTag::Signer,
295 Type::Vector(inner) => {
296 let Vector { element_type, .. } = &*inner;
297 TypeTag::Vector(Box::new(element_type.clone().try_into()?))
298 }
299 Type::Datatype(dt) => {
300 let dt: &Datatype = &dt;
301 TypeTag::Struct(Box::new(dt.try_into()?))
302 }
303 Type::Reference(_, _) => return Err("unexpected reference type"),
304 })
305 }
306}
307
308impl TryFrom<&Datatype> for StructTag {
309 type Error = &'static str;
310
311 fn try_from(dt: &Datatype) -> Result<Self, Self::Error> {
312 let Datatype {
313 module,
314 name,
315 type_arguments,
316 ..
317 } = dt;
318 Ok(StructTag {
319 address: *module.address(),
320 module: module.name().to_owned(),
321 name: name.to_owned(),
322 type_params: type_arguments
323 .iter()
324 .map(|t| t.clone().try_into())
325 .collect::<Result<Vec<TypeTag>, _>>()?,
326 })
327 }
328}
329
330#[test]
335fn enum_size() {
336 assert_eq!(std::mem::size_of::<Type>(), 16);
337}