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