1use iota_sdk_types::{Argument, StructTag, TypeTag};
6use iota_types::{
7 error::ExecutionError, execution::ExecutionResult, invariant_violation, transfer::Receiving,
8};
9
10use crate::{
11 execution_value::{RawValueType, Value},
12 type_resolver::TypeTagResolver,
13};
14
15pub type TransactionIndex = usize;
16
17pub trait ExecutionMode {
18 type ArgumentUpdates;
20 type ExecutionResults;
22
23 fn allow_arbitrary_function_calls() -> bool;
25
26 fn allow_arbitrary_values() -> bool;
30
31 fn skip_conservation_checks() -> bool;
33
34 fn packages_are_predefined() -> bool;
37
38 fn empty_arguments() -> Self::ArgumentUpdates;
39
40 fn empty_results() -> Self::ExecutionResults;
41
42 fn add_argument_update(
43 resolver: &impl TypeTagResolver,
44 acc: &mut Self::ArgumentUpdates,
45 arg: Argument,
46 _new_value: &Value,
47 ) -> Result<(), ExecutionError>;
48
49 fn finish_command(
50 resolver: &impl TypeTagResolver,
51 acc: &mut Self::ExecutionResults,
52 argument_updates: Self::ArgumentUpdates,
53 command_result: &[Value],
54 ) -> Result<(), ExecutionError>;
55
56 fn allow_auth_context() -> bool;
59
60 const TRACK_EXECUTION: bool;
63
64 fn add_argument_update_v2(
65 acc: &mut Self::ArgumentUpdates,
66 arg: Argument,
67 bytes: Vec<u8>,
68 type_: TypeTag,
69 ) -> Result<(), ExecutionError>;
70
71 fn finish_command_v2(
72 acc: &mut Self::ExecutionResults,
73 argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
74 command_result: Vec<(Vec<u8>, TypeTag)>,
75 ) -> Result<(), ExecutionError>;
76}
77
78#[derive(Copy, Clone)]
79pub struct Normal;
80
81impl ExecutionMode for Normal {
82 type ArgumentUpdates = ();
83 type ExecutionResults = ();
84
85 fn allow_arbitrary_function_calls() -> bool {
86 false
87 }
88
89 fn allow_arbitrary_values() -> bool {
90 false
91 }
92
93 fn skip_conservation_checks() -> bool {
94 false
95 }
96
97 fn packages_are_predefined() -> bool {
98 false
99 }
100
101 fn empty_arguments() -> Self::ArgumentUpdates {}
102
103 fn empty_results() -> Self::ExecutionResults {}
104
105 fn add_argument_update(
106 _resolver: &impl TypeTagResolver,
107 _acc: &mut Self::ArgumentUpdates,
108 _arg: Argument,
109 _new_value: &Value,
110 ) -> Result<(), ExecutionError> {
111 Ok(())
112 }
113
114 fn finish_command(
115 _resolver: &impl TypeTagResolver,
116 _acc: &mut Self::ExecutionResults,
117 _argument_updates: Self::ArgumentUpdates,
118 _command_result: &[Value],
119 ) -> Result<(), ExecutionError> {
120 Ok(())
121 }
122
123 fn allow_auth_context() -> bool {
124 false
125 }
126
127 const TRACK_EXECUTION: bool = false;
128
129 fn add_argument_update_v2(
130 _acc: &mut Self::ArgumentUpdates,
131 _arg: Argument,
132 _bytes: Vec<u8>,
133 _type_: TypeTag,
134 ) -> Result<(), ExecutionError> {
135 invariant_violation!("should not be called");
136 }
137
138 fn finish_command_v2(
139 _acc: &mut Self::ExecutionResults,
140 _argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
141 _command_result: Vec<(Vec<u8>, TypeTag)>,
142 ) -> Result<(), ExecutionError> {
143 invariant_violation!("should not be called");
144 }
145}
146
147#[derive(Copy, Clone)]
148pub struct Genesis;
149
150impl ExecutionMode for Genesis {
151 type ArgumentUpdates = ();
152 type ExecutionResults = ();
153
154 fn allow_arbitrary_function_calls() -> bool {
155 true
156 }
157
158 fn allow_arbitrary_values() -> bool {
159 true
160 }
161
162 fn packages_are_predefined() -> bool {
163 true
164 }
165
166 fn skip_conservation_checks() -> bool {
167 false
168 }
169
170 fn empty_arguments() -> Self::ArgumentUpdates {}
171
172 fn empty_results() -> Self::ExecutionResults {}
173
174 fn add_argument_update(
175 _resolver: &impl TypeTagResolver,
176 _acc: &mut Self::ArgumentUpdates,
177 _arg: Argument,
178 _new_value: &Value,
179 ) -> Result<(), ExecutionError> {
180 Ok(())
181 }
182
183 fn finish_command(
184 _resolver: &impl TypeTagResolver,
185 _acc: &mut Self::ExecutionResults,
186 _argument_updates: Self::ArgumentUpdates,
187 _command_result: &[Value],
188 ) -> Result<(), ExecutionError> {
189 Ok(())
190 }
191
192 fn allow_auth_context() -> bool {
193 false
194 }
195
196 const TRACK_EXECUTION: bool = false;
197
198 fn add_argument_update_v2(
199 _acc: &mut Self::ArgumentUpdates,
200 _arg: Argument,
201 _bytes: Vec<u8>,
202 _type_: TypeTag,
203 ) -> Result<(), ExecutionError> {
204 invariant_violation!("should not be called");
205 }
206
207 fn finish_command_v2(
208 _acc: &mut Self::ExecutionResults,
209 _argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
210 _command_result: Vec<(Vec<u8>, TypeTag)>,
211 ) -> Result<(), ExecutionError> {
212 invariant_violation!("should not be called");
213 }
214}
215
216#[derive(Copy, Clone)]
217pub struct System;
218
219impl ExecutionMode for System {
223 type ArgumentUpdates = ();
224 type ExecutionResults = ();
225
226 fn allow_arbitrary_function_calls() -> bool {
227 true
229 }
230
231 fn allow_arbitrary_values() -> bool {
232 true
235 }
236
237 fn skip_conservation_checks() -> bool {
238 false
239 }
240
241 fn packages_are_predefined() -> bool {
242 true
243 }
244
245 fn empty_arguments() -> Self::ArgumentUpdates {}
246
247 fn empty_results() -> Self::ExecutionResults {}
248
249 fn add_argument_update(
250 _resolver: &impl TypeTagResolver,
251 _acc: &mut Self::ArgumentUpdates,
252 _arg: Argument,
253 _new_value: &Value,
254 ) -> Result<(), ExecutionError> {
255 Ok(())
256 }
257
258 fn finish_command(
259 _resolver: &impl TypeTagResolver,
260 _acc: &mut Self::ExecutionResults,
261 _argument_updates: Self::ArgumentUpdates,
262 _command_result: &[Value],
263 ) -> Result<(), ExecutionError> {
264 Ok(())
265 }
266
267 fn allow_auth_context() -> bool {
268 false
269 }
270
271 const TRACK_EXECUTION: bool = false;
272
273 fn add_argument_update_v2(
274 _acc: &mut Self::ArgumentUpdates,
275 _arg: Argument,
276 _bytes: Vec<u8>,
277 _type_: TypeTag,
278 ) -> Result<(), ExecutionError> {
279 invariant_violation!("should not be called");
280 }
281
282 fn finish_command_v2(
283 _acc: &mut Self::ExecutionResults,
284 _argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
285 _command_result: Vec<(Vec<u8>, TypeTag)>,
286 ) -> Result<(), ExecutionError> {
287 invariant_violation!("should not be called");
288 }
289}
290
291#[derive(Copy, Clone)]
292pub struct Authentication;
293
294impl ExecutionMode for Authentication {
295 type ArgumentUpdates = ();
296 type ExecutionResults = ();
297
298 fn allow_arbitrary_function_calls() -> bool {
299 false
300 }
301
302 fn allow_arbitrary_values() -> bool {
303 false
304 }
305
306 fn skip_conservation_checks() -> bool {
307 false
308 }
309
310 fn packages_are_predefined() -> bool {
311 false
312 }
313
314 fn empty_arguments() -> Self::ArgumentUpdates {}
315
316 fn empty_results() -> Self::ExecutionResults {}
317
318 fn add_argument_update(
319 _resolver: &impl TypeTagResolver,
320 _acc: &mut Self::ArgumentUpdates,
321 _arg: Argument,
322 _new_value: &Value,
323 ) -> Result<(), ExecutionError> {
324 Ok(())
325 }
326
327 fn finish_command(
328 _resolver: &impl TypeTagResolver,
329 _acc: &mut Self::ExecutionResults,
330 _argument_updates: Self::ArgumentUpdates,
331 _command_result: &[Value],
332 ) -> Result<(), ExecutionError> {
333 Ok(())
334 }
335
336 fn allow_auth_context() -> bool {
337 true
338 }
339
340 const TRACK_EXECUTION: bool = false;
341
342 fn add_argument_update_v2(
343 _acc: &mut Self::ArgumentUpdates,
344 _arg: Argument,
345 _bytes: Vec<u8>,
346 _type_: TypeTag,
347 ) -> Result<(), ExecutionError> {
348 invariant_violation!("should not be called");
349 }
350
351 fn finish_command_v2(
352 _acc: &mut Self::ExecutionResults,
353 _argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
354 _command_result: Vec<(Vec<u8>, TypeTag)>,
355 ) -> Result<(), ExecutionError> {
356 invariant_violation!("should not be called");
357 }
358}
359
360pub struct DevInspect<const SKIP_ALL_CHECKS: bool>;
364
365impl<const SKIP_ALL_CHECKS: bool> ExecutionMode for DevInspect<SKIP_ALL_CHECKS> {
366 type ArgumentUpdates = Vec<(Argument, Vec<u8>, TypeTag)>;
367 type ExecutionResults = Vec<ExecutionResult>;
368
369 fn allow_arbitrary_function_calls() -> bool {
370 SKIP_ALL_CHECKS
371 }
372
373 fn allow_arbitrary_values() -> bool {
374 SKIP_ALL_CHECKS
375 }
376
377 fn skip_conservation_checks() -> bool {
378 SKIP_ALL_CHECKS
379 }
380
381 fn packages_are_predefined() -> bool {
382 false
383 }
384
385 fn empty_arguments() -> Self::ArgumentUpdates {
386 vec![]
387 }
388
389 fn empty_results() -> Self::ExecutionResults {
390 vec![]
391 }
392
393 fn add_argument_update(
394 resolver: &impl TypeTagResolver,
395 acc: &mut Self::ArgumentUpdates,
396 arg: Argument,
397 new_value: &Value,
398 ) -> Result<(), ExecutionError> {
399 let (bytes, type_tag) = value_to_bytes_and_tag(resolver, new_value)?;
400 acc.push((arg, bytes, type_tag));
401 Ok(())
402 }
403
404 fn finish_command(
405 resolver: &impl TypeTagResolver,
406 acc: &mut Self::ExecutionResults,
407 argument_updates: Self::ArgumentUpdates,
408 command_result: &[Value],
409 ) -> Result<(), ExecutionError> {
410 let command_bytes = command_result
411 .iter()
412 .map(|value| value_to_bytes_and_tag(resolver, value))
413 .collect::<Result<_, _>>()?;
414 acc.push((argument_updates, command_bytes));
415 Ok(())
416 }
417
418 fn allow_auth_context() -> bool {
419 false
420 }
421
422 const TRACK_EXECUTION: bool = true;
423
424 fn add_argument_update_v2(
425 acc: &mut Self::ArgumentUpdates,
426 arg: Argument,
427 bytes: Vec<u8>,
428 type_: TypeTag,
429 ) -> Result<(), ExecutionError> {
430 acc.push((arg, bytes, type_));
431 Ok(())
432 }
433
434 fn finish_command_v2(
435 acc: &mut Self::ExecutionResults,
436 argument_updates: Vec<(Argument, Vec<u8>, TypeTag)>,
437 command_result: Vec<(Vec<u8>, TypeTag)>,
438 ) -> Result<(), ExecutionError> {
439 acc.push((argument_updates, command_result));
440 Ok(())
441 }
442}
443
444fn value_to_bytes_and_tag(
445 resolver: &impl TypeTagResolver,
446 value: &Value,
447) -> Result<(Vec<u8>, TypeTag), ExecutionError> {
448 let (type_tag, bytes) = match value {
449 Value::Object(obj) => {
450 let tag = resolver.get_type_tag(&obj.type_)?;
451 let mut bytes = vec![];
452 obj.write_bcs_bytes(&mut bytes, None)?;
453 (tag, bytes)
454 }
455 Value::Raw(RawValueType::Any, bytes) => {
456 (TypeTag::Vector(Box::new(TypeTag::U8)), bytes.clone())
458 }
459 Value::Raw(RawValueType::Loaded { ty, .. }, bytes) => {
460 let tag = resolver.get_type_tag(ty)?;
461 (tag, bytes.clone())
462 }
463 Value::Receiving(id, seqno, assigned_type) => {
464 let Some(ty) = assigned_type else {
465 invariant_violation!("Receiving value used before type assignment");
466 };
467 let value_type = resolver.get_type_tag(ty)?;
468 (
469 StructTag::new_transfer_receiving(value_type).into(),
470 Receiving::new(*id, *seqno).to_bcs_bytes(),
471 )
472 }
473 };
474 Ok((bytes, type_tag))
475}