1use crate::execution_value::{RawValueType, Value};
5use move_core_types::language_storage::TypeTag;
6use std::marker::PhantomData;
7use sui_types::error::{ExecutionError, ExecutionErrorTrait};
8use sui_types::execution_status::ExecutionFailure;
9use sui_types::{execution::ExecutionResult, transaction::Argument, transfer::Receiving};
10
11pub type TransactionIndex = usize;
12
13pub trait ExecutionMode {
14 type ArgumentUpdates;
16 type ExecutionResults;
18 type Error: ExecutionErrorTrait;
20
21 fn allow_arbitrary_function_calls() -> bool;
23
24 fn allow_arbitrary_values() -> bool;
27
28 fn skip_conservation_checks() -> bool;
30
31 fn packages_are_predefined() -> bool;
34
35 fn empty_arguments() -> Self::ArgumentUpdates;
36
37 fn empty_results() -> Self::ExecutionResults;
38
39 fn add_argument_update(
40 acc: &mut Self::ArgumentUpdates,
41 arg: Argument,
42 _new_value: &Value,
43 ) -> Result<(), ExecutionError>;
44
45 fn finish_command(
46 acc: &mut Self::ExecutionResults,
47 argument_updates: Self::ArgumentUpdates,
48 command_result: &[Value],
49 ) -> Result<(), ExecutionError>;
50
51 const TRACK_EXECUTION: bool;
54
55 fn add_argument_update_v2(
56 acc: &mut Self::ArgumentUpdates,
57 arg: Argument,
58 bytes: Vec<u8>,
59 type_: TypeTag,
60 ) -> Result<(), ExecutionError>;
61
62 fn finish_command_v2(
63 acc: &mut Self::ExecutionResults,
64 argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
65 command_result: Vec<(Vec<u8>, TypeTag)>,
66 ) -> Result<(), ExecutionError>;
67}
68
69#[derive(Copy, Clone)]
70pub struct Normal<E = ExecutionFailure>(PhantomData<fn() -> E>);
71
72impl<E> ExecutionMode for Normal<E>
73where
74 E: ExecutionErrorTrait,
75{
76 type ArgumentUpdates = ();
77 type ExecutionResults = ();
78 type Error = E;
79
80 fn allow_arbitrary_function_calls() -> bool {
81 false
82 }
83
84 fn allow_arbitrary_values() -> bool {
85 false
86 }
87
88 fn skip_conservation_checks() -> bool {
89 false
90 }
91
92 fn packages_are_predefined() -> bool {
93 false
94 }
95
96 fn empty_arguments() -> Self::ArgumentUpdates {}
97
98 fn empty_results() -> Self::ExecutionResults {}
99
100 fn add_argument_update(
101 _acc: &mut Self::ArgumentUpdates,
102 _arg: Argument,
103 _new_value: &Value,
104 ) -> Result<(), ExecutionError> {
105 Ok(())
106 }
107
108 fn finish_command(
109 _acc: &mut Self::ExecutionResults,
110 _argument_updates: Self::ArgumentUpdates,
111 _command_result: &[Value],
112 ) -> Result<(), ExecutionError> {
113 Ok(())
114 }
115
116 const TRACK_EXECUTION: bool = false;
117
118 fn add_argument_update_v2(
119 _acc: &mut Self::ArgumentUpdates,
120 _arg: Argument,
121 _bytes: Vec<u8>,
122 _type_: TypeTag,
123 ) -> Result<(), ExecutionError> {
124 invariant_violation!("should not be called");
125 }
126
127 fn finish_command_v2(
128 _acc: &mut Self::ExecutionResults,
129 _argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
130 _command_result: Vec<(Vec<u8>, TypeTag)>,
131 ) -> Result<(), ExecutionError> {
132 invariant_violation!("should not be called");
133 }
134}
135
136#[derive(Copy, Clone)]
137pub struct Genesis;
138
139impl ExecutionMode for Genesis {
140 type ArgumentUpdates = ();
141 type ExecutionResults = ();
142 type Error = ExecutionError;
143
144 fn allow_arbitrary_function_calls() -> bool {
145 true
146 }
147
148 fn allow_arbitrary_values() -> bool {
149 true
150 }
151
152 fn packages_are_predefined() -> bool {
153 true
154 }
155
156 fn skip_conservation_checks() -> bool {
157 false
158 }
159
160 fn empty_arguments() -> Self::ArgumentUpdates {}
161
162 fn empty_results() -> Self::ExecutionResults {}
163
164 fn add_argument_update(
165 _acc: &mut Self::ArgumentUpdates,
166 _arg: Argument,
167 _new_value: &Value,
168 ) -> Result<(), ExecutionError> {
169 Ok(())
170 }
171
172 fn finish_command(
173 _acc: &mut Self::ExecutionResults,
174 _argument_updates: Self::ArgumentUpdates,
175 _command_result: &[Value],
176 ) -> Result<(), ExecutionError> {
177 Ok(())
178 }
179
180 const TRACK_EXECUTION: bool = false;
181
182 fn add_argument_update_v2(
183 _acc: &mut Self::ArgumentUpdates,
184 _arg: Argument,
185 _bytes: Vec<u8>,
186 _type_: TypeTag,
187 ) -> Result<(), ExecutionError> {
188 invariant_violation!("should not be called");
189 }
190
191 fn finish_command_v2(
192 _acc: &mut Self::ExecutionResults,
193 _argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
194 _command_result: Vec<(Vec<u8>, TypeTag)>,
195 ) -> Result<(), ExecutionError> {
196 invariant_violation!("should not be called");
197 }
198}
199
200#[derive(Copy, Clone)]
201pub struct System<E = ExecutionError>(PhantomData<fn() -> E>);
202
203impl<E> ExecutionMode for System<E>
207where
208 E: ExecutionErrorTrait,
209{
210 type ArgumentUpdates = ();
211 type ExecutionResults = ();
212 type Error = E;
213
214 fn allow_arbitrary_function_calls() -> bool {
215 true
217 }
218
219 fn allow_arbitrary_values() -> bool {
220 true
223 }
224
225 fn skip_conservation_checks() -> bool {
226 false
227 }
228
229 fn packages_are_predefined() -> bool {
230 true
231 }
232
233 fn empty_arguments() -> Self::ArgumentUpdates {}
234
235 fn empty_results() -> Self::ExecutionResults {}
236
237 fn add_argument_update(
238 _acc: &mut Self::ArgumentUpdates,
239 _arg: Argument,
240 _new_value: &Value,
241 ) -> Result<(), ExecutionError> {
242 Ok(())
243 }
244
245 fn finish_command(
246 _acc: &mut Self::ExecutionResults,
247 _argument_updates: Self::ArgumentUpdates,
248 _command_result: &[Value],
249 ) -> Result<(), ExecutionError> {
250 Ok(())
251 }
252
253 const TRACK_EXECUTION: bool = false;
254
255 fn add_argument_update_v2(
256 _acc: &mut Self::ArgumentUpdates,
257 _arg: Argument,
258 _bytes: Vec<u8>,
259 _type_: TypeTag,
260 ) -> Result<(), ExecutionError> {
261 invariant_violation!("should not be called");
262 }
263
264 fn finish_command_v2(
265 _acc: &mut Self::ExecutionResults,
266 _argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
267 _command_result: Vec<(Vec<u8>, TypeTag)>,
268 ) -> Result<(), ExecutionError> {
269 invariant_violation!("should not be called");
270 }
271}
272
273pub struct DevInspect<const SKIP_ALL_CHECKS: bool>;
277
278impl<const SKIP_ALL_CHECKS: bool> ExecutionMode for DevInspect<SKIP_ALL_CHECKS> {
279 type ArgumentUpdates = Vec<(Argument, Vec<u8>, TypeTag)>;
280 type ExecutionResults = Vec<ExecutionResult>;
281 type Error = ExecutionError;
282
283 fn allow_arbitrary_function_calls() -> bool {
284 SKIP_ALL_CHECKS
285 }
286
287 fn allow_arbitrary_values() -> bool {
288 SKIP_ALL_CHECKS
289 }
290
291 fn skip_conservation_checks() -> bool {
292 SKIP_ALL_CHECKS
293 }
294
295 fn packages_are_predefined() -> bool {
296 false
297 }
298
299 fn empty_arguments() -> Self::ArgumentUpdates {
300 vec![]
301 }
302
303 fn empty_results() -> Self::ExecutionResults {
304 vec![]
305 }
306
307 fn add_argument_update(
308 acc: &mut Self::ArgumentUpdates,
309 arg: Argument,
310 new_value: &Value,
311 ) -> Result<(), ExecutionError> {
312 let (bytes, type_tag) = value_to_bytes_and_tag(new_value)?;
313 acc.push((arg, bytes, type_tag));
314 Ok(())
315 }
316
317 fn finish_command(
318 acc: &mut Self::ExecutionResults,
319 argument_updates: Self::ArgumentUpdates,
320 command_result: &[Value],
321 ) -> Result<(), ExecutionError> {
322 let command_bytes = command_result
323 .iter()
324 .map(value_to_bytes_and_tag)
325 .collect::<Result<_, _>>()?;
326 acc.push((argument_updates, command_bytes));
327 Ok(())
328 }
329
330 const TRACK_EXECUTION: bool = true;
331
332 fn add_argument_update_v2(
333 acc: &mut Self::ArgumentUpdates,
334 arg: Argument,
335 bytes: Vec<u8>,
336 type_: TypeTag,
337 ) -> Result<(), ExecutionError> {
338 acc.push((arg, bytes, type_));
339 Ok(())
340 }
341
342 fn finish_command_v2(
343 acc: &mut Self::ExecutionResults,
344 argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
345 command_result: Vec<(Vec<u8>, TypeTag)>,
346 ) -> Result<(), ExecutionError> {
347 acc.push((argument_updates, command_result));
348 Ok(())
349 }
350}
351
352fn value_to_bytes_and_tag(value: &Value) -> Result<(Vec<u8>, TypeTag), ExecutionError> {
353 let (type_tag, bytes) = match value {
354 Value::Object(obj) => {
355 let tag = obj.type_.type_.clone();
356 let mut bytes = vec![];
357 obj.write_bcs_bytes(&mut bytes, None)?;
358 (tag, bytes)
359 }
360 Value::Raw(RawValueType::Any, bytes) => {
361 (TypeTag::Vector(Box::new(TypeTag::U8)), bytes.clone())
363 }
364 Value::Raw(RawValueType::Loaded { ty, .. }, bytes) => {
365 let tag = ty.type_.clone();
366 (tag, bytes.clone())
367 }
368 Value::Receiving(id, seqno, _) => (
369 Receiving::type_tag(),
370 Receiving::new(*id, *seqno).to_bcs_bytes(),
371 ),
372 };
373 Ok((bytes, type_tag))
374}