1use super::*;
2use crate::predicates::*;
3use codec::Codec;
4use core::fmt::Debug;
5use core::marker::PhantomData;
6pub use hash_db::Hasher;
7
8#[derive(PartialEq)]
9#[cfg_attr(feature = "std", derive(Debug))]
10pub enum ExecError<Address> {
11 Require {
12 msg: &'static str,
13 },
14 CallMethod {
15 call_method: PredicateCallInputs<Address>,
16 expected: &'static str,
17 },
18 CallAddress {
19 address: Address,
20 },
21 CodecError {
22 type_name: &'static str,
23 },
24 ExternalError {
25 msg: &'static str,
26 },
27 Unexpected {
28 msg: &'static str,
29 },
30 Unimplemented,
32}
33
34impl<Address> From<&'static str> for ExecError<Address> {
35 fn from(msg: &'static str) -> ExecError<Address> {
36 ExecError::<Address>::ExternalError { msg }
37 }
38}
39
40pub fn codec_error<Address>(expected_type_name: &'static str) -> ExecError<Address> {
42 ExecError::CodecError {
43 type_name: expected_type_name,
44 }
45}
46
47pub type ExecResult<Address> = core::result::Result<bool, ExecError<Address>>;
49pub type ExecResultT<T, Address> = core::result::Result<T, ExecError<Address>>;
51pub type ExecResultTOf<T, Ext> = core::result::Result<T, ExecError<AddressOf<Ext>>>;
53pub type AddressOf<Ext> = <Ext as ExternalCall>::Address;
55pub type HashOf<Ext> = <Ext as ExternalCall>::Hash;
57pub type HashingOf<Ext> = <Ext as ExternalCall>::Hashing;
59pub type PropertyOf<Ext> = Property<<Ext as ExternalCall>::Address>;
61
62pub trait MaybeAddress: Codec + Debug + Clone + Eq + PartialEq + Default {}
64impl<T: Codec + Debug + Clone + Eq + PartialEq + Default> MaybeAddress for T {}
65
66pub trait MaybeHash:
67 AsRef<[u8]>
68 + AsMut<[u8]>
69 + Default
70 + Codec
71 + Debug
72 + core::hash::Hash
73 + Send
74 + Sync
75 + Clone
76 + Copy
77 + Eq
78 + PartialEq
79 + Ord
80{
81}
82impl<
83 T: AsRef<[u8]>
84 + AsMut<[u8]>
85 + Default
86 + Codec
87 + Debug
88 + core::hash::Hash
89 + Send
90 + Sync
91 + Clone
92 + Copy
93 + Eq
94 + PartialEq
95 + Ord,
96 > MaybeHash for T
97{
98}
99
100pub const NOT_VARIABLE: &'static [u8] = b"Not";
101pub const AND_VARIABLE: &'static [u8] = b"And";
102pub const OR_VARIABLE: &'static [u8] = b"Or";
103pub const FOR_ALL_VARIABLE: &'static [u8] = b"ForAllSuchThat";
104pub const THERE_EXISTS_VARIABLE: &'static [u8] = b"ThereExistsSuchThat";
105pub const EQUAL_VARIABLE: &'static [u8] = b"Equal";
106pub const IS_CONTAINED_VARIABLE: &'static [u8] = b"IsContained";
107pub const IS_LESS_VARIABLE: &'static [u8] = b"IsLessThan";
108pub const IS_STORED_VARIABLE: &'static [u8] = b"IsStored";
109pub const IS_VALID_SIGNATURE_VARIABLE: &'static [u8] = b"IsValidSignature";
110pub const VERIFY_INCLUSION_VARIABLE: &'static [u8] = b"VerifyInclusion";
111
112pub trait ExternalCall {
113 type Address: MaybeAddress;
115 type Hash: MaybeHash;
117 type Hashing: Hasher<Out = Self::Hash>;
119
120 fn not_address() -> Self::Address;
123 fn and_address() -> Self::Address;
125 fn or_address() -> Self::Address;
127 fn for_all_address() -> Self::Address;
129 fn there_exists_address() -> Self::Address;
131 fn equal_address() -> Self::Address;
133 fn is_contained_address() -> Self::Address;
135 fn is_less_address() -> Self::Address;
137 fn is_stored_address() -> Self::Address;
139 fn is_valid_signature_address() -> Self::Address;
141 fn verify_inclusion_address() -> Self::Address;
143
144 fn vec_to_address(key: &Vec<u8>) -> Option<Self::Address> {
145 match key {
146 x if x.as_slice() == NOT_VARIABLE => Some(Self::not_address()),
147 x if x.as_slice() == AND_VARIABLE => Some(Self::and_address()),
148 x if x.as_slice() == OR_VARIABLE => Some(Self::or_address()),
149 x if x.as_slice() == FOR_ALL_VARIABLE => Some(Self::for_all_address()),
150 x if x.as_slice() == THERE_EXISTS_VARIABLE => Some(Self::there_exists_address()),
151 x if x.as_slice() == EQUAL_VARIABLE => Some(Self::equal_address()),
152 x if x.as_slice() == IS_CONTAINED_VARIABLE => Some(Self::is_contained_address()),
153 x if x.as_slice() == IS_LESS_VARIABLE => Some(Self::is_less_address()),
154 x if x.as_slice() == IS_STORED_VARIABLE => Some(Self::is_stored_address()),
155 x if x.as_slice() == IS_VALID_SIGNATURE_VARIABLE => {
156 Some(Self::is_valid_signature_address())
157 }
158 x if x.as_slice() == VERIFY_INCLUSION_VARIABLE => {
159 Some(Self::verify_inclusion_address())
160 }
161 _ => None,
162 }
163 }
164
165 fn secp256k1() -> Self::Hash;
167
168 fn hash_of<S: Encode>(s: &S) -> Self::Hash {
170 Encode::using_encoded(s, Self::Hashing::hash)
171 }
172
173 fn ext_call(
175 &self,
176 to: &Self::Address,
177 input_data: PredicateCallInputs<Self::Address>,
178 ) -> ExecResultT<Vec<u8>, Self::Address>;
179
180 fn ext_caller(&self) -> Self::Address;
182
183 fn ext_address(&self) -> Self::Address;
185
186 fn ext_is_stored(&self, address: &Self::Address, key: &[u8], value: &[u8]) -> bool;
192
193 fn ext_verify(&self, hash: &Self::Hash, signature: &[u8], address: &Self::Address) -> bool;
196
197 fn ext_verify_inclusion_with_root(
200 &self,
201 leaf: Self::Hash,
202 token_address: Self::Address,
203 range: &[u8],
204 inclusion_proof: &[u8],
205 root: &[u8],
206 ) -> bool;
207
208 fn ext_is_decided(&self, property: &PropertyOf<Self>) -> bool;
211 fn ext_is_decided_by_id(&self, id: Self::Hash) -> bool;
213 fn ext_get_property_id(&self, property: &PropertyOf<Self>) -> Self::Hash;
215 fn ext_set_predicate_decision(
217 &self,
218 game_id: Self::Hash,
219 decision: bool,
220 ) -> ExecResult<Self::Address>;
221
222 fn is_placeholder(target: &Vec<u8>) -> bool {
226 return target.len() < 20 && target.get(0) == Some(&(b'V' as u8));
227 }
228
229 fn is_label(target: &Vec<u8>) -> bool {
232 return target.len() < 20 && target.get(0) == Some(&(b'L' as u8));
233 }
234
235 fn sub_bytes(target: &Vec<u8>, start_index: u128, end_index: u128) -> Vec<u8> {
237 target
238 .as_slice()
239 .get((start_index as usize)..(end_index as usize))
240 .unwrap_or(vec![].as_slice())
241 .to_vec()
242 }
243
244 fn sub_array(target: &Vec<Vec<u8>>, start_index: usize, end_index: usize) -> Vec<Vec<u8>> {
246 target
247 .as_slice()
248 .get((start_index)..(end_index))
249 .unwrap_or(vec![].as_slice())
250 .to_vec()
251 }
252
253 fn get_input_value(target: &Vec<u8>) -> Vec<u8> {
255 Self::sub_bytes(target, 1, target.len() as u128)
256 }
257
258 fn bytes_to_u128(target: &Vec<u8>) -> ExecResultT<u128, Self::Address> {
260 Decode::decode(&mut &target[..]).map_err(|_| codec_error::<Self::Address>("u128"))
261 }
262
263 fn bytes_to_range(target: &Vec<u8>) -> ExecResultT<Range, Self::Address> {
265 Decode::decode(&mut &target[..]).map_err(|_| codec_error::<Self::Address>("Range"))
266 }
267
268 fn bytes_to_address(target: &Vec<u8>) -> ExecResultT<Self::Address, Self::Address> {
270 Decode::decode(&mut &target[..]).map_err(|_| codec_error::<Self::Address>("Address"))
271 }
272
273 fn bytes_to_bool(target: &Vec<u8>) -> ExecResultT<bool, Self::Address> {
275 Decode::decode(&mut &target[..]).map_err(|_| codec_error::<Self::Address>("bool"))
276 }
277
278 fn bytes_to_property(target: &Vec<u8>) -> ExecResultT<PropertyOf<Self>, Self::Address> {
280 Decode::decode(&mut &target[..])
281 .map_err(|_| codec_error::<Self::Address>("PropertyOf<Ext>"))
282 }
283
284 fn bytes_to_bytes_array(target: &Vec<u8>) -> ExecResultT<Vec<Vec<u8>>, Self::Address> {
286 Decode::decode(&mut &target[..]).map_err(|_| codec_error::<Self::Address>("Vec<Vec<u8>>"))
287 }
288
289 fn prefix_label(source: &Vec<u8>) -> Vec<u8> {
290 Self::prefix(b'L', source)
291 }
292
293 fn prefix_variable(source: &Vec<u8>) -> Vec<u8> {
294 Self::prefix(b'V', source)
295 }
296
297 fn prefix(prefix: u8, source: &Vec<u8>) -> Vec<u8> {
298 vec![vec![prefix], source.clone()].concat()
299 }
300}
301
302pub trait OvmExecutor<P> {
303 type ExtCall: ExternalCall;
304 fn execute(
305 executable: P,
306 call_method: PredicateCallInputs<AddressOf<Self::ExtCall>>,
307 ) -> ExecResultT<Vec<u8>, AddressOf<Self::ExtCall>>;
308}
309
310pub struct AtomicExecutor<P, Ext> {
311 _phantom: PhantomData<(P, Ext)>,
312}
313
314impl<P, Ext> OvmExecutor<P> for AtomicExecutor<P, Ext>
315where
316 P: predicates::AtomicPredicateInterface<AddressOf<Ext>>,
317 Ext: ExternalCall,
318{
319 type ExtCall = Ext;
320 fn execute(
321 predicate: P,
322 call_method: PredicateCallInputs<AddressOf<Ext>>,
323 ) -> ExecResultT<Vec<u8>, Ext::Address> {
324 match call_method {
325 PredicateCallInputs::AtomicPredicate(atomic) => {
326 match atomic {
327 AtomicPredicateCallInputs::Decide { inputs } => {
328 return Ok(predicate.decide(inputs)?.encode());
329 }
330 AtomicPredicateCallInputs::DecideTrue { inputs } => {
331 predicate.decide_true(inputs)?;
332 return Ok(true.encode());
333 }
334 };
335 }
336 other => Err(ExecError::CallMethod {
337 call_method: other,
338 expected: "AtomicPredicateCallInputs",
339 }),
340 }
341 }
342}
343
344pub struct BaseAtomicExecutor<P, Ext> {
345 _phantom: PhantomData<(P, Ext)>,
346}
347
348impl<P, Ext> OvmExecutor<P> for BaseAtomicExecutor<P, Ext>
349where
350 P: predicates::BaseAtomicPredicateInterface<AddressOf<Ext>>,
351 Ext: ExternalCall,
352{
353 type ExtCall = Ext;
354 fn execute(
355 predicate: P,
356 call_method: PredicateCallInputs<AddressOf<Ext>>,
357 ) -> ExecResultT<Vec<u8>, Ext::Address> {
358 match call_method {
359 PredicateCallInputs::BaseAtomicPredicate(atomic) => {
360 match atomic {
361 BaseAtomicPredicateCallInputs::Decide { inputs } => {
362 return Ok(predicate.decide(inputs)?.encode());
363 }
364 BaseAtomicPredicateCallInputs::DecideTrue { inputs } => {
365 predicate.decide_true(inputs)?;
366 return Ok(true.encode());
367 }
368 BaseAtomicPredicateCallInputs::DecideWithWitness { inputs, witness } => {
369 return Ok(predicate.decide_with_witness(inputs, witness)?.encode());
370 }
371 };
372 }
373 other => Err(ExecError::CallMethod {
374 call_method: other,
375 expected: "BaseAtomicPredicateCallInputs",
376 }),
377 }
378 }
379}
380
381pub struct LogicalConnectiveExecutor<P, Ext> {
382 _phantom: PhantomData<(P, Ext)>,
383}
384
385impl<P, Ext> OvmExecutor<P> for LogicalConnectiveExecutor<P, Ext>
386where
387 P: predicates::LogicalConnectiveInterface<AddressOf<Ext>>,
388 Ext: ExternalCall,
389{
390 type ExtCall = Ext;
391 fn execute(
392 predicate: P,
393 call_method: PredicateCallInputs<AddressOf<Ext>>,
394 ) -> ExecResultT<Vec<u8>, Ext::Address> {
395 match call_method {
396 PredicateCallInputs::LogicalConnective(atomic) => {
397 match atomic {
398 LogicalConnectiveCallInputs::IsValidChallenge {
399 inputs,
400 challenge_inputs,
401 challenge,
402 } => {
403 return Ok(predicate
404 .is_valid_challenge(inputs, challenge_inputs, challenge)?
405 .encode())
406 }
407 };
408 }
409 other => Err(ExecError::CallMethod {
410 call_method: other,
411 expected: "LogicalConnectiveCallInputs",
412 }),
413 }
414 }
415}
416
417pub struct DecidableExecutor<P, Ext> {
418 _phantom: PhantomData<(P, Ext)>,
419}
420
421impl<P, Ext> OvmExecutor<P> for DecidableExecutor<P, Ext>
422where
423 P: predicates::DecidablePredicateInterface<AddressOf<Ext>>,
424 Ext: ExternalCall,
425{
426 type ExtCall = Ext;
427 fn execute(
428 predicate: P,
429 call_method: PredicateCallInputs<AddressOf<Ext>>,
430 ) -> ExecResultT<Vec<u8>, Ext::Address> {
431 match call_method {
432 PredicateCallInputs::DecidablePredicate(atomic) => {
433 match atomic {
434 DecidablePredicateCallInputs::DecideWithWitness { inputs, witness } => {
435 return Ok(predicate.decide_with_witness(inputs, witness)?.encode());
436 }
437 };
438 }
439 other => Err(ExecError::CallMethod {
440 call_method: other,
441 expected: "DecidablePredicateCallInputs",
442 }),
443 }
444 }
445}
446
447pub struct CompiledExecutor<P, Ext> {
448 _phantom: PhantomData<(P, Ext)>,
449}
450
451impl<P, Ext> OvmExecutor<P> for CompiledExecutor<P, Ext>
452where
453 P: predicates::CompiledPredicateInterface<AddressOf<Ext>>,
454 Ext: ExternalCall,
455{
456 type ExtCall = Ext;
457 fn execute(
458 predicate: P,
459 call_method: PredicateCallInputs<AddressOf<Ext>>,
460 ) -> ExecResultT<Vec<u8>, Ext::Address> {
461 match call_method {
462 PredicateCallInputs::CompiledPredicate(atomic) => {
463 match atomic {
464 CompiledPredicateCallInputs::IsValidChallenge {
465 inputs,
466 challenge_inputs,
467 challenge,
468 } => {
469 return Ok(predicate
470 .is_valid_challenge(inputs, challenge_inputs, challenge)?
471 .encode());
472 }
473 CompiledPredicateCallInputs::Decide { inputs, witness } => {
474 return Ok(predicate.decide(inputs, witness)?.encode());
475 }
476 CompiledPredicateCallInputs::DecideTrue { inputs, witness } => {
477 return Ok(predicate.decide_true(inputs, witness)?.encode());
478 }
479 CompiledPredicateCallInputs::DecideWithWitness { inputs, witness } => {
480 return Ok(predicate.decide_with_witness(inputs, witness)?.encode());
481 }
482 CompiledPredicateCallInputs::GetChild {
483 inputs,
484 challenge_input,
485 } => {
486 return Ok(predicate.get_child(inputs, challenge_input)?.encode());
487 }
488 };
489 }
490 other => Err(ExecError::CallMethod {
491 call_method: other,
492 expected: "CompiledPredicateCallInputs",
493 }),
494 }
495 }
496}