sui_adapter_latest/static_programmable_transactions/loading/
ast.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use 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//**************************************************************************************************
21// AST Nodes
22//**************************************************************************************************
23
24#[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(/* is mut */ 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(/* T for vector<T> */ 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
147//**************************************************************************************************
148// impl
149//**************************************************************************************************
150
151impl 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
278//**************************************************************************************************
279// Traits
280//**************************************************************************************************
281
282impl 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//**************************************************************************************************
331// Tests
332//**************************************************************************************************
333
334#[test]
335fn enum_size() {
336    assert_eq!(std::mem::size_of::<Type>(), 16);
337}