1use iota_types::{
6 error::ExecutionError, execution::ExecutionResult, transaction::Argument, transfer::Receiving,
7};
8use move_core_types::language_storage::TypeTag;
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
57#[derive(Copy, Clone)]
58pub struct Normal;
59
60impl ExecutionMode for Normal {
61 type ArgumentUpdates = ();
62 type ExecutionResults = ();
63
64 fn allow_arbitrary_function_calls() -> bool {
65 false
66 }
67
68 fn allow_arbitrary_values() -> bool {
69 false
70 }
71
72 fn skip_conservation_checks() -> bool {
73 false
74 }
75
76 fn packages_are_predefined() -> bool {
77 false
78 }
79
80 fn empty_arguments() -> Self::ArgumentUpdates {}
81
82 fn empty_results() -> Self::ExecutionResults {}
83
84 fn add_argument_update(
85 _resolver: &impl TypeTagResolver,
86 _acc: &mut Self::ArgumentUpdates,
87 _arg: Argument,
88 _new_value: &Value,
89 ) -> Result<(), ExecutionError> {
90 Ok(())
91 }
92
93 fn finish_command(
94 _resolver: &impl TypeTagResolver,
95 _acc: &mut Self::ExecutionResults,
96 _argument_updates: Self::ArgumentUpdates,
97 _command_result: &[Value],
98 ) -> Result<(), ExecutionError> {
99 Ok(())
100 }
101}
102
103#[derive(Copy, Clone)]
104pub struct Genesis;
105
106impl ExecutionMode for Genesis {
107 type ArgumentUpdates = ();
108 type ExecutionResults = ();
109
110 fn allow_arbitrary_function_calls() -> bool {
111 true
112 }
113
114 fn allow_arbitrary_values() -> bool {
115 true
116 }
117
118 fn packages_are_predefined() -> bool {
119 true
120 }
121
122 fn skip_conservation_checks() -> bool {
123 false
124 }
125
126 fn empty_arguments() -> Self::ArgumentUpdates {}
127
128 fn empty_results() -> Self::ExecutionResults {}
129
130 fn add_argument_update(
131 _resolver: &impl TypeTagResolver,
132 _acc: &mut Self::ArgumentUpdates,
133 _arg: Argument,
134 _new_value: &Value,
135 ) -> Result<(), ExecutionError> {
136 Ok(())
137 }
138
139 fn finish_command(
140 _resolver: &impl TypeTagResolver,
141 _acc: &mut Self::ExecutionResults,
142 _argument_updates: Self::ArgumentUpdates,
143 _command_result: &[Value],
144 ) -> Result<(), ExecutionError> {
145 Ok(())
146 }
147}
148
149#[derive(Copy, Clone)]
150pub struct System;
151
152impl ExecutionMode for System {
156 type ArgumentUpdates = ();
157 type ExecutionResults = ();
158
159 fn allow_arbitrary_function_calls() -> bool {
160 true
162 }
163
164 fn allow_arbitrary_values() -> bool {
165 true
168 }
169
170 fn skip_conservation_checks() -> bool {
171 false
172 }
173
174 fn packages_are_predefined() -> bool {
175 true
176 }
177
178 fn empty_arguments() -> Self::ArgumentUpdates {}
179
180 fn empty_results() -> Self::ExecutionResults {}
181
182 fn add_argument_update(
183 _resolver: &impl TypeTagResolver,
184 _acc: &mut Self::ArgumentUpdates,
185 _arg: Argument,
186 _new_value: &Value,
187 ) -> Result<(), ExecutionError> {
188 Ok(())
189 }
190
191 fn finish_command(
192 _resolver: &impl TypeTagResolver,
193 _acc: &mut Self::ExecutionResults,
194 _argument_updates: Self::ArgumentUpdates,
195 _command_result: &[Value],
196 ) -> Result<(), ExecutionError> {
197 Ok(())
198 }
199}
200
201pub struct DevInspect<const SKIP_ALL_CHECKS: bool>;
205
206impl<const SKIP_ALL_CHECKS: bool> ExecutionMode for DevInspect<SKIP_ALL_CHECKS> {
207 type ArgumentUpdates = Vec<(Argument, Vec<u8>, TypeTag)>;
208 type ExecutionResults = Vec<ExecutionResult>;
209
210 fn allow_arbitrary_function_calls() -> bool {
211 SKIP_ALL_CHECKS
212 }
213
214 fn allow_arbitrary_values() -> bool {
215 SKIP_ALL_CHECKS
216 }
217
218 fn skip_conservation_checks() -> bool {
219 SKIP_ALL_CHECKS
220 }
221
222 fn packages_are_predefined() -> bool {
223 false
224 }
225
226 fn empty_arguments() -> Self::ArgumentUpdates {
227 vec![]
228 }
229
230 fn empty_results() -> Self::ExecutionResults {
231 vec![]
232 }
233
234 fn add_argument_update(
235 resolver: &impl TypeTagResolver,
236 acc: &mut Self::ArgumentUpdates,
237 arg: Argument,
238 new_value: &Value,
239 ) -> Result<(), ExecutionError> {
240 let (bytes, type_tag) = value_to_bytes_and_tag(resolver, new_value)?;
241 acc.push((arg, bytes, type_tag));
242 Ok(())
243 }
244
245 fn finish_command(
246 resolver: &impl TypeTagResolver,
247 acc: &mut Self::ExecutionResults,
248 argument_updates: Self::ArgumentUpdates,
249 command_result: &[Value],
250 ) -> Result<(), ExecutionError> {
251 let command_bytes = command_result
252 .iter()
253 .map(|value| value_to_bytes_and_tag(resolver, value))
254 .collect::<Result<_, _>>()?;
255 acc.push((argument_updates, command_bytes));
256 Ok(())
257 }
258}
259
260fn value_to_bytes_and_tag(
261 resolver: &impl TypeTagResolver,
262 value: &Value,
263) -> Result<(Vec<u8>, TypeTag), ExecutionError> {
264 let (type_tag, bytes) = match value {
265 Value::Object(obj) => {
266 let tag = resolver.get_type_tag(&obj.type_)?;
267 let mut bytes = vec![];
268 obj.write_bcs_bytes(&mut bytes, None)?;
269 (tag, bytes)
270 }
271 Value::Raw(RawValueType::Any, bytes) => {
272 (TypeTag::Vector(Box::new(TypeTag::U8)), bytes.clone())
274 }
275 Value::Raw(RawValueType::Loaded { ty, .. }, bytes) => {
276 let tag = resolver.get_type_tag(ty)?;
277 (tag, bytes.clone())
278 }
279 Value::Receiving(id, seqno, _) => (
280 Receiving::type_tag(),
281 Receiving::new(*id, *seqno).to_bcs_bytes(),
282 ),
283 };
284 Ok((bytes, type_tag))
285}