sui_adapter_latest/static_programmable_transactions/typing/
ast.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use crate::static_programmable_transactions::{
    linkage::resolved_linkage::ResolvedLinkage, loading::ast as L, spanned::Spanned,
};
use indexmap::IndexSet;
use move_vm_types::values::VectorSpecialization;
use std::cell::OnceCell;
use sui_types::base_types::{ObjectID, ObjectRef};

//**************************************************************************************************
// AST Nodes
//**************************************************************************************************

#[derive(Debug)]
pub struct Transaction {
    /// Gathered BCS bytes from Pure inputs
    pub bytes: IndexSet<Vec<u8>>,
    // All input objects
    pub objects: Vec<ObjectInput>,
    /// All pure inputs
    pub pure: Vec<PureInput>,
    /// All receiving inputs
    pub receiving: Vec<ReceivingInput>,
    pub commands: Commands,
}

/// The original index into the `input` vector of the transaction, before the inputs were split
/// into their respective categories (objects, pure, or receiving).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InputIndex(pub u16);

#[derive(Debug)]
pub struct ObjectInput {
    pub original_input_index: InputIndex,
    pub arg: ObjectArg,
    pub ty: Type,
}

pub type ByteIndex = usize;

#[derive(Debug)]
pub struct PureInput {
    pub original_input_index: InputIndex,
    // A index into `byte` table of BCS bytes
    pub byte_index: ByteIndex,
    // the type that the BCS bytes will be deserialized into
    pub ty: Type,
    // Information about where this constraint came from
    pub constraint: BytesConstraint,
}

#[derive(Debug)]
pub struct ReceivingInput {
    pub original_input_index: InputIndex,
    pub object_ref: ObjectRef,
    pub ty: Type,
    // Information about where this constraint came from
    pub constraint: BytesConstraint,
}

pub type Commands = Vec<Command>;

pub type ObjectArg = L::ObjectArg;

pub type Type = L::Type;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Information for a given constraint for input bytes
pub struct BytesConstraint {
    /// The command that first added this constraint
    pub command: u16,
    /// The argument in that command
    pub argument: u16,
}

pub type ResultType = Vec<Type>;

pub type Command = Spanned<Command_>;

#[derive(Debug)]
pub struct Command_ {
    /// The command
    pub command: Command__,
    /// The type of the return values of the command
    pub result_type: ResultType,
    /// Markers to drop unused results from the command. These are inferred based on any usage
    /// of the given result `Result(i,j)` after this command. This is leveraged by the borrow
    /// checker to remove unused references to allow potentially reuse of parent references.
    /// The value at result `j` is unused and can be dropped if `drop_value[j]` is true.
    pub drop_values: Vec</* drop value */ bool>,
}

#[derive(Debug)]
pub enum Command__ {
    MoveCall(Box<MoveCall>),
    TransferObjects(Vec<Argument>, Argument),
    SplitCoins(/* Coin<T> */ Type, Argument, Vec<Argument>),
    MergeCoins(/* Coin<T> */ Type, Argument, Vec<Argument>),
    MakeMoveVec(/* T for vector<T> */ Type, Vec<Argument>),
    Publish(Vec<Vec<u8>>, Vec<ObjectID>, ResolvedLinkage),
    Upgrade(
        Vec<Vec<u8>>,
        Vec<ObjectID>,
        ObjectID,
        Argument,
        ResolvedLinkage,
    ),
}

pub type LoadedFunctionInstantiation = L::LoadedFunctionInstantiation;

pub type LoadedFunction = L::LoadedFunction;

#[derive(Debug)]
pub struct MoveCall {
    pub function: LoadedFunction,
    pub arguments: Vec<Argument>,
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Location {
    TxContext,
    GasCoin,
    ObjectInput(u16),
    PureInput(u16),
    ReceivingInput(u16),
    Result(u16, u16),
}

// Non borrowing usage of locations, moving or copying
#[derive(Clone, Debug)]
pub enum Usage {
    Move(Location),
    Copy {
        location: Location,
        /// Was this location borrowed at the time of copying?
        /// Initially empty and populated by `memory_safety`
        borrowed: OnceCell<bool>,
    },
}

pub type Argument = Spanned<Argument_>;
pub type Argument_ = (Argument__, Type);

#[derive(Clone, Debug)]
pub enum Argument__ {
    /// Move or copy a value
    Use(Usage),
    /// Borrow a value, i.e. `&x` or `&mut x`
    Borrow(/* mut */ bool, Location),
    /// Read a value from a reference, i.e. `*&x`
    Read(Usage),
    /// Freeze a mutable reference, making an `&t` from `&mut t`
    Freeze(Usage),
}

//**************************************************************************************************
// impl
//**************************************************************************************************

impl Usage {
    pub fn new_move(location: Location) -> Usage {
        Usage::Move(location)
    }

    pub fn new_copy(location: Location) -> Usage {
        Usage::Copy {
            location,
            borrowed: OnceCell::new(),
        }
    }

    pub fn location(&self) -> Location {
        match self {
            Usage::Move(location) => *location,
            Usage::Copy { location, .. } => *location,
        }
    }
}

impl Argument__ {
    pub fn new_move(location: Location) -> Self {
        Self::Use(Usage::new_move(location))
    }

    pub fn new_copy(location: Location) -> Self {
        Self::Use(Usage::new_copy(location))
    }

    pub fn location(&self) -> Location {
        match self {
            Self::Use(usage) | Self::Read(usage) => usage.location(),
            Self::Borrow(_, location) => *location,
            Self::Freeze(usage) => usage.location(),
        }
    }
}

//**************************************************************************************************
// traits
//**************************************************************************************************

impl TryFrom<Type> for VectorSpecialization {
    type Error = &'static str;

    fn try_from(value: Type) -> Result<Self, Self::Error> {
        Ok(match value {
            Type::U8 => VectorSpecialization::U8,
            Type::U16 => VectorSpecialization::U16,
            Type::U32 => VectorSpecialization::U32,
            Type::U64 => VectorSpecialization::U64,
            Type::U128 => VectorSpecialization::U128,
            Type::U256 => VectorSpecialization::U256,
            Type::Address => VectorSpecialization::Address,
            Type::Bool => VectorSpecialization::Bool,
            Type::Signer | Type::Vector(_) | Type::Datatype(_) => VectorSpecialization::Container,
            Type::Reference(_, _) => return Err("unexpected reference in vector specialization"),
        })
    }
}